过滤器是应用在容器和servlet之间的一个类,在服务器启动是由容器创建,过滤器需要声明是对哪个servlet或者是url-pattern过滤。所以在web.xml需要这么写:
<filter>
<filter-name></filter-name>
<filter-class></filter-class>
</filter>
<filter-mapping>
<filter-name></filter-name>
<url-pattern></url-pattern>
//和下面的servlet-name只能存在一个
<servlet-name></servlet-name>
</filter-mapping>
</filter>
-----------
然后在创建这个Filter类的时候和创建xxx类似,也需要实现Filter接口,实现其中的方法。
init()
doFilter()
destroy(),分别是在创建过滤器的时候,过滤的时候,销毁过滤器的时候。
我们重点关注doFilter(request,response,fiterChain)这个方法。如果在过滤器过滤用户请求的时候,我们会得到:请求对象,响应对象以及过滤链对象。
在过滤的时候,利用这3个对象可以做很多操作。比如:
public class CharFilter implements Filter {
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest arg0,
ServletResponse arg1,
FilterChain
arg2) throws IOException, ServletException {
HttpServletRequest
request = (HttpServletRequest)arg0;
HttpServletResponse response =
(HttpServletResponse)arg1;
response.setContentType("text/html;charset=gbk");
arg2.doFilter(new
MyRequest(request), arg1);
}
//内部类,创建了一个httpServletRequest的子类。以便能传到过滤链对象的doFilter方法中。
public class MyRequest extends
HttpServletRequestWrapper{
private HttpServletRequest
request;
public
MyRequest(HttpServletRequest request) {
super(request);
this.request
= request;
}
//重写了getParameter方法,让Servlet调用此方法时,得到我们包装过后的值。
@Override
public String
getParameter(String name) {
String value
= this.request.getParameter(name);
if(value ==
null){
return
null;
}
try {
byte[]
by = value.getBytes("ISO8859-1");
value
= new String(by,"gbk");
} catch
(UnsupportedEncodingException e) {
e.printStackTrace();
}
if(value.indexOf("他妈的")
!= -1){
value
= value.replaceAll("他妈的", "");
}
return
value;
}
}
@Override
public void init(FilterConfig arg0) throws
ServletException {
}
}
----------------------------
1.上面代码过滤器代码部分,将响应对象的格式设置成了gbk格式,并且偷梁换柱的把本来的ServletRequest
arg0换成了我们新写的一个请求对象。达到了过滤的目的。
2.内部类部部分,利用ServletRequestWrapper这个包装器,用原来的请求对象作为参数,传到自定义的内中,重写getParameter的方法,但是其实仍然是调用之前的请求对象,获得值之后,对他进行过滤。
-------------------
像ServletRequestWrapper这种类,就被称作是包装器,就是专门用来包装请求 或响应对象的。