一、什么是过滤器
过滤器是介于客户端与服务器目标资源之间的一道过滤技术。对访问请求进行过滤,过滤器可以先行一步对请求进行预处理。比如判断用户是否登录,是否具备访问权限等。最重要的是,一个过滤器可以拦截一个或多个访问请求进行过滤,一个请求也可以被多个过滤器过滤。如果为一个请求配置了多个过滤器,那么系统会将多个过滤器组合在一起,形成一个过滤器链,系统会自动安排请求穿越整个链路,除非我们在其中的过滤器中不进行下一步传递。而且,过滤器不限于过滤servlet,它可以过滤所有的访问请求,比如静态html,图片等。
客户端发送过来的请求会先经过过滤器处理,再到达目标Servlet,响应时,原路返回之前途径过的过滤器,后拦截的先响应。
二、过滤器的实现
通过实现servlet-api中的filter接口,即可实现过滤器,通过@WebFilter指定过滤的访问请求即可。
注解:
public @interface WebFilter {
String description() default "";
String displayName() default "";
WebInitParam[] initParams() default {}; //初始化参数,示例:initParams ={@WebInitParam(name="charset",value="UTF-8")}
String filterName() default "";
String smallIcon() default "";
String largeIcon() default "";
String[] servletNames() default {}; //指定需要拦截的servlet的名称
String[] value() default {}; // 指定需要过滤(被拦截)的请求地址,必须 / 开头,支持多个
String[] urlPatterns() default {}; //等价value,指定需要过滤(被拦截)的请求地址,必须 / 开头
DispatcherType[] dispatcherTypes() default {DispatcherType.REQUEST}; //转发调度的类型,默认为Request
boolean asyncSupported() default false;
}
过滤器Filter接口:
public interface Filter {
void init(FilterConfig var1) throws ServletException; //初始化一个过滤器
void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException; //执行过滤业务规则,并指定是否放行:传递给下一个过滤器或目标资源
void destroy(); //销毁
}
自定义过滤器,拦截所有请求,解决中文乱码问题:
@WebFilter(value = "/*",filterName = "EncodeFilter",displayName = "编码过滤器",initParams ={@WebInitParam(name="charset",value="UTF-8")})
public class EncodeFilter implements Filter {
private String charset;
@Override
public void init(FilterConfig filterConfig) { //每个过滤器都只初始化 1 次
//通过 过滤器配置对象,获取到配置参数
charset=filterConfig.getInitParameter("charset");
System.out.println("EncodeFilter 过滤器完成初始化。。。");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("EncodeFilter 拦截到请求:"+ servletRequest.getServerName());
servletRequest.setCharacterEncoding(this.charset);
servletResponse.setContentType("text/html;charset=utf-8");
filterChain.doFilter(servletRequest,servletResponse);//请求通过后,一定要手动放行
System.out.println("响应再次经过EncodeFilter这里");
}
@Override
public void destroy() { //每个过滤器都只初始化 1 次
System.out.println("EncodeFilter 过滤器销毁了。。。");
}
}
三、过滤器的生命周期
1、容器启动时会自动初始化所有的过滤器,调用他们的init方法,且仅初始化1次。
2、每次请求来访,都将调用doFilter方法进行过滤处理,并由业务规则判断是否放行。
3、容器关闭时,所有过滤器都被销毁,调用容器的destory,且仅销毁1次。先初始化的过滤器也先被销毁。
过滤器链上,过滤器的执行顺序:根据过滤器的名称排序,前面的先执行,如EncodeFilter 优先TokenFilter。
四、过滤器匹配模式
通过url设置拦截请求时有三种模式:
- 精确模式:如:/index.jsp、 /myservlet ,全名匹配
- 后缀拦截模式:如:“ *.jsp”、“* *.do”
- 通配符(*)拦截模式: 拦截所有请求:“/*” ,拦截/a/b /路径下所有请求:/a/b/*