javaweb

javaweb

1.基础概念

  • 静态web

    • html,css
    • 提供给所有人看的数据始终不会改变
  • 动态web

    • 数据始终都在改变,每个人在不同时间不同地点看到的数据不同(淘宝之类的)

    • Servlet/jsp,asp,php

      在Java中动态资源开发技术统称为javaweb

1.2 web程序

能通过浏览器访问到的程序

  • 我们能访问的任何资源,都存在这个某一个计算机上

  • URL

  • 这个统一的web资源都会放在同一个文件下,web应用程序--》Tomcat

  • 一个web应用由多部分组成(静态web,动态web)

    • html,css,js
    • jsp,servlet
    • java程序
    • jar包
    • 配置文件

    web应用程序写好后想要被访问到:需要一个服务器来统一管理

1.3丶静态web

1638947966626

  • 静态页面的缺点:
    • Web页面无法动态更新,所有用户看到的都是同一个页面
    • 它无法与数据库交互(数据无法持久化,用户无法交互)

1.4丶动态web

1638949813290

缺点:

  • 动态资源出现问题就要重新编写我们的后台程序,重新发布
    • 停机维护

优点:

  • Web页面可以动态更新,所有用户看到的都是同一个页面
  • 它可以与数据库交互(数据能持久化,用户能交互)

1638950187570

2.Tomcat

2.1丶Tomcat基础

(1)Tomcat目录

1638952221836

(2)丶启动和配置

1638952240817

访问测试:https://localhost:8080/

(3)丶配置文件

1638952411991

1638953357932

这里可以配置访问端口

  • Tomcat的默认端口号:8080
  • mysql:3306
  • http:80
  • https:443

1638954318717

访问的localhost只是我们设置的,我们可以设置成任意的(但是你在这里直接更改还不行,你得去window设置(C:\Windows\System32\drivers\etc)里面添加一个域名跟你想修改的配置),但是它真正实现访问的是你的主机ip127.0.0.1

端口号同理

面试题

2.2 请你谈一谈网站是如何访问的!

  1. 输入一个域名,回车

  2. 就会在本地C:\Windows\System32\drivers\etc配置文件下查找是否有这个域名映射;

    1. 有:就直接返回这个IP地址对应的web程序

      #	127.0.0.1       localhost
      #	::1             localhost
      

      2.没有:去DNS服务器找,找到就返回,找不到就报错

      1638955772869

2.3 发布一个Web网站

1638956749231

http://localhost:8080/shinian/html/zhuye.html

访问地址(上面)

网站应该有的结构:

--webapps:Tomcat服务器的web服务器
	-shinian
	-Root:网站的目录名
		-index.html/jsp 默认的首页
		-WEB-IF 放网站程序的
			-web.xml
			-classes:java程序
			-lib:web应用所依赖的jar包
		-static	资源目录
        	-html
        	-js
        	-img
        -......	
	

3.HTTP

3.1 什么是HTTP

  • HTTP(超文本传输协议)是一个简单的请求-响应协议
  • Https:安全的
    • 443

3.2 两个时代

  • http1.0
    • HTTP/1.0 客户端与服务器连接后,一次只能获取一个web资源
  • http2.0
    • HTTP/1.1 客户端与服务器连接后,一次能获取多个web资源

3.3 请求

客户端--发请求(Request)--服务器

百度为例:

请求 URL: https://www.baidu.com/	域名
请求方法: GET					   请求方式 :Get/Post
状态代码: 200 OK					状态码
远程地址: 14.215.177.39:443			主机Ip地址和端口号
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9			能接收的资源
Accept-Encoding: gzip, deflate, br					接收的编码
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6		语言
Cache-Control: max-age=0
Connection: keep-alive

1.请求行

  • 请求行中的请求方式:GET
  • 有哪些方式:GET,Post等
    • get:请求能够携带的参数比较少,大小有限制,会在浏览器的URL地址栏显示数据内容,不安全,但高效
    • Post:请求能够携带的参数比较多,大小没限制,不会在浏览器的URL地址栏显示数据内容,安全,但不高效

2.消息头:

Accept:				告诉浏览器,它所支持的数据类型
Accept-Encoding: gzip, deflate, br					接收的编码
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6		语言
Cache-Control: max-age=0			缓存控制
Connection: keep-alive				告诉浏览器,请求完成是断开还是连接
Host:		主机

3.4 响应

服务器--响应(Respond)--客户端

Cache-Control: private					缓存控制
Connection: keep-alive					连接
Content-Encoding: gzip					编码
Content-Type: text/html;charset=utf-8	类型

1.响应体

Accept:				告诉浏览器,它所支持的数据类型
Accept-Encoding: gzip, deflate, br					接收的编码
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6		语言
Cache-Control: max-age=0			缓存控制
Connection: keep-alive				告诉浏览器,请求完成是断开还是连接
Host:		主机
Refresh:		告诉客户端,多久刷新一次
location:让网页重新定位

2.响应状态码(重点):

200:请求成功

3**:请求重定向

  • 重定向:你重新到我给你的新位置去;

4xx:找不到资源 404

  • 资源不存在

5xx:服务器代码错误 500 502:网关错误

3.5 常见面试题

当你的浏览器地址栏输入并回车的一瞬间到页面能够展示回来,经历了什么?

4.Maven

为什么要学这个技术?

  1. 在javaweb开发中,需要大量的导包,手动导入太麻烦
  2. 在此基础上Maven诞生了!

4.1 Maven项目架构管理工具

我们目前只用来导包

Maven核心思想:约定大于配置

  • 有约束,不要去违反

Maven会规定你该如何去编写我们的java代码,必须按照这个规范来;

4.2 配置环境

在环境变量中,配置如下配置

  • M2_HOME maven目录下的bin目录
  • MAVEN_HOME maven的目录
  • 在系统的path中配置 %MAVEN_HOME%\bin

4.3 阿里云镜像

  • 镜像:morris

    • 加速我们的下载
  • 国内推荐阿里云镜像

    <mirror>
        <id>nexus-aliyun</id>
        <mirrorOf>central</mirrorOf>
        <name>Nexus aliyun</name>
    <url>http://maven.aliyun.com/nexus/content/groups/public</url>
    </mirror>
    

4.4 本地仓库

在本地的仓库就会有远程仓库

建立一个本地仓库:localRepository

<localRepository>D:\Maven\apache-maven-3.8.4\maven-repo</localRepository>

4.5 在Idea使用Maven

  1. 创建一个Maven项目

1638973049051

1639048767905

1639048599916

1639049847095

2.此时的Maven仓库多了什么东西?

3.IDEA里的Maven设置

1639049200043

4.6.不勾选模板创建一个普通Maven

1639049700492

4.7 标记文件夹功能

1639050120471

4.8 在Maven中配置Tomcat

1639050730314

1639050963979

必须的配置:为什么会有这个问题,因为我们访问一个网站是需要一个文件夹的,IDEA不会给默认**

1639051284340

4.9 pom.xml(Maven的核心配置文件)

1639052257487

在配置文件中导入其他包的依赖,Maven的高级之处在于它能够帮你导入这个jar包所依赖的其他jar包

Maven遇到的问题:

<!--在build中配置resources,来防止我们资源导出失败的问题-->
<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering>
        </resource>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering>
        </resource>
    </resources>
</build>

5.Servlet

5.1 基础概念

  • Servlet是一种实现动态Web的一门技术

  • 本质:servlet其实就是对请求和响应的封装

  • 你想实现一个Servlet,必须有两个步骤:

    • 编写一个类实现Servlet接口
    • 将这个java类部署到服务器上

    把实现了Servlet接口的java程序叫做 Servlet

5.2 HelloServlet

  1. 构建一个普通的Maven项目,删掉里面的src目录,用户我们的学习就在这个项目里面建立Moudel,这个空工程的就是Maven主工程

  2. 关于Maven的父子工程的理解:

    1. 父项目会有:

      <modules>
              <module>Servlet-01</module>
          </modules>
      

      2.子项目会有:

      <parent>
       <artifactId>JavaWeb-01-Maven2</artifactId>
        <groupId>com.LiuDeHen</groupId>
        <version>1.0-SNAPSHOT</version>
      </parent>
      

      注意:这里子项目中没有parent的话后面在子项目里调用包时可能会因为子项目没有指向父项目,而需要用到父项目的包二无法自动导包

    ​ 3.就跟继承一样,父项目的java子项目可以直接用

    son extends father
    
  3. Maven环境优化

    1. 修改子项目web.xbl为最新的

      <?xml version="1.0" encoding="UTF-8"?>
             <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
              http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
              version="4.0"
              metadata-complete="true">
              </web-app>
      
    2. 将maven的结构搭建完整(webapps里一般要有java源目录和resources资源目录

  4. 编写一个Servlet程序

    1. 编写一个普通类

    2. 实现Servlet接口,这里我们直接继承HttpServelt

      1. Servlet接口有两个实现类,HttpServlet和GenericServlet
      public class HelloServlet extends HttpServlet {
      //    由于Get和Post只是实现请求的不同方式,可以相互调用,业务逻辑都一样
          @Override
          protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              PrintWriter writer = resp.getWriter();    //响应流
              writer.write("helloServlet");
          }
      
          @Override
          protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              super.doPost(req, resp);
          }
      

      3.为什么要继承HttpServlet

      1639062246093

      5.编写servlet映射

      为什么需要映射勒,因为servlet就是一个java程序而已,我们想要通过浏览器访问到,必须通过web服务器,所以我们就需要再web服务器里注册映射我们写的servlet,并且再给浏览器一个能够访问的路径

      <!-- 注册映射servlet-->
        <servlet>
      <!-- 自定义一个name 与下面访问地址的name对应-->
            <servlet-name>hello</servlet-name>
      <!--servlet类的位置-->
            <servlet-class>com.LiuDeHen.servlet.HelloServlet</servlet-class>
        </servlet>
      
          <servlet-mapping>
              <servlet-name>hello</servlet-name>
      <!--访问地址,这样前台就可以通过这个访问了-->
              <url-pattern>/hello</url-pattern>
          </servlet-mapping>
      

      运行后会加载到webapp这个包下,然后就会解析web.xml(下面这个图),就会访问到servlet程序

      1639059435538

      ​ 上图中访问地址前必须必须要有/

6.配置Tomcat

注意:配置项目发布路径就可以了

7.测试

启动Tomcat会出现一个target

5.3 Servlet原理

1639061826822

5.4 Mapping问题

  1. 一个Servlet指定一个映射

     <servlet-mapping>
            <servlet-name>hello</servlet-name>
    <!--访问地址,这样前台就可以通过这个访问了-->
            <url-pattern>/hello</url-pattern>
        </servlet-mapping>
    
  2. 一个Servlet指定多个映射

    <servlet-mapping>
            <servlet-name>hello</servlet-name>
    <!--访问地址,这样前台就可以通过这个访问了-->
            <url-pattern>/hello</url-pattern>
        </servlet-mapping>
        <servlet-mapping>
            <servlet-name>hello</servlet-name>
            <!--同一个name,不同访问地址也可以访问到同一个Servlet-->
            <url-pattern>/hello1</url-pattern>
        </servlet-mapping>
    
  3. 默认请求路径

    <servlet-mapping>
            <servlet-name>hello</servlet-name>
            <!--此时仍然访问的是Servlet而不是先访问index页面-->
            <url-pattern>/*</url-pattern>
        </servlet-mapping>
    
  4. 使用通配符

        <servlet-mapping>
            <servlet-name>hello</servlet-name>
            <!--访问地址,任意字符都能访问到-->
            <url-pattern>/hello/*</url-pattern>
        </servlet-mapping>
    
    
  5. 指定一些前缀后缀

 <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <!--*不像其他类型,前面不能有任何东西,但是在访问的时候,前面可以有任何文件夹-->
        <url-pattern>*.lc</url-pattern>
    </servlet-mapping>

6.优先级问题

​ 假如我定义了一个404报错Servlet,使用的是通配符地址,那么我访问/hello,是访问的hello页面还是404页面?

肯定是hello页面,固有的映射路径优先级最高,如果找不到才会找默认路径

5.5 ServletContext

Web服务器在启动的时候,它会为每一个Web程序都创建一个ServletContext对象,它代表了当前的Web应用,(一个web只有一个ServetContext

1 共享数据

我在这个Servlet中保存的数据,可以在另一个Servlet拿到

注意:响应时要设置响应编码格式不然会出现?

1639099477418

在当前Servlet设置		
    					ServletContext servletContext = this.getServletContext();
        				servletContext.setAttribute("User","你好");
在另外一个Servlet获取
        resp.setContentType("text/html");
        resp.setCharacterEncoding("GBK");
        ServletContext servletContext = this.getServletContext();
        Object user = servletContext.getAttribute("User");
        PrintWriter writer = resp.getWriter();
        writer.write(user.toString());

2 获取初始化参数

设置初始化需要的配置文件

<context-param>
    <param-name>url</param-name>
    <param-value>jdbc:mysql//localhost:3306/lc</param-value>
</context-param>x
获取:		
ServletContext servletContext = this.getServletContext();
        String s=servletContext.getInitParameter("url");
        resp.getWriter().print(s);

3 请求转发

  ServletContext servletContext = this.getServletContext();
  RequestDispatcher dispatcher = servletContext.getRequestDispatcher("/hello");//转发地址
  dispatcher.forward(req,resp);           //调用forword实现请求转发

这个只是转发,并不会改变我们的地址

1639102608627

1639103075825

4 读取资源文件

Properties

  • 在java目录下新建properties

  • 在resource下新建properties

    发现:都被导包到同一个路径下(target里的)classes,俗称为classpath

    思路:我们只需要给一个流

    username:root
    pwd:lc20010725
    
     InputStream stream = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.Properties");
            Properties p=new Properties();
            p.load(stream);
            String user = p.getProperty("username");
            String pwd = p.getProperty("pwd");
            resp.getWriter().print(user+":"+pwd);
    

    注意:我们读的文件是target里导出的文件

5.6 HttpServletResponse

web服务器接收到客户端的请求,针对这个请求,会分别创建一个代表请求的HttpServletRequest,代表响应的HttpServletResponse

  • 如果要获取客户端请求过来的参数:找HttpServletRequest
  • 如果要获取服务器响应的信息:找HttpServletResponse

常用分类:

1 向客户端发送消息(ServletResponse里的):

ServletOutputStream getOutputStream() throws IOException;
PrintWriter getWriter() throws IOException;

2 向浏览器发送响应头的方法:

ServletResponse里的:
	void setCharacterEncoding(String var1);

    void setContentLength(int var1);

    void setContentLengthLong(long var1);

    void setContentType(String var1);
    
HttpServletResponse里的:
	void sendRedirect(String var1) throws IOException;

    void setDateHeader(String var1, long var2);

    void addDateHeader(String var1, long var2);

    void setHeader(String var1, String var2);

    void addHeader(String var1, String var2);

    void setIntHeader(String var1, int var2);

    void addIntHeader(String var1, int var2);

3 状态码:

int SC_CONTINUE = 100;
    int SC_SWITCHING_PROTOCOLS = 101;
    int SC_OK = 200;
    int SC_CREATED = 201;
    int SC_ACCEPTED = 202;
    int SC_NON_AUTHORITATIVE_INFORMATION = 203;
    int SC_NO_CONTENT = 204;
    int SC_RESET_CONTENT = 205;
    int SC_PARTIAL_CONTENT = 206;
    int SC_MULTIPLE_CHOICES = 300;
    int SC_MOVED_PERMANENTLY = 301;
    int SC_MOVED_TEMPORARILY = 302;
    int SC_FOUND = 302;
    int SC_SEE_OTHER = 303;
    int SC_NOT_MODIFIED = 304;
    int SC_USE_PROXY = 305;
    int SC_TEMPORARY_REDIRECT = 307;
    int SC_BAD_REQUEST = 400;
    int SC_UNAUTHORIZED = 401;
    int SC_PAYMENT_REQUIRED = 402;
    int SC_FORBIDDEN = 403;
    int SC_NOT_FOUND = 404;
    int SC_METHOD_NOT_ALLOWED = 405;
    int SC_NOT_ACCEPTABLE = 406;
    int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
    int SC_REQUEST_TIMEOUT = 408;
    int SC_CONFLICT = 409;
    int SC_GONE = 410;
    int SC_LENGTH_REQUIRED = 411;
    int SC_PRECONDITION_FAILED = 412;
    int SC_REQUEST_ENTITY_TOO_LARGE = 413;
    int SC_REQUEST_URI_TOO_LONG = 414;
    int SC_UNSUPPORTED_MEDIA_TYPE = 415;
    int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
    int SC_EXPECTATION_FAILED = 417;
    int SC_INTERNAL_SERVER_ERROR = 500;
    int SC_NOT_IMPLEMENTED = 501;
    int SC_BAD_GATEWAY = 502;
    int SC_SERVICE_UNAVAILABLE = 503;
    int SC_GATEWAY_TIMEOUT = 504;
    int SC_HTTP_VERSION_NOT_SUPPORTED = 505;

常见应用(*重定向):

  1. 在客户端输入数据
  2. 下载文件
    resp.setCharacterEncoding("UTF-8");
    resp.setContentType("txt/html");
    //        1.找到资源路径
    //        相对路径
    //        String path = this.getServletContext().getRealPath("/WEB-INF/classes/1.txt");
    //        绝对路径
            String path="D:\\JavaWeb-01-Maven2\\Response\\target\\Response\\WEB-INF\\classes\\1.png";
    //        2.获取文件名
            String filename = path.substring(path.lastIndexOf("\\") + 1);
    //        3.想办法让浏览器支持我们下载
            resp.setHeader("Content-disposition","attachment;filename"+ URLEncoder.encode(filename,"UTF-8"));
    //        4.获取下载文件的流
            FileInputStream in = new FileInputStream(path);
    //        5.创建一个缓冲区
            int len=0;
            byte[] buffer = new byte[1024];
    //        6.获取输出流对象
            ServletOutputStream out = resp.getOutputStream();
    //        7.将OutputStream流写到缓存区,再使用响应的输出流将缓存流数据输出到客户端
    //          从输入流中读取一定数量的字节,并将其存储在缓冲区数组
            while ((len=in.read(buffer))>0){
                    out.write(buffer,0,len);
            }
            out.close();
            in.close();
    
    3.验证码功能:

    ​ 就不写了,我们要知道响应的传给浏览器信息的时候,编码格式,文件格式,包括上面的下载,也就是要设置它的响应头的内容

    4.实现重定向(重点):

    1639117377363

    b收到一个来自客户端a的请求后,它会通知a去访问另外一个web资源c,这就叫重定向

    常见场景:

    • 用户登录

      void sendRedirect(String var1) throws IOException;
      

      测试:

      //        resp.setHeader("location","/Response_war/down");
      //        resp.setStatus(302);
      //       重定向就是由上面两步构成
              resp.sendRedirect("/Response_war/down");
      

      面试题:请你谈谈重定向(拽)和转发(怂)的区别?

      拽哥叫别人自己去,怂逼帮它去

      相同点:

      • 都会跳转页面

      不同点:

      • 转发不改变地址 307

      • 重定向改变地址 302

        总结:转发是一次请求,重定向两次,转发是服务器内部完成,而重定向是在客户端完成

5.7 HttpServletRequest

概念:

HttpServletRequest代表客户端的请求,用户通过Http协议访问服务器,Http请求中的所有信息都会封装到HttpServletRequest,通过HttpServletRequest可以获取到客户端的所有信息

应用:

1.获取前端的传递参数

 String username = req.getParameter("username");
 String pwd = req.getParameter("pwd");
 String[] hobbies = req.getParameterValues("hobbies");

2.请求转发

 req.getRequestDispatcher("/Succes.jsp").forward(req,resp);

6.Cookie和Session

6.1 会话

会话:用户打开一个浏览器,点开很多超链接,访问不同web资源,到关闭浏览器,这就是会话

有效会话:当一个同学来过教室,下次再来教室里的时候,其他同学就知道你曾经来过,称之为有状态会话

例子:怎么证明你是中国公民

你 国家

1.你有身份证 国家给你的身份证

2.国家数据库里有你信息 国家数据库里有你信息

那么在网站上怎么证明你来过呢?

客户端 服务端

1.当客户端访问服务端的时候,服务端会给客户端一个信件,客户端下次访问带上信件就可以了 Cookie

2.服务端登记你来过,下次你来的时候自动匹配你 Session

6.2 保存会话的两种技术

Cookie

  • 客户端技术(响应,请求)

Session

  • 服务器技术,利用这个技术就可以保存用户的会话信息?我们可以把数据放到Session中

6.3 Cookie(饼干,信件)

1639225365169

站在面向对象的角度

  1. 客户端去获取Cookie

  2. 服务端去响应给客户端Cookie

    //        获取Cookie,因为Cookie是服务端给客户端,所以客户端去获取(面向对象的角度)
            Cookie[] cookies = req.getCookies();
    //			获取cookie 的key值
    		cookies[i].getName()
    //            获取cookie的 value值
       	    cookies[i].getValue()
    //            新建一个cookie
            Cookie cookie = new Cookie("time",System.currentTimeMillis()+"");
    //        设置到期时间
            cookie.setMaxAge(24*60*60);
    //        服务端给客户端一个Cookie
            resp.addCookie(cookie);
    

    Cookie:一般会保存在本地 用户目录下的 Appdate下

细节:

  • 一个网站Cookie是否有上限!
  • 一个Cookie只能保存一个信息
  • 一个web站点可以给浏览器发送多个Cookie,最多存放20个Cookie
  • Cookie大小上限4kb
  • 浏览器Cookie上限为300

删除Cookie:

  • 不设置有效期,关闭浏览器,自动失效
  • 设置有效期为0

6.4 Session

1639225925451

什么是Session:

  • 服务器会给每一个用户(浏览器)创建一个Session对象

  • 一个Session独占一个浏览器,只要浏览器没有关闭,Session就一直存在

  • 一访问web程序就会产生一个Session,同一个浏览器只有一个Seesion

    //        获取Session
            HttpSession session = req.getSession();
    //        设置Session(设置类型为object,比Cookie广)
            session.setAttribute("Test",new Test(20,"lc","Code"));
    //        获取ID
            String id = session.getId();
    //        判断这个Session是不是新的
            if(session.isNew()){
                out.write("Session创建成功,ID"+id);
            }else{
                out.write("Session已经在服务器中存在,ID"+id);
            }
    
    //        获取name为“Test”的Session
            Test T =(Test)session.getAttribute("Test");
    //        移除那个key为Test的session
            session.removeAttribute("Test");
    
    //        手动注销Session
    //        session.invalidate();
    

    移除和注销是不同的,移除了Session还是那个Session,只是那个属性为Test的Session没有了

    //在配置里注销(自动注销):	 
    <session-config>
            <session-timeout>15</session-timeout>
    </session-config>
    

    而注销

1639223755904

再一次访问,ID不同因为是另外一个Session了

1639223820693

总结:Session和Cookie的区别
	1.Cookie是把数据写到用户的客户端
	2.Session把用户的数据写到服务端(保存重要信息,减少服务器资源的浪费)
	3.Session对象由服务器创建,cookie也是由服务器创建给客户端

使用场景:

  • 保存一个登录用户的信息
  • 购物车信息
  • 在网站中经常用到的数据保存到Session

Session的SessionID是服务端响应了一个Cookie给客户端

1639225689983

7.JSP

7.1什么是JSP

Java Server Pages:java服务端页面,也和Servlet一样,用于动态Web技术!

最大的特点:

  • 写JSP就像在写HTML
  • 区别:
    • HTML只给用户提供静态数据
    • Jsp页面可以嵌入java代码,为用户提供动态数据

7.2 JSP原理

思路:JSP到底怎么执行的!

  • 服务器内部工作
    • 发现页面转换成java程序

1639381802021

JSP只有在被访问时才会转化为java和class文件

(重)浏览器向服务器发送请求的时候,不管访问你什么资源,其实都是在访问Servlet!

Jsp最终也会被转换为JAVA程序

JSP实质上就是一个Servlet

看JSP源码

1639380132609

1639380835380

1.判断请求方式

2.JSP内置对象

    final javax.servlet.jsp.PageContext pageContext;			//页面上下文
	javax.servlet.http.HttpSession session = null;				//session
    final javax.servlet.ServletContext application;				//applicationContext
    final javax.servlet.ServletConfig config;					//Config配置
    javax.servlet.jsp.JspWriter out = null;						//out输出
    final java.lang.Object page = this;							//当前页面
    HttpServletRequest request									//请求
    HttpServletResponse response								//响应

3.输出页面前的代码

 response.setContentType("text/html; charset=UTF-8");			//设置响应的类型
      pageContext = _jspxFactory.getPageContext(this, request, response,
      			null, false, 8192, true);
      _jspx_page_context = pageContext;
      application = pageContext.getServletContext();
      config = pageContext.getServletConfig();
      out = pageContext.getOut();
      _jspx_out = out;

1639381668859

在java代码中:

java代码会被原封不动的输出

而HTML代码就会被输出成:

out.write("\r\n");

7.3 JSP基础语法

作为java技术的一种扩张,支持java所有的语法,也有自己的一些扩充的语法

1.JSP表达式

<%--JSP表达式
作用:用来将程序的输出,输出到客户端
<%= 变量或者表达式%>
--%>
<%=1+2%>


一般用EL表达式替代
${} 跟<%=%>等同

2.JSP脚本片段

<%--JSP脚本片段--%>
<%
int a=7;
out.print("当前a为:"+a);
%>

3.JSP脚本片段嵌入HTML

<%--在代码里嵌入HTML代码--%>
<%
    for (int i = 0; i <3 ; i++) {
%>
        <h1>你好刘超</h1> <%=1%>
<%
    }
%>

为什么能怎么写,java代码在转换后还是java代码,而HTML代码会被转换成out.print("你好刘超“);

4.JSP声明

<%--JSP声明--%>
<%!int a=10;
    static {
        int b;
    }
%>

Jsp声明会被编译到类里,作用域高
普通<%%>写的带代码都在jsp.java文件里的JspService方法里,

7.4 JSP指令

<%@ page errorPage="err/500.jsp" %>

<%--指令
两个页面合二为一
--%>
<%@ include file="comom/Header.jsp"%>
<h1>我是内容</h1>
<%@ include file="comom/Footer.jsp"%>
<hr>

<%--JSP标签
拼接页面实际还是三个页面
--%>
<jsp:include page="comom/Header.jsp"/>
<h1>我是内容</h1>
<jsp:include page="comom/Footer.jsp"/>

7.5 9大内置对象及作用域

作用域:

  • Pagecontext 存东西 保存的东西只在一个页面中有效
  • Request 存东西 保存的东西在这次请求中有效
  • Response
  • Session 存东西 保存的东西在一次会话中(浏览器从开启到关闭)有效
  • Application(ServletContext) 存东西 凌驾于所有Servlet之上,保存的数据在服务器中,从服务器开启到关闭
  • config(ServletConfig)
  • out
  • page
  • exception
pageContext.setAttribute("1","a");   存东西  保存的东西只在一个页面中有效
request.setAttribute("2","b");  	 存东西  保存的东西在这次请求中有效
session.setAttribute("3","c");		 存东西  保存的东西在一次会话中(浏览器从开启到关闭)有效
application.setAttribute("4","d");   存东西   凌驾于所有Servlet之上,保存的数据在服务器中,从服务器开启到关闭

作用域:

request: 从客户端向服务端发送请求,产生得数据,用户用完就不用了,比如:看新闻

session:从客户端向服务端发送请求,产生得数据,用户用完还有用,比如:购物车,登录

application:从客户端向服务端发送请求,产生得数据,一个用户用完了,另外一个用户还能用到,比如聊天信息

7.6 JSP标签,JSTL标签和EL表达式

EL表达式:${}

  • 获取数据

  • 执行运算

  • 获取web开发得常用对学校

    JSP标签

    <jsp:forward page="jsptag2.jsp">
        <jsp:param name="name" value="刘超"/>
        <jsp:param name="age" value="20"/>
    </jsp:forward>
    

JSTL标签

JSTL标签库是为了弥补HTML得不足

<!--    JSTL依赖-->
<dependency>
    <groupId>javax.servlet.jsp.jstl</groupId>
    <artifactId>jstl-api</artifactId>
    <version>1.2</version>
</dependency>
<!--standard标签库-->
<dependency>
    <groupId>taglibs</groupId>
    <artifactId>standard</artifactId>
    <version>1.1.2</version>
</dependency>

1639401485893

JSTL使用步骤:

  • 导入taglibs
  • 使用对应方法

1639403126573

1639403175366

8.JavaBean

实体类

javaBean特有得写法

  • 必须要有一个无参构造
  • 属性必须私有化
  • 必须由对应得get/set方法

一般用来和数据库得字段做映射 ORM

ORM:对象关系映射

  • 表---》类
  • 字段---》字段
  • 行记录---》对象

9.MVC三层架构

什么是MVC:model view controller 模型,视图,控制器

9.1 早些年的架构

1639536941305

用户直接访问控制层,控制层直接操作数据库

servlet -- CRUD --->数据库
    弊端:程序十分臃肿,不利于维护
    Servlet代码中:处理请求,响应,视图跳转,处理JDBC,处理业务代码,处理逻辑代码
    
    架构:没有什么是加一层解决不了的

9.2 三层架构

1639551495487

Model:

  • 业务处理:业务逻辑()
  • 数据持久层:CRUD(DAO)

View:

  • 展示数据
  • 提供链接发起Servlet请求(a ,img,from...)

Controller(Servlet):

  • 接收用户的请求:(req:请求参数,Session信息...)
  • 交给业务层处理对应的代码
  • 控制视图的跳转
登录--》接收用户的登录请求--》处理用户的请求(获取登录参数username,password)--》交给业务层(判断用户名密码是否正常:事务)--》Dao层查询用户名和密码是否正常--》数据库

10.Filter过滤器(重点)

filter:过滤器,用来过滤网站的数据

  • 处理中文乱码
  • 登录验证...

1639552568259

Filter开发步骤:

  1. 导包

    1639553333197

  2. 编写过滤器

    1. 导包不要错

    2. 重写3个方法

      //    web服务器服务器启动,就会初始化
          @Override
          public void init(FilterConfig filterConfig) throws ServletException {
              System.out.println("开启过滤器");
          }
      //    chain:链
      //      1过滤的所有代码,在特定的特定请求的时候都会执行
      //      2必须要让过滤器继续执行
          @Override
          public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
                          servletRequest.setCharacterEncoding("utf-8");
                          servletResponse.setCharacterEncoding("utf-8");
                          servletResponse.setContentType("text/utf-8;charset=UTF-8");
      //                    让我们的请求继续走,如果不写,程序到这里拦截停止
                          filterChain.doFilter(servletRequest,servletResponse);
      
          }
      //web服务器关闭,才会停止
          @Override
          public void destroy() {
              System.out.println("关闭过滤器");
          }
      

3.在web.xml中配置FIlter

<filter>
        <filter-name>filter</filter-name>
        <filter-class>com.LiuDeHen.Filter.DemoFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>filter</filter-name>
<!--        select下的所有请求,都会经过这个过滤器-->
        <url-pattern>/select/*</url-pattern>
    </filter-mapping>

11.监听器

//统计在线人数
public class ListenerServlet implements HttpSessionListener {
//    创建Session监听,一旦创建就会触发一次
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        ServletContext context = se.getSession().getServletContext();
        System.out.println(se.getSession().getId());
        Integer l = (Integer) context.getAttribute("OnlineCount");
        if (l==null){
                l=new Integer(1);
        }else{
            int i=l;
            l=i+1;
        }
        context.setAttribute("OnlineCount",l);
    }
    //    销毁Session监听,一旦销毁就会触发一次
    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        ServletContext context = se.getSession().getServletContext();
        se.getSession().invalidate();
        Integer l = (Integer) context.getAttribute("OnlineCount");
        if (l==null){
            l=new Integer(0);
        }else{
            int i=l;
            l=i--;
        }
        context.setAttribute("OnlineCount",l);
    }

在xml里注册监听器

<listener>   
    <listener-class>com.LiuDeHen.Listener.ListenerServlet</listener-class>
</listener>

12.过滤器和监听器常见应用

监听器:GUI经常用到

过滤器:

用户登录之后才能进入主页!

  1. 用户登录之后,向Session中放入用户的数据
  2. 进入主页的时候判断用户是否已经登录,要求:在过滤器中实现
@Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest req=(HttpServletRequest) servletRequest;
        HttpServletResponse resp=(HttpServletResponse) servletResponse;

        if (req.getSession().getAttribute("username_ID")==null){
            resp.sendRedirect("/login.jsp");
        }
        filterChain.doFilter(servletRequest,servletResponse);
    }

13 JDBC复习

基础配置

什么是JDBC:java连接数据库

1639654292263

需要jar包支持:

  • java.sql
  • javax.sql
  • mysql驱动(必须导入)

实验环境搭建:

CREATE DATABASE JDBC
USE JDBC;
CREATE TABLE users(
id INT PRIMARY KEY,
`name` VARCHAR(40),
`password` VARCHAR(40),
email VARCHAR(60),
birthday DATE
);
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(1,'张三','123','24@11.com','2021-9-2');
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(2,'张si','123','24@11.com','2021-9-2');
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(3,'张wu','123','24@11.com','2021-9-2');
SELECT * FROM users

导入数据库依赖:

<dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.49</version>
        </dependency>

JDBC步骤:

  1. 加载驱动
  2. 连接数据库,代表数据库
  3. 拿到操作数据库的对象Statem
  4. 编写sql
  5. 执行sql
  6. 关闭连接
//        配置信息
        String url="jdbc:mysql://localhost:3306/jdbc?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSl=true";
        String username="root";
        String password="lc20010725";
//        加载驱动
        Class.forName("com.mysql.jdbc.Driver");
//        获取连接
        Connection connection = DriverManager.getConnection(url, username, password);
//        操作数据库的对象statement;
        Statement statement = connection.createStatement();
//          编写sql
        String sql="select * from users";
//        执行sql,返回结果集
        ResultSet resultSet = statement.executeQuery(sql);
//         取出数据
        while (resultSet.next()){
            System.out.println("id"+resultSet.getObject("id"));
            System.out.println("name"+resultSet.getObject("name"));
            System.out.println("password"+resultSet.getObject("password"));
            System.out.println("email"+resultSet.getObject("email"));
            System.out.println("birthday"+resultSet.getObject("birthday"));
        }
//        关闭连接
        resultSet.close();
        statement.close();
        connection.close();

预编译sql

        //        1配置信息
        String url="jdbc:mysql://localhost:3306/jdbc?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSl=true";
        String username="root";
        String password="lc20010725";
//        2加载驱动
        Class.forName("com.mysql.jdbc.Driver");
        //        3获取连接
        Connection connection = DriverManager.getConnection(url, username, password);
        //          4编写sql
        String sql="insert into users(id,name,password,email,birthday) values (?,?,?,?,?)";
        //        5预编译
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        preparedStatement.setInt(1,1);//给第一个占位符填充
        preparedStatement.setString(2,"lc");
        preparedStatement.setString(3,"123");
        preparedStatement.setString(4,"12@qq.com");
        preparedStatement.setDate(5,new Date(new java.util.Date().getTime()));
//6执行sql
        int i = preparedStatement.executeUpdate();
        if (i>0){
            System.out.println("插入成功");
        }
//        7关闭连接
        preparedStatement.close();
        connection.close();

事务

要么都成功,要么都失败!

ACID原则:保证数据的安全性

开启事务
    事务提交	commit()
    事务回滚  	rollback()
    关闭事务
    

junit单元测试

依赖

<dependency>
           <groupId>junit</groupId>
           <artifactId>junit</artifactId>
           <version>4.11</version>
       </dependency>

@Test只有在方法上有效

 @Test
    public void test(){
        System.out.println("你好");
    }
//        配置信息
        String url="jdbc:mysql://localhost:3306/jdbc?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSl=true";
        String username="root";
        String password="lc20010725";
        Connection connection=null;
        try {
    //        加载驱动
    Class.forName("com.mysql.jdbc.Driver");
//        获取连接
    connection = DriverManager.getConnection(url, username, password);
//    false为开启事务
    connection.setAutoCommit(false);
    String sql="update account set money=money-100 where name='A'";
    connection.prepareStatement(sql).executeUpdate();
//    制造错误
//    int i=1/0;
    String sql2="update account set money=money+100 where name='B'";
    connection.prepareStatement(sql2).executeUpdate();
//    提交事务
    connection.commit();
    System.out.println("提交成功");
}catch (Exception e){
//            出现异常就回滚
            try {
                connection.rollback();
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
}finally {
            //        关闭连接
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
posted @ 2022-03-14 18:36  又菜又ai  阅读(185)  评论(0)    收藏  举报