过滤器介绍
- 过滤器是servlet规范当中定义的一种特殊组件,用来拦截容器的调用过程。通过Filter技术,可以管理web服务器的所有web资源,例如servlet,jsp,静态图片文件或静态html文件等进行拦截,从而实现一些特殊的功能。例如实现url级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。
下面先介绍代码:
public class FileterDemo1 implements Filter {
private FilterConfig config;//保存容器传递过来的FilterConfig对象,它可以用来获取过滤器初始化参数
public FileterDemo1() {
System.out.println("===过滤器实例化===");
}
public void destroy() {
System.out.println("===过滤器销毁===");
}
/**
* 在调用目标资源执之前,先执行此方法
*/
public void doFilter(
ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
System.out.println("FilterDemo1执行前");
/*对request和response进行一些处理*/
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
String content = request.getParameter("content");//得到表单提交内容
String illegal = config.getInitParameter("illegal");//得到配置的过滤器初始化参数
if(content.indexOf(illegal)!=-1) {//如果评论内容有设置的敏感词,就不再调用目标资源的service方法
out.println("评论内容含有敏感词");
}else {
/*如果评论内容正常,就会去调用目标资源(这里是一个servlet)的service方法*/
chain.doFilter(request, response);
}
System.out.println("FilterDemo1执行后");
}
public void init(FilterConfig fConfig) throws ServletException {
config = fConfig;//将容器传递过来的FilterConfig对象保存下来
System.out.println("===过滤器初始化===");
}
}
下面是要过滤的资源(servlet)的代码
public void service(
HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
System.out.println("service begin...");
String content = request.getParameter("content");
PrintWriter out = response.getWriter();
out.println("你的看法是:"+content);
System.out.println("service end....");
}
}
下面是用户提交内容的表单的代码
<body>
<form action="CommentServlet" method="post">
请输入评论内容:<input name="content" />
<input type="submit" value="确定"/>
</form>
</body>
下面是过滤器和servlet的配置信息
<filter>
<display-name>FileterDemo1</display-name>
<filter-name>FileterDemo1</filter-name>
<filter-class>demo4.FileterDemo1</filter-class>
<init-param>
<param-name>illegal</param-name>
<param-value>大</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>FileterDemo1</filter-name>
<!-- <url-pattern>/*</url-pattern> -->
<servlet-name>CommentServlet</servlet-name>
</filter-mapping>
<servlet>
<description></description>
<display-name>CommentServlet</display-name>
<servlet-name>CommentServlet</servlet-name>
<servlet-class>demo4.CommentServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CommentServlet</servlet-name>
<url-pattern>/CommentServlet</url-pattern>
</servlet-mapping>
下面是程序运行效果:
没有敏感词:
评论带有敏感词的:从配置文件可以看出配置的敏感词是”大”
下面总结以下过滤器的实现步骤
- 编写java类,需要实现Filter接口,当然用开发工具可以直接新建一个Filter,在这个java类里写过滤逻辑
在web.xml配置过滤器:主要是两大项
注册Filter:在
<filter>
元素里注册,其中:<filter-name>
是为过滤器指定一个名字,可以随意写,但是不能为空<filter-class>
指定过滤器的完整的限定类名,从包名开始<init-param>
用于为过滤器指定初始化参数,它的子元素<param-name>
指定参数的名字 ,<param-value>
指定参数值,可以使用FilterConfig对象利用参数名得到参数值,当然<init-param>
也可以不配置
映射Filter:在
<filter-mapping>
配置<filter-mapping>
设置一个Filter所负责拦截的资源。一个Filter拦截的资源可以通过两种方式指定:servlet名称和资源访问的请求路径<filter-name>
设置Filter的注册名,该值必须和<filter>
元素中的一样<url-pattern>
设置filter所拦截的请求路径(过滤关联的URL样式)<servlet-name>
指定过滤器所拦截的servlet名称<dispatcher>
指定过滤器所拦截的资源被servlet容器调用的方式,可以是REQUEST,INCLUDE,FORWARD和ERROR之一,默认REQUEST。此元素可以设置多个,其中:- REQUEST:当用户直接访问页面时,Web容器将会调用过滤器。如果目标资源是通过RequestDispatcher的include()或forward()方法访问时,那么该过滤器就不会被调用。
- INCLUDE:如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用。
- FORWARD:如果目标资源是通过RequestDispatcher的forward()方法访问时,那么该过滤器将被调用,除此之外,该过滤器不会被调用。
- ERROR:如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。
Filter链:
在一个web应用中,可以开发编写多个Filter,这些Filter组合起来称之为一个Filter链。
web服务器根据Filter在web.xml文件中的注册顺序,决定先调用哪个Filter,当第一个Filter的doFilter方法被调用时,web服务器会创建一个代表Filter链FilterChain对象传递给该方法。在doFilter方法中,开发人员如果调用了FilterChain对象的doFilter方法,则web服务器会检查FilterChain对象中是否还有 filter,如果有,则调用第2个filter,如果没有,则调用目标资源。
Filter的声明周期
Filter的实例化和初始化: web容器启动时,就会创建Filter的实例对象,并调用其init方法,完成对象的初始化功能。Filter对象只会创建一次,init方法也只会执行一次。通过init方法的参数,可以得到代表filter配置信息的FilterConfig对象。
Filter的销毁 :web容器调用destroy方法销毁Filter,destroy方法在Filter的声明周期也只会执行一次,在该方法中,可以释放过滤器使用的资源。
FilterConfig接口: 用户在配置filter时,可以使用
<init-param>
为filter配置一些初始化参数,当web容器实例化Filter对象,调用其init方法时,会把封装filter初始化参数的filterConfig对象传递进来。因此开发人员在编写filter时,通过filterConfig对象的方法,就可获得:String getFilterName():得到filter的名称
String getInitParameter(String name): 返回在部署描述中指定名称的初始化参数的值。如果不存在返回null.
public ServletContext getServletContext():返回Servlet上下文对象的引用。