目录
前言
过滤器概述
什么是过滤器
过滤器详细
过滤器的生命周期
过滤器的应用
创建一个简单的Filter类步骤
注意:指定拦截路径,我们有两种方式
实例
前言
本篇博客的核心
- 知道过滤器的整个拦截过程
- 知道如何指定拦截路径
- 知道过滤器的生命周期
过滤器概述
什么是过滤器
过滤器JavaWeb三大组件之一,它与Servlet很相似!不它过滤器是用来拦截请求的,而不是处理请求的。
当用户请求某个Servlet时,会先执行部署在这个请求上的Filter,如果Filter“放行”,那么会继承执行用户请求的Servlet;如果Filter不“放行”,那么就不会执行用户请求的Servlet。
接下来,我画一幅图帮助大家理解
过滤器详细
过滤器的生命周期
我们之前学习过Servlet的生命周期。那么我先来复习一下Servlet
- 1 Servlet 创建:启动服务器,当浏览器访问servlet后,由服务器创建
- 2 Servlet 初始化:自动调用init 方法进行初始化,完成初始化操作
- 3 Servlet运行:调用service方法:运行
- 4 Servlet销毁: 在服务器关闭时,调用dertroy 方法 销毁Servlet对象,清除内存缓存
Filter 的生命周期
1 Filter 创建:启动服务器,由服务器自动创建
2 Filter 初始化:自动调用init(FilterConfig) 方法,完成初始化操作
3 Filter 运行:调用doFilter(ServletRequest req,ServletResponse res,FilterChain chain)方法
4 Filter 销毁 :在服务器关闭时,调用dertroy 方法 销毁Filter 对象,清除内存缓存
注意:在Filter 的生命周期中,像创建,初始化,销毁,都是服务器,帮我们做的。我们真正需要做的就是 学会重写doFilter(ServletRequest req,ServletResponse res,FilterChain chain)方法
根据实际的拦截需要,写方法体
大家请看Filter 的源码
java">package javax.servlet;import java.io.IOException;public interface Filter { // 一但,我们创建 该对象,就会立即调用init()方法,完成初始化default void init(FilterConfig filterConfig) throws ServletException {} // 实际操作,需要的方法void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException; // 当关闭服务器,后,自动调用该方法,销毁该对象default void destroy() {} }
过滤器的应用
创建一个简单的Filter类步骤
- 0 添加Servlet jar包
- 1 创建一个实现类 ,实现Filter 接口
- 2 重写 doFilter ()方法
- 3 指定拦截路径
注意:指定拦截路径,我们有两种方式
1 通过xml 配置文件
2 通过注解方式
实例
写一个前端登录的表单,来测试 是否可以通过路径拦截?
本次,我使用的是 在xml 配置文件,添加拦截的路径
代码如下
- 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"><filter><filter-name>loginFilter</filter-name><filter-class>fs.Filter.loginFilter</filter-class></filter><filter-mapping><filter-name>loginFilter</filter-name><url-pattern>/login/*</url-pattern></filter-mapping></web-app>
过程展示图如下:
运行结果大家是否发现:我在配置文件指定的路径:
<url-pattern>/login/*</url-pattern>按理来说,我们登录表单,请求路径是 / login 。因此我们也是要写成这样的,当提交表单后,我们写的Filter 类,指定的路径,如果是这个,那么刚好被拦截,判断是否满足条件,如果满足,就放行,让Servlet 来处理请求。
但我这里写成这种方式,其实是为了方便以后。如果之后你改了请求路径如 login121,login1等
都是可以被拦截的。我写的是前缀锁定。只有前缀是一样的,不管后面是什么,都会被拦截。
之前是在配置文件中指定拦截路径,现在我们也试一下注解方式
之前,我们是通过在xml配置文件 写拦截路径,是比较麻烦。这里有一种更方便的方式:通过注解来写拦截路径。
大家可以回忆之前,写Servlet 路径的注解。本质是一样的。我们使用注解本质上还剩在配置文件中,添加。只不过这个方式简单点,相对我们来说。
java">@WebServlet("/login/*")
之前说,如果满足Filter 拦截条件,就放行!,让servlet 去执行请求的业务
那么现在有个问题,应该怎么去放行,怎么体现“放行” 呢?
我们之前看源码的时候,注意到
doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) 有一个参数 FilterChain filterChain我们要表示放行时,代码
filterChain.doFilter(servletRequest,servletResponse);大家请看实例,来理解
之前做一个简单的前后端项目,要求:登录,查看列表,修改,删除,添加功能
在这个项目中,只有登录成功后,才可以进行其他操作。
因此当我们点击查看列表,修改,删除,添加功能 前端界面时,都必须要看是否登录,如果没有登录,就会跳到登录界面。因此我们需要Filter 拦截,而拦截条件是 :是否登录。
我们写的Filter 类代码如下:
java">package fs.filter;import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; import java.util.Objects;@WebFilter("/users/*") public class checkLoginFilter implements javax.servlet.Filter {@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest req =(HttpServletRequest) servletRequest;HttpServletResponse resp=(HttpServletResponse) servletResponse;//验证登录是, 如果用户对象否为空if (Objects.nonNull(req.getSession().getAttribute("login"))){filterChain.doFilter(req,resp);}else {resp.sendRedirect("/login.jsp");}// 跳转到登录页面} }
看了代码发现:
把登录成功的用户对象用session域存起来
- 这样就可以在任意请求中使用,只要当前会话没有结束【浏览器没有关闭】
拦截路径,我使用了前缀锁定,这样就可以使用在多个请求地址不同的前端界面上
使用向下转型
- doFilter方法提供的参数 都是HttpServletRequest 或HttpServletResponse 类型 对象的父类,没有从域中获得数据的方法。