定义
-
Filter 过滤器
-
针对服务器:拦截传入的请求和传出的响应
-
修改或处理客户端与服务器交互的数据流
-
后期会有熔断器 Hystrixs【分布式SpringCloud,类似保险丝】
架构
- 原来:客户端 —— 服务器
- 现在:客户端 —— 过滤器 —— 服务器【双向拦截处理】
- 过滤器其实是个filterChain
- 过滤器1 —— 过滤器2 —— … —— 过滤器x —— … —— 过滤器n
应用场景
1.统一处理中文乱码
-
原来的解决方案
- 设置编码格式
- 获取参数
-
用过滤器
- 提取公共的处理部分F
2.屏蔽敏感词
- getParameter(没法set回去)
- 调用String的replace方法
- setAttribute
- 下一个要拿参数的对象,就得getAttribute
3.控制资源访问权限
- 比如登陆后才能有的权限
package com.microsoft.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class LoginFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)servletRequest;
HttpServletResponse response = (HttpServletResponse)servletResponse;
HttpSession session = request.getSession();
String username = (String) session.getAttribute("username");
// 不是登录状态
if(username == null){
response.sendRedirect("/login.jsp");
}
else{
filterChain.doFilter(servletRequest,servletResponse);
}
}
}
使用
- 与servlet类似,Filter是Java提供的一个接口,开发者实现就好
- 创建一个filter包,创建类,导包javax.servlet.Filter
- 与servlet不同,有一个doFilter抽象方法就行,这个必须实现(接口内方法有default修饰,不一定要实现,JDK8新特性)
package com.microsoft.filter;
import javax.servlet.*;
import java.io.IOException;
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void destroy() {
}
// 核心
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
}
}
- 在web.xml中配置(重复过滤,url追加即可)
<filter>
<filter-name>character</filter-name>
<filter-class>com.microsoft.filter.CharacterFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>character</filter-name>
<url-pattern>/user</url-pattern>
<url-pattern>/test</url-pattern>
</filter-mapping>
- 处理代码(处理完业务逻辑,一定要filterChain.doFilter,不然请求会停留在过滤器)
package com.microsoft.filter;
import javax.servlet.*;
import java.io.IOException;
public class CharacterFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("UTF-8");
// 串起来,类似转发、重定向,请求才能接着走
filterChain.doFilter(servletRequest,servletResponse);
}
}
- 当然也可以用注解配置——@WebFilter(url)
- 优点:简单方便
- 缺点:不能决定顺序,顺序是随机的
- 如果对顺序没有要求,可以注解
生命周期
-
与servlet类似,但不同是,servlet访问才创建,filter一开Tomcat就创建并初始化
-
创建——无参构造器(Filter一定要进行配置)
-
初始化——init()
-
使用——doFilter()
- 拦截
- 处理
- 放行(在filterChain.doFilter(servletRequest,servletResponse)执行后)
-
回收——destroy()
-
【单例模式】模拟执行
-
Tomcat启动:无参构造+init()
-
第一次访问:doFilter()
-
第二次访问:doFilter()
-
。。。
-
第n次访问:doFilter()
-
关闭服务器:destroy()
-
拦截次序
- A拦截 —— B拦截 —— MyServlet —— B放行 —— A放行
<servlet>
<servlet-servlet>MyServlet</filter-name>
<servlet-class>com.microsoft.servlet.MyServlet</filter-class>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/servlet</url-pattern>
</servlet-mapping>
<filter>
<filter-name>AFilter</filter-name>
<filter-class>com.microsoft.filter.AFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>BFilter</filter-name>
<filter-class>com.microsoft.filter.BFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>BFilter</filter-name>
<url-pattern>/servlet</url-pattern>
</filter-mapping>
- B拦截 —— A拦截 —— MyServlet —— A放行 —— B放行
<servlet>
<servlet-servlet>MyServlet</filter-name>
<servlet-class>com.microsoft.servlet.MyServlet</filter-class>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/servlet</url-pattern>
</servlet-mapping>
<filter>
<filter-name>BFilter</filter-name>
<filter-class>com.microsoft.filter.BFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>BFilter</filter-name>
<url-pattern>/servlet</url-pattern>
</filter-mapping>
<filter>
<filter-name>AFilter</filter-name>
<filter-class>com.microsoft.filter.AFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
- 结论:过滤器的执行顺序和url-pattern标签匹配的精确程度无关,之和他们的filter-mapping标签在web.xml文件中的顺序有关,从上往下配置顺序执行。