1. 过滤器简介:
在一个Web应用中,有很多web组件,它们都用于响应特定的客户请求。不过,在这些web组件响应客户请求的过程中,可能都会完成一些相同的操作。如果在多个web组件中编写完成同样操作的程序代码,显然会导致重复编码,从而降低开发效率和软件的可维护性。
为了解决上述问题,过滤器Filter应运而生。它是在Java Servlet 2.3规范中出现的技术,Filter可认为是Servlet的一种加强版。过滤器能够对一部分客户请求先进行预处理,然后再把请求转发给相应的web组件,等到web组件生成了响应结果后,过滤器还能对响应结果进行检查和修改,然后再把修改后的响应结果发送给客户。各个web组件中的相同操作可以放到同一个过滤器中来完成,这样就能减少重复编码。
2. 过滤器的过滤功能:
1. 过滤器能够在目标web组件被调用之前检查ServletRequest对象,修改请求头和请求正文的内容,或者对请求进行预处理操作。
2. 过滤器能够在目标web组件被调用之后检查ServletResponse对象,修改响应头和响应正文。
3. 过滤器Filter的常见种类:
1. 用户授权的Filter:Filter负责检查用户请求,根据请求过滤用户的非法请求。
2. 日志Filter:详细记录某些特殊的用户请求。
3. 负责解码的Filter:包括对非标准编码的请求进行解码。
4. 能改变XML内容的XSLT Filter等。
5. Filter可负责拦截多个请求或响应,一个请求或响应也可被多个Filter拦截。
4. 过滤器Filter的实现:
创建Filter必须实现javax.servlet.Filter接口,在该接口中定义了如下三个方法:
1. void init(FilterConfig config):用于完成Filter的初始化。
2. void destroy():用于Filter销毁前,完成某些资源的回收。
3. void doFilter(ServletRequest request,ServletResponse response,FilterChain chain):实现过滤功能,该方法就是对每个请求及响应增加的额外处理。
实现doFilter()方法就可实现对用户请求进行预处理,也可实现对服务器响应进行后处理。它们的分界线为是否调用了
chain.doFilter(...)。执行该方法之前,即对用户请求进行预处理,执行该方法之后,即对服务器响应进行后处理。
Filter的配置:
<filter>
<filter-name>XXX</filter-name>
<filter-class>XXX</filter-class>
</filter>
<filter-mapping>
<filter-name>XXX</filter-name>
<url-pattern>XXX</url-pattern>
</filter-mapping>
url-pattern配置Filter拦截的URL模式。Filter可以同时拦截多个请求,因此在配置Filter的URL模式时通常会使用模式字符串。譬如" /* "即表示该Filter会拦截所有用户请求。
看个例子吧:
各文件源代码:
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<filter>
<filter-name>CommentContentFilter</filter-name>
<filter-class>web.CommentContentFilter</filter-class>
<init-param>
<param-name>illegalString</param-name>
<param-value>sex,gay</param-value>
</init-param>
</filter>
<filter>
<filter-name>CommentSizeFilter</filter-name>
<filter-class>web.CommentSizeFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CommentSizeFilter</filter-name>
<url-pattern>/comment</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CommentContentFilter</filter-name>
<url-pattern>/comment</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>CommentServlet</servlet-name>
<servlet-class>web.CommentServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CommentServlet</servlet-name>
<url-pattern>/comment</url-pattern>
</servlet-mapping>
</web-app>
comment.jsp :
<%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="comment" method="post">
<input type="text" name="comment"><input type="submit" value="confirm">
</form>
</body>
</html>
CommentServlet.java:
public class CommentServlet extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter pw=response.getWriter();
String comment=request.getParameter("comment");
pw.println("<h3>"+comment+"</h3>");
}
}
CommentContentFilter.java:
public class CommentContentFilter implements Filter{
private FilterConfig config;
@Override
public void destroy() {
System.out.println("destroy...");
}
@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
System.out.println("Content doFilter...");
HttpServletRequest request=(HttpServletRequest)req;
HttpServletResponse response=(HttpServletResponse)res;
String comment=request.getParameter("comment");
String illegalString=config.getInitParameter("illegalString");
System.out.println(illegalString);//sex,gay
PrintWriter pw=response.getWriter();
String[] illegals=illegalString.split(",");
for(int i=0;i<illegals.length;i++){
String illegal=illegals[i];
if(comment.indexOf(illegal)>=0){
pw.println("<h3>illegal string...</h3>");
return;
}
}
chain.doFilter(request, response);
pw.println("<h3>Content doFilter has executed...</h3>");
}
@Override
public void init(FilterConfig config) throws ServletException {
this.config=config;
System.out.println("init...");
}
}
CommentSizeFilter.java:
public class CommentSizeFilter implements Filter {
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
System.out.println("Size doFilter...");
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
PrintWriter pw=response.getWriter();
String comment = request.getParameter("comment");
if(comment.length()>10){
pw.println("<h3>Comment's size illegal...</h3>");
return;
}
chain.doFilter(request, response);
pw.println("<h3>Size doFilter has executed...</h3>");
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
}
这两个过滤器会过滤长度超过10的评论以及含sex,gay等字眼的评论!