javaweb

xml

xml介绍

xml是可扩展的标记性语言

xml的主要作用:

  1. 用来保存数据,而且这些数据具有自我描述性
  2. 它还可以作为项目或者模块的配置文件
  3. 还可以作为网络传输数据的格式(现在主要是JSON)

xml元素是指从开始标签到结束标签的部分 元素可以包含其他元素、文本或者两者的混合物 元素也可以拥有属性

xml属性可以提供元素的额外信息

早期解析技术:DOM和Sax

语法

<?xml version="1.0" encoding="utf-8" ?>
<!--以上内容就是xml声明 version:xml版本 encoding:xml本身文件编码-->
<books> <!--books表示多个图书信息-->
    <book sn="SN1231231231"><!--book表示一个图书信息 sn属性表示图书序列号-->
        <name>超能立方</name><!--name表示书名-->
        <author>水落声声</author><!--author表示作者-->
        <price>10</price><!--price表示价格-->
    </book>
    <book sn="SN2323231123"><!--book表示一个图书信息 sn属性表示图书序列号-->
        <name>照明商店</name><!--name表示书名-->
        <author>姜草</author><!--author表示作者-->
        <price>99</price><!--price表示价格-->
    </book>
</books>
  1. 元素要闭合
  2. 大小写敏感
  3. 必须正确嵌套
  4. xml文档必须有根元素
  5. 属性值必须加引号
  6. 特殊字符

dom4j解析技术

  1. 创建Book类

    public class Book {
        private String sn;
        private String name;
        private String author;
        private int price;
    
        public Book() {
        }
    
        public Book(String sn, String name, String author, int price) {
            this.sn = sn;
            this.name = name;
            this.author = author;
            this.price = price;
        }
    
        @Override
        public String toString() {
            return "Book{" +
                    "sn='" + sn + '\'' +
                    ", name='" + name + '\'' +
                    ", author='" + author + '\'' +
                    ", price=" + price +
                    '}';
        }
    
        public String getSn() {
            return sn;
        }
    
        public void setSn(String sn) {
            this.sn = sn;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getAuthor() {
            return author;
        }
    
        public void setAuthor(String author) {
            this.author = author;
        }
    
        public int getPrice() {
            return price;
        }
    
        public void setPrice(int price) {
            this.price = price;
        }
    }
    
  2. 采用dom4j解析xml

    public class Dom4jTest {
    
        @Test
        public void test1() throws DocumentException {
            //创建一个SAXReader对象 去读取xml配置文件 生成Document对象
            SAXReader saxReader = new SAXReader();
            Document read = saxReader.read("src/com/chenxiii/javaweb/xmlFile/xml/books.xml");
            System.out.println(read);
    
            //读取Books.xml生成Book类
            //通过Document对象获取根元素
            Element rootElement = read.getRootElement();
            System.out.println(rootElement);
            //通过根元素获取book标签对象 element()和elements()都是通过标签名查找子元素
            List<Element> books = rootElement.elements("book");
            //遍历 处理每个book标签转换为Book类
            for (Element book : books) {
                System.out.println(book.asXML());
                Element nameEle = book.element("name");
                String name = nameEle.getText(); //getText()获取标签中的文本内容
                String price = book.elementText("price"); //elementText()获得指定标签名的文本内容
                String author = book.elementText("author");
    
                String sn = book.attributeValue("sn"); //获取属性
    
                System.out.println(new Book(sn, name, author, Integer.parseInt(price)));
            }
        }
    }
    

JavaWeb

所有通过Java语言编写可以通过浏览器访问的程序称为JavaWeb

JavaWeb是基于请求和响应开发的

工程目录:

image-20211015191641137

Servlet

  1. Servlet是Java EE规范之一 规范就是接口
  2. Servlet是JavaWeb三大组件之一 三大组件分别是:Servlet程序 Filter过滤器 Listener监听器
  3. Servlet是运行在服务器上的一个java小程序 它可以接受客户端发送过来的请求 并响应数据给客户端

第一个Servlet程序

  1. 实现Servlet接口 重写方法

    public class HelloServlet implements Servlet {
        @Override
        public void init(ServletConfig servletConfig) throws ServletException {
    
        }
    
        @Override
        public ServletConfig getServletConfig() {
            return null;
        }
    
        // 是专门用来处理请求和响应
        @Override
        public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
            System.out.println("Hello Servlet");
        }
    
        @Override
        public String getServletInfo() {
            return null;
        }
    
        @Override
        public void destroy() {
    
        }
    }
    
  2. 配置web.xml文件

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
    
        <!--servlet标签给Tomcat配置Servlet程序-->
        <servlet>
            <!--servlet-name标签 Servlet程序起一个别名 一般是类名-->
            <servlet-name>HelloServlet</servlet-name>
            <!--servlet-class 是Servlet程序的全类名-->
            <servlet-class>com.chenxiii.servlet.HelloServlet</servlet-class>
        </servlet>
    
        <!--servlet-mapping标签给servlet程序配置访问地址-->
        <servlet-mapping>
            <!--servlet-name标签是告诉服务器当前配置的地址给哪个Servlet程序使用-->
            <servlet-name>HelloServlet</servlet-name>
            <!--url-pattern配置访问地址
                /           在服务器解析的时候表示地址为http://ip:port/工程路径
                /hello      表示地址为http://ip:port/工程路径/hello
            -->
            <url-pattern>/hello</url-pattern>
        </servlet-mapping>
    
    </web-app>
    
  3. 常见错误

    • invalid url-partten xxx :url-pattern中没有以斜杠开头
    • servletservlet-name 一定是要和 servlet-mapping 中的servlet-name一致

Servlet生命周期

  1. 执行Servlet构造器方法 在第一次访问创建Servlet程序的时候调用
  2. 执行init初始化方法 在第一次访问创建Servlet程序的时候调用
  3. 执行service方法 每次访问都调用
  4. 执行destroy销毁方法 在web工程停止的时候调用
public class HelloServlet implements Servlet {

    public HelloServlet() {
        System.out.println("Constructor");
    }

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("init");
    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    // 是专门用来处理请求和响应
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("Hello Servlet");
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {
        System.out.println("destroy");
    }
}

获取请求方式

    // 是专门用来处理请求和响应
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("Hello Servlet");
        // 类型转换 HttpServletRequest是ServletRequest的实现类 有getMethod()方法
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        //获取请求方式
        String method = httpServletRequest.getMethod();
        System.out.println(method);
        if ("GET".equals(method)) {
            doGet();
        } else {
            doPost();
        }
    }
    
    public void doGet() {
        System.out.println("get请求");
    }

    public void doPost() {
        System.out.println("post请求");
    }

HttpServlet

实际开发中很少去实现Servlet接口 一般都是继承HttpServlet类的方式去实现Servlet

public class HelloHttp extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // get请求时调用
        System.out.println("HelloHttp doGet");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // post请求调用
        System.out.println("HelloHttp doPost");
    }
}

Servlet继承体系

image-20211015210358251

ServletConfig类

Servlet程序的配置信息类

  1. 可以获取Servlet程序的别名 servlet-name的值
  2. 获取初始化参数 init-param
  3. 获取ServletContext对象

Servlet程序和ServletConfig对象都是由Tomcat负责 Servlet程序默认是第一次访问的时候创建 ServletConfig是每个Servlet程序创建时 就创建一个对应的ServletConfig对象

实现Servlet接口的类

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("init");
        //可以获取Servlet程序的别名 servlet-name的值
        System.out.println("别名: " + servletConfig.getServletName());
        //获取初始化参数 init-param
        System.out.println("初始化参数username的值: " + servletConfig.getInitParameter("username"));
        System.out.println("初始化参数password的值: " + servletConfig.getInitParameter("password"));
        //获取ServletContext对象
        System.out.println(servletConfig.getServletContext());
    }

继承HttpServlet的类

    @Override
    public void init(ServletConfig config) throws ServletException {
        /**
         *     public void init(ServletConfig config) throws ServletException {
         *         this.config = config;
         *         this.init();
         *     }
         *     GenericServlet类中的init方法 如果重写方法没有调用父类的init()方法 则无法获取ServletConfig
         */
        super.init(config);// 重写父类的init(ServletConfig config)
        System.out.println("重写了init方法");
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // get请求时调用
        System.out.println("HelloHttp doGet");

        // 也可以使用ServletConfig对象 但是获取不到别的ServletConfig对象所包含的信息
        ServletConfig servletConfig = getServletConfig();
    }

初始化参数配置在web.xml的servlet标签中

    <!--servlet标签给Tomcat配置Servlet程序-->
    <servlet>
        <!--servlet-name标签 Servlet程序起一个别名 一般是类名-->
        <servlet-name>HelloServlet</servlet-name>
        <!--servlet-class 是Servlet程序的全类名-->
        <servlet-class>com.chenxiii.servlet.HelloServlet</servlet-class>
        <!--init-param是初始化参数-->
        <init-param>
            <!--参数名-->
            <param-name>username</param-name>
            <!--参数值-->
            <param-value>root</param-value>
        </init-param>
        <init-param>
            <!--参数名-->
            <param-name>password</param-name>
            <!--参数值-->
            <param-value>123456</param-value>
        </init-param>
    </servlet>

ServletContext类

ServletContext是一个接口 表示Servlet上下文对象

一个web工程 只有一个ServletContext对象实例

ServletContext是一个域对象(域对象是可以像Map一样存取数据的对象 这里的域是存取数据的操作范围)

  1. 获取web.xml中配置的上下文参数context-param
  2. 获取当前的工作路径 格式:/工程路径/…
  3. 获取工程部署后在服务器磁盘上的绝对路径
  4. 像Map一样存取数据
  5. ServletContext对象在web工程部署启动的时候创建 在web工程停止的时候销毁
//	tomcat/context1   
@Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获取ServletContext对象
        ServletContext context = getServletContext();

        System.out.println("保存之前context中key1的值=" + context.getAttribute("key1")); //null
        context.setAttribute("key1", "value1");
        System.out.println("保存之后context中key1的值=" + context.getAttribute("key1")); //value1

    }
//	tomcat/context2    
@Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//        1. 获取web.xml中配置的上下文参数context-param
        ServletContext context = getServletConfig().getServletContext();
        String username = context.getInitParameter("username");
        System.out.println("username=" + username);
//        2. 获取当前的工作路径 格式:/工程路径/...
        System.out.println("当前工程路径=" + context.getContextPath());
//        3. 获取工程部署后在服务器磁盘上的绝对路径
        // 斜杠被解析为 http://ip:port/工程路径
        System.out.println("工程部署的路径=" + context.getRealPath("/"));
//        4. 像Map一样存取数据
        //先访问tomcat/context1后访问tomcat/context2则是value1
        //直接访问tomcat/context2则是null
        System.out.println("context中key1的值=" + context.getAttribute("key1")); //value1
    }

Http协议

协议是值双方或多方相互约定好的规则

HTTP协议是指客户端和服务器之间通信时 发送的数据需要遵守的规则

HTTP传输的数据称为报文

请求的HTTP协议格式

请求分为GET请求和POST请求

GET请求:
  1. 请求行
    1. 请求的方式 GET
    2. 请求的资源路径[+?+请求参数]
    3. 请求地协议的版本号 HTTP/1.1
  2. 请求头
    1. key:value 不同的键值对表示不同的含义

image-20211015220503709

POST请求
  1. 请求行

    1. 请求的方式 POST
    2. 请求的资源路径[+?+请求参数]
    3. 请求地协议的版本号 HTTP/1.1
  2. 请求头

    1. key:value 不同的键值对表示不同的含义

      空行

  3. 请求体 发送给服务器的数据

image-20211015221106854

响应的HTTP协议格式

  1. 响应行

    1. 响应的协议和版本号
    2. 响应状态码
    3. 响应状态描述符
  2. 响应头

    1. key:value 不同的键值对表示不同的含义

      空行

  3. 响应体 回传给客户端的数据

image-20211017134300122

常用响应码

  1. 200 请求成功
  2. 302 请求重定向
  3. 404 服务器已经收到但是数据不存在(地址错误)
  4. 500 服务器已经收到请求但是服务器内部错误

HttpServletRequest

只要每次有请求进入Tomcat服务器 Tomcat服务器就会把请求过来的HTTP协议信息解析好封装到Request对象中 然后传递到service方法(doGet和diPost) 我们可以通过HttpServletRequest对象 获取到所有请求地信息

常用API

        // 获取请求的资源路径
        System.out.println(request.getRequestURI());
        // 获取请求的统一资源定位符 绝对路径
        System.out.println(request.getRequestURL());
        // 获取客户端的ip
        System.out.println(request.getRemoteHost());
        // 获取请求头    如User-Agent
        System.out.println(request.getHeader("User-Agent"));
        // 获取请求方式
        System.out.println(request.getMethod());

获取参数

        // 参数为表单中的name属性
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        // 获取多个值
        String[] hobbies = request.getParameterValues("hobby");
        System.out.println(username);
        System.out.println(password);
        System.out.println(Arrays.asList(hobbies));
<form action="http://localhost:8080/tomcat/para" method="get">
	用户名:<input type="text" name="username">
	密码:<input type="password" name="password">
	兴趣爱好: <input type="checkbox" name="hobby" value="Java">Java
	<input type="checkbox" name="hobby" value="Spring">Spring
	<input type="checkbox" name="hobby" value="Docker">Docker
	<input type="submit">
</form>

POST中文乱码

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 设置请求体的字符集为utf-8 从而解决中文乱码问题
        // 该设置要在所有获取参数之前
        request.setCharacterEncoding("UTF-8");
        // 参数为表单中的name属性
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        // 获取多个值
        String[] hobbies = request.getParameterValues("hobby");
        System.out.println(username);
        System.out.println(password);
        System.out.println(Arrays.asList(hobbies));
    }
<form action="http://localhost:8080/tomcat/para" method="post">
	用户名:<input type="text" name="username">
	密码:<input type="password" name="password">
	兴趣爱好: <input type="checkbox" name="hobby" value="Java">Java
	<input type="checkbox" name="hobby" value="Spring">Spring
	<input type="checkbox" name="hobby" value="Docker">Docker
	<input type="submit">
</form>

请求转发

服务器收到请求后 服务器从一个资源跳转到另一个资源

image-20211017142306657

特点:

  1. 浏览器地址栏没有变化
  2. 他们是一次请求
  3. 他们共享Request域中的数据
  4. 可以转发到WEB-INF目录下 getRequestDispatcher("/WEB-INF/xxx.html") /表示web-app目录
  5. 不可以工程外的资源
//	/servlet1
public class ServletDemo01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取请求参数
        String username = request.getParameter("username");
        System.out.println("servlet1 username=" + username);
        //设置信息
        request.setAttribute("key", "info");
        //转发到servlet2
        //请求转发必须以/开头 /表示地址为http://ip:port/工程名
        RequestDispatcher requestDispatcher = request.getRequestDispatcher("/servlet2");
        requestDispatcher.forward(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }
}
//	/servlet2
public class ServletDemo02 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取请求参数
        String username = request.getParameter("username");
        System.out.println("servlet2 username=" + username);
        //获取信息
        Object key = request.getAttribute("key");
        System.out.println("info=" + key);
        //处理业务
        System.out.println("servlet2 处理业务");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }
}

HttpServletResponse

在每次请求进来 服务器会创建一个HttpServletResponse对象传递给Servlet程序使用 HttpServletRequest表示请求过来的信息 HttpServletResponse表示响应的信息

往客户端回传数据

服务器向浏览器传递字符串

public class ServletResponseDemo01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println(response.getCharacterEncoding());// 默认字符集ISO-8859-1

        //设置服务器字符集
        //response.setCharacterEncoding("UTF-8");
        //通过响应头设置浏览器使用utf-8字符集
        //response.setHeader("Content-Type", "text/html;charset=utf-8");

        // 同时设置服务器和客户端都使用utf-8字符集 还设置了响应头
        // 此方法一定要在获取流对象前使用才生效
        response.setContentType("text/html;charset=utf-8");

        // 给客户端返回字符串
        PrintWriter writer = response.getWriter();
        writer.write("牛逼");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }
}

请求重定向

是指客户端给服务器发送请求 然后服务器告诉客户端 给你一个新地址 去新地址访问

image-20211017154819252

特点:

  1. 浏览器地址栏会发生变化
  2. 两次请求
  3. 不共享Request域中的数据
  4. 不能访问WEB-INF目录
  5. 可以访问工程外的资源
//	/response1
public class ServletResponseDemo02 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("到此一游");
        //设置响应状态码302
        //response.setStatus(302);
        //设置响应头
        //response.setHeader("Location", "http://localhost:8080/tomcat/response3");
        
        
        response.sendRedirect("http://localhost:8080/tomcat/response3");
    }
}
//	/response2
public class ServletResponseDemo03 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.getWriter().write("response3");
    }
}

JSP

java server pages Java的服务器页面

jsp主要作用是代替Servlet程序回传html页面的数据

当我们第一次访问jsp页面时 Tomcat服务器会把jsp页面翻译成一个java源文件 并且对它编译成一个.class字节码程序

page指令

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>

language:表示jsp翻译后是什么语言文件 目前只支持Java

contentType:表示jsp的返回数据类型是什么

pageEncoding:表示当前jsp页面文件本身的字符集

import:跟java源代码一样 用于导入包、类

autoFlush:设置当out输出流缓冲区满了之后 是否自动刷新缓冲区 默认值为true

buffer:设置out缓冲区大小 默认是8KB

errpage:设置当jsp页面运行时出错自动跳转去的页面路径

isErrorPage:设置当前jsp页面是否是错误信息页面 默认是false 如果是true可以获取异常信息

session:设置访问当前jsp页面 是否会创建HttpSession对象 默认是true

extends:设置jsp翻译出来的java类默认继承谁

常用脚本

声明脚本
<%! 声明java代码 %>

可以给jsp翻译出来的java类定义属性和方法甚至是静态代码块、内部类等。

<body>
    <%--声明类的属性--%>
    <%!
        private Integer id;
        private String name;
        private static Map<String, Object> map;
    %>
    <%--声明static静态代码块--%>
    <%!
       static {
           map = new HashMap<String, Object>();
           map.put("key1", "value1");
           map.put("key2", "value2");
           map.put("key3", "value3");
       }
    %>
    <%--声明类方法--%>
    <%!
        public int abc() {
            return 12;
        }
    %>
    <%--声明内部类--%>
    <%!
        public static class A {
            private int id = 3;
        }
    %>
</body>
表达式脚本
<%=表达式%>

作用:在jsp页面上输出数据

    <%--输出整型--%>
    <%=12%>
    <%--输出浮点型--%>
    <%=12.0%>
    <%--输出字符串--%>
    <%="字符串"%>
    <%--输出对象--%>
    <%="字符串也是对象"%>
  1. 所有的表达式脚本都会被翻译带_jspService()方法中
  2. 表达式脚本都会被翻译成out.print()输出到页面上
  3. 由于所有的表达式脚本都会被翻译带_jspService()方法中 所以jspService()中对象都可以直接使用
  4. 表达式脚本不能以分号结束
代码脚本
<% 
    java语句
%>

作用:可以在jsp页面中 编写我们自己需要的功能

<%
    int i = 12;
    if (i == 12) {
        System.out.println("牛逼");
    }

    for (int j = 0; j < 5; j++) {
        System.out.println("很牛逼");
    }

    // 翻译后java文件中_jspService方法内的代码都可以写
    String username = request.getParameter("username");
    System.out.println("username=" + username);
%>
  1. 代码脚本翻译后都在_jspService方法中
  2. 由于代码脚本翻译后都在_jspService方法中 所以方法内对象都可以使用
  3. 代码脚本还可以由多个代码脚本块组合完成一个java语句
  4. 代码脚本还可以和表达式脚本一起组合使用 在jsp界面上输出数据
三种注释
<!--html注释-->

html注释会被翻译到java源代码中 在_jspService方法里 以out.write输出到客户端

<%
    // 单行java注释
    /*
        多行java注释
     */
%>

java注释会被翻译到java源代码中

<%--jsp注释--%>

jsp注释可以注释掉jsp页面中所有代码

jsp九大内置对象

jsp中的内置对象是指tomcat在翻译jsp页面成为Servlet源代码后 内部提供的九大对象 叫做内置对象

image-20211018104124720

jsp四大域对象

  1. pageContext (PageContextImpl类) 当前jsp页面范围内有效
  2. request (HttpServletRequest类) 一次请求内有效
  3. session (HttpSession类) 一个会话范围内有效(打开浏览器访问服务器,直到关闭浏览器)
  4. application (ServletContext类) 整个web工程范围内有效(只要web工程不停止 数据都在)

域对象是可以像Map一样存取数据的对象 四个域对象功能一样 不同的是它们对数据的存取范围

四个域在使用的时候 优先顺序是按从小到大排列的

<body>
<%
    pageContext.setAttribute("key", "pageContext");
    request.setAttribute("key", "request");
    session.setAttribute("key", "session");
    application.setAttribute("key", "application");
%>
pageContext域是否有值<%=pageContext.getAttribute("key")%><br>
request域是否有值<%=request.getAttribute("key")%><br>
session域是否有值<%=session.getAttribute("key")%><br>
application域是否有值<%=application.getAttribute("key")%><br>

</body>

out和response.getWriter输出的区别

image-20211018111418228

由于jsp翻译之后 底层源代码都是使用out来进行输出 所以一般情况下 使用out来输出 避免打乱页面输出内容的顺序

jsp的常用标签

静态包含
  1. 静态包含不会翻译被包含的jsp界面
  2. 静态包含其实是把被包含的jsp界面的代码拷贝到包含的位置执行输出

main.jsp

<body>
    头部信息<br>
    主题信息<br>
    <%--
     <%@include file=""%> 就是静态包含
     file属性指定你要包含的jsp页面路径
     地址中的一个/表示 http://ip:port/工程路径 映射到代码的web目录
    --%>
    <%@include file="footer.jsp"%>
</body>

footer.jsp

<body>
底部信息<br>
</body>
动态包含
  1. 动态包含会把包含的jsp页面也翻译成为jsp代码
  2. 动态包含底层代码调用方法调用被包含的jsp页面执行
  3. 动态包含还可以传递参数
    <%--
        page属性指定你要包含的jsp界面
        动态包含也可以像静态包含一样 把被包含的内容执行输出到包含位置
    --%>
    <jsp:include page="/include/footer.jsp">
        <jsp:param name="username" value="zhangsan"/>
    </jsp:include>
<body>
底部信息<br>
<%=request.getParameter("username")%>
</body>

image-20211018114721057

转发
<%--
    <jsp:forward page=""></jsp:forward> 请求转发标签 功能是请求转发
    page属性设置请求转发路径
--%>
<jsp:forward page="scope2.jsp"></jsp:forward>

Listener监听器

Listener监听器是Javaweb的三大组件之一 三大组件分别是:Servlet程序 Filter过滤器 Listener监听器

Listener它是Java EE的规范 就是接口

监听器的作用是监听某种事物的变化 然后通过回调函数 反馈给客户去做一些相应的事

ServletContextListener

ServletContextListener可以监听ServletContext的创建和销毁

ServletContext对象在web工程启动的时候创建 在web工程停止的时候销毁

监听到创建和销毁之后都会分别调用ServletContext的监听器方法反馈

  1. 编写一个类实现ServletContextListener

  2. 实现其两个方法

    public class MyServletContextListener implements ServletContextListener {
        @Override
        public void contextInitialized(ServletContextEvent servletContextEvent) {
            System.out.println("ServletContext对象创建");
        }
    
        @Override
        public void contextDestroyed(ServletContextEvent servletContextEvent) {
            System.out.println("ServletContext对象销毁");
        }
    }
    
  3. 到web.xml中配置监听器

        <listener>
            <listener-class>com.chenxiii.jsp.listener.MyServletContextListener</listener-class>
        </listener>
    

EL表达式

简介

Expression Language 是表达式语言

作用:主要是替代jsp页面中的表达式脚本 在jsp页面中进行数据的输出 因为EL表达式在输出数据的时候 要比jsp表达式脚本简洁的多

<%
    request.setAttribute("key", "value");
%>

表达式脚本输出:<%=request.getAttribute("key")%><br/>
EL表达式输出:${key}

若key值找不到则 EL表达式在输出null时输出空串 JSP表达式输出null

当四个域中都有相同key的数据的时候 EL表达式会按照四个域的大小从小到大去进行搜索

EL表达式输出Bean对象

<%
    Person person = new Person();
    person.setName("牛逼");
    person.setPhones(new String[]{"123123", "123123123123"});
    List<String> cities = new ArrayList<>();
    cities.add("beijing");
    cities.add("hangzhou");
    person.setCities(cities);
    Map<String, Object> map = new HashMap<>();
    map.put("key1", "value1");
    map.put("key2", "value2");
    person.setMap(map);

    pageContext.setAttribute("p", person);

%>

输出Person: ${p}<br/>
输出Person的name属性: ${p.name}<br/>
输出Person的phones属性: ${p.phones[0]}<br/>
输出Person的list属性: ${p.cities}<br/>
输出Person的list属性个别元素: ${p.cities[0]}<br/>
输出Person的map属性: ${p.map}<br/>
输出Person的map属性个别元素: ${p.map.key1}<br/>

EL表达式找的不是属性 而是属性的get方法

运算

关系运算

${12 == 12}<br/>
${12 eq 12}<br/

逻辑运算

${12 eq 12 && 12 lt 11}<br/>
${12 == 12 || 12 > 11}<br/>
${12 eq 12 and 12 lt 11}<br/>
${12 == 12 or 12 > 11}<br/>

算术运算

${12 + 13}<br/>

empty运算 可以判断数据是否为空 为空输出true

<%
    // 以下情况为true
    /*值为null的时候*/
    request.setAttribute("emptyNull", null);
    /*值为空串的时候*/
    request.setAttribute("emptyStr", "");
    /*值是Object类型数组 长度为0的时候*/
    request.setAttribute("emptyArr", new Object[]{});
    /*list集合 元素个数为0*/
    List<String> list = new ArrayList<>();
    request.setAttribute("emptyList", list);
    /*map集合 元素个数为0*/
    Map<String, Object> emptyMap = new HashMap<>();
    request.setAttribute("emptyMap", emptyMap);
%>
${empty emptyNull}<br/>
${empty emptyStr}<br/>
${empty emptyArr}<br/>
${empty emptyList}<br/>
${empty emptyMap}<br/>

三元运算

<%--牛逼--%>
${12 == 12 ? "牛逼" : "不牛逼"}

点运算和[]运算

点运算可以输出Bean对象中某个属性的值

[]运算可以输出有序集合中某个元素的值 还可以输出map集合中key里含有特殊字符的key值

输出Person: ${p}<br/>
输出Person的name属性: ${p.name}<br/>
输出Person的phones属性: ${p.phones[0]}<br/>

11个隐含对象

变量类型作用
pageContextPageContextlmpl它可以获取jsp中的九大内置对象
pageScopeMap<String,Object>它可以获取pageContext域中的数据
requestScopeMap<String,Object>它可以获取Request域中的数据
sessionScopesessionScope它可以获取Session域中的数据
applicationScopeMap<String,Object>它可以获取ServletContext域中的数据
paramMap<String,String>它可以获取请求参数的值
paramValuesMap<String,String[]>它也可以获取请求参数的值,获取多个值的时候使用。
headerMap<String,String>它可以获取请求头的信息
headerValuesMap<String,String[]>它可以获取请求头的信息,它可以获取多个值的情况
cookieMap<String,Cookie>它可以获取当前请求的Cookie信息
initParamMap<String,String>它可以获取在web.xml中配置的context-param上下文参数

JSTL

JSTL 标签库 全称是指 JSP Standard Tag Library JSP 标准标签库。是一个不断完善的开放源代码的 JSP 标 签库。

EL 表达式主要是为了替换 jsp 中的表达式脚本,而标签库则是为了替换代码脚本。这样使得整个 jsp 页面 变得更佳简洁。

功能范围URI前缀
核心标签库–重点http://java.sun.com/jsp/jstl/corec
格式化http://java.sun.com/jsp/jstl/fmtfmt
函数http://java.sun.com/jsp/jstl/functionsfn
数据库(不使用)http://java.sun.com/jsp/jstl/sqlsql
XML(不使用)http://java.sun.com/jsp/jstl/xmlx

jsp标签库中使用taglib指令引入标签库

CORE 标签库
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
XML 标签库
<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>
FMT 标签库
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
SQL 标签库
<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>
FUNCTIONS 标签库
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>

核心库

c:set

作用:可以往域中保存数据

    <%--
    <c:set />
            作用:set 标签可以往域中保存数据域对象.setAttribute(key,value);
            scope 属性设置保存到哪个域
            page 表示 PageContext 域(默认值)
            request 表示 Request 域
            session 表示 Session 域
            application 表示 ServletContext 域
            var 属性设置 key 是多少
            value 属性设置值
    --%>
    保存之前:${requestScope.abc}<br/>
    <c:set scope="request" var="abc" value="牛逼"/>
    保存之后:${requestScope.abc}<br/>
c:if

作用:用来做if判断

    <%--
    <c:if />
        if 标签用来做 if 判断。
        test 属性表示判断的条件(使用 EL 表达式输出)
    --%>
    <c:if test="${12 == 12}">
        <h1>真牛逼</h1>
    </c:if>
c:choose c:when c:otherwise

作用:多路判断 跟switch相似

    <%--
    <c:choose> <c:when> <c:otherwise>标签
        作用:多路判断。跟 switch ... case .... default 非常接近
        choose 标签开始选择判断
        when 标签表示每一种判断情况
        test 属性表示当前这种判断情况的值
        otherwise 标签表示剩下的情况
        <c:choose> <c:when> <c:otherwise>标签使用时需要注意的点:
            1、标签里不能使用 html 注释,要使用 jsp 注释
            2、when 标签的父标签一定要是 choose 标签
    --%>
    <%
        request.setAttribute("height", 178);
    %>
    <c:choose>
        <c:when test="${requestScope.height > 190}">
            <h2>好高</h2>
        </c:when>
        <c:when test="${requestScope.height > 180}">
            <h2>有点高</h2>
        </c:when>
        <c:otherwise>
            <h2>还可以</h2>
        </c:otherwise>
    </c:choose>
c:forEach
    <%--
    遍历 1 到 10,输出
        begin 属性设置开始的索引
        end 属性设置结束的索引
        var 属性表示循环的变量(也是当前正在遍历到的数据)
        for (int i = 1; i < 10; i++)
    --%>
    <c:forEach begin="1" end="10" var="i">
        ${i}<br/>
    </c:forEach>

文件上传

  1. 要有一个 form 标签,method=post 请求
  2. form 标签的 encType 属性值必须为 multipart/form-data 值
  3. 在 form 标签中使用 input type=file 添加上传的文件
  4. 编写服务器代码(Servlet 程序)接收,处理上传的数据。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

<form action="http://localhost:8080/tomcat/upload" method="post" enctype="multipart/form-data">
    用户名: <input type="text" name="username">
    头像: <input type="file" name="photo">
    <input type="submit" value="上传">
</form>

</body>
</html>
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 导入commons-upload.jar commons-io.jar

        // 1.判断上传的数据是否是多段数据(只有多段的数据 才是文件上传)
        if(ServletFileUpload.isMultipartContent(req)) {
            // 创建FileItemFactory工厂实现类
            FileItemFactory factory = new DiskFileItemFactory();
            // 创建用于解析上传数据的工具类ServletFileUpload类
            ServletFileUpload servletFileUpload = new ServletFileUpload(factory);
            //解析上传的数据得到每一个表单项
            try {
                List<FileItem> fileItems = servletFileUpload.parseRequest(req);

                //判断每一个表单项是普通类型还是上传的文件
                for (FileItem fileItem : fileItems) {
                    if (fileItem.isFormField()) {
                        // 普通表单项
                        System.out.println("表单项的name属性值:" + fileItem.getFieldName());
                        // 参数utf-8解决乱码问题
                        System.out.println("表单项的value属性值:" + fileItem.getString("UTF-8"));
                    } else {
                        // 上传的文件
                        System.out.println("表单项的name属性值:" + fileItem.getFieldName());
                        // 参数utf-8解决乱码问题
                        System.out.println("文件名:" + fileItem.getName());
                        fileItem.write(new File("e:\\" + fileItem.getName()));
                    }
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

HTTP协议说明

image-20211018202549187

API说明

ServletFileUpload 类,用于解析上传的数据。
FileItem 类,表示每一个表单项。
boolean ServletFileUpload.isMultipartContent(HttpServletRequest request);
判断当前上传的数据格式是否是多段的格式。
public List<FileItem> parseRequest(HttpServletRequest request)
解析上传的数据
boolean FileItem.isFormField()
判断当前这个表单项,是否是普通的表单项。还是上传的文件类型。
true 表示普通类型的表单项
false 表示上传的文件类型
String FileItem.getFieldName()
获取表单项的 name 属性值
String FileItem.getString()
获取当前表单项的值。
String FileItem.getName();
获取上传的文件名
void FileItem.write( file );
将上传的文件写到 参数 file 所指向抽硬盘位置 。

文件下载

  1. 获取要下载的文件名
  2. 读取要下载的文件内容
  3. 把下载的文件内容回传到客户端
  4. 在回传前 通过响应头告诉客户端返回的数据类型
  5. 通过响应头告诉客户端收到的数据用于下载使用
public class DownloadServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String downloadFileName = "1.png";
        // 读取下载文件内容 通过ServletContext对象
        ServletContext servletContext = req.getServletContext();

        // 获取要下载的文件类型
        String mimeType = servletContext.getMimeType("/file/" + downloadFileName);
        System.out.println(mimeType);
        // 通过响应头告诉客户端返回的数据类型
        resp.setContentType(mimeType);

        // 通过响应头告诉客户端数据是用于下载的
        //"Content-Disposition" 表示收到的数据怎么处理
        //attachment表示附件 表示下载使用
        //filename= 表示指定下载的文件名
        //url编码是把汉字转换为%xx%xx格式
        resp.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("美少女.png", "UTF-8"));


        // /被服务器解析表示地址http://ip:port/工程名/ 映射到代码的webapp目录
        InputStream is = servletContext.getResourceAsStream("/file/" + downloadFileName);
        // 获取响应的输出流
        OutputStream os = resp.getOutputStream();
        // 读取输入流中的全部数据 赋值给输出流 输出到客户端
        IOUtils.copy(is, os);

    }
}

Cookie

是服务器通知客户端保存键值对的一种技术

客户端有了Cookie后 每次请求都发送给服务器

每个Cookie的大小不超过4kb

创建Cookie

        // 创建Cookie对象
        Cookie cookie = new Cookie("key", "value");
        Cookie cookie2 = new Cookie("key2", "value2");
        //通知客户端保存cookie
        resp.addCookie(cookie);
        resp.addCookie(cookie2);

        resp.getWriter().write("cookie 创建成功");

Cookie获取

服务器获取

        Cookie[] cookies = req.getCookies(); //获取全部Cookie

并没有直接获取某个Cookie的方法 只有遍历查找

public static Cookie findCookie(String name, Cookie[] cookies) {
    if (name == null || cookies == null || cookies.length == 0) {
        return null;
    }
    for (Cookie cookie : cookies) {
        if (name.equals(cookie.getName())) {
            return cookie;
        }
    }
    return null;
}

Cookie值修改

方法一:

//创建同名的Cookie 在构造器中赋予新的值
Cookie cookie = new Cookie("key", "value333");
//传递给客户端 通知客户端保存修改
resp.addCookie(cookie);

方法二:

//查找需要修改的Cookie对象
Cookie cookie = CookieUtils.findCookie("key", req.getCookies());
//调用setValue方法赋予新值
if (cookie != null) {
    cookie.setValue("Cookie888");
    //通知客户端保存修改
    resp.addCookie(cookie);
}

注:Cookie不包含空格 方括号 圆括号 等号 逗号 双引号 斜杠 问号 冒号 分号 中文等

Cookie存活

设置默认Cookie

    protected void defaultLife(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // setMaxAge()
        // 正数 指定秒数后过期
        // 负数 关闭浏览器删除
        // 0   立刻删除
        Cookie cookie = new Cookie("life", "life");
        cookie.setMaxAge(-1);
        resp.addCookie(cookie);
    }

立刻删除Cookie

    protected void deleteNow(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // setMaxAge()
        // 正数 指定秒数后过期
        // 负数 关闭浏览器删除
        // 0   立刻删除
        Cookie cookie = CookieUtils.findCookie("key2", req.getCookies());
        if (cookie!= null) {
            cookie.setMaxAge(0);
            resp.addCookie(cookie);
        }
    }

指定存活时间

    protected void live(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // setMaxAge()
        // 正数 指定秒数后过期
        // 负数 关闭浏览器删除
        // 0   立刻删除
        Cookie cookie = new Cookie("live", "3600");
        cookie.setMaxAge(10);
        resp.addCookie(cookie);
    }

Path属性

可以有效过滤哪些Cookie可以发送给服务器 哪些不发

path请求的地址来进行有效的过滤

    protected void pathCookie(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Cookie cookie = new Cookie("path1", "path1");
        //req.getContextPath()得到工程路径
        cookie.setPath(req.getContextPath() + "/abc"); 
        //"工程路径 + /abc" 可以访问Cookie
        resp.addCookie(cookie);
    }

Session

是一个接口( HttpSession )

是一个会话 用来维护一个客户端和服务器之间关联的一种技术

每个客户端都有自己的一个Session会话

Session会话中 经常用来保存用户登录之后的信息

创建Session和获取

    protected void createOrGetSession(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //创建和获取Session对象 第一次是创建新的 之后都是获取之前的Session
        HttpSession session = req.getSession();
        //判断是否是新创建出来的
        boolean aNew = session.isNew();
        //获取Session会话的唯一标识id
        String id = session.getId();

        resp.getWriter().write("Session id=" + id + "<br />");
        resp.getWriter().write("Session isNew=" + aNew + "<br />");
    }

Session域中数据的存取

    protected void getAttribute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Object key = req.getSession().getAttribute("key");
        resp.getWriter().write("key=" + key);
    }
    protected void setAttribute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = req.getSession();
        session.setAttribute("key", "value");
    }

Session生命周期

在Tomcat服务器配置文件web.xml中默认时长为30分钟

    protected void defaultLife(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取默认超时时长
        int max = req.getSession().getMaxInactiveInterval();
        resp.getWriter().write("默认超时时长=" + max); //默认超时时长=1800
    }

在web.xml中设置默认时长 设置所有Session默认时长为20分钟

    <session-config>
        <session-timeout>20</session-timeout>
    </session-config>

只修改个别Session的超时时长 Session超时是指客户端两次请求的最大间隔时长

    protected void life3(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置当前Session3秒后超时
        //负数表示永不超时(极少使用)
        req.getSession().setMaxInactiveInterval(3);
    }

image-20211021215104664

让Session会话马上超时

    protected void deleteNow(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置Session会话马上超时
        req.getSession().invalidate();
    }

浏览器和Session之间关联的技术内幕

Session技术底层其实是基于Cookie技术实现的

image-20211021220554054

iter().write(“Session id=” + id + “
”);
resp.getWriter().write(“Session isNew=” + aNew + “
”);
}






### Session域中数据的存取

```java
    protected void getAttribute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Object key = req.getSession().getAttribute("key");
        resp.getWriter().write("key=" + key);
    }
    protected void setAttribute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = req.getSession();
        session.setAttribute("key", "value");
    }

Session生命周期

在Tomcat服务器配置文件web.xml中默认时长为30分钟

    protected void defaultLife(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取默认超时时长
        int max = req.getSession().getMaxInactiveInterval();
        resp.getWriter().write("默认超时时长=" + max); //默认超时时长=1800
    }

在web.xml中设置默认时长 设置所有Session默认时长为20分钟

    <session-config>
        <session-timeout>20</session-timeout>
    </session-config>

只修改个别Session的超时时长 Session超时是指客户端两次请求的最大间隔时长

    protected void life3(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置当前Session3秒后超时
        //负数表示永不超时(极少使用)
        req.getSession().setMaxInactiveInterval(3);
    }

[外链图片转存中…(img-iwiXQSnk-1634828158770)]

让Session会话马上超时

    protected void deleteNow(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置Session会话马上超时
        req.getSession().invalidate();
    }

浏览器和Session之间关联的技术内幕

Session技术底层其实是基于Cookie技术实现的

[外链图片转存中…(img-IIFZSdeB-1634828158770)]

Filter

是三大组件之一

是Java EE的规范 也就是接口

作用:拦截请求 过滤相应

场景:

  1. 权限检查
  2. 日记操作
  3. 事务管理

基本使用

编写一个类实现Filter接口 实现过滤方法doFilter

public class AdminFilter 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("过滤器执行");
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        HttpSession session = httpServletRequest.getSession();
        Object user = session.getAttribute("user");
        if (user == null) {
            servletRequest.getRequestDispatcher("/login.jsp").forward(servletRequest, servletResponse);
            return;
        } else {
            //让程序继续访问目标资源
            filterChain.doFilter(servletRequest, servletResponse);
        }
    }

    @Override
    public void destroy() {

    }
}

配置Filter

    <!--配置一个过滤器-->
    <filter>
        <!--给filter起别名-->
        <filter-name>AdminFilter</filter-name>
        <!--配置filter的全类名-->
        <filter-class>com.chenxiii.filter.AdminFilter</filter-class>
    </filter>
    <!--配置Filter过滤器的拦截路径-->
    <filter-mapping>
        <!--表示当前的拦截器给哪个filter使用-->
        <filter-name>AdminFilter</filter-name>
        <!--配置拦截路径-->
        <!--/ 表示http://ip:port/工程路径/-->
        <!--/admin/* 表示http://ip:port/工程路径/admin/ 目录下全部文件-->
        <url-pattern>/admin/*</url-pattern>
    </filter-mapping>

生命周期

  1. 构造器方法 在web工程启动时执行
  2. init 初始化方法 在web工程启动时执行
  3. doFilter 过滤方法 每次拦截到请求执行
  4. destroy 销毁 web工程停止时执行

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-swG9YOvf-1635087439787)(javaweb2.assets/image-20211024204531243.png)]

FilterConfig类

Tomcat在每次创建Filter时 会同时创建一个FilterConfig类 包含了Filter配置文件的配置信息

作用:获取配置器的内容

  1. 获取Filter的别名 filter-name
  2. 获取在Filter中配置的 init-param 初始化参数
  3. 获取ServletContext对象
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("2.初始化方法");

        System.out.println("filter-name=" + filterConfig.getFilterName());//filter-name=AdminFilter
        System.out.println("初始化参数param = " + filterConfig.getInitParameter("username"));//初始化参数param = zhangsan
        System.out.println(filterConfig.getServletContext());//org.apache.catalina.core.ApplicationContextFacade@10f4a20f
    }

参数配置

<!--配置一个过滤器-->
    <filter>
        <!--给filter起别名-->
        <filter-name>AdminFilter</filter-name>
        <!--配置filter的全类名-->
        <filter-class>com.chenxiii.filter.AdminFilter</filter-class>
        
        <init-param>
            <param-name>username</param-name>
            <param-value>zhangsan</param-value>
        </init-param>
    </filter>
    <!--配置Filter过滤器的拦截路径-->
    <filter-mapping>
        <!--表示当前的拦截器给哪个filter使用-->
        <filter-name>AdminFilter</filter-name>
        <!--配置拦截路径-->
        <!--/ 表示http://ip:port/工程路径/-->
        <!--/admin/* 表示http://ip:port/工程路径/admin/ 目录下全部文件-->
        <url-pattern>/admin/*</url-pattern>
    </filter-mapping>

FilterChain 过滤器链

image-20211024210248962

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("前置1111111");
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("后置33333");
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("前置222222");
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("后置44444");
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gq9RwEYS-1635087439789)(javaweb2.assets/image-20211024210342003.png)]

若 Filter2 中没有后置代码 则直接执行Filter1的后置代码

在多个Filter过滤器执行的时候 执行顺序是在web.xml中从上到下的顺序

多个Filter过滤器执行的特点:

  1. 所有Filter和目标资源都默认执行在同一个线程中
  2. 多个Filter共同执行的时候 使用同一个Request对象 Request域中数据共享

拦截路径

  1. 精确匹配

    <url-pattern>/chain/a.jsp</url-pattern>
    
  2. 目录匹配

    <url-pattern>/admin/*</url-pattern>
    
  3. 后缀名匹配 不能 / 开头

    <url-pattern>*.html</url-pattern>
    

Filter过滤器只关心地址是否匹配 不关心资源是否存在

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值