文章目录
过滤器Filter
简介
Filter也属于Servlet规范,和Servlet的理解是一样的,不过功能不同
利用Filter, 在请求发送过来的时候,请求不会直接发给客户端,而是会被Filter拦截,当filter放行时,请求才会发送到服务器
同理,在相应发送到客户端时,相应不会直接发送到客户端,而是会被filter拦截,当filter放行时,相应才会发送到客户端
Filter 开发步骤
和Servlet类似
-
新建类实现Filter接口,然后实现其中的三个方法:init,doFilter, destroy
-
配置Filter,可以使用注解@webFilter(), 也可以在xml文件中配置: ,
// 这是过滤器类
package Fitler;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/**
* @ClassName : filterDemo01
* @Author : YuYun
* @Date : 2022-04-18 11:13:40
* @Description :这是过滤器类
*/
// 表示拦截放给demoFilter.do的请求,其他的他不会拦截
@WebFilter("/demoFilter.do")
public class filterDemo01 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("拦截器初始化。。。。。");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("请求发到拦截器》。。。");
// 放行请求
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("相应发送到拦截器.........");
}
@Override
public void destroy() {
}
}
这是demoFilter.do
package Controller;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
@WebServlet("/demoFilter.do")
public class DemoFilter extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("demo01.....");
req.getRequestDispatcher("demo02.do").forward(req, resp);
}
}
这是demo02.do
package Controller;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @ClassName : Demo02
* @Author : YuYun
* @Date : 2022-04-18 11:15:49
* @Description :
*/
@WebServlet("/demo02.do")
public class Demo02 extends HttpServlet {
@Override
public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("这是Demo02");
resp.sendRedirect("succ.html");
}
}
这是succ.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>这是succ.html页面</title>
</head>
<body>
<h1> 这是succ 页面</h1>
</body>
</html>
运行结果:
拦截器初始化。。。。。
请求发到拦截器》。。。
demo01.....
这是Demo02
相应发送到拦截器.........
过滤器链(filterChain)
这三个过滤器就是一个过滤器链,在实际开发中,这些过滤器的作用都是不一样的,扮演的角色也不同
上图的打印顺序是:
A, B, C demo03, service, C2, B2, A2
过滤顺序说明:如果使用注解,那么过滤的顺序就是类名的字符串顺序
如果使用xml文件配置,那么过滤的顺序就是在xml文件里边配置的顺序
这是Demo03.do:
package Controller;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @ClassName : Demo03
* @Author : YuYun
* @Date : 2022-04-18 11:48:43
* @Description :
*/
@WebServlet("/demo03.do")
public class Demo03 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("这是demo03.......");
}
}
这是A过滤器:
package Fitler;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/**
* @ClassName : filterA
* @Author : YuYun
* @Date : 2022-04-18 11:49:26
* @Description :
*/
@WebFilter("/demo03.do")
public class filterA 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("A");
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("A2");
}
@Override
public void destroy() {
}
}
这是过滤器B:
package Fitler;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/**
* @ClassName : filterB
* @Author : YuYun
* @Date : 2022-04-18 11:50:15
* @Description :
*/
@WebFilter("/demo03.do")
public class filterB 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("B");
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("B2");
}
@Override
public void destroy() {
}
}
这是过滤器c:
package Fitler;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/**
* @ClassName : filterC
* @Author : YuYun
* @Date : 2022-04-18 11:51:02
* @Description :
*/
@WebFilter("/demo03.do")
public class filterC 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("C");
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("C2");
}
@Override
public void destroy() {
}
}
过滤器的作用:
通常,事务的管理要应用在service层上边,所以,我们通常利用filter层来进行事务的管理,让事务前置。另外修改编码格式的操作通常也会放在filter层上边
Filter生命周期(摘录自尚硅谷笔记)
和Servlet生命周期类比,Filter生命周期的关键区别是:在Web应用启动时创建对象
生命周期阶段 | 执行时机 | 执行次数 |
---|---|---|
创建对象 | Web应用启动时 | 一次 |
初始化 | 创建对象后 | 一次 |
拦截请求 | 接收到匹配的请求 | 多次 |
销毁 | Web应用卸载前 | 一次 |
过滤器匹配规则
本节要探讨的是在filter-mapping中如何将Filter同它要拦截的资源关联起来。
精确匹配
指定被拦截资源的完整路径:
<!-- 配置Filter要拦截的目标资源 -->
<filter-mapping>
<!-- 指定这个mapping对应的Filter名称 -->
<filter-name>Target01Filter</filter-name>
<!-- 通过请求地址模式来设置要拦截的资源 -->
<url-pattern>/Target01Servlet</url-pattern>
</filter-mapping>
模糊匹配
相比较精确匹配,使用模糊匹配可以让我们创建一个Filter就能够覆盖很多目标资源,不必专门为每一个目标资源都创建Filter,提高开发效率。
前杠后星
在我们配置了url-pattern为/user/*之后,请求地址只要是/user开头的那么就会被匹配。
<filter-mapping>
<filter-name>Target02Filter</filter-name>
<!-- 模糊匹配:前杠后星 -->
<!--
/user/Target02Servlet
/user/Target03Servlet
/user/Target04Servlet
-->
<url-pattern>/user/*</url-pattern>
</filter-mapping>
极端情况:/*匹配所有请求
前星后缀
下面我们使用png图片来测试后缀拦截的效果,并不是只能拦截png扩展名。
创建一组img标签
<img th:src="@{/./images/img017.png}"/><br/>
<img th:src="@{/./images/img018.png}"/><br/>
<img th:src="@{/./images/img019.png}"/><br/>
<img th:src="@{/./images/img020.png}"/><br/>
<img th:src="@{/./images/img024.png}"/><br/>
<img th:src="@{/./images/img025.png}"/><br/>
创建Filter
<filter>
<filter-name>Target04Filter</filter-name>
<filter-class>com.atguigu.filter.filter.Target04Filter</filter-class>
</filter>
<filter-mapping>
<filter-name>Target04Filter</filter-name>
<url-pattern>*.png</url-pattern>
</filter-mapping>
前杠后缀,星号在中间
配置方式如下:
<url-pattern>/*.png</url-pattern>
按照这个配置启动Web应用时会抛出异常:
java.lang.IllegalArgumentException: Invalid /*.png in filter mapping
**结论:这么配是*不允许*的!
匹配Servlet名称
<filter-mapping>
<filter-name>Target05Filter</filter-name>
<!-- 根据Servlet名称匹配 -->
<servlet-name>Target01Servlet</servlet-name>
</filter-mapping>
>
前杠后缀,星号在中间
配置方式如下:
<url-pattern>/*.png</url-pattern>
按照这个配置启动Web应用时会抛出异常:
java.lang.IllegalArgumentException: Invalid /*.png in filter mapping
**结论:这么配是*不允许*的!
匹配Servlet名称
<filter-mapping>
<filter-name>Target05Filter</filter-name>
<!-- 根据Servlet名称匹配 -->
<servlet-name>Target01Servlet</servlet-name>
</filter-mapping>