Filter
Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。
Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter。通过Filter技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截,如下所示:
当然,Filter是如何实现拦截的呢?
Filter接口中有一个doFilter方法,当我们编写好Filter,并配置对哪个web资源进行拦截后,WEB服务器每次在调用web资源的service方法之前,都会先调用一下filter的doFilter方法,因此,在该方法内编写代码可达到如下目的:
- 调用目标资源之前,让一段代码执行。
- 是否调用目标资源(即是否让用户访问web资源)。
- 调用目标资源之后,让一段代码执行。
web服务器在调用doFilter方法时,会传递一个filterChain对象进来,filterChain对象是filter接口中最重要的一个对 象,它也提供了一个doFilter方法,开发人员可以根据需求决定是否调用此方法,调用该方法,则web服务器就会调用web资源的service方 法,即web资源就会被访问,否则web资源不会被访问
因此,过滤器一般用于登录权限验证、资源访问权限控制、敏感词汇过滤、字符编码转换等等操作,便于代码重用,不必每个servlet中还要进行相应的操作。
下面是过滤器的简单应用:
1:创建过滤器
如图,新建一个class,实现接口Filter(注意:是javax.servlet中的Filter)。
2:重写过滤器的doFilter(request,response,chain)方法。另外两个init()、destroy()方法一般不需要重写。在doFilter方法中进行过滤操作。
常用代码有:获取请求、获取响应、获取session、放行。
剩下的代码就是根据session的属性进行过滤操作、设置编码格式等等了,看情况而定。
HttpServletRequest request=(HttpServletRequest) arg0;//获取request对象 HttpServletResponse response=(HttpServletResponse) arg1;//获取response对象 HttpSession session=request.getSession();//获取session对象
过滤操作代码......
chain.doFilter(request, response);//放行,通过了当前过滤器,递交给下一个filter进行过滤
3:在web.xml中配置过滤器。这里要谨记一条原则:在web.xml中,监听器>过滤器>servlet。也就是说web.xml中监听器配置在过滤器之前,过滤器配置在servlet之前,否则会出错。
<filter> <filter-name>loginFilter</filter-name>//过滤器名称 <filter-class>com.ygj.control.loginFilter</filter-class>//过滤器类的包路径 <init—param> //可选 <param—name>参数名</param-name>//过滤器初始化参数 <param-value>参数值</param-value> </init—pamm> </filter>
<filter-mapping>//过滤器映射 <filter-name>loginFilter</filter-name> <url—pattern>指定过滤器作用的对象</url-pattern>
在配置中需要注意的有两处:一是<filter-class>指明过滤器类所在的包路径。二是<url-pattren>处定义过滤器作用的对象。一般有以下规则:
1:作用与所有web资源:<url—pattern>/*</url-pattern>。则客户端请求访问任意资源文件时都要经过过滤器过滤,通过则访问文件,否则拦截。
2:作用于某一文件夹下所有文件:<url—pattern>/dir/*</url-pattern>
3:作用于某一种类型的文件:<url—pattern>*.扩展名</url-pattern>。比如<url—pattern>*.jsp</url-pattern>过滤所有对jsp文件的访问请求。
4:作用于某一文件夹下某一类型文件:<url—pattern>/dir/*.扩展名</url-pattern>
如果一个过滤器需要过滤多种文件,则可以配置多个<filter-mapping>,一个mapping定义一个url-pattern来定义过滤规则。
<filter> <filter-name>loginFilter</filter-name> <filter-class>com.ygj.control.loginFilter</filter-class> </filter> <filter-mapping> <filter-name>loginFilter</filter-name> <url-pattern>*.jsp</url-pattern> </filter-mapping> <filter-mapping> <filter-name>loginFilter</filter-name> <url-pattern>*.do</url-pattern> </filter-mapping>
例1:用过滤器实现登录验证,没登录则驳回访问请求并重定向到登录页面。
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException { HttpServletRequest request=(HttpServletRequest) arg0; HttpServletResponse response=(HttpServletResponse) arg1; HttpSession session=request.getSession(); String path=request.getRequestURI(); Integer uid=(Integer)session.getAttribute("userid"); if(path.indexOf("/login.jsp")>-1){//登录页面不过滤 arg2.doFilter(arg0, arg1);//递交给下一个过滤器 return; } if(path.indexOf("/register.jsp")>-1){//注册页面不过滤 arg2.doFilter(request, response); return; } if(uid!=null){//已经登录 arg2.doFilter(request, response);//放行,递交给下一个过滤器 }else{ response.sendRedirect("login.jsp"); } }
例2:设置字符编码
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest request2=(HttpServletRequest) request; HttpServletResponse response2=(HttpServletResponse) response; request2.setCharacterEncoding("UTF-8"); response2.setCharacterEncoding("UTF-8"); chain.doFilter(request, response); }