第九章_过滤器

简介:

9.1Filter API

过滤器中使用的接口包括FilterFilterConfigFilterChain

过滤器类必须实现javax.servlet.Filter接口。这个接口提供了3个方法:initdoFilterdestroy

当过滤器启动服务时,比如应用程序启动时,Servlet容器就会调用init方法。这个方法只调用一次,并且应该包含过滤器的初始化代码。签名如下:

void init(FilterConfig filterConfig)

每次调用与过滤器相关的资源时,Servlet容器都会调用Filter实例的doFilter方法。该方法会收到一个ServletRequestServletResponseFilteChain

下面是doFilter的签名:

void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)

doFilter方法实现中的最后一行代码应该是调用FilterChain中的doChain方法。

filterChain.doFilter(request, response)

一个资源可以与多个过滤器关联。FilterChain.doFilter()通常会引发调用链中的下一个过滤器被调用。在链中的最后一个过滤器中调用FilterChain.doFilter()会引发资源本身被调用。

如果你没有调用,那么程序的处理将会在这个地方出现停止,并且不会调用请求。

注意:doFilter方法是FilterChain接口中唯一的方法。它与Filter中的doFilter方法稍有不通。在FilterChain中,doFilter只有两个参数,而不是三个。

Filter中的最后一个声明周期方法是destroy,方法签名如下:

void destroy()

这个方法在过滤器即将终止服务之前,由servlet容器调用,一般发生在应用程序停止的时候。

除非一个过滤器类在部署描述符的多个filter元素中进行了声明,否则servlet容器将只给每一类过滤器创建一个实例。由于servlet/JSP应用程序通常是多用户的应用程序,因此可以同时通过多个线程访问一个过滤器实例,但你必须谨慎处理好多线程的问题。

 

9.2、过滤器的配置

FilterConfig访问ServletContext

ServletContext getServletContext()

获取它的名称:

Java.lang.String getFilterName()

获取参数:

java.util.Enumeration<java.lang.String> getInitParameterNames()

java.lang.String getInitParameter(java.lang.String parameterName)

 

配置过滤器有两种方法:

1、利用注解@WebFilter

他有以下属性:

asyncSupported:指定过滤器是否支持异步操作模式

description:过滤器的描述

dispatcherTypes:应用过滤器的dispatcher类型

displayName:过滤器的显示名称

filterName:过滤器的名称

initParams:初始参数

largeIcon:过滤器的大图标名称

servletNames:适用于过滤器的Servlets名称

smallIcon:过滤器的小图标名称

urlPatterns:应用过滤器的URL模式

value:应用过滤器的URL模式

[html]  view plain  copy
 print ?
  1. @WebFilter(filterName="DataCompressionFilter"urlPatterns={"/*"})  
相当于web.xml中的

[html]  view plain  copy
 print ?
  1. <filter>  
  2.     <filter-name>DataCompressionFilter</filter-name>  
  3.     <filter-class>  
  4.         the fully-qualified name of the filter class  
  5.     </filter-class>  
  6.   </filter>  

再举个例子。下面的过滤器中设置了两个初始参数

[html]  view plain  copy
 print ?
  1. @WebFilter(filterName="Security Filter"urlPatterns={"/*"},   
  2.     initParams = {  
  3.         @WebInitParam(name="frequency"value="1909"),  
  4.         @WebInitParam(name="resolution"value="1024")  
  5.     }  
  6. )  
相当于

[html]  view plain  copy
 print ?
  1. <filter>  
  2.     <filter-name>Security Filter</filter-name>  
  3.     <filter-class>filterclass</filter-class>  
  4.     <init-param>  
  5.         <param-name>frequency</param-name>  
  6.         <param-value>1909</param-value>  
  7.     </init-param>  
  8.     <init-param>  
  9.         <param-name>resolution</param-name>  
  10.         <param-value>1024</param-value>  
  11.     </init-param>  
  12.   </filter>  
  13.   <filter-mapping>  
  14.     <filter-name>Security Filter</filter-name>  
  15.     <url-pattern>/*</url-pattern>  
  16.   </filter-mapping>  

9.3、范例1:日志过滤器

来看一个例子,其中有一个简单的过滤器,用于在一个文本文件中记录请求URI。文本文件的名称可以通过一个初始参数进行配置。此外,日志中的每个入口前面都可以添加一个也是初始参数的预设字符串。从日志中可以推断出一些有价值的信息,例如应用程序中的拿一项资源最受欢迎,或者网站每天哪个时间段的访问量最大等。

LoggingFilter.class

[html]  view plain  copy
 print ?
  1. package filter;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileNotFoundException;  
  5. import java.io.IOException;  
  6. import java.io.PrintWriter;  
  7. import java.util.Date;  
  8.   
  9. import javax.servlet.Filter;  
  10. import javax.servlet.FilterChain;  
  11. import javax.servlet.FilterConfig;  
  12. import javax.servlet.ServletException;  
  13. import javax.servlet.ServletRequest;  
  14. import javax.servlet.ServletResponse;  
  15. import javax.servlet.annotation.WebFilter;  
  16. import javax.servlet.annotation.WebInitParam;  
  17. import javax.servlet.http.HttpServletRequest;  
  18. @WebFilter(filterName = "LoggingFilter"urlPatterns = {"/*"},   
  19.     initParams = {  
  20.         @WebInitParam(name = "logFileName"value = "log.txt"),   
  21.         @WebInitParam(name = "prefix"value = "URI: ")  
  22.     }  
  23. )  
  24. public class LoggingFilter implements Filter{  
  25.     private PrintWriter logger ;  
  26.     private String prefix ;  
  27.   
  28.     @Override  
  29.     public void init(FilterConfig filterConfig) throws ServletException {  
  30.         prefix = filterConfig.getInitParameter("prefix") ;  
  31.         String logFileName = filterConfig.getInitParameter("logFileName") ;  
  32.         //容器的路径  
  33.         String appPath = filterConfig.getServletContext().getRealPath("/") ;  
  34.         System.out.println("logFileName:" + logFileName);  
  35.         System.out.println(appPath);  
  36.         try {  
  37.             logger = new PrintWriter(new File(appPath, logFileName)) ;  
  38.         } catch (FileNotFoundException e) {  
  39.             e.printStackTrace();  
  40.             throw new ServletException(e.getMessage()) ;  
  41.         }  
  42.     }  
  43.       
  44.     @Override  
  45.     public void doFilter(ServletRequest request, ServletResponse response,  
  46.             FilterChain filterChain) throws IOException, ServletException {  
  47.         System.out.println("LoggingFilter.doFilter");  
  48.         HttpServletRequest httpServletRequest = (HttpServletRequest)request ;  
  49.         logger.println(new Date() + " " + prefix + httpServletRequest.getRequestURI());  
  50.         logger.flush();   
  51.         filterChain.doFilter(request, response);  
  52.     }  
  53.       
  54.     @Override  
  55.     public void destroy() {  
  56.         System.out.println("destroying filter");  
  57.         if(logger != null){  
  58.             logger.close();   
  59.         }  
  60.     }  
  61.       
  62.   
  63. }  

例如,我输入http://localhost:8089/filter/

在tomcat的项目目录下生成一个log.txt文件并记录刚才的访问。




9.4、范例2:图片保护过滤器

本例中的ImageProtectorFilter防止通过在浏览器的地址栏中直接输入图片URL来下载图片。只有在页面中单击图片的链接时,才会显示应用程序中的图片。过滤器通过查看HTTP标头referer的值进行工作。值为空表示当前请求没有相当的引用页,换句话说,该资源是直接输入其URL进行请求的。标头referer值非空的资源,将以原始页面作为引用页。

ImageProtectorFilter.java

[html]  view plain  copy
 print ?
  1. package filter;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import javax.servlet.Filter;  
  6. import javax.servlet.FilterChain;  
  7. import javax.servlet.FilterConfig;  
  8. import javax.servlet.ServletException;  
  9. import javax.servlet.ServletRequest;  
  10. import javax.servlet.ServletResponse;  
  11. import javax.servlet.annotation.WebFilter;  
  12. import javax.servlet.http.HttpServletRequest;  
  13.   
  14. @WebFilter(filterName = "ImageProtetorFilter"urlPatterns = {"*.png","*.jpg","*.gif"})  
  15. public class ImageProtectorFilter implements Filter{  
  16.   
  17.     @Override  
  18.     public void destroy() {  
  19.     }  
  20.   
  21.     @Override  
  22.     public void doFilter(ServletRequest request, ServletResponse response,  
  23.             FilterChain chain) throws IOException, ServletException {  
  24.         System.out.println("ImageProtecorFilter");  
  25.         HttpServletRequest httpServletRequest = (HttpServletRequest)request ;  
  26.         String referer = httpServletRequest.getHeader("referer") ;  
  27.         System.out.println("referer:" + referer);  
  28.         if(referer != null){  
  29.             chain.doFilter(request, response);  
  30.         }else{  
  31.             throw new ServletException("Image not availabe") ;  
  32.         }  
  33.     }  
  34.   
  35.     @Override  
  36.     public void init(FilterConfig filterConfig) throws ServletException {  
  37.     }  
  38.   
  39. }  

image.jsp
[html]  view plain  copy
 print ?
  1. <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>  
  2. <html>  
  3.   <head>  
  4.     <title>image</title>  
  5.   </head>  
  6.     
  7.   <body>  
  8.     <img src="image/logo.png"/>  
  9.   </body>  
  10. </html>  
当直接在浏览器中输入:http://localhost:8089/filter/image/logo.png

会出现错误: Image not availabe

通过访问浏览器:http://localhost:8089/filter/image.jsp可以得到图片


9.5、范例3:下载计数过滤器

本例中的下载计数过滤器可以计算某一个资源被下载了多少次。当你想要知道你的文档或者视频的受欢迎程度时,这个就很有帮助了。为了简便起见,这些数字会被保存在一个属性文件中,而不是保存在一个数据库中。资源URI做为属性文件的属性键。

DownloadCounterFilter.java

[html]  view plain  copy
 print ?
  1. package filter;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileNotFoundException;  
  5. import java.io.FileReader;  
  6. import java.io.FileWriter;  
  7. import java.io.IOException;  
  8. import java.util.Properties;  
  9. import java.util.concurrent.ExecutorService;  
  10. import java.util.concurrent.Executors;  
  11.   
  12. import javax.servlet.Filter;  
  13. import javax.servlet.FilterChain;  
  14. import javax.servlet.FilterConfig;  
  15. import javax.servlet.ServletException;  
  16. import javax.servlet.ServletRequest;  
  17. import javax.servlet.ServletResponse;  
  18. import javax.servlet.annotation.WebFilter;  
  19. import javax.servlet.http.HttpServletRequest;  
  20. @WebFilter(filterName = "DownloadCounterFilter"urlPatterns = {"/*"})  
  21. public class DownloadCounterFilter implements Filter{  
  22.     ExecutorService executorService = Executors.newSingleThreadExecutor() ;  
  23.     Properties downloadLog ;  
  24.     File logFile ;  
  25.     @Override  
  26.     public void destroy() {  
  27.         // TODO Auto-generated method stub  
  28.         executorService.shutdown();  
  29.     }  
  30.   
  31.     @Override  
  32.     public void doFilter(ServletRequest request, ServletResponse response,  
  33.             FilterChain chain) throws IOException, ServletException {  
  34.         // TODO Auto-generated method stub  
  35.         HttpServletRequest httpServletRequest = (HttpServletRequest)request ;  
  36.         final String uri = httpServletRequest.getRequestURI() ;  
  37.         executorService.execute(new Runnable(){  
  38.             @Override  
  39.             public void run() {  
  40.                 // TODO Auto-generated method stub  
  41.                 String property = downloadLog.getProperty(uri) ;  
  42.                 if(property == null){  
  43.                     downloadLog.setProperty(uri, "1") ;  
  44.                 }else{  
  45.                     int count = 0 ;  
  46.                     try {  
  47.                         count = Integer.parseInt(property) ;  
  48.                     } catch (NumberFormatException e) {  
  49.                         e.printStackTrace();  
  50.                     }  
  51.                     count ++ ;  
  52.                     downloadLog.setProperty(uri, Integer.toString(count)) ;  
  53.                 }  
  54.                 try {  
  55.                     downloadLog.store(new FileWriter(logFile), "");  
  56.                 } catch (IOException e) {  
  57.                     e.printStackTrace();  
  58.                 }  
  59.             }  
  60.         });  
  61.         chain.doFilter(request, response);  
  62.     }  
  63.   
  64.     @Override  
  65.     public void init(FilterConfig filterConfig) throws ServletException {  
  66.         // TODO Auto-generated method stub  
  67.         System.out.println("DownloadCounterFilter");  
  68.         String appPath = filterConfig.getServletContext().getRealPath("/") ;  
  69.         logFile = new File(appPath, "downloadLog.txt") ;  
  70.         if(!logFile.exists()){  
  71.             try {  
  72.                 logFile.createNewFile() ;  
  73.             } catch (IOException e) {  
  74.                 e.printStackTrace();  
  75.             }  
  76.         }  
  77.         downloadLog = new Properties() ;  
  78.         try {  
  79.             downloadLog.load(new FileReader(logFile));  
  80.         } catch (FileNotFoundException e) {  
  81.             e.printStackTrace();  
  82.         } catch (IOException e) {  
  83.             e.printStackTrace();  
  84.         }  
  85.     }  
  86.   
  87. }  

9.6、过滤器的顺序

如果多个过滤器应用于同一个资源,那么调用顺序就很重要,必须用部署描述符管理应该先调用哪一个过滤器。加入filter1必须在filter2之前调用,那么在部署描述符中,Filter1的声明就要放在Filter2的声明之前。

目录
相关文章
|
3月前
|
设计模式
深入浅出过滤器模式
深入浅出过滤器模式
22 0
|
8月前
|
前端开发
前端学习笔记202303学习笔记第五天-声明和使用过滤器
前端学习笔记202303学习笔记第五天-声明和使用过滤器
39 0
|
9月前
JavaWeb第十二章课后题 过滤器Filter详解
JavaWeb第十二章课后题 过滤器Filter详解
106 0
|
7月前
|
设计模式 NoSQL Java
如何用最简单的方式解释依赖注入?
如何用最简单的方式解释依赖注入?
42 0
|
11月前
|
前端开发
前端学习笔记202303学习笔记第五天-私有过滤器和全局过滤器
前端学习笔记202303学习笔记第五天-私有过滤器和全局过滤器
49 0
|
11月前
|
前端开发
前端学习笔记202303学习笔记第五天-使用全局过滤器过滤时间
前端学习笔记202303学习笔记第五天-使用全局过滤器过滤时间
35 0
|
前端开发
前端工作小结23-过滤器的使用
前端工作小结23-过滤器的使用
55 0
前端工作小结23-过滤器的使用
|
前端开发 Java 应用服务中间件
SpringMVC——框架概述&第一个注解的SpringMVC程序
SpringMVC——框架概述&第一个注解的SpringMVC程序
SpringMVC——框架概述&第一个注解的SpringMVC程序
|
数据安全/隐私保护
过滤器 - 基础篇
过滤器 - 基础篇
147 0
过滤器 - 基础篇
过滤器知识点20160907
过滤器知识点20160907
70 0