Java——JavaWeb

1、Tomcat

1.1、安装Tomcat

  1. Tomcat官网:https://tomcat.apache.org/index.html
    在这里插入图片描述
  2. 解压即可

1.2、Tomcat启动和配置

  1. Tomcat目录介绍:
    在这里插入图片描述
  2. 启动/关闭Tomcat:
    在这里插入图片描述
  3. 访问测试: http://localhost:8080/
    在这里插入图片描述

1.3、配置文件

  • 可以配置启动的端口号:默认是8080

        <Connector port="8080" protocol="HTTP/1.1"
                   connectionTimeout="20000"
                   redirectPort="8443" />
    
  • 可以配置主机启动的名称:默认的注解名为localhost->127.0.0.1

  • 默认网站应用存放的位置为:webapps

          <Host name="localhost"  appBase="webapps"
                unpackWARs="true" autoDeploy="true">
    

    在这里插入图片描述

  • 网站是如何进行访问的:

    1. 输入一个域名
    2. 检查本机的C:\Windows\System32\drivers\etc\hosts配置文件下有没有这个域名映射
      1. 有:直接返回对应的IP地址
      2. 没有:去DNS服务器查找,找到就返回,找不到就返回找不到

2、HTTP

2.1、HTTP请求

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

  • 百度:

    Request URL: https://www.baidu.com/		请求地址
    Request Method: GET		get方法/post方法
    Status Code: 200 OK		状态码:200
    Remote Address: 182.61.200.7:443
    Referrer(远程) Policy: strict-origin-when-cross-origin
    
    Accept: text/htmlapplication/signed-exchange;v=b3;q=0.9
    Accept-Encoding: gzip, deflate, br
    Accept-Language: zh-CN,zh;q=0.9		语言
    Cache-Control: max-age=0
    Connection: keep-alive
    Cookie: BIDUPSID=D733CC6C26608FED3DECDAE23B8DE55C; PSTM=1647917034; BAIDUID=D733CC6C26608FEDE84F1F68645CADBA:FG=1; BD_UPN=12314753; BDSFRCVID_BFESS=OR-OJexroG0CZ3oDk5-N2ru_CgKK0gOTDYrEOwXPsp3LGJLVcf13EG0PtfOEtU8MaXv6ogKKWeOTHx8F_2uxOjjg8UtVJeC6EG0Ptf8g0M5; H_BDCLCKID_SF_BFESS=tb4tVCIafII3jtOY5-__-4_tbh_X5-RLf26xVp7F5l8-h45uDJ5Fjx332-7v-4omWa7MblQVyJcxOKQeDUrqMntlXl6EKlOXaHTO3RbN3KJmhlC9bT3v5tDW-UJe2-biWav-2MbdJqvP_IoG2Mn8M4bb3qOpBtQmJeTxoUJ25DnJhbLGe6-Bej5yjaAqq-jeHDrKBRbaHJOoDDvsjfbcy4LbKxnxJUJztKORBKKEaDoKff7JbURvD--g3-OkbfQ9babTQ-tbBp3k8MQnb6L5QfbQ0hOhWMQJQRbu3xnKJJ7JOpv5bfnxybvbQRPH-Rv92DQMVU52QqcqEIQHQT3m5-5bbN3ut6IefRKqoK-yJDvDqTrP-trf5DCShUFsWhDLB2Q-XPoO3KJToCOvQ-4hqf6XKlod3-biWbRM2Mbgy4op8P3y0bb2DUA1y4vp5-KDt2TxoUJ25q7pfMK9XtQi56KebPRiL-Q9QgbOVpQ7tt5W8ncFbT7l5hKpbt-q0x-jLTnhVn0MBCK0HPonHjD5DTcy3j; ZFY=YSqfBkC0:B5ioEC90tsGe:BQDSEYHC3:BI9jHB2PbOuYTU:C; BAIDUID_BFESS=CDDFE4691243C3E75428BCCC3B72A945:FG=1; baikeVisitId=82be6391-cccb-45ea-995b-75caf7dd760d; B64_BOT=1; BA_HECTOR=84ag2481ag240l00011hc7td515; COOKIE_SESSION=246325_0_8_8_11_8_1_0_8_8_0_0_246364_0_68_0_1657009641_0_1657009573%7C9%23331664_53_1655720451%7C9; BDRCVFR[n9IS1zhFc9f]=mk3SLVN4HKm; delPer=0; BD_CK_SAM=1; PSINO=1; ab_sr=1.0.1_ZWI4NGRlOWEzMzYzYWM0ZDk0MzJkNGY2ZGEzN2Y0MmRiMzhhMzM3NjlmMmQ5MGFiYjdmNjlmMWIyM2Q4NzVhZjkzYWQzYjA0YTA2OTQwMmU5Y2M2MjkwYjU3ZTU0N2M2ZjVhMjFmNWEyNDhkODk0ZDI4OWJmYTc0MmIxM2Y1NjkyMzE5M2ZjMDA5ZjNhZDgxMGZlZjViYTc2MGFiOWU2Zg==; BD_HOME=1; H_PS_PSSID=36544_36757_36726_36454_31253_36413_36690_36167_36694_36696_36569_36777_36775_36745_36762_36768_36765_26350_36711_36649; BDRCVFR[S4-dAuiWMmn]=I67x6TjHwwYf0; H_PS_645EC=4e80A460UGYdLhDqr8h090BJbOKecLNdgYFGXvBtBmGT9AyGDR3duV4gAyL1DtxWVQ; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598
    Host: www.baidu.com
    sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="100", "Google Chrome";v="100"
    sec-ch-ua-mobile: ?0
    sec-ch-ua-platform: "Windows"
    Sec-Fetch-Dest: document
    Sec-Fetch-Mode: navigate
    Sec-Fetch-Site: none
    Sec-Fetch-User: ?1
    Upgrade-Insecure-Requests: 1
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.88 Safari/537.36
    
  1. 请求行:请求好的请求方式:GET;请求方式:Get,Post,Delete,Put···

    1. get: 请求能够携带的参数比较少,大小有限制,会在浏览器的URL地址栏显示数据内容,不安全,但高效
    2. post: 请求能够携带的参数没有限制,大小没有限制,补会在浏览器的URL地址栏显示数据内容,安全,但不高效
  2. 消息头:

    Accept:		告诉服务器,它所支持的数据类型
    Accept-Encoding:		支持那种编码格式
    Accept-Language:		告诉服务器,它的语言环境
    Cache-Control:		缓存控制
    Connection:		告诉服务器,请求完成时断开还是保持连接
    Host:		主机
    ···
    

2.2、HTTP响应

  • 服务器——响应——客户端

  • 百度:

    
    Connection: keep-alive		连接
    Content-Encoding: gzip		编码
    Content-Type: text/html; charset=utf-8		类型
    
  1. 响应体
    Accept:		告诉服务器,它所支持的数据类型
    Accept-Encoding:		支持那种编码格式
    Accept-Language:		告诉服务器,它的语言环境
    Cache-Control:		缓存控制
    Connection:		告诉服务器,请求完成时断开还是保持连接
    Host:		主机
    ···
    Refresh:	告诉客户端,多久刷新一次
    Location:	让网页重新定位
    
  2. 响应状态码:
    1. 200: 请求响应成功
    2. 3xx: 请求重定向
    3. 404: 找不到资源
    4. 5xx: 服务器代码错误
      1. 500服务器代码错误
      2. 502网关错误

3、Maven

为什么要学习这个技术

  1. 在JavaWeb开发中,需要使用大量的jar包,我们手动去导入
  2. 如何能够让一个东西自动帮我们导入和配置这个jar包,因此,Maven诞生了

3.1、Maven项目架构管理工具

  • 目前用来就是方便导入jar包
  • Maven的核心思想:约定大于配置
    1. 有约束,不要去违反
    2. Maven会规定好我们该如何编写我们的Java代码,必须按照这个规范来;

3.2、下载安装Maven

  1. 官网: https://maven.apache.org/
    在这里插入图片描述
  2. 解压即可

3.3、配置环境变量

  • 在系统环境变量中,配置如下配置
    1. M2_HOME:Maven目录下的bin目录
    2. MAVEN_HOME:Maven的目录
    3. 在系统的path中配置MAVEN_HOME(%MAVEN_HOME%\bin)
      在这里插入图片描述
      在这里插入图片描述
    4. 测试Maven是否安装成功,保证必须配置完毕
      在这里插入图片描述

3.4、阿里云镜像

  • 镜像: mirrors
    • 作用:加速下载
  • 国内建议使用阿里云的镜像
    <mirror>
      <id>aliyunmaven</id>
      <mirrorOf>*</mirrorOf>
      <name>阿里云公共仓库</name>
      <url>https://maven.aliyun.com/repository/public</url>
    </mirror>
    

3.5、本地仓库

  • 建立一个本地仓库:
    <localRepository>E:\Practical software\Java\Maven\maven-repo</localRepository>
    

3.6、在IDEA中使用Maven

  1. 创建一个MavenWeb项目
    在这里插入图片描述
    在这里插入图片描述
  2. 等待项目初始化完毕
    在这里插入图片描述
  3. IDEA中的Maven设置:IDEA项目常见成功后,看一眼Maven的配置
    在这里插入图片描述
    在这里插入图片描述
  4. 标记文件夹的功能
    在这里插入图片描述

3.7、在IDEA中配置Tomcat

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

3.8、pom.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<!--Maven版本和头文件-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
    <!--这里是配置的GAV-->
  <groupId>org.example</groupId>
  <artifactId>javaweb-01-maven</artifactId>
  <version>1.0-SNAPSHOT</version>
    <!--
    Package:项目的打包方式
    jar:java应用
    war:JavaWeb应用
    -->
  <packaging>war</packaging>

  <name>javaweb-01-maven Maven Webapp</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>
    
    <!--配置-->
  <properties>
      <!--项目的默认构建编码-->
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <!--编码版本-->
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
  </properties>
    
    <!--项目依赖-->
  <dependencies>
      <!--具体依赖的jar包配置文件-->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

    <!--项目构建用的东西-->
  <build>
    <finalName>javaweb-01-maven</finalName>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-war-plugin</artifactId>
          <version>3.2.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

  • Maven由于他的约定大于配置,我们之后可能遇到我们写的配置文件,无法被导出或者生效的问题,解决方案:

    <!--在build中配置properties中防止资源导出失败-->
        <build>
            <resources>
                <resource>
                    <directory>src/main/java</directory>
                    <includes>
                        <include>**/*.properties</include>
                        <include>**/*.xml</include>
                    </includes>
                    <filtering>false</filtering>
                </resource>
                <resource>
                    <directory>src/main/resources</directory>
                    <includes>
                        <include>**/*.properties</include>
                        <include>**/*.xml</include>
                    </includes>
                    <filtering>false</filtering>
                </resource>
            </resources>
        </build>
    

3.9、Maven目录树

在这里插入图片描述

4、Servlet

4.1、Servlet简介

  • Servlet就是Sun公司开发动态web的一门技术
  • Sun在这些API中提供一个接口叫做:Servlet,如果你想开发一个Servlet程序,只需要完成两个步骤:
    1. 编写一个类,实现Servlet接口
    2. 把开发好的Java类部署到web服务器中。
  • 把实现了Servlet接口的Java程序叫做 Servlet

4.2、HelloServlet

Servlet接口Sun公式有两个默认的实现类:HttpServlet,

  1. 构建一个普通的Maven项目,删除src目录。以后在项目建立Model。这个空的工程就是Maven的主工程

  2. 导入所需的依赖:

    		<dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>javax.servlet-api</artifactId>
                <version>4.0.1</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
            <dependency>
                <groupId>javax.servlet.jsp</groupId>
                <artifactId>javax.servlet.jsp-api</artifactId>
                <version>2.3.3</version>
            </dependency>
    
  3. 关于Maven父子工程的理解:

    1. 父项目中会有:
          <modules>
              <module>Servlet01</module>
          </modules>
      
    2. 子项目会有:
          <parent>
              <artifactId>javaweb-02-servlet</artifactId>
              <groupId>org.example</groupId>
              <version>1.0-SNAPSHOT</version>
          </parent>
      
    3. 父项目中的java子项目可以直接使用
      son extends father
      
  4. Maven环境优化

    1. 修改web.xml为最新的
    2. 将Maven的结构搭建完整
  5. 编写一个Servlet

    1. 编写一个普通类
    2. 实现Servlet接口,这里直接继承HttpServlet:
      package com.javastudy.servlet;
      
      import javax.servlet.ServletException;
      import javax.servlet.http.HttpServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      import java.io.IOException;
      import java.io.PrintWriter;
      
      public class HelloServlet extends HttpServlet {
              
              
          //由于get或者post只是请求实现的不同方式,可以相互调用,业务逻辑都一样
          @Override
          protected void doGet( HttpServletRequest req, HttpServletResponse resp ) throws ServletException, IOException {
              
              
              PrintWriter writer = resp.getWriter();//响应流  
              
              writer.print("Hello Servlet");
          }
      
          @Override
          protected void doPost( HttpServletRequest req, HttpServletResponse resp ) throws ServletException, IOException {
              
              
              
          }
      }
      
      
  6. 编写Servlet的映射:

    1. 为什么需要映射:我们写的是Java程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要在web服务器中注册我们写的Servlet,还需要给它一个浏览器能够访问的路径

    2. xml文件:

      <!--注册Servlet-->
          <servlet>
              <servlet-name>Hello</servlet-name>
              <servlet-class>com.javastudy.servlet.HelloServlet</servlet-class>
          </servlet>
          <!--Servlet的请求路径-->
          <servlet-mapping>
              <servlet-name>Hello</servlet-name>
              <url-pattern></url-pattern>
          </servlet-mapping>
      
    3. HelloServlet类

      package com.javastudy.servlet;
      
      import javax.servlet.ServletException;
      import javax.servlet.http.HttpServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      import java.io.IOException;
      import java.io.PrintWriter;
      
      public class HelloServlet extends HttpServlet {
              
              
          //由于get或者post只是请求实现的不同方式,可以相互调用,业务逻辑都一样
          @Override
          protected void doGet( HttpServletRequest req, HttpServletResponse resp ) throws ServletException, IOException {
              
              
              System.out.println("进入doGet方法");
              PrintWriter writer = resp.getWriter();//响应流
              writer.print("Hello Servlet");
          }
      
          @Override
          protected void doPost( HttpServletRequest req, HttpServletResponse resp ) throws ServletException, IOException {
              
              
          }
      }
      
  7. 配置Tomcat:

    1. 注意:配置项目发布的路径就可以了
  8. 启动测试:

4.3、Servlet原理

  • Servlet是由Web服务器调用,Web服务器在收到浏览器请求之后,会:
    在这里插入图片描述

4.4、Mapping问题

  • 一个Servlet可以指定一个映射路径:

    <servlet-mapping>
        <servlet-name>Hello</servlet-name>
        <url-pattern>/Hello</url-pattern>
    </servlet-mapping>
    
  • 一个Servlet可以指定多个映射路径:

      <servlet-mapping>
            <servlet-name>Hello</servlet-name>
            <url-pattern>/Hello</url-pattern>
        </servlet-mapping>
        <servlet-mapping>
            <servlet-name>Hello</servlet-name>
            <url-pattern>/Hello1</url-pattern>
        </servlet-mapping>
        <servlet-mapping>
            <servlet-name>Hello</servlet-name>
            <url-pattern>/Hello2</url-pattern>
        </servlet-mapping>
    
  • 一个Servlet可以指定通用映射路径:

        <servlet-mapping>
            <servlet-name>Hello</servlet-name>
            <url-pattern>/Hello/*</url-pattern>
        </servlet-mapping>
    
  • 默认请求路径:

        <!--默认请求路径-->
        <servlet-mapping>
            <servlet-name>Hello</servlet-name>
            <url-pattern>/*</url-pattern>
        </servlet-mapping>
    
  • 指定一些后缀或者前缀等等···

        <!--可以自定义请求映射,*前面不能加映射路径-->
        <servlet-mapping>
            <servlet-name>Hello</servlet-name>
            <url-pattern>*.javastudy</url-pattern>
        </servlet-mapping>
    
  • 优先级问题:

    1. 指定了固有的映射优先级最高,如果找到就会走默认的处理请求:
          <!--404-->
          <servlet>
              <servlet-name>error</servlet-name>
              <servlet-class>com.javastudy.servlet.ErrorServlet</servlet-class>
          </servlet>
          <servlet-mapping>
              <servlet-name>error</servlet-name>
              <url-pattern>/*</url-pattern>
          </servlet-mapping>
      

4.5、ServletContext对象

web容器在启动的时候,它会为每个web程序都创建一个对应的ServletContext对象,它代表当前的web应用

4.5.1、共享数据

  • 在这个Servlet中保存的数据,可以在另外一个Servlet中拿到
    在这里插入图片描述

  • 放置数据的类:

    package com.javastudy.servlet;
    
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    public class HelloServlet extends HttpServlet {
          
          
        @Override
        protected void doGet( HttpServletRequest req, HttpServletResponse resp ) throws ServletException, IOException {
          
          
            //this.getInitParameterNames()  初始化参数
            //this.getServletConfig()       Servlet配置
            //this.getServletContext()      Servlet上下文
            ServletContext context = this.getServletContext();
            String username = "Java学不会";    //数据
            context.setAttribute("username",username);      //将一个数据保存宰了Servlet中,名字为:username    值为:username
            System.out.println("Hello");
        }
    }
    
    
  • 读取数据的类:

    package com.javastudy.servlet;
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    public class GetServlet extends HttpServlet {
          
          
        @Override
        protected void doGet( HttpServletRequest req, HttpServletResponse resp ) throws ServletException, IOException, IOException {
          
          
            ServletContext context = this.getServletContext();
            String username =(String) context.getAttribute("username");
            resp.setContentType("text/html");
            resp.setCharacterEncoding("utf-8");
            resp.getWriter().println("名字:"+username);
        }
    }
    
    
  • web.xml:

        <servlet>
            <servlet-name>hello</servlet-name>
            <servlet-class>com.javastudy.servlet.HelloServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>hello</servlet-name>
            <url-pattern>/hello</url-pattern>
        </servlet-mapping>
        <servlet>
            <servlet-name>get</servlet-name>
            <servlet-class>com.javastudy.servlet.GetServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>get</servlet-name>
            <url-pattern>/get</url-pattern>
        </servlet-mapping>
    
  • 测试结果:

    • 如果没有访问/hello路径就访问/get路径得到的数据为空
      在这里插入图片描述

4.5.2、获取初始化参数

  • web.xml文件:

        <context-param>
            <param-name>url</param-name>
            <param-value>E:java/study</param-value>
        </context-param>
        <servlet>
            <servlet-name>url</servlet-name>
            <servlet-class>com.javastudy.servlet.ServletDemo03</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>url</servlet-name>
            <url-pattern>/url</url-pattern>
        </servlet-mapping>
    
  • 获取初始化内容:

        protected void doGet( HttpServletRequest req, HttpServletResponse resp ) throws ServletException, IOException {
          
          
            ServletContext context = this.getServletContext();
            String url = context.getInitParameter("url");
            resp.getWriter().println(url);
        }
    

4.5.3、请求转发

  • A无法直接到C,A通过B连接到C
    在这里插入图片描述

  • web.xml文件:

    <servlet-mapping>
        <servlet-name>get</servlet-name>
        <url-pattern>/get</url-pattern>
    </servlet-mapping>
    <servlet>
        <servlet-name>url</servlet-name>
        <servlet-class>com.javastudy.servlet.ServletDemo03</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>url</servlet-name>
        <url-pattern>/url</url-pattern>
    </servlet-mapping>
    <servlet>
        <servlet-name>sd4</servlet-name>
        <servlet-class>com.javastudy.servlet.ServletDemo04</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>sd4</servlet-name>
        <url-pattern>/sd4</url-pattern>
    </servlet-mapping>
    
  • 实现代码:

        protected void doGet( HttpServletRequest req, HttpServletResponse resp ) throws ServletException, IOException {
          
          
            ServletContext context = this.getServletContext();
            System.out.println("进入了ServletDemo04");
            /*RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp");  //转发的请求路径
            requestDispatcher.forward(req,resp);    //调用forward实现请求转发*/
            context.getRequestDispatcher("/url").forward(req, resp);
        }
    

4.5.4、读取资源文件(Properties)

  • 在Java目录下新建properties
    -*在resources目录下新建properties

  • 发现:都被打包到了同一个路径下:classes,我们俗称这个路径为classpath

  • 需要一个文件流

        protected void doGet( HttpServletRequest req, HttpServletResponse resp ) throws ServletException, IOException {
          
          
            InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/com/javastudy/servlet/aa.properties");
    
            Properties prop = new Properties();
            prop.load(is);
            String user = prop.getProperty("username");
            String pwd = prop.getProperty("password");
    
            resp.getWriter().print(user+":"+pwd);
        }
    
  • / 代表当前web项目下
    在这里插入图片描述

4.6、HttpServletResponse

  • Web服务器接收到客户端的HTTP请求,针对这个请求,分别创建一个代表请求的HttpServletResponse对象,代表响应的一个HttpServletResponse;
  • 如果要获取客户端请求过来的参数:找HttpServletResponse
  • 如果要给客户端响应信息:找HttpServletResponse

4.6.1、简单分类

  • 负责向浏览器发送数据的方法:

    public ServletOutputStream getOutputStream() throws IOException;
    
    public PrintWriter getWriter() throws IOException;
    
  • 负责向浏览器发送数据的方法:

    public void setCharacterEncoding(String charset);
    
    public void setContentLength(int len);
    
    public void setContentLengthLong(long len)
    
    public void setContentType(String type);
    
    public void setDateHeader(String name, long date);
    
    public void addDateHeader(String name, long date);
    
    public void setHeader(String name, String value);
    
    public void addHeader(String name, String value);
    
    public void setIntHeader(String name, int value);
    
    
  • 响应的状态码:

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

4.6.2、下载文件

  • 下载文件步骤:
    1. 获取下载文件的路径
    2. 下载的文件名
    3. 设置浏览器能够支持下载需要的东西
    4. 获取下载文件的输入流
    5. 创建缓冲区
    6. 获取inpuutStream对象
    7. 将FileinputStream流写入到buffer缓冲区
    8. 使用OutputStream将缓冲区中的数据输出到客户端
    package com.javastudy.servlet;
    
    import javax.servlet.ServletException;
    import javax.servlet.ServletOutputStream;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.net.URLEncoder;
    
    public class FileServlet extends HttpServlet {
          
          
        @Override
        protected void doGet( HttpServletRequest req, HttpServletResponse resp ) throws ServletException, IOException {
          
          
            //获取下载文件的路径
            String realPath = "E:\\Download\\java\\javaweb-02-servlet\\response\\target\\classes\\Java学不会.png";
            System.out.println("下载文件的路径:"+realPath);
            //下载的文件名
            String fileName = realPath.substring(realPath.lastIndexOf("\\")+1);
            //设置浏览器能够支持下载需要的东西,中文文件名RLEncoder.encode编码
            resp.setHeader("Content-disposition","attachment;filename="+ URLEncoder.encode(fileName,"UTF-8"));
            //获取下载文件的输入流
            FileInputStream in = new FileInputStream(realPath);
            //创建缓冲区
            int len = 0;
            byte[] buffer = new byte[1024];
            //获取inpuutStream对象
            ServletOutputStream out = resp.getOutputStream();
            //将FileinputStream流写入到buffer缓冲区
            while((len=in.read(buffer))!=-1){
          
          
                out.write(buffer,0,len);
            }
            out.close();
            in.close();
            //使用OutputStream将缓冲区中的数据输出到客户端
        }
    
        @Override
        protected void doPost( HttpServletRequest req, HttpServletResponse resp ) throws ServletException, IOException {
          
          
            
        }
    }
    
    

4.6.3、验证码功能

  • 验证码怎么来的?
    • 前段实现
    • 后端实现,需要用到Java图片类,生成一个图片
    package com.javastudy.servlet;
    
    import javax.imageio.ImageIO;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.awt.*;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import java.util.Random;
    
    public class ImageServlet extends HttpServlet {
          
          
        @Override
        protected void doGet( HttpServletRequest req, HttpServletResponse resp ) throws ServletException, IOException {
          
          
            //如何浏览器5买走自动刷新一次;
            resp.setHeader("refresh","5");
    
            //在内存中创建一个图片
            BufferedImage image = new BufferedImage(80,20, BufferedImage.TYPE_INT_RGB);
            //得到图片
            Graphics2D g = (Graphics2D) image.getGraphics();
            //设置图片的背景颜色
            g.setColor(Color.WHITE);
            g.fillRect(0,0,80,20);
            //给图片写数据
            g.setColor(Color.BLUE);
            g.setFont(new Font("微软雅黑",Font.BOLD,20));
            g.drawString(makeNume(),0,20);
    
            //高数浏览器,这个请求用图片的方式打开
            resp.setContentType("image/png");
            //网站存在缓存,不让浏览器缓存
            resp.setDateHeader("expires",-1);
            resp.setHeader("Cache-Control","no-Cache");
            resp.setHeader("Pragma","no-cache");
    
            //把图片写个浏览器
            ImageIO.write(image,"png",resp.getOutputStream());
        }
    
        //生成随机数
        private String makeNume(){
          
          
            Random random = new Random();
            String num = random.nextInt(9999999) + "";
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < 7-num.length(); i++) {
          
          
                sb.append("0");
            }
            num = sb.toString() + num;
            return num;
    
        }
        @Override
        protected void doPost( HttpServletRequest req, HttpServletResponse resp ) throws ServletException, IOException {
          
          
    
        }
    }
    
    

4.6.4、实现重定向

在这里插入图片描述

  • Web资源收到客户端请求后,会通知客户端去访问另外一个Web资源,这个过程就叫重定向

        @Override
        protected void doGet( HttpServletRequest req, HttpServletResponse resp ) throws ServletException, IOException {
          
          
            
            /*resp.setHeader("Location","/response_war/image");
            resp.setStatus(302);*/
            resp.sendRedirect("/response_war/image");//重定向
        }
    

4.7、HttpServletRequest

  • HttpServletRequest代表客户端的请求,用户通过HTTP协议访问服务器;HTTP请求中的所有信息会被封装到HttpServletRequest,通过这个HttpServletRequest的方法,获得客户端的所有信息:

4.7.1、获取客户端参数,请求转发

在这里插入图片描述

  • index.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
        <head>
            <title>登录</title>
        </head>
        <body>
            <h1>登录</h1>
            <div style="text-align: center">
                <%--这里表单表示:以post方式提交表单,提交到我们的login请求--%>
                <form action="${pageContext.request.contextPath}/login" method="post">
                用户名:<input type="text" name="username"><br>
                密码:<input type="password" name="password"><br>
                爱好:
                <input type="checkbox" name="hobbys" value="女孩">女孩
                <input type="checkbox" name="hobbys" value="代码">代码
                <input type="checkbox" name="hobbys" value="电影">电影
                <input type="checkbox" name="hobbys" value="唱歌">唱歌
                <br>
                <input type="submit">
                </form>
            </div>
    
        </body>
    </html>
    
  • LoginServlet

    package com.javastudy.servlet;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.util.Arrays;
    
    public class LoginServlet extends HttpServlet {
          
          
        @Override
        protected void doGet( HttpServletRequest req, HttpServletResponse resp ) throws ServletException, IOException {
          
          
            req.setCharacterEncoding("UTF-8");
            resp.setCharacterEncoding("UTF-8");
            String username = req.getParameter("username");
            String password = req.getParameter("password");
            String[] hobbys = req.getParameterValues("hobbys");
            System.out.println("======================");
            System.out.println(username);
            System.out.println(password);
            System.out.println(Arrays.toString(hobbys));
            System.out.println("======================");
    
    
            //这里/代表当前web应用
            req.getRequestDispatcher("/success.jsp").forward(req,resp);
    
        }
    
        @Override
        protected void doPost( HttpServletRequest req, HttpServletResponse resp ) throws ServletException, IOException {
          
          
            doGet(req,resp);
        }
    }
    
    

5、Cookie、Session

5.1、会话

  • 会话: 用户打开一个浏览器,点击了很多超链接,访问多个web资源,关闭浏览器,这个过程称之为会话
  • 有状态会话:客户端访问过这个网站,下次再来网站会知道这个客户端,曾经来过,称之为有状态会话
    1. 服务端给客户端一个信件,客户端下次访问服务端带上信件就可以了 (cookie)
    2. 服务器登记你来过,下次你来的时候我匹配你 (seesion)

5.2、保存会话的两种技术

5.2.1、cookie

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

  • 从请求中拿到cookie信息

  • 服务器响应给客户端cookie

    Cookie[] cookies = req.getCookies();    //获得cookie
    cookie.getName();		//获得cookie中的key
    cookie.getValue();		//获得cookie中的value
    Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis()+"");		//新建一个cookie
    cookie.setMaxAge(24*60*60);		//设置cookie的有效期
    resp.addCookie(cookie);			//响应个客户端一个cookie
    
  • cookie:一般会保存在本地的 用户目录下 appdata

    1. 一个cookie只能保存一个信息
    2. 一个web站点可以给浏览器发送多个cookie,最多存放20个cookie
    3. cookie大小有4kb
    4. 300个cookie浏览器上限
  • 删除cookie

    1. 不设置有效期,关闭浏览器,自动失效
    2. 设置有效期时间为0

5.2.2、session

  • 服务器技术,利用这个技术,可以保存用户的会话信息。我们可以把信息或者数据放在session中

  • 常见场景:网站登录之后,你下次不用再登录了,第二次访问直接就上去了!

  • Cookie是把用户的数据写给用户的浏览器,浏览器保存(可以保存多个)

  • Session把用户的数据写到用户独占的Session中,服务器端保存(保存重要的信息,减少服务器资源的浪费)

  • Session对象由服务器创建

  • 使用session

    public class SessionDemo01 extends HttpServlet {
          
          
        @Override
        protected void doGet( HttpServletRequest req, HttpServletResponse resp ) throws ServletException, IOException {
          
          
            //解决乱码问题
            resp.setCharacterEncoding("UTF-8");
            req.setCharacterEncoding("UTF-8");
            resp.setContentType("text/html;charset=utf-8");
    
            //得到Session
            HttpSession session = req.getSession();
    
            //给Session中存放东西
            session.setAttribute("name",new Person("Java学不会",2));
    
            //获取Session的ID
            String id = session.getId();
    
            //判断Session是不是新建的
            if(session.isNew()){
          
          
                resp.getWriter().write("session创建成功:ID:"+id);
            }else{
          
          
                resp.getWriter().write("session已经在服务器中存在了:ID:"+id);
            }
    
        }
    
        @Override
        protected void doPost( HttpServletRequest req, HttpServletResponse resp ) throws ServletException, IOException {
          
          
            super.doPost(req, resp);
        }
    }
    
  • 注销session

    public class SessionDemo03 extends HttpServlet {
          
          
        @Override
        protected void doGet( HttpServletRequest req, HttpServletResponse resp ) throws ServletException, IOException {
          
          
            HttpSession session = req.getSession();
            session.removeAttribute("name");
            session.invalidate();
    
        }
        @Override
        protected void doPost( HttpServletRequest req, HttpServletResponse resp ) throws ServletException, IOException {
          
          
            super.doPost(req, resp);
        }
    }
    
  • 自动注销

    <!--    设置session默认的失效时间-->
        <session-config>
    <!--        单位为分钟-->
            <session-timeout>1</session-timeout>
        </session-config>
    

6、JSP

  • JSP最终也会被转换为一个Java类

  • JSP本质上就是一个Servelet

    //初始化
      public void _jspInit() {
          
          
      }
    //注销
      public void _jspDestroy() {
          
          
      }
    //JSPService
      public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
    
  1. 判断请求

  2. 内置一些对象

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

    response.setContentType("text/html");		//设置响应的页面类型
          pageContext = _jspxFactory.getPageContext(this, request, response,
          			null, true, 8192, true);
          _jspx_page_context = pageContext;
          application = pageContext.getServletContext();
          config = pageContext.getServletConfig();
          session = pageContext.getSession();
          out = pageContext.getOut();
          _jspx_out = out;
    
  • 在JSP中
    1. 在JSP中只要是Java代码就会原装不动的输出
    2. 如果是HTML代码,就会被装换为out.write(“\r\n”);

6.1、9大内置对象

  • PageContext 存东西

  • Request 存东西

    1. 客户端向服务器发送请求,产生的数据,用户看完就没用了,比如:新闻
  • Response

  • Session 存东西

    1. 客户端向服务器发送请求,产生的数据,用户用完一会还有用,比如:购物车
  • Application (ServletContext) 存东西

    1. 客户端向服务器发送器请求,产生的数据,一个用户用完了,其它用户可能使用,比如:聊天记录
  • config (servletConfig)

  • out

  • page

  • exception

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
        <head>
            <title>Title</title>
        </head>
        <body>
        <%--    内置对象--%>
            <%
    
                pageContext.setAttribute("name1","Java学不会1");//保存的数据只在一个页面中有效
                request.setAttribute("name2","Java学不会2");//保存的数据只在一次请求有效,请求转发会携带这个数据
                session.setAttribute("name3","Java学不会3");//保存的数据只在一次会话有效,从打开浏览器到关闭浏览器
                application.setAttribute("name4","Java学不会4");//保存的数据只在服务器中有效,从打开服务器到关闭服务器
            %>
    
            <%--脚本判断中的代码,会被原封不动的生成到.jsp.java
            要求:必须保存Java语法的正确性--%>
            <%
                 //从pageContext取出,通过寻找方式来
                //从底层到高层(作用域)
                String name1 = (String) pageContext.findAttribute("name1");
                String name2 = (String) pageContext.findAttribute("name2");
                String name3 = (String) pageContext.findAttribute("name3");
                String name4 = (String)  pageContext.findAttribute("name4");
    
            %>
    <%--使用El表达式输出   ${
          
          }--%>
            <h1>取出的值为:</h1>
            <h3>${
          
          name1}</h3>
            <h3>${
          
          name2}</h3>
            <h3>${
          
          name3}</h3>
            <h3>${
          
          name4}</h3>
        </body>
    </html>
    

6.2、JSP标签、JSTL标签、EL表达式

  • 依赖包

    <!--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>
    
  • EL表达式:${}

    1. 获取数据
    2. 执行运算
    3. 获取web开发的常用对象
  • JSP标签 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

            <jsp:forward page="jsptag2.jsp">
                <jsp:param name="name" value="Java学不会"/>
                <jsp:param name="age" value="2023"/>
            </jsp:forward>
    
  • JSTL表达式

    1. JsTL标签库的使用就是为了弥补HTML标签的不足;他自定义许多标签,标签的功能和Java代码一样
        <body>
            <form action="coreif.jsp" method="get">
                <input type="text" name="username" value="${param.username}">
                <input type="submit" value="登录">
            </form>
            <%--判断如果提交的用户名是管理员,则登录成功--%>
            <c:if test="${param.username=='admin'}" var="isAdmin" >
                <c:out value=" 管理员欢迎你">
                </c:out>
                <c:out value="${isAdmin}"></c:out>
            </c:if>
        </body>
    
        <body>
    
            <c:set var="score" value="85"></c:set>
            <c:choose>
                <c:when test="${score>=90}">你的成绩为优秀</c:when>
    
                <c:when test="${score>=80}">你的成绩为良好</c:when>
    
                <c:when test="${score>=70}">你的成绩为不错</c:when>
    
            </c:choose>
        </body>
    
        <body>
    
            <%
                ArrayList<String> people = new ArrayList<>();
                people.add("张三");
                people.add("李四");
                people.add("王五");
                people.add("赵六");
                people.add("田七");
                request.setAttribute("list",people);
            %>
    
            <%--var,每一遍历出来的变量
            items,要遍历的对象--%>
            <c:forEach var="people" items="${list}">
                <c:out value="${people}">
                </c:out>
            </c:forEach>
        </body>
    

6.3、JavaBean(实体类)

  • JavaBean有特定的写法:
    1. 必须要有一个无参构造
    2. 属性必须私有化
    3. 必须有对应的get/set方法
    4. 一般用来和数据库的字段做映射 ORM
  • ORM:对象关系映射
    1. 表——>类
    2. 字段——>属性
    3. 行记录——>对象

7、Filter(过滤器)

  • Filter:过滤器,用来过滤网站的数据
    1. 处理中文乱码
    2. 登录验证
  • Filter开发步骤
    1. 导包:不要导错
      在这里插入图片描述
  1. 编写代码

    public class CharacterEncodingFilter implements Filter {
          
          
        @Override
        //初始化
        public void init( FilterConfig filterConfig ) throws ServletException {
          
          
            System.out.println("初始化");
        }
    
        @Override
        //Chain:链
        /*
        1.过滤中的所有代码,在过滤特定请求的时候都会执行
        2.必须要让过滤器继续同行   chain.doFilter(request,response); 
        */
        public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain ) throws IOException, ServletException {
          
          
    
            request.setCharacterEncoding("utf-8");
            response.setCharacterEncoding("utf-8");
            response.setContentType("text/html;charset=UTF-8");
            System.out.println("执行前");
            chain.doFilter(request,response);       //让请求继续走,如果不写,程序到这里就被拦截停止
            System.out.println("执行后");
        }
    
        @Override
        //销毁,web服务器关闭过滤器销毁
        public void destroy( ) {
          
          
            System.out.println("销毁");
    
        }
    }
    
  2. 在web.xml中配置Filter

    	<filter>
            <filter-name>CharacterEncodingFilter</filter-name>
            <filter-class>com.javastudy.filter.CharacterEncodingFilter</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>CharacterEncodingFilter</filter-name>
            <!--只要是/servlet的任何请求都会经过这个过滤器-->
            <url-pattern>/servlet/*</url-pattern>
        </filter-mapping>
    

    8、监听器

  • 实现一个监听器的接口(有N种)
    1. 实现监听器接口
    //统计网站在线人数:统计session
    public class OnlineCountListener implements HttpSessionListener {
          
          
        @Override
        //创建session监听
        public void sessionCreated( HttpSessionEvent se ) {
          
          
            ServletContext ctx = se.getSession().getServletContext();
            System.out.println(se.getSession().getId());
            Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
    
            if(onlineCount==null){
          
          
                onlineCount=new Integer(1);
            }else{
          
          
                int count =onlineCount.intValue();
                onlineCount=new Integer(count+1);
            }
            ctx.setAttribute("OnlineCount",onlineCount);
        }
    
        @Override
        //销毁session监听
        public void sessionDestroyed( HttpSessionEvent se ) {
          
          
            ServletContext ctx = se.getSession().getServletContext();
            Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
            se.getSession().invalidate();
            if(onlineCount==null){
          
          
                onlineCount=new Integer(0);
            }else{
          
          
                int count =onlineCount.intValue();
                onlineCount=new Integer(count-1);
            }
            ctx.setAttribute("OnlineCount",onlineCount);
        }
        /*
        session销毁:
        1.手动销毁
        2.自动销毁
         */
    }
    
  1. web.xml中注册监听器

        <!--注册监听器-->
        <listener>
            <listener-class>com.javastudy.listener.OnlineCountListener</listener-class>
        </listener>
    

9、单元测试

  • 依赖

            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
            </dependency>
    
  • @Test注解只有在方法上有效,只要加了个注解的方法,就可以直接运行

        @Test
        public void hello(){
          
          
            System.out.println("hello");
        }
    

猜你喜欢

转载自blog.csdn.net/qq_45042462/article/details/125622845