从01开始 从01开始
首页
  • 计算机科学导论
  • 数字电路
  • 计算机组成原理

    • 计算机组成原理-北大网课
  • 操作系统
  • Linux
  • Docker
  • 计算机网络
  • 计算机常识
  • Git
  • JavaSE
  • Java高级
  • JavaEE

    • Ant
    • Maven
    • Log4j
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • Servlet
  • Spring
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC
  • SpringBoot
  • 学习网课的心得
  • 输入法
  • 节假日TodoList
  • 其他
  • 关于本站
  • 网站日记
  • 友人帐
  • 如何搭建一个博客
GitHub (opens new window)

peterjxl

人生如逆旅,我亦是行人
首页
  • 计算机科学导论
  • 数字电路
  • 计算机组成原理

    • 计算机组成原理-北大网课
  • 操作系统
  • Linux
  • Docker
  • 计算机网络
  • 计算机常识
  • Git
  • JavaSE
  • Java高级
  • JavaEE

    • Ant
    • Maven
    • Log4j
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • Servlet
  • Spring
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC
  • SpringBoot
  • 学习网课的心得
  • 输入法
  • 节假日TodoList
  • 其他
  • 关于本站
  • 网站日记
  • 友人帐
  • 如何搭建一个博客
GitHub (opens new window)
  • JavaSE

  • JavaSenior

  • JavaEE

  • JavaWeb

    • 服务器软件

    • 环境管理和配置管理-科普篇
    • Servlet入门

      • 什么是Servlet
      • Servlet入门案例
      • Servlet生命周期
      • Servlet中的注解
      • Tomcat集成IDEA
      • Servlet体系结构
      • HTTP协议基础
      • 深入request和response对象
      • request对象基本使用
      • request其他功能
      • Servlet实现登录功能
      • HTTP协议基础-响应
      • Response对象基本使用
      • response对象之重定向
      • response输出字符到浏览器
      • response输出字节数据
      • 验证码案例
      • ServletContext
      • 文件下载案例
      • Cookie笔记
      • Cookie的更多细节
      • Cookie实践:记住上次访问时间
      • JSP入门
      • JSP的内置对象和案例
      • IDEA与JavaWeb的小技巧
      • Session笔记
      • 验证码案例
      • JSP深入学习
      • MVC开发模式
      • EL表达式和JSTL标签
      • JSTL标签库
      • 案例:列表的增删改查
      • Filter学习
        • 什么是Filter
        • 快速入门
        • ​WebFilter​​源码
        • 过滤器执行流程
        • 过滤器生命周期方法
        • 通过路径和方式配置过滤器
        • 过滤器链(配置多个过滤器)
      • Filter案例
      • Listener学习
      • Java中的Ajax
      • Java中的JSON
      • Servlet
    • JavaWeb
  • Spring

  • 主流框架

  • SpringMVC

  • SpringBoot

  • Java并发

  • Java源码

  • JVM

  • 韩顺平

  • Java
  • Java
  • JavaWeb
  • Servlet入门
2023-04-17
目录

Filter学习

# 135.Filter学习

Servlet,Filter和Listener被称为JavaWeb的三大组件,今天我们就开始学习Filter(重点掌握)和Listener(了解)

# 什么是Filter

Filter,就是过滤器的意思,例如:

  • 生活中的过滤器:净水器, 空气净化器

  • JavaWeb中的过滤器:当访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊的功能,例如有些功能是得登录后才能使用,如果我们在每个Servlet里都加上判断是否登录的代码,就非常难以维护。

    我们可以加个过滤器,有请求时先判断用户是否登录了,是则放行这个请求,这样就减少了重复代码

  • 过滤器的作用:一般用于完成通用的操作。如:登录验证、统一字符编码处理(比如我们之前的doPost方法里要设置编码为UTF8)、敏感字符过滤(比如游戏中不能骂人)...

‍

‍

# 快速入门

编写过滤器的步骤:

  • 定义一个类,实现接口Filter
  • 复写Filter的方法
  • 配置拦截路径: 例如注解@WebFilter("/*")​,或者通过web.xml

‍

我们写个Servlet演示下:

package com.peterjxl.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter("/*")  // 拦截路径,这样访问所有资源之前都会执行该过滤器
public class FilterDemo1 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("FilterDemo1被执行了。。。。");

        // 放行请求,如果不放行则相当于不返回数据给浏览器
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {

    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

‍

注意:如果不放行,访问任何资源都是不会有数据返回给浏览器的

‍

也可以通过web.xml配置:

<filter>
     <filter-name>demo1</filter-name>
     <filter-class>com.peterjxl.filter.FilterDemo1</filter-class>
 </filter>
 <filter-mapping>
     <filter-name>demo1</filter-name>
	<!-- 配置拦截路径 -->
     <url-pattern>/*</url-pattern>
 </filter-mapping>
1
2
3
4
5
6
7
8
9

‍

‍

# ​WebFilter​​源码

我们可以看看注解WebFilter​的源码:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WebFilter {
    String description() default "";

    String displayName() default "";

    WebInitParam[] initParams() default {};

    String filterName() default "";

    String smallIcon() default "";

    String largeIcon() default "";

    String[] servletNames() default {};

    String[] value() default {};

    String[] urlPatterns() default {};

    DispatcherType[] dispatcherTypes() default {DispatcherType.REQUEST};

    boolean asyncSupported() default false;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

‍

ElementType.TYPE表明可以使用在类上,

RUNTIME表明保留到运行阶段

Documented表明生成文档

其他的属性我们可以忽略,主要是看urlPatterns,和WebServlet的注解差不多

‍

# 过滤器执行流程

  1. 执行过滤器
  2. 执行放行后的资源
  3. 回来执行过滤器放行代码下边的代码

举个生活的例子:你坐公交去会所,公交车是一个过滤器,交钱后给你放行;等你从会所回来,又坐公交车,那么还得交钱,然后放行。相当于原路返回。

‍

‍

‍

‍

package com.peterjxl.filter;

import javax.servlet.*;
import javax.servlet.annotation.*;
import java.io.IOException;

@WebFilter("/*")
public class FilterDemo2 implements Filter {
    public void init(FilterConfig config) throws ServletException {
    }

    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        //对request对象请求消息增强,例如判断是否登陆
        System.out.println("filterDemo2执行了....");

        //放行
        chain.doFilter(request, response);

        //对response对象的响应消息增强,例如判断登陆成功,在响应消息中设置登录信息
        System.out.println("filterDemo2回来了...");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

‍

需要注意的是,过滤器中拿到的request对象和具体Servlet中拿到的request对象是同一个,因为我们doFilter里传的就是request和response对象

‍

重启Tomcat,访问index.jsp,可以看到输出了

filterDemo2执行了....
filterDemo2回来了...
1
2

‍

‍

# 过滤器生命周期方法

​Filter​接口有3个方法,分别代表3个生命周期:

  1. ​init​: 在服务器启动后,会创建Filter对象,然后调用init方法。该方法只执行一次,常用于加载资源
  2. ​doFilter​: 每一次请求被拦截资源时,会执行。一般会执行多次
  3. ​destroy​: 如果服务器是正常关闭,则会执行destroy方法, Filter对象被销毁。只执行一次,常用于释放资源

‍

我们可以写个Servlet,然后关闭和启动一次Tomcat,观察方法是否被执行了

package com.peterjxl.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

/**
 * 演示生命周期
 */
@WebFilter("/*")
public class FilterDemo3 implements Filter {
    public void init(FilterConfig config) throws ServletException {
        System.out.println("FilterDemo3 Init....");
    }

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

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        chain.doFilter(request, response);
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

‍

‍

‍

# 通过路径和方式配置过滤器

我们访问资源的时候,除了浏览器访问之外,还可以通过转发的方式访问;而过滤器可以根据请求的方式来配置是否执行过滤器,例如转发的时候就不执行过滤器。

‍

拦截路径配置方式:

  1. 具体资源路径: /index.jsp 只有访问index.jsp资源时,过滤器才会被执行
  2. 拦截目录: /user/* 访问/user下的所有资源时,过滤器都会被执行
  3. 后缀名拦截: *.jsp 访问所有后缀名为jsp资源时,过滤器都会被执行
  4. 拦截所有资源:/* 访问所有资源时,过滤器都会被执行

‍

‍

拦截方式配置:资源被访问的方式。例如设置浏览器直接请求资源,才能被拦截器拦截,这样服务器内部转发的就不会被拦截,可以通过注解和web.xml配置。

通过注解配置拦截方式:设置dispatcherTypes属性, 可以设置多个,例如

@WebFilter(value="/index.jsp"  dispatcherTypes = DispatcherType.Request)
1

‍

有如下访问方式:

  • REQUEST:默认值,也就是浏览器直接请求资源的方式
  • FORWARD:转发访问资源的方式,如果过滤器配置了这个属性,那么只有转发的资源才会被过滤器执行
  • INCLUDE:包含访问资源,了解即可
  • ERROR:错误跳转资源,了解即可
  • ASYNC:异步访问资源,SYNC就是同步,加个A就是反义词,因此ASYNC就是异步,了解即可

‍

可以配置多个拦截方式:

//浏览器直接请求index.jsp或者转发访问index.jsp,该过滤器会被执行
@WebFilter(value="/index.jsp",dispatcherTypes ={ DispatcherType.FORWARD, DispatcherType.REQUEST})
1
2

‍

‍

web.xml配置:在filter-mapping​下 设置 <dispatcher></dispatcher>​ 标签即可

‍

# 过滤器链(配置多个过滤器)

执行顺序:如果有两个过滤器,分别是过滤器1和过滤器2,假设先执行了过滤器1,则过滤器的执行流程为:

  • 过滤器1
  • 过滤器2
  • 资源执行
  • 过滤器2剩下的代码
  • 过滤器1剩下的代码

更多过滤器的情况同理,相当于原路返回

还是以坐公车去会所为例,相当于要转车,去到目的地获取想要的资源;然后回来的时候还是一样,原路返回,转车。

‍

那么怎么判断哪个过滤器先执行呢?有如下规则:

  1. 注解配置:按照类名的字符串比较规则比较,值小的先执行。如: AFilter 和 BFilter,AFilter就先执行了。
  2. web.xml配置: <filter-mapping>​ 谁定义在上边,谁先执行

‍

我们可以创建两个Servlet来演示下:

package com.peterjxl.filter;

import javax.servlet.*;
import javax.servlet.annotation.*;
import java.io.IOException;

@WebFilter("/*")
public class FilterDemo6 implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        System.out.println("filterDemo6执行了...");
        chain.doFilter(request, response);
        System.out.println("filterDemo6回来了...");
    }

    public void init(FilterConfig config) throws ServletException {
    }

    public void destroy() {
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

‍

‍

package com.peterjxl.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter("/*")
public class FilterDemo7 implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        System.out.println("filterDemo7执行了...");
        chain.doFilter(request, response);
        System.out.println("filterDemo7回来了...");
    }

    public void init(FilterConfig config) throws ServletException {
    }

    public void destroy() {
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

‍

重启Tomcat,随便访问某个路径,控制台输出:

filterDemo6执行了...
filterDemo7执行了...
filterDemo7回来了...
filterDemo6回来了...
1
2
3
4

‍

‍

‍

‍

‍

‍

‍

在GitHub上编辑此页 (opens new window)
上次更新: 2023/5/6 21:54:08
案例:列表的增删改查
Filter案例

← 案例:列表的增删改查 Filter案例→

Theme by Vdoing | Copyright © 2022-2023 粤ICP备2022067627号-1 粤公网安备 44011302003646号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式