Filter(过滤器) 是JavaWeb的三大组件之一,用于在Servlet之外对Request或者Response进行修改。
1.基本流程:
2.实现方式
方法一:实现javax.servlet.Filter
接口,在web.xml中配置:
<web-app>
<display-name>Archetype Created Web Application</display-name>
<filter>
<filter-name>filter1</filter-name>
<filter-class>com.wantao.filter.Filter1</filter-class>
<init-param>
<param-name>name</param-name>
<param-value>Selenium</param-value>
</init-param>
</filter>
<filter>
<filter-name>filter2</filter-name>
<filter-class>com.wantao.filter.Filter2</filter-class>
</filter>
<filter-mapping>
<filter-name>filter1</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>filter2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
方法二:实现javax.servlet.Filter
接口,在Filter类上使用注解@WebFilter
(servlet3.0及以上版本才可以)
@Slf4j
@WebFilter(filterName="filter3",urlPatterns="/*")
public class Filter3 implements Filter{
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("filter3 init");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
log.info("filter3 doFilter");
chain.doFilter(request, response);
}
@Override
public void destroy() {
log.info("filter3 destory");
}
}
方法三:实现javax.servlet.Filter
接口,将Filter在配置类中进行注册(SpringBoot)
@Bean
public FilterRegistrationBean myFilter(){
FilterRegistrationBean filterRegistrationBean=new FilterRegistrationBean();
filterRegistrationBean.setFilter(new MyFilter());//设置Filter
filterRegistrationBean.addUrlPatterns("/threadLocal/*");//设置url
return filterRegistrationBean;
}
3.Filter详解
package com.wantao.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import lombok.extern.slf4j.Slf4j;
/**
* @author wantao
* @date 2019-05-21 5:32:30 PM
* @description talk is cheap,show me your code
*/
@Slf4j
public class Filter1 implements Filter {
private FilterConfig config;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
this.config=filterConfig;//在web.xml中的filter中设置好init-param参数,可通过FilterCOnfig对象在init方法中调用
log.info("filter1 init");
log.info("filter init-param:"+config.getInitParameter("name"));
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
log.info("filter1 doFilter");
filterChain.doFilter(request, response);//不调用此方法,则请求会停止
}
@Override
public void destroy() {
log.info("filter1 destory");
}
}
1.以Filter1为例子,可以看到它重写了init(),doFilter(),destory()方法
在下图中可以看出来init只被执行了一次,而刷新页面(重新发出请求)则是反复的调用doFilter方法.
2.在doFilter方法中,必须调用filterChain.doFilter(request, response);
,以调用下一个Filter,否则请求会停留在此filter,而无法传递过去,你就无法访问web服务器中的资源.
3 .在web.xml中,filter可以配置一些属性,如:
①设置初始化参数
<init-param>
<param-name>name</param-name>
<param-value>Selenium</param-value>
</init-param>
并通过FilterConfig对象在init()方法中调用
private FilterConfig config;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
this.config=filterConfig;//在web.xml中的filter中设置好init-param参数,可通过FilterCOnfig对象在init方法中调用
log.info("filter1 init");
log.info("filter init-param:"+config.getInitParameter("name"));
}
②可以在<filter-mapping></filter-mapping>
中在<url-pattern>/*</url-pattern>
后面通过<dispatcher></dispatcher>
设置请求过滤的级别(默认是REQUEST)
REQUEST:表示仅当直接请求Servlet时才生效。
FORWARD:表示仅当某Servlet通过FORWARD到该Servlet时才生效。
INCLUDE:JSP中可以通过<jsp:include>标签请求某Servlet或调用RequestDispatcher的include()方法请求某Servlet,仅这种情况下有效。
ERROR:JSP中可以通过<%@ page errorPage=”error.jsp”>标签指定错误处理页面,仅这种情况下有效。
4.在web.xml中filter按照定义的顺序由上到下执行(所以我们在使用CharacterEncodingFilter
时必须定义在所有的filter之前)
在@WebFilter
中,好像是按照filter name 的顺序执行(看到有人说有时这个顺序也不一定,我建议还是在web.xml中配置好一点),如:filterA比filterB先执行