过滤器(Filter)是 J2EE Servlet模块性的组件。Filter的作用是对URL进行统一的拦截处理。Filter通常用于应用程序层面进行全局处理。
1. 实现Filter
开发过滤器三要素
- 任何过滤器都要实现javax.servlet.Filter接口
- 在 Filter接口的 doFilter()方法中编写过滤器的功能代码。
- 在web.xml中对过滤器进行配置,说明拦截URL的范围
接下来具体实现:
- xml配置方式:
public class FirstFilter implements Filter {
public void destroy() {
//...
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("过滤器FirstFilter已生效");
chain.doFilter(req,resp);
}
public void init(FilterConfig config) throws ServletException {
//...
}
}
<filter>
<filter-name>First</filter-name>
<filter-class>Filter.FirstFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>First</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
- 注解@WebFilter配置方式
属性名 | 类型 | 描述 |
---|---|---|
filterName | String | 指定过滤器的 name 属性,等价于 <filter-name> |
value | String[] | 该属性等价于 urlPatterns 属性。但是两者不应该同时使用。 |
urlPatterns | String[] | 指定一组过滤器的 URL 匹配模式。等价于 <url-pattern> 标签。 |
servletNames | String[] | 指定过滤器将应用于哪些 Servlet。取值是 @WebServlet 中的 name 属性的取值,或者是 web.xml 中 <servlet-name> 的取值。 |
dispatcherTypes | DispatcherType | 指定过滤器的转发模式。具体取值包括:ASYNC、ERROR、FORWARD、INCLUDE、REQUEST。 |
initParams | WebInitParam[] | 指定一组过滤器初始化参数,等价于 <init-param> 标签。 |
asyncSupported | boolean | 声明过滤器是否支持异步操作模式,等价于 <async-supported> 标签。 |
description | String | 该过滤器的描述信息,等价于 <description> 标签。 |
displayName | String | 该过滤器的显示名,通常配合工具使用,等价于 <display-name> 标签。 |
@WebFilter(filterName = "FirstFilter", urlPatterns = "/*")
public class FirstFilter implements Filter { //...}
2. 过滤器生命周期
- 初始化 :
Filter.init()
服务器启动后 - 提供服务 :
Filter.doFilter()
- 销毁 :
Filter.destroy()
服务器关闭前
过滤器对象在Web应用启动时被创建且全局唯一。唯一的过滤器 对象在并发环境中采用”多线程“提供服务。
3. 过滤器参数化
过滤器为了增强灵活性,允许配置信息放在web.xml。在web.xml中配置<init-param>
设置过滤器参数
- xml方式
<filter>
<filter-name>First</filter-name>
<filter-class>Filter.FirstFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8
</init-param>
</filter>
<filter-mapping>
<filter-name>First</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
public class FirstFilter implements Filter {
String encoding;
public void init(FilterConfig config) throws ServletException {
encoding = config.getInitParameter("encoding");
}
......
}
- 注解方式
@WebFilter(filterName = "FirstFilter", urlPatterns = "/*",
initParams = {
@WebInitParam(name = "encoding",value = "UTF-8"),
@WebInitParam(name = "P2",value = "V2")
})
public class FirstFilter implements Filter {
String encoding;
public void init(FilterConfig config) throws ServletException {
encoding = config.getInitParameter("encoding");
}
}
4. 过滤链
过滤链过滤器的执行顺序以
<filter-mapping>
的顺序为准。调用chain.doFilter()
将请求向后转递。
- xml方式
<filter>
<filter-name>FilterA</filter-name>
<filter-class>Filter.FilterA</filter-class>
</filter>
<filter-mapping>
<filter-name>FilterA</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>FilterB</filter-name>
<filter-class>Filter.FilterB</filter-class>
</filter>
<filter-mapping>
<filter-name>FilterB</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>FilterC</filter-name>
<filter-class>Filter.FilterC</filter-class>
</filter>
<filter-mapping>
<filter-name>FilterC</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
public class FilterA implements Filter {
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("A is printed")
chain.doFilter(req,resp);
}
}
public class FilterB implements Filter {
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("B is printed")
chain.doFilter(req,resp);
}
}
public class FilterC implements Filter {
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("C is printed")
chain.doFilter(req,resp);
}
}
public class FirstServlet extends HttpServlet {
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Servlet is printed")
}
}
输出:
A is printed
B is printed
C is printed
Servlet is printed
如果将输出语句位置调换
public class FilterA implements Filter {
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
chain.doFilter(req,resp);
System.out.println("A is printed")
}
}
输出:
Servlet is printed
C is printed
B is printed
A is printed
- 注解方式
使用注解方式时,过滤链按照名称的字典顺序,很不合理。
eg:字符集过滤器
Web中文乱码的解决
- GET请求 :server.xml增加URIEncoding="UTF-8"
- POST请求 :使用request.setCharacterEncoding("UTF-8")
- 响应 response.setContentType("text/html;charset=UTF-8")
@WebFilter(filterName = "CharacterEncodingFilter")
public class CharacterEncodingFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//因为Tomcat中request的实现类继承自HttpServletRequest
//所以可以转化为HttpServletRequest,以防ServletRequest不含有某些方法
//详情见前面的 Java Web(3)HttpServletRequest和HttpServletResponse
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
chain.doFilter(request, response);
}
public void init(FilterConfig config) throws ServletException {
}
}
网友评论