Filter
1、Filter
1.1、Filter概述
Filter 表示过滤器,是 JavaWeb 三大组件(Servlet、Filter、Listener)之一。
过滤器可以把对资源的请求拦截下来,从而实现一些特殊的功能。
过滤器一般完成一些通用的操作。
我们希望实现的效果是用户如果登陆过了就跳转到品牌数据展示的页面;如果没有登陆就跳转到登陆页面让用户进行登陆,要实现这个效果需要在每一个资源中都写上这段逻辑,而像这种通用的操作,我们就可以放在过滤器中进行实现。这个就是权限控制,以后我们还会进行细粒度权限控制。过滤器还可以做 统一编码处理
、 敏感字符处理
等等…
1.2、 Filter快速入门
新建filter-demo的maven项目
导入需要的依依赖坐标
添加一个helow.jsp文件启动服务器测试是否可以访问,不能访问再找原因
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h1>hello JSP~</h1> </body> </html>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>filter-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!--servlet-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!--jsp-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
<!--jstl-->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
</plugin>
</plugins>
</build>
</project>
1、定义了,实现Filter接口,并重写里面的所有的方法
创建com.zcl.webs.filter包
下创建FilterDemo类
package com.zcl.webs.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/**
* TODO:
*
* @author zcl
* @date 2022/3/30 6:36
*/
@WebFilter("/*")
public class FilterDemo implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("FilterDemo.....");
// 需要放行
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void destroy() {
}
}
2、配置Filter拦截资源路径,在类上定义@WebFilter(“路径”)
@WebFilter("/*")
3、放行
// 需要放行
filterChain.doFilter(servletRequest,servletResponse);
如果不写放行代码就会一直被拦截浏览器就会访问到,显示空白
1.3、Filter执行流程
我们通过以下问题来研究过滤器的执行流程:
-
放行后访问对应资源,资源访问完成后,还会回到Filter中吗?
从上图就可以看出肯定 会 回到Filter中
-
如果回到Filter中,是重头执行还是执行放行后的逻辑呢?
如果是重头执行的话,就意味着
放行前逻辑
会被执行两次,肯定不会这样设计了;所以访问完资源后,会回到放行后逻辑
,执行该部分代码。
通过上述的说明,我们就可以总结Filter的执行流程如下:
以后我们可以将对请求进行处理的代码放在放行之前进行处理,而如果请求完资源后还要对响应的数据进行处理时可以在放行后进行逻辑处理。
1.4 Filter使用细节
拦截路径的配置
拦截路径表示 Filter 会对请求的哪些资源进行拦截,使用 @WebFilter
注解进行配置。如:@WebFilter("拦截路径")
拦截路径有如下四种配置方式:
- 拦截具体的资源:/index.jsp:只有访问index.jsp时才会被拦截
- 目录拦截:/user/*:访问/user下的所有资源,都会被拦截
- 后缀名拦截:*.jsp:访问后缀名为jsp的资源,都会被拦截
- 拦截所有:/*:访问所有资源,都会被拦截
通过上面拦截路径的学习,大家会发现拦截路径的配置方式和 Servlet
的请求资源路径配置方式一样,但是表示的含义不同。
过滤器链
过滤器链是指在一个Web应用,可以配置多个过滤器,这多个过滤器称为过滤器链。
上图中的过滤器链执行是按照以下流程执行:
- 执行
Filter1
的放行前逻辑代码 - 执行
Filter1
的放行代码 - 执行
Filter2
的放行前逻辑代码 - 执行
Filter2
的放行代码 - 访问到资源
- 执行
Filter2
的放行后逻辑代码 - 执行
Filter1
的放行后逻辑代码
以上流程串起来就像一条链子,故称之为过滤器链。
我们现在使用的是注解配置Filter,而这种配置方式的优先级是按照过滤器类名(字符串)的自然排序。
比如有如下两个名称的过滤器 :
BFilterDemo
和AFilterDemo
。那一定是AFilterDemo
过滤器先执行。
1.5、登录案例拦截
需求:访问服务器资源时,需要先进行登录验证,如果没有登录,则自动跳转到登录页面
分析:我们要实现该功能是在每一个资源里加入登陆状态校验的代码吗?显然是不需要的,只需要写一个 Filter
,在该过滤器中进行登陆状态校验即可。而在该 Filter
中逻辑如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P93chCxT-1648597691143)(image/Filter/image-20220330074618907.png)]
示例Filter拦截代码
创建LoginFilter类实现Filter接口
package com.zcl.webs.filter; /**
* TODO:
*
* @author zcl
* @date 2022/3/30 7:26
*/
import javax.servlet.*;
import javax.servlet.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* 登录验证的连接器
*/
@WebFilter("/*")
public class LoginFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
// 强转request
HttpServletRequest req = (HttpServletRequest) request;
// 通过数组存储跟登录有关的路径放行
String[] urls = {"/css/","/imgs/","/login.jsp","/loginServlet","/register.jsp","/registerServlet","/checkCodeServlet"};
// 获取当前访问路径
String url = req.getRequestURL().toString();
// 循环判断url是否包含urls
for (String u : urls) {
if(url.contains(u)){
// 放行
chain.doFilter(request, response);
return;
}
}
// 1、判断是否有Session
Object user = req.getSession().getAttribute("user");
// 判断user是否为null
if(user != null){
// 登录过了
// 放行
chain.doFilter(request, response);
}else {
// 没有登录,跳转登录页面,并提示
req.setAttribute("login_msg","您尚未登录");
// 转发到登录页面
req.getRequestDispatcher("/login.jsp").forward(req,response);
}
}
@Override
public void init(FilterConfig config) throws ServletException {
}
@Override
public void destroy() {
}
}