Javaweb后端阶段

java web

一.XML

①.概述
  1. 概念:可扩展标记语言

    • 可扩展:标签都是自定义的。
  2. 功能

    • 存储数据
      1. 配置文件
      2. 在网络中传输

    properties

    name=zhangsan
    age=23
    gender=nan
    

    xml

    <user id="1">
    	<name>zhangsan</name>
        <age>23</age>
    </user>
    <user id="2">
    	<name>zhangsan</name>
        <age>23</age>
    </user>
    
  3. xml与html的区别

    • xml标签都是自定义的,html标签是预定义的

    • xml的语法严格,html语法松散

    • xml是存储数据的,html是展示数据的

    • w3c 万维网联盟

②.快速入门
  1. 基本语法

    • xml文档的后缀名 .xml
    • xml第一行必须定义为文档声明
    • xml文档中有且只有一个根标签
    • 属性值必须使用引号(单双都可以)
    • 标签必须正确关闭
    • xml标签名称区分大小写
  2. 快速入门

    <?xml version="1.0" ?>
    <users>
    <user id="1">
        <name>张三</name>
        <age>23</age>
    </user>
    <user id="2">
    	<name>李四</name>
        <age>23</age>
    </user>
    </users>
    
  3. 组成部分

    • 文档声明

      1. 格式:<? xml 属性列表 ?>

      2. 属性列表:

        • version:版本号,必须的属性

        • encoding:编码方式。告知解析引擎当前文档使用的字符集,默认为:ISO-8869-1

        • standalone:是否独立

          • 取值:

            yes:不依赖其他文件

            no:依赖其他文件

    • 指令(了解):结合css

      • <? xml-stylesheet type="text/css" href="a.css" ?>
    • 标签:标签名称自定义的

      • 规则
        1. 名称可以包含字母,数字以及其他的字符
        2. 名称不能以数字或者标点符号开始
        3. 名称不能以字母 xml(或者 XML,xml等等)开始
        4. 名称不能包含空格
    • 属性:

    • id属性值唯一

    • 文本:

      • CDATA区:在该区域中的数据会被原样展示

        • 格式:<![CDATA [数据]]>
③.约束
  • 作用: 规定xml文档的书写规则

谁编写xml? --用户(程序员)
谁编译xml? --软件(框架)

  • 作为框架的使用者程序员:
    1. 能够在xml中引入约束文档
    2. 能够简单的读懂约束文档
  • 分类:
    1. DTD:一种简单的约束技术
    2. Schema:一种复杂的约束技术
④.DTD 约束技术
  1. DTD的引入

    • 内部dtd

    • 外部dtd

      • 本地:
      • 网络:
  2. DTD语法

    1. 元素定义
    <!ELEMENT 元素名称 (元素内容)>
    
    元素内容的5种形式:
    1)#PCDATA:表示元素中嵌套的内容是普通文本字符串
    2)子元素:说明元素包含的元素。student(id,name,age)
    3)混合内容:表示元素既可以包含字符数据,也可以包含子元素。student(#PCDATA|name)
    4)EMPTY:表示元素即不包含字符数据,也不包含子元素。是一个空元素
    5)ANY:表示元素可以包含任何字符数据和子元素
    
    • 定义元素时元素内容中可以包含一些符号
      1. ?: 表示该对象可以出现0次或1次
      2. * : 表示该对象可以出现0次或多次
      3. + : 表示该对象可以出现1次或多次
      4. | : 表示在列出的对象中选择一个
      5. , : 表示对象必须按照指定的顺序出现
      6. () : 用于给元素进行分组
    1. 属性定义
    <!ATTLIST 元素名
    	属性名1 属性类型 设置说明
    	属性名2 属性类型 设置说明
    	...
    >
    元素名 是属性所属元素的名字,属性名 是属性的名称,属性类型 用来指定该属性属于哪种类型,设置说明 用来说明该属性是否必须出现
    
    • 设置说明
      定义元素属性时,有四种设置说明可以选择

      设置说明含义
      #REQUIRED表示该属性是必须的
      #IMPLIED表示元素可以包含该属性,也可以不包含该属性
      #FIXED表示一个固定的属性默认值
      默认值和FIXED一样
    • 属性类型

      属性名含义
      CADATA字符数据
      Enumerated枚举类型
      ID一个ID类型的属性,用于唯一标识xml文档中的一个元素
      IDREF和IDREFS使元素之间建立关系
⑤.Schema约束
  • 引入:

    1. 填写xml文档的根元素

    2. 引入xsi前缀。 xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”

    3. 引入xsd文件命名空间 xsi:schemalocation=“http://www.itcast.cn/xml student.xsd”

    4. 为每一个xsd约束声明一个前缀,作为标识

      xmlns:a=“http://www.itcast.cn/xml”

      <?xml version="1.0" encoding="UTF-8" ?>
      <xsd:schema xmlns = "http://www.itcast.cn/xml"
                  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                  targetNamespace="http://www.itcast.cn/xml" elementFormDefault="qualified">
          <xsd:element name="students" type="studentsType"/>
          <xsd:complexType name="studentsType">
              <xsd:sequence>
                  <xsd:element name="student" type="studentType" minOccurs="0" maxOccurs="unbounded"/>
              </xsd:sequence>
          </xsd:complexType>
          <xsd:complexType name="studentType">
              <xsd:sequence>
                  <xsd:element name="name" type="xsd:string"/>
                  <xsd:element name="age" type="ageType"/>
                  <xsd:element name="sex" type="sexType"/>
              </xsd:sequence>
              <xsd:attribute name="number" type="numberType" use="required"/>
          </xsd:complexType>
          <xsd:simpleType name="ageType">
              <xsd:restriction base="xsd:int">
                  <xsd:minInclusive value="0"/>
                  <xsd:maxInclusive value="150"/>
              </xsd:restriction>
          </xsd:simpleType>
          <xsd:simpleType name="sexType">
              <xsd:restriction base="xsd:string">
                  <xsd:enumeration value="male"/>
                  <xsd:enumeration value="female"/>
              </xsd:restriction>
          </xsd:simpleType>
          <xsd:simpleType name="numberType">
              <xsd:restriction base="xsd:string">
                  <xsd:pattern value="[a~z]"/>
              </xsd:restriction>
          </xsd:simpleType>
      </xsd:schema>
      
      <?xml version="1.0" encoding="UTF-8" ?>
      <students
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="
              http://www.itcast.cn/xml student.xsd
              "
              xmlns="http://www.itcast.cn/xml"
      >
      <student number="z">
          <name>tom</name>
          <age>19</age>
          <sex>female</sex>
      </student>
      
      </students>
      
  • 语法

    1. 元素定义
    <xs:element name="xxx" type="yyy">
    element用于声明一个元素,xxx指元素的名称,yyy指元素的数据类型
    在XML Schema中还有很多内建的数据类型,
    xs:String:表示字符串类型
    xs:decimal:表示小数类型
    xs:integer:表示整数类型
    xs:boolean:表示布尔类型
    XS:date:表示日期类型
    XS:time:表示时间类型
    
    1. 属性的定义
    <xs:attribute name="xxx" type="yyy">
    attribute表示声明一个属性,xxx表示属性名称,yyy表示属性类型
    
    1. 简单类型
⑥.解析
  • 操作xml文档

    1. 解析(读取):将文档中的数据读取到内存中
    2. 写入:将内存中的数据保存在xml文档中。持久化的存储
  • 解析xml的方式

  1. DOM:将标记语言一次性加载进内存,在内存中形成一颗dom树

    • 优点:操作方便,可以对文档进行CRUD的所有操作
    • 缺点:占内存
  2. SAX:逐行读取,基于事件驱动的

    • 优点:不占内存
    • 缺点:只能读取,不能增删改
  • xml常见的解析器

    1.JAXP:sun公司提供的解析器,支持dom和sax两种思想
    2.DOM4J:一款优秀的解析器
    3.Jsoup:是一款java的HTML解析器,可直接解析某个URL地址,HTML文本内容。
    4.PULL:Android操作系统内置的解析器,sax方式的

Ⅰ.Jsoup解析器
  • 快速入门

    1. 导入jar包
    2. 获取Document对象
    3. 获取对应的标签Element对象
    4. 获取数据
  • 代码实现

  /**
   * jsoup入门
   */
  public class Demo01 {
      public static void main(String[] args) throws IOException {
          //1.引入jar包
          
          //2.1 获取xml文件的url地址
          String path = Demo01.class.getClassLoader().getResource("students.xml").getPath();
          //2.2获取Document对象
          Document document = Jsoup.parse(new File(path),"utf-8");
          //3.获取元素对象
          Elements elements = document.getElementsByTag("name");
          //打印元素个数
          System.out.println(elements.size());
          Element element = elements.get(0);
          //4.获取元素文本
          String name = element.text();
          System.out.println(name);
      }
  }
Ⅱ.对象
  1. Jsoup:工具类,可以解析HTML或xml文档,返回Document

    • parse():解析html或xml文档,返回Document

    • parse(File in,String charsetName):解析xml或html文件

      //2.1 获取xml文件的url地址
      String path = Demo01.class.getClassLoader().getResource("students.xml").getPath();
      //2.2获取Document对象
      Document document = Jsoup.parse(new File(path),"utf-8");
      
    • parse(String html):解析xml或html字符串

      public class Demo02 {
          public static void main(String[] args) throws IOException {
              String str = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" +
                      "<students>\n" +
                      "    <student>\n" +
                      "        <name>tom</name>\n" +
                      "        <age>16</age>\n" +
                      "        <gender>male</gender>\n" +
                      "    </student>\n" +
                      "    <student>\n" +
                      "        <name>jack</name>\n" +
                      "        <age>21</age>\n" +
                      "        <gender>female</gender>\n" +
                      "    </student>\n" +
                      "</students>";
              Document document = Jsoup.parse(str);
              System.out.println(document);
          }
      }
      
    • parse(URL url,int timroutMillis):通过网络路径获取指定的html或xml文档对象

      URL url = new URL("https://www.sina.com.cn/");
              Document document = Jsoup.parse(url, 10000);
              System.out.println(document);
      
    1. Document:文档对象。代表内存中的dom树

      • 获取Element对象

        • getElementById(String id) : 根据Id属性值获取唯一的element对象
        Element element = document.getElementById("1");
        System.out.println(element);
        
        • getElementsByTag(String tagName) : 根据标签名获取元素对象集合
        Elements elements = document.getElementsByTag("age");
        System.out.println(elements);
        
        • getElementsByAttribute(String key) : 根据属性名称获取元素对象集合
        Elements elements1 = document.getElementsByAttribute("name");
        System.out.println(elements1);
        
        • getElementsByAttributeValue(String key,String value) : 根据对应的属性名和属性名获取元素对象集合
        Elements elements2 = document.getElementsByAttributeValue("name", "lz_001");
        System.out.println(elements2);
        
    2. Elements:元素Element对象的集合。可以当作ArrayList<Element>来使用

    3. Element:元素对象

      • 获取子元素对象
        • getElementById(String id) : 根据Id属性值获取唯一的element对象
        • getElementsByTag(String tagName) : 根据标签名获取元素对象集合
        • getElementsByAttribute(String key) : 根据属性名称获取元素对象集合
        • getElementsByAttributeValue(String key,String value) : 根据对应的属性名和属性名获取元素对象集合
      • 获取属性值
        • String attr(String key) : 根据属性名称获取属性值
      • 获取元素文本内容
        • String text() : 获取元素纯文本内容
        • String html() : 获取标签体的所有内容(包括子标签)
    4. Node:节点对象

      • 是Document对象和Element对象的父类
      • 执行增删改的操作
Ⅲ.快速查询
  1. selector:选择器

    • 使用方法:Elements select(String cssQuery)
    • 语法:参考Selector类定义的语法
  2. Xpath:

    • 需要额外导入jar包
    • 查询w3cshool参考手册

二.Tomcat

①.wed服务器软件
  1. 服务器:安装了服务器软件的计算机
  2. 服务器软件:接收用户的请求,处理请求,做出响应
  3. wed服务器软件:接收用户的请求,处理请求,做出响应
②.Tomcat
  1. tomcat

    1. 下载:http://tomcat.apache.org/

    2. 安装:解压压缩包,安装目录不要有中文和空格

      • 目录结构

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RxjqdjFq-1603158978887)(C:\Users\谜语菌\Documents\img\目录结构.jpg)]

    3. 卸载:删除目录

    4. 启动:

    • bin/startup.bat,双击运行文件

    • 访问:浏览器输入:http://locahost:8080 回车自己访问自己
      http://别人ip:8080 访问别人

    • 可能遇到的问题:

       1. 窗口闪退
      
    • 原因:没有正确配置JAVA_HOME环境变量
      解决方案,将JDK根目录配置在JAVA_HOME中

      2. 启动报错(端口号被占用)
      
    • 解决:关闭占用端口号的程序,更改自己的端口号
      netstat -ano 查看程序端口—》PID
      - 启动任务处理器-关闭PID

    1. 关闭
    • 正常关闭
    • bin/shutdown.bat
    • Ctrl+c
    • 强制关闭
    • 直接关闭窗口
    1. 配置
    • 部署项目的方式

      1. 直接将项目放在wedapp目录中
      • 简化部署:将项目打包成一个war包,将war包放置到wedapp下会自动解压缩。
      1. 配置conf/server.xml文件
      <Host>标签中
      <Context dovNase="xxx" path="yyy" />
      xxx:项目存放路径
      yyy:虚拟目录
      
      1. 在conf\Catalina\localhost创建任意名称的xml文件,在里面编写
      <Context dovNase="xxx" />
      xxx:项目存放路径
      虚拟目录:xml文件名称
      
    • 静态项目和动态项目

      • 目录结构

        1. Java动态项目的目录结构
      -- 项目的根目录
        -- WED-INF目录
          -- wed.xml: wed项目的核心配置文件
          -- classes目录:放置字节码文件的目录
          -- lib目录:放置依赖的jar包
      
  2. 将Tomcat集成到IDEA中,并且创建JavaEE项目,部署项目

    Run ---> Edit... ---> Defaults ---> Tomcat Server ---> Local
    Configure... ---> 配置安装目录 ---> OK
    
    解决web目录下没有web.xml文件
    Ctrl+Shift+Alt+S 快捷键进入Project structure管理界面
    先择左边菜单栏的Facet,点击后,看到Deployment的输入框
    点击右面加号,添加web.xml文件,文件目录设置在web下
    
  3. IDEA与Tomcat的相关配置

IDEA会为每一个Tomcat部署的项目单独建立一份配置文件

三.Servlet

①.简介
  • 概念:运行在服务器端的小程序

    • Servlet就是一个接口,定义了java类被浏览器访问到(tomcat识别)的规则。
    • 将来我们定义一个类,实现Servlet接口,复写方法
  • 快速入门

    1. 创建JavaEE项目

    2. 定义一个类,实现Servlet接口

    3. 实现接口中的抽象方法

      public class ServletDemo implements Servlet {
          @Override
          public void init(ServletConfig servletConfig) throws ServletException {
              System.out.println("init...");
          }
      
          @Override
          public ServletConfig getServletConfig() {
              System.out.println("getServletConfig...");
              return null;
          }
          //提供服务的类
          @Override
          public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
              System.out.println("service...");
          }
      
          @Override
          public String getServletInfo() {
              System.out.println("getServletInfo");
              return null;
          }
      
          @Override
          public void destroy() {
              System.out.println("destroy");
          }
      }
      
    4. 配置Servlet

      <!-- <servlet>用于注册Servlet,他的两个子元素<servlet-name>和<servlet-class>分别指定Servlet的名称和全类名 -->
      <servlet>
      	<servlet-name>demo</servlet-name>
          <servlet-class>cn.lczy.wed.servlet.HelloServlet</servlet-class>
      </servlet>
      <!-- <servlet-mapping>用于映射Servlet对外访问的虚拟路径 --> <servlet-mapping>
          <servlet-name>demo</servlet-name>
      	<url-pattern>/demo</url-pattern>
      </servlet-mapping>
      
  • 实现原理

    1. 当服务器接收到客户端浏览器的请求后,会解析请求URL路径,获取访问的Servlet的资源路径
    2. 查找web.xml文件,是否对应的<url-pattern>标签体内容
    3. 如果有,则找到对应的<servlet-class>全类名
    4. tomcat会将字节码文件加载进内存,并且创建对象
    5. 调用其方法
②.servlet的生命周期
  1. 生命周期

    • 创建===执行init方法,只执行一次
      • 什么时候被创建
        • 默认情况下,第一次被访问时,Servlet被创建
        • 可以配置执行Servlet的创建时机
          • 在web.xml标签下配置
            1. 第一次被访问时创建,默认
              • 的值为负数
            2. 在服务器启动时创建
              • 的值为0或正整数
      • Servlet的init(),只执行一次,说明Servlet在内存中只有一个对象,Servlet是单例的
        • 多个用户同时访问时,可能出现线程安全问题
        • 解决:尽量不要在Servlet中定义成员变量,即使定义了成员变量,也不要对值进行修改
    • 提供服务===执行service方法,执行多次
      • 每次访问Servlet时,Service方法都会被调用一次
    • 销毁===执行destroy方法,只执行一次
      • Serlet被销毁时执行。服务器关闭时,Servlet被销毁
      • 只有服务器正常关闭时,才会执行destroy方法
      • destroy方法在Servlet被销毁之前执行,一般用于释放资源
  2. 方法

      /**
      * 初始化方法
      * 在Servlet创建时执行init(),并且只执行一次
      */
     @Override
     public void init(ServletConfig servletConfig) throws ServletException {
         System.out.println("init...");
     }
    
     /**
      * 获取ServletConfig对象
      * ServletConfig:Servlet的配置对象
      * @return
      */
     @Override
     public ServletConfig getServletConfig() {
         return null;
     }
    
     /**
      * 提供服务的方法
      * 每一次Servlet被访问时执行,执行多次
      */
     @Override
     public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
         System.out.println("Servlet...");
     }
    
     /**
      * 获取Servlet的一些信息,版本,作者等等
      * @return
      */
     @Override
     public String getServletInfo() {
         return null;
     }
    
     /**
      * 销毁方法
      * 当服务器正常关闭时执行,并且执行一次
      */
     @Override
     public void destroy() {
         System.out.println("destroy...");
     }
    
③.Servlet3.0
  • 好处

    • 支持注解配置。可以不需要web.xml了
  • 步骤

    1. 创建JavaEE项目,选择Servlet的版本3.0以上
    2. 定义一个类,实现Servlet接口
    3. 复写方法
    4. 在类上使用@webServlet注解,进行配置
      • @webServlet(“虚拟路径”)@WebServlet("/demo")
④.Servlet的体系结构

Servlet – 接口
|
GenericServlet – 抽象类
|
HttpServlet – 抽象类

  • GenericServlet:将Servlet接口中的方法做了默认空实现,只将service()方法作为抽象

    • 将来定义Servlet类时可以继承GenericServlet,实现service()即可
  • HttpServlet:对HTTP协议的一种封装,简化操作

    1. 定义类继承HttpServlet
    2. 复写doGet/doPost方法
    <body>
        <form action="/demo1" method="post">
            <input type="text"/>
            <input type="submit" value="提交" />
        </form>
    </body>
    
    @WebServlet("/demo1")
    public class ServletDemo1 extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("doGet...");
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("doPost...");
        }
    }
    
⑤.Servlet相关配置
  • urlpartten : Servlet访问路径
    1. 一个Servlet可以定义多个访问路径:@wedServlet({"/demo1","/demo2"…})
    2. 路径定义规则
      • /xxx
      • /xxx/xxx
      • *.do

四.HTTP

①.概述
  • 概念:Hyper Text Transfer Protocol 超文本传输协议
    • 传输协议:定义了,客户端和服务器通信时,发送数据的格式
    • 特点:
      1. 基于TCP/IP的高级协议
      2. 默认端口号:80
      3. 基于请求/响应模型:一次请求对应一次响应
      4. 无状态的:每次请求之间相互独立,不能交互数据
    • 历史版本
      • 1.0 : 每一次请求响应都会建立新的连接
      • 1.1 : 复用连接
②.请求消息

客户端发送给服务器端的数据

  • 请求消息数据格式

    1. 请求行
      | 请求方式 | 请求url | 请求协议/版本|
      | POST | /login.html | HTTP/1.1 |

      • 请求方式:
        • HTTP协议有七种请求方式,常用的有两种
          • GET:
            1. 请求参数在请求行中,在url后
            2. 请求的url长度有限制
            3. 不太安全
          • POST:
            1. 请求参数在请求体中
            2. 请求的url长度没有限制
            3. 相对安全
    2. 请求头:客户端浏览器给服务器的一些信息
      请求头名称: 请求头值

      • 常见的请求头

        1. User-Agent:浏览器告诉服务器,我访问你是哦那个的浏览器版本信息
        • 可以在服务器端获取该头信息,解决浏览器兼容性问题
        1. Referer:告诉服务器,当前请求从哪里来?
          • 作用
            1. 防盗链
            2. 统计工作
    3. 请求空行
      空行,用于分割POST请求的请求头和请求体

    4. 请求体(正文)

      • 封装POST请求消息的请求参数
    • 字符串格式
    //请求行
    POST /login.html HTTP/1.1
    //请求头
    Host: localhost
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:77.0) Gecko/20100101 Firefox/77.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
    Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
    Accept-Encoding: gzip, deflate
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 17
    Origin: http://localhost
    Connection: keep-alive
    Referer: http://localhost/Servlet1/login.html
    Cookie: Idea-5c063c53=8e0ad809-17a7-4a3b-94a6-f8f4b166358e
    Upgrade-Insecure-Requests: 1
    //请求空行
    
    //请求体
    username=zhangsan
    
③.响应消息

服务器端发送给客户端的数据

  • 响应数据格式

    1. 响应行

      • HTTP/1.1 200 OK
      • 组成:协议/版本 响应状态码 状态码描述
      • 响应状态码:服务器告诉客户端浏览器本次请求和响应的状态
        • 分类
          1. 1xx:服务器等待接收客户端消息,没有接收完成,等待一段时间发送1xx状态码
          2. 2xx:成功
          3. 3xx:重定向。代表302(重定向) 304(访问缓存)
          4. 4xx:客户端错误。代表404(请求路径没有对应的资源)405(没有对应的doxxx方法)
          5. 5xx:服务器端错误。代表:500(服务器内部错误)
    2. 响应头

      • 格式:头名称:值
      • 常见的响应头
        1. Content-Type: 服务器告诉客户端本次响应体数据格式以及编码格式
        2. Content-disposition:服务器告诉客户端以什么格式打开响应体数据
          • 值:in-line:默认值当前页面打开
          • 值:attachment;filename=xxx:以附件形式打开响应体
    3. 响应空行

    4. 响应体:传输的数据

    5. 字符串表示形式

      //响应行
      HTTP/1.1 200 OK 
      //响应头
      Content-Type: text/html;charset=UTF-8
      Content-Length: 98
      Date: Fri, 07 Aug 2020 02:28:05 GMT
      Keep-Alive: timeout=20
      Connection: keep-alive
      //响应空行
      
      //响应体
      <html>
        <head>
          <title>标题</title>
        </head>
        <body>
       hello 响应
        </body>
      </html>
      

五.Request和Response

  • 请求和响应
  • 原理
    1. Tomcat服务器,会根据请求的url中的资源路径,创建对应的ServletDemo的对象。
    2. Tomcat服务器,会创建request和response对象,request对象中封装请求消息数据
    3. Tomcat将request和response两个对象传递给service方法,并且调用
    4. 程序员,通过request对象获取请求消息数据,通过response对象设置响应消息数据。
    5. 服务器在浏览器做出响应之前,会从response对象中拿程序员设置的响应消息数据,进行响应
  • request和response对象是由服务器创建的。我们来使用他们
  • request对象是用来获取请求消息,response对象是用来设置响应消息
①.Request
1.继承体系结构

ServletRequest – 接口
| 继承
HttpServletRequest – 接口
| 实现
org.apache.catalina.connector.RequestFacade 类(tomcat)

2.方法
  • request:获取请求行消息
    GET /Setvlet1/demo?name=zhangsan HTTP/1.1

    返回值类型方法功能
    StringgetMethod()获取请求方式:GET
    StringgetContextPath()获取虚拟目录:/Setvlet1
    StringgetServletPath()获取Servlet路径:/demo
    StringgetQueryString()获取GET方式请求参数:name=zhangsan
    StringgetRequestURI()获取请求URI:/Servlet1/demo
    StringBuffergetRequestURL()获取请求URL:http://localhost/Servlet1/demo
    StringgetProtocol()获取协议及版本:HTTP/1.1
    StringgetRemoteAddr()获取客户机的IP地址
    • URL:统一资源定位符 : http://localhost/Servlet1/demo – 中华人民共和国
  • URI:统一资源标识符 : /Servlet1/demo – 共和国

  • 获取请求头数据

    返回值类型方法功能
    StringgetHeader(String name)通过请求头的名称获取请求头的值
    Enumeration<String>getHeaderNames()获取所有的请求头名称
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //1. 获取全部头名称
            Enumeration<String> headerNames = request.getHeaderNames();
            while (headerNames.hasMoreElements()){
                String headername = headerNames.nextElement();
                String header = request.getHeader(headername);
                System.out.println(headername+" = "+header);
            }
        }
    
  • 获取请求体数据

    • 请求体:只有POST请求方式,才有请求体,在请求体中封装了POST请求的请求参数

    • 步骤:

      1. 获取流对象

        返回值类型方法功能
        BufferedReadergetReader()获取字符输入流,只能操作字符数据
        ServletInputStreamgetInputStream()获取字节输入流,可以操作所有类型数据(文件上传)
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        	//1. 获取流对象
        	BufferedReader reader = request.getReader();
        	//2. 读取流对象
        	String line = null;
        	while ((line=reader.readLine())!=null){
        		System.out.println(line);
        	}
        }
        
        1. 再从流对象中拿数据
3.其他方法
  1. 获取请求参数,通用方式

    返回值方法作用
    StringgetParameter(String name)根据参数名称获取参数值
    String[]getParameterValues(String name)根据参数名称获取参数值的数组
    Enumeration<String>getParameterNames()获取所有请求的参数名称
    Map<String,String[]>getParameterMap()获取所有参数的map集合
  • 中文乱码问题

    1. get方式:Tomcat 8 已经解决

    2. post方式:会乱码

      • 解决:在获取参数前,设置request的编码request.setCharacterEncoding(utf-8);
<form action="/ServletDemo4" method="post">
        <input type="text" placeholder="请输入用户名" name="username"/><br/>
        <input type="password" placeholder="请输入密码" name="password"/><br/>
        <input type="checkbox" name="hobby" value="学习"/>学习
        <input type="checkbox" name="hobby" value="运动"/>运动
        <input type="checkbox" name="hobby" value="看书"/>看书
        <input type="checkbox" name="hobby" value="电子游戏"/>电子游戏 <br/>
        <input type="submit" value="提交" />
    </form>
@WebServlet("/ServletDemo4")
public class ServletDemo4 extends HttpServlet {
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//修改编码
		request.setCharacterEncoding("utf-8");
		//1. 获取username
		String username = request.getParameter("username");
		System.out.println(username);
		System.out.println("========================");
		//2. 获取hobby
		String[] hobbys = request.getParameterValues("hobby");
		for(String hobby:hobbys){
			System.out.println(hobby);
		}
		System.out.println("========================");
		//3. 获取请求参数名称
		Enumeration<String> names = request.getParameterNames();
		while (names.hasMoreElements()){
			String name = names.nextElement();
			System.out.println(name);
		}
		System.out.println("========================");
		//4. 获取所有参数集合
		Map<String, String[]> parameterMap = request.getParameterMap();
		Set<String> keys = parameterMap.keySet();
		for(String key:keys){
			String[] values = parameterMap.get(key);
			System.out.println(key+"=");
			for(String value:values){
				System.out.println(value);
			}
}
  	    }
  	
  	        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  	            this.doPost(request,response);
  	    }
  	}
  	运行结果:
  	4365456456
  	========================
  	运动
  	看书
  	电子游戏
  	========================
  	username
  	password
  	hobby
  	========================
  	username=4365456456
  	password=31231231
  	hobby=运动
  	看书
  	电子游戏
2. 请求转发:一种服务器内部的资源跳转方式
  • 步骤

    1. 通过request对象获取请求转发器对象:getRequestDispatcher(String path)

    2. 使用RequestDispatcher对象来进行转发:forward(ServletRequest request,ServletResponse response)

      返回值类型方法名功能
      RequestDispatchergetRequestDispatcher(String path)过request对象获取请求转发器对象
      voidforward(ServletRequest request,ServletResponse response)使用RequestDispatcher对象来进行转发
      @WebServlet("/ServletDemo5")
      public class ServletDemo5 extends HttpServlet {
      	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      		System.out.println("/ServletDemo5被访问了...");
      		//获取转发对象
      		/*RequestDispatcher dispatcher = request.getRequestDispatcher("/ServletDemo6");
      		dispatcher.forward(request,response);*/
      		request.getRequestDispatcher("/ServletDemo6").forward(request,response);
      	}
      	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      		this.doPost(request,response);
      	}
      }
      
      @WebServlet("/ServletDemo6")
      public class ServletDemo6 extends HttpServlet {
      	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      		System.out.println("/ServletDemo6被访问了...");
      	}
      	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      		this.doPost(request, response);
      	}
      }
      	结果打印:
      	/ServletDemo5被访问了...
      	/ServletDemo6被访问了...
      
    • 特点
      1. 浏览器地址栏路径不发生变化
      2. 只能转发到当前服务器内部资源中
      3. 转发只用到一次请求
    1. 共享数据

      • 域对象:一个有作用范围的对象,可以在范围内共享数据

      • request域:代表一次请求的范围,一般用于请求转发多个资源中贡献数据

      • 方法

      返回值方法功能
      voidsetAttribute(String name,Objet obj)存储数据
      ObjectgetAttitude(String name)通过键获取值
      voidremoveAttribute(String name)通过键移除键值对
      @WebServlet("/ServletDemo5")
      public class ServletDemo5 extends HttpServlet {
      protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      	System.out.println("/ServletDemo5被访问了...");
      	//存储数据
      	request.setAttribute("msg","hello");
      	//获取转发对象
      	/*RequestDispatcher dispatcher = request.getRequestDispatcher("/ServletDemo6");
      	dispatcher.forward(request,response);*/
        request.getRequestDispatcher("/ServletDemo6").forward(request,response);
          }
      
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              this.doPost(request,response);
          }
      }
      
      @WebServlet("/ServletDemo6")
      public class ServletDemo6 extends HttpServlet {
      protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      	Object msg = request.getAttribute("msg");
      	System.out.println(msg.toString());
      	System.out.println("/ServletDemo6被访问了...");
      }
      
      protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      	this.doPost(request, response);
      }
      }
      输出结果:
      /ServletDemo5被访问了...
      hello
      /ServletDemo6被访问了...
      
    2. 获取ServletContext

      • ServletContext getServletContext()
②.Response
  1. 功能(方法):设置响应消息

    • 设置响应行

      1. 格式:HTTP/1.1 200 0k

        返回值方法名功能
        voidsetStatus(int sc)设置状态码
    • 设置响应头

      返回值方法名功能
      voidsetHeader(String name,String value)设置响应头
    • 设置响应体

      • 步骤

        1. 获取输出流

          返回值方法名功能
          PrintWritergetWriter()获取字符输出流
          ServletOutputStreamgetOutputStream()获取字节输出流
        2. 使用输出流,将数据输出到客户端浏览器

  2. 案例:

    /**
     * 重定向
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    	response.setStatus(302);
    	response.setHeader("location","/ServletDemo1");
     //重定向专属方法
     String contextPath = request.getContextPath();
     response.sendRedirect(contextPath+"/ServletDemo1");
    }
    /*
    forward 和 redirect 的区别
    ·转发特点:forward
    1. 浏览器地址栏路径不发生变化
    2. 只能转发到当前服务器内部资源中
    3. 转发只用到一次请求,可以使用request对象来共享数据
    ·重定向特点:redirect
    1. 地址栏发生变化
    2. 重定向可以访问其他站点(服务器)的资源
    3. 重定向是两次请求,不可以使用request对象来共享数据
     */
    /*
     路径的写法
     1. 路径的分类
        a.相对路径:通过绝对路径可以确定唯一资源
        如: ./index.html	不以/开头以.开头路径
        
        规则:找到当前资源与目标资源之间的相对位置关系
        b.绝对路径:通过绝对路径可以确定唯一资源
        如:http://localhost/day/Demo		/day/Demo
        以/开头的路径
        
        规则:判断定义的路径给谁用
        i. 给客户端用:需要加虚拟目录、建议动态获取
        ii.给服务器用:不需要加虚拟目录
     */
    
    /*
     *输出字符到浏览器
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 设置编码
        response.setCharacterEncoding("GBK");
        //2. 服务器要求浏览器的解码规则
    	response.setContentType("text/html Charset=utf-8");
        //3. 获取字符输出流
    	PrintWriter writer = response.getWriter();
        //4. 输出字符
    	writer.write("Demo运行了...");
    }
    
    
    /*
     *验证码
     *本质:
     *目的:防止恶意表单操作
     */
     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
         int w = 100;
         int h = 50;
         //1. 创建图片对象
         BufferedImage bi = new BufferedImage(w,h,BufferedImage.TYPE_3BYTE_BGR);
         //2. 获取画笔对象
         Graphics graphics = bi.getGraphics();
         //3. 设置画笔颜色
         graphics.setColor(Color.pink);
         //4. 填充颜色
         graphics.fillRect(0,0,w,h);
         //5. 画边框
         graphics.setColor(Color.blue);
         graphics.drawRect(0,0,w-1,h-1);
         //6. 设置循环字符
         String str = "ABCDEFGHIJKMLNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
         Random random = new Random();
         for(int i = 1;i<5;i++){
             int index = random.nextInt(str.length());
             char ch = str.charAt(index);
             //7. 画验证码
             graphics.drawString(ch+"",w/5*i,25);
         }
         //8. 画干扰线
         graphics.setColor(Color.GREEN);
         //9. 随机生成坐标点
         for(int i = 0;i<10;i++){
             int x1 = random.nextInt(w);
             int x2 = random.nextInt(w);
             int y1 = random.nextInt(h);
             int y2 = random.nextInt(h);
             graphics.drawLine(x1,y1,x2,y2);
         }
    
         //输出图片
         ImageIO.write(bi,"jpg",response.getOutputStream());
    }
    
    <body>
        <img id="checkCode" src="/ServletDemo2" />
        <a id = "change" href="">看不清楚...</a>
        <script>
            var img = document.getElementById("checkCode");
            img.onclick = function () {
                var date = new Date().getTime();
                img.src = "/ServletDemo2?"+date;
            }
        </script>
    </body>
    

六.ServletContext对象

  1. 概念:代表整个web应用,可以和程序的容器(服务器)来通信

  2. 获取

    • 通过request对象获取
      request.getServletContext();

    • HttpServlet获取
      this.getServletContext()

      protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      	ServletContext servletContext1 = request.getServletContext();
      	System.out.println(servletContext1);
      	ServletContext servletContext2 = this.getServletContext();
      	System.out.println(servletContext2);
      }
      //
      org.apache.catalina.core.ApplicationContextFacade@d762a41
      org.apache.catalina.core.ApplicationContextFacade@d762a41
      
  3. 功能

    • 获取MIME类型

      1. MIME类型:在互联网通信过程中定义的一种文件数据类型

        • 格式: 大类型/小类型 text/html image/ipeg
        • 获取:String getMimeType(String file)
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        	ServletContext context = request.getServletContext();
        	String fileName = "aaa.html";
        	String mimeType = context.getMimeType(fileName);
        	System.out.println(mimeType);
        }
        //
        text/html
        
    • 域对象:共享数据

      返回值方法功能
      voidsetAttribute(String name,Objet obj)存储数据
      ObjectgetAttitude(String name)通过键获取值
      voidremoveAttribute(String name)通过键移除键值对
      • ServletContext对象范围:所有用户所有请求的数据
    • 获取文件的真实(服务器)路径

      1. 方法:String getRealPath(String path)

        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        	ServletContext context = request.getServletContext();
        	String realPath = context.getRealPath("/b.txt");//web目录下的资源访问
        	File file = new File(realPath);
        	System.out.println(file);
           String c = context.getRealPath("/WEB-INF/c.txt");//WEB-INF目录下的资源访问
        	File file = new File(c);
        	System.out.println(file);
        	String a = context.getRealPath("/WEB-INF/classes/a.txt");//src目录下的资源访问
        	File file = new File(a);
        	System.out.println(file);
        }
        
        //D:\Test\utu\out\artifacts\utu_war_exploded\b.txt
        //D:\Test\utu\out\artifacts\utu_war_exploded\WEB-INF\c.txt
        
  4. 下载案例

    <body>
        <a href="/ServletDemo7?fileName=树.png">下载</a>
        <a href="/ServletDemo7?fileName=二比小姐姐.mp4">下载</a>
    </body>
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    	//获取请求的文件名称
    	String name = request.getParameter("fileName");
    	ServletContext context = this.getServletContext();
    	//获取文件路径
    	String realPath = context.getRealPath("/img/"+name);
    	//设置编码
    	String mimeType = context.getMimeType(name);
    	response.setHeader("Content-Type",mimeType);
    	//解决中文文件名问题
    	//获取浏览器信息
    	String header = request.getHeader("User-Agent");
    	String fileName = DownUitl.getFileName(header, name);
    
    	//设置下载形式
    	response.setHeader("Content-disposition","attachment;filename="+fileName);
    	//关联字节流
    	FileInputStream fis = new FileInputStream(realPath);
    	ServletOutputStream ops = response.getOutputStream();
    	byte[] bytes = new byte[1024 * 8];
    	int len = 0;
    	while ((len = fis.read(bytes))!=-1){
    		ops.write(bytes,0,len);
    	}
    	fis.close();
    	ops.close();
    }
    
    public class DownUitl {
        public static String getFileName(String agent,String filename) throws UnsupportedEncodingException {
            if(agent.contains("MSIE")){
                //IE浏览器
                filename = URLEncoder.encode(filename, "utf-8");
                filename = filename.replace("+"," ");
            }else if(agent.contains("Firefox")){
                //火狐
                BASE64Encoder base64Encoder = new BASE64Encoder();
                filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8"))+ "?=";
            }else {
                //其他
                filename = URLEncoder.encode(filename, "utf-8");
            }
            return filename;
        }
    }
    
    

七.会话技术

  1. 会话的概念
    一次会话中包含多次请求和响应
    一次会话:浏览器第一次给服务器资源,发送请求,会话建立,直到一方断开为止
    • 功能:在一次会话范围内的多次请求间,共享数据
    • 方式:
      1. 客户端会话技术:Cookie
      2. 服务器端会话技术Session
①.Cookie
  1. 概念
    客户端会话技术:将数据保存在客户端

  2. 快速入门

    • 使用步骤

      1. 创建Cookie对象,绑定数据
        • new Cookie(String name,String value)
      2. 发送Cookie对象
        • response.addCookie(Cookie cookie)
      3. 获取Cookie,拿到数据
        • Cookie[] request.getCookies()
      protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      	//1. 创建Cookie对象
      	Cookie cookie = new Cookie("name","zhangsan");
      	//2. 发送Cookie对象
      	response.addCookie(cookie);
      }
      
      protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      	//获取Cookie对象
      	Cookie[] cookies = request.getCookies();
      	if(cookies != null){
      		for (Cookie cookie : cookies) {
      			String name = cookie.getName();
      			String value = cookie.getValue();
      			System.out.println(name+"---"+value);
      		}
      	}
      }
      name---zhangsan
      
  3. 原理

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gpBJ3xQU-1603158978891)(C:\Users\谜语菌\Documents\img\cookie.jpg)]
    基于响应头set-cookie和请求头cookie实现

  4. cookie细节

    1. 一次可不可以发送多个cookie?

      • 可以
      • 可以创建多个Cookie对象,使用response调用多次addCookie方法发送cookie即可
    2. cookie在浏览器中保存多长时间?

      • 默认情况下,当浏览器关闭后Cookie信息销毁

      • 持久化存储:

        setMaxAge(int Seconds)
        1. 正数:将Cookie数据写到硬盘文件中,持久化存储。cookie存活时间
        2. 负数:默认值
        3.:删除cookie信息
        
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        	//1. 创建Cookie对象
        	Cookie cookie = new Cookie("name","zhangsan");
        	cookie.setMaxAge(30);
        	//2. 发送Cookie对象
        	response.addCookie(cookie);
        }
        
    3. cookie能不能存中文?

    在tomcat8 之前 cookie中不能直接存储中文
    需要将中文数据转码---一般采用URL编码(%E3)
    在tomcat8 之后 cookie中可以直接存储中文
    
    1. cookie共享问题?
    假设在一个tomcat服务器中,部署了多个web项目,在这些项目中Cookie能否共享?
    ·默认情况下不可共享
    ·setPath(String path):设置cookie的获取范围。默认情况下,设置当前的虚拟目录
    如果可以共享,则可以将path设置为"/"
    
    不同的tomcat服务器间cookie的共享问题
    ·setDomain(String path):如果设置一级域名相同,那么多个服务器之间cookie可以共享
    setDomain(".baidu.com"),那么tieba.baidu.com 和 news.baidu.com中的Cookie可以共享
    
  5. Cookie的特点和作用

    1. cookie存储数据在客户端浏览器(安全性低)
    2. 浏览器对于单个cookie 的大小有限制(4kb),以及 对同一个域名下的总cookie数量(20)也有限制
    • 作用
    cookie一般用于存储少量的不太敏感的数据
    在不登录的情况下,完成服务器对客户端的身份识别
    
  6. 案例:记住上一次访问时间

    /**
     *需求
     *1. 访问一个Servlet,如果是第一次访问,则提示:您好欢迎您首次访问
     *2. 如果不是第一次访问,则提示:欢迎回来,您上次访问时间为:xxx
    */
    @WebServlet("/cookieDemo2")
    public class CookieDemo2 extends HttpServlet {
        boolean b = false;
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            response.setCharacterEncoding("GBK");
            response.setContentType("text/html utf-8");
            //获取全部的Cookie对象
            Cookie[] cookies = request.getCookies();
    
            if(cookies == null ||b == false){
                //第一次访问
                //获取当前时间
                Date date = new Date();
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
                String date_v = sdf.format(date);
                //设置URL编码
                date_v = URLEncoder.encode(date_v, "utf-8");
                //创建Cookie
                Cookie cookie = new Cookie("Time",date_v);
                //设置存活时间
                cookie.setMaxAge(60*60*24);
                //发送
                response.addCookie(cookie);
                //响应数据
                response.getWriter().write("首次访问");
                System.out.println("嘿嘿");
            }
            if(cookies != null && cookies.length > 0){
                //遍历Cookies
                for(Cookie cookie:cookies){
                    //获取cookie名称
                    String name = cookie.getName();
                    if("Time".equals(name)){
                        b = true;
                        //非第一次访问
                        //设置时间
                        Date date = new Date();
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
                        String date_v = sdf.format(date);
                        //URL编码
                        date_v = URLEncoder.encode(date_v,"utf-8");
                        cookie.setValue(date_v);
                        cookie.setMaxAge(60*60*24);
                        response.addCookie(cookie);
                        //URL解码
                        String value = cookie.getValue();
                        value = URLDecoder.decode(value, "utf-8");
                        response.getWriter().write("您好上次访问时间为:"+value);
                    }
                }
            }
        }
    
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request, response);
        }
    }
    
    
②.Session
  1. 概念:服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端对象中。HttpSession

  2. 快速入门

    • 获取HttSession对象
      HttpSession session = request.getSession();

    • 使用HttSession对象

      返回值类型方法功能
      ObjectgetAttribute(String name)获取数据
      voidsetAttribute(String name,Object value)存储数据
      voidtemoveAttribute(String name)删除数据
      @WebServlet("/SessionDemo")
      public class SessionDemo extends HttpServlet {
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              //1. 获取Session对象
              HttpSession session = request.getSession();
              session.setAttribute("msg","Holl,Session");
          }S
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              this.doPost(request, response);
          }
      }
      @WebServlet("/SessionDemo1")
      public class SessionDemo1 extends HttpServlet {
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              //获取Session
              HttpSession session = request.getSession();
              //获取数据
              Object msg = session.getAttribute("msg");
              response.getWriter().write(msg.toString());
          }
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              this.doPost(request, response);
          }
      }
      
  3. Session原理

    • Session的实现依赖于Cookie
    • Cookie响应头,请求头携带Session的内存ID
  4. 细节

    1. 客户端关闭后,服务器不关闭,两次获取session是否为同一个?
    //默认情况下不是
    /*
     *如果需要相同,则可以创建Cookie,键为JSESSIONID,设置最大存活时间,让Cookie持久化存储
     */
    @WebServlet("/SessionDemo")
    public class SessionDemo extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //1. 获取Session对象
            HttpSession session = request.getSession();
            session.setAttribute("msg","Holl,Session");
        }
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request, response);
        }
    }
    @WebServlet("/SessionDemo2")
    public class SessionDemo2 extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //获取Session
            HttpSession session = request.getSession();
            //获取cookie对象
            Cookie cookie = new Cookie("JSESSIONID",session.getId());
            cookie.setMaxAge(60*60);
            response.addCookie(cookie);
            response.getWriter().write(session.toString());
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request, response);
        }
    }
    
    1. 客户端不关闭,服务器关闭后,两次获取的Session是同一个吗?
    不是同一个,但是要确保数据不丢失
    a.session的钝化:
       在服务器正常关闭之前,将session对象序列化到硬盘上
    b.session的活化:
       在服务器启动后,将session文件转化为内存中的session对象即可
    
    1. session什么情况下被销毁
    1. 服务器关闭
    2. session对象调用invalidate()
    3. session默认失效时间 30分钟
       选择性配置修改
       <session-config>
         <session-timeout>60</session-timeout>
       </session-config>
    
  5. session特点

    1. session用于存储一次会话的多次请求的数据,存在服务器
    2. session可以存储任意类型,任意大小的数据
    3. session与cookie的区别
    a. session存储数据在服务器端,cookie在客户端
    b. session没有数据大小限制,cookie有
    c. session数据安全,cookie相对不安全
    
  6. 案例:验证码

八.JSP

①JSP入门学习
  1. 概念
    Java Server Pages:Java服务器端页面
    可以理解为:一个特殊的页面,其中既可以定义HTML标签,也可以写Java代码
    用于简化书写

  2. 原理

    JSP本质上是一个Servlet
    a. 服务器解析请求消息,找是否存在index.jsp资源
    b. 找到后,将index.jsp转换为.java文件
    c. 编译.Java文件,生成.class字节码文件
    d.由字节码文件提供访问
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-znQR1BXz-1603158978896)(C:\Users\谜语菌\Documents\img\jsp.jpg)]

  3. JSP的脚本:JSP定义Java代码的方式

    • <% 代码 %>:定义的Java代码,在service方法中
    • <%! 代码 %>:定义的Java代码,类的成员位置
    • <%= 代码 %>:定义的Java代码,会输出到页面上
  4. JSP内置对象

    • 在JSP中可以直接使用的对象
    • request
    • response
    • out:字符输出流对象,可以将数据输出到页面上
      • response.getWrier()和out的区别
        • 在tomcat服务器真正给客户端做出响应之前,会先找到response缓冲区数据,再找out缓冲区数据
        • response.getWriter()数据输出永远在out.write()之前

    练习

    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    
    <%!//时间参数
       String lastTime = null; %>
        <%
            //获取全部的Cookie对象
            Cookie[] cookies = request.getCookies();
            //遍历Cookies
            for(int i = 0;cookies != null&&i<cookies.length;i++){
                if("lastTime".equals(cookies[i])){
                    lastTime = cookies[i].getValue();
                    break;
                }
            }
            if(lastTime == null){
                out.write("欢迎首次访问");
            }else {
                //URL解码
                lastTime = URLDecoder.decode(lastTime,"utf-8");
                out.write("欢迎回家,您上次访问时间为:"+lastTime);
            }
            //记录访问时间
            Date date = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
            lastTime = sdf.format(date);
            //URL编码
            lastTime = URLEncoder.encode(lastTime, "utf-8");
            //创建Cookie对象
            Cookie cookie = new Cookie("lastTime",lastTime);
            //发送Cookie
            response.addCookie(cookie);
        %>
    </body>
    </html>
    
②.指令
  1. 作用:配置JSP页面,导入资源文件

  2. 格式

    <%@ 指令名称 属性名1=属性值1 属性名2=属性值2 ... %>
    
  3. 分类

    a. page    :配置JSP页面
       i. contentTyoe:等同于response.setContentType()
          1. 设置响应体的mime类型以及字符集
          2. 设置当前jsp页面的编码(只能是高级的IDE才能生效,如果使用低级工具,则需要设置pageEncoding属性设置当前页面字符集)
       ii. import:导包
       iii. errorPage:当前页面发生异常后,会自动跳转到指定的错误页面
       iiii. isErrorPage:标识当前页面是否是错误页面
          1. ture:是,可以使用内置对象exception
          2. false:否,默认值,不可以使用内置对象exceotion
    b. include :页面包含的。导入页面的资源文件
       i. <%@include file="top.jsp"%>
    c. taglib  :导入资源
       i. <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
       prefix:前缀,自定义的
    
③.注释
  1. HTML注释:只能注释html

  2. JSP注释:注释所有
    <%-- --%>

④.内置对象

在JSP页面中不需要创建就可以直接使用的对象,有九个

变量名真实类型作用
pageContextPageContext当前页面共享数据,还可以获取其他八个对象
requstHttpServletRequest一次请求访问的多个资源(转发)
sessionHttpSession一次会话的多个请求间
applicationServletContext所有用户间共享数据
responseHttpServletResponse响应对象
pageObject当前页面的对象(this)
outJspWriter输出对象,数据输出到页面上
configServletConfigServlet的配置对象
exceptionThrowable异常对象

九.EL和JSTL

①.EL表达式
Ⅰ.概述
  1. 概念:Expression Language 表达式
  2. 作用:替换和简化jsp页面中的java代码的编写
  3. 语法:${表达式}
  4. 注意:
    • jsp默认支持默认表达式,如果忽略el表达式
      • 设置jsp中page指令中:isELIgnored=“true” 忽略当前jsp页面中所有的el表达式
      • ${表达式}:忽略当前这个el表达式
  5. 使用
    1. 运算
    2. 获取值
Ⅱ.EL的使用
  • 运算
    i. 运算符

      1. 算数运算符: + - * /(div) %(mod)
      2. 比较运算符: > < >= <= == !=
      3. 逻辑运算符: &&(and) ||(or) !(not)
      4. 空运算符: empty
         - 功能:用于判断字符串、集合、数组对象是否为null并且长度是否为0
         - ${empty list}
         - ${not empty list}
    
  • 获取值

    1. el表达式只能从域对象中获取值

    2. 语法

      1. ${域名称.键名}:从指定域中获取指定键的值
      pageScope         --> pageContext
      requstScope       -->request
      sessionScope      -->session
      applicationScope  -->application(ServletContext)
      //举例
      //存储键值对
      request.setAttribute("name","张三");
      request.getRequestDispatcher("/el.jsp").forward(request,response);
      //获取值
      ${requestScope.name}
      
      1. ${键名}:表示依次从最小到大的域中查找该键对应的值,直到找到位置

      2. 获取对象.List集合.Map集合的值

        • 对象
        ${域名.键名.属性名}  |  本质上去调用对象的方法
        通过对象的属性来获取
        i. setter或getter方法,去掉set或get,在剩余部分,首字母变为小写
        ii. setName ---> Name ---> name
        
        • List集合
        ${域名.键名[索引]}
        
        • Map集合
        ${域名.键名.key名称}
        ${域名.键名["key名称"]}
        
Ⅲ.隐式对象

el表达式中有11个隐式对象

  1. pageConntext
获取jsp其他八个对象
${pageContext.qequest.contextPath}:动态获取虚拟目录
②.JSTL
  1. 概念:Javaserver Pages Tag Library JSP标准标签库

    是由Apache组织提供的开源的免费的jsp标签 <标签>

  2. 作用:用于简化和替换jsp页面上的Java代码

  3. 使用步骤

    a. 导入jstl相关jar包
    b. 引入标签库:taglib指令 <%@ taglib %>
    c. 使用标签
    
  4. 常用的JSTL标签

    • if :相当于if语句
    a. 属性
       test 必须属性,接收boolean表达式
          i. 如果表达式为true,则显示if标签体的内容,false不显示
          ii. 一般情况下,test属性值会结合el表达式一起使用
          iii. if标签没有else情况,想要else情况,重新定义一个if标签
    <c:if test="true">
    <h1>你好</h1>
    </c:if>
    
    • choose :相当于switch语句
    <%-- 
        完成数字编号对应的星期几
        1. 域中存储数字
        2. 使用choose标签               相当于switch声明
        3. 使用when标签做数字判断         相当于case
        4. otherwise标签做其他情况的声明  相当于default
    --%>
    
    <% 
        request.setAttribute("numder",44);
    %>
    <c:choose>
        <c:when test="${requestScope.numder == 1}"><h1>星期一</h1></c:when>
        <c:when test="${requestScope.numder == 2}"><h1>星期二</h1></c:when>
        <c:when test="${requestScope.numder == 3}"><h1>星期三</h1></c:when>
        <c:when test="${requestScope.numder == 4}"><h1>星期四</h1></c:when>
        <c:when test="${requestScope.numder == 5}"><h1>星期五</h1></c:when>
        <c:when test="${requestScope.numder == 6}"><h1>星期六</h1></c:when>
        <c:when test="${requestScope.numder == 7}"><h1>星期日</h1></c:when>
    
        <c:otherwise>数字输入错误</c:otherwise>
    </c:choose>
    
    • foreach :相当于for语句
    <%-- 
       foreach:相当于Java代码的for语句
       1. 完成重复操作
       for(int i = 0;i<10;i++){
       
       }
       属性:
          begin:开始值
          end:结束值
          var:临时变量
          step:步长
          varStatus:循环状态对象
             i. index:容器中元素的索引,从零开始
             ii. count:循环次数,从1开始
       2. 遍历容器
       List<User> list;
       for(User user:list){
       
       }
       属性:
          items:容器对象
          var:容器中元素的临时变量
          varStatus:循环状态对象
             i. index:容器中元素的索引,从零开始
             ii. count:循环次数,从1开始
    --%>
    <%
       List<String> list = new ArrayList<>();
       list.add("zhansan");
       list.add("lisi");
       list.add("wangwu");
       request.setAttribute("list",list);
    %>
    <c:forEach items="${list}" var="name">
       ${name}<br>
    </c:forEach>
    
    <c:forEach begin="1" end="10" var="i" step="1">
       ${i}<br>
    </c:forEach>
    
  5. 练习

    <body>
        <%
            Date date = new Date();
            ArrayList<User> list = new ArrayList<>();
            list.add(new User("张三",17,date));
            list.add(new User("李四",14,date));
            list.add(new User("王五",19,date));
            list.add(new User("赵六",21,date));
            request.setAttribute("list",list);
        %>
    
        <table border="1" width="500">
            <tr>
                <th>编号</th>
                <th>姓名</th>
                <th>年龄</th>
                <th>日期</th>
            </tr>
            <c:forEach items="${requestScope.list}" var="user" varStatus="s">
                <c:if test="${s.count % 2 == 0}">
                    <tr bgcolor="#98fb98">
                        <td>${s.count}</td>
                        <td>${user.name}</td>
                        <td>${user.age}</td>
                        <td>${user.birstr}</td>
                    </tr>
                </c:if>
                <c:if test="${s.count % 2 != 0}">
                    <tr bgcolor="#ffc0cb">
                        <td>${s.count}</td>
                        <td>${user.name}</td>
                        <td>${user.age}</td>
                        <td>${user.birstr}</td>
                    </tr>
                </c:if>
            </c:forEach>
        </table>
    </body>
    

十. Servlet高级

①.Filter:过滤器
Ⅰ.过滤器概念

当访问服务器资源时,过滤器可以将请求拦截下来,完成一些特殊功能

  • 过滤器的作用
    一般用于完成通用的操作,如登录验证,统一编码设置,敏感字符过滤
Ⅱ.过滤器的快速入门
  1. 步骤

    • 定义一个类,实现接口Filter
    • 复写方法
    • 配置拦截路径
      1. web.xml
      2. 注解
    @WebFilter("/index.jsp")
    public class FilterDemo implements Filter{
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
    
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            System.out.println("doFilter...");
            //放行
            filterChain.doFilter(servletRequest,servletResponse);
        }
    
        @Override
        public void destroy() {
    
        }
    }
    
Ⅱ.过滤器的细节
  1. web.xml配置

    <filter>
    	<filter-name>FiltDemo</filter-name>
    	<filter-class>com.wed.Filter.FilterDemo</filter-class>
    </filter>
    <filter-mapping>
    	<filter-name>FiltDemo</filter-name>
    	<!-- 拦截路径 -->
    	<url-pattern>/index.jsp</url-pattern>
    </filter-mapping>
    
  2. 过滤器执行流程

    1. 执行过滤器
    2. 执行放行后的资源
    3. 回来执行放行后的代码
    @WebFilter("/*")
    public class FilterDemo1 implements Filter {
        public void destroy() {
        }
    
        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
            System.out.println("FilterDemo1过去了...");
            //放行
            chain.doFilter(req, resp);
            System.out.println("FilterDemo1回来了...");
        }
    
        public void init(FilterConfig config) throws ServletException {
    
        }
    }
    /*
    	FilterDemo1过去了...
    	index.jsp
    	FilterDemo1回来了...
    */
    
  3. 过滤器生命周期方法

    @WebFilter("/*")
    public class FilterDemo2 implements Filter {
        //服务器正常关闭后,销毁Filter对象,执行destroy方法,一般用于释放资源
        public void destroy() {
            System.out.println("destroy...");
        }
        //每一次请求拦截资源时执行,
        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
            System.out.println("doFilter...");
            chain.doFilter(req, resp);
        }
        //服务器启动后会创建Filter对象,然后调用init方法,一般用于加载资源
        public void init(FilterConfig config) throws ServletException {
            System.out.println("init");
        }
    }
    
  4. 过滤器配置详解

    • 拦截路径配置

      a. 具体资源路径  /index.jsp  只有访问index.jsp资源时,过滤器才会执行
      b. 拦截目录     /user/*      访问/user下所有资源时,过滤器都会执行
      c. 后缀名拦截:  *.jsp        访问所有后缀名为jsp资源时,过滤器都会被执行
      d. 拦截所有资源 /*            访问所有资源时过滤器都会被执行
      
    • 拦截方式配置:资源被访问的方式

      1. 注解配置
         * 设置dispatcherTypes属性
            a. REQUEST:默认值。浏览器直接请求资源
            b. FORWARD:转发访问资源
            c. INCLUDE:包含访问资源
            d. ERROR  :错误跳转
            e. ASYNC  :异步访问资源
      2. web.xml配置
         * 设置<dispatcher></dispatcher>标签即可
      
  5. 过滤器链(配置多个过滤器)

    执行顺序:如果有两个过滤器:过滤器1 过滤器2
       过滤器1
       过滤器2
       资源执行
       过滤器2
       过滤器1
       
    过滤器先后顺序
       a. 注解配置:按照类名的字符串比较规则,值小的先执行
          如:AFilter和BFilter,A先执行
             Demo6 和 Demo18 , 18先执行
       b.web.xml配置:<filter-mpping>上面的先执行
    
    

十一.MVC开发模式和三层架构

①.MVC开发模式
  1. JSP演变历史

    早期只有servlet,只能使用response输出标签数据,非常麻烦
    后来出现jsp,简化了servlet的开发,如果过度使用jsp,在jsp中即写大量的java代码,又写html标签,造成难于维护,难于分工协作
    再后来,java的web开发,倡圣mVc开发模式,使得程序的设计更加合理性
    
  2. MVC:
    a. Model,模型。javaBean

    • 完成具体的业务操作,如:查询数据库,封装对象

    b. View,视图。JSP

    • 展示数据

    c. Controller,控制器。Servlet

    • 获取用户的输入

    • 调用模型

    • 将数据交给视图进行展示

  3. 优点

    1. 耦合性低,方便维护,有利于分工合作
    2. 重用性低
  4. 缺点

    1. 使的项目结构变得复杂,对开发人员要求高
②.三层架构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6yYimHPP-1603158978901)(C:\Users\谜语菌\Documents\img\三层架构.jpg)]

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值