第九章_过滤器
来源:互联网 发布:淘宝网客服电话多少 编辑:程序博客网 时间:2024/05/16 06:45
9.1、Filter API
过滤器中使用的接口包括Filter、FilterConfig和FilterChain
过滤器类必须实现javax.servlet.Filter接口。这个接口提供了3个方法:init、doFilter和destroy。
当过滤器启动服务时,比如应用程序启动时,Servlet容器就会调用init方法。这个方法只调用一次,并且应该包含过滤器的初始化代码。签名如下:
void init(FilterConfig filterConfig)
每次调用与过滤器相关的资源时,Servlet容器都会调用Filter实例的doFilter方法。该方法会收到一个ServletRequest、ServletResponse和FilteChain。
下面是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模式
@WebFilter(filterName="DataCompressionFilter", urlPatterns={"/*"})相当于web.xml中的
<filter> <filter-name>DataCompressionFilter</filter-name> <filter-class> the fully-qualified name of the filter class </filter-class> </filter>
再举个例子。下面的过滤器中设置了两个初始参数
@WebFilter(filterName="Security Filter", urlPatterns={"/*"}, initParams = {@WebInitParam(name="frequency", value="1909"),@WebInitParam(name="resolution", value="1024")})相当于
<filter> <filter-name>Security Filter</filter-name> <filter-class>filterclass</filter-class> <init-param> <param-name>frequency</param-name> <param-value>1909</param-value> </init-param> <init-param> <param-name>resolution</param-name> <param-value>1024</param-value> </init-param> </filter> <filter-mapping> <filter-name>Security Filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
9.3、范例1:日志过滤器
来看一个例子,其中有一个简单的过滤器,用于在一个文本文件中记录请求URI。文本文件的名称可以通过一个初始参数进行配置。此外,日志中的每个入口前面都可以添加一个也是初始参数的预设字符串。从日志中可以推断出一些有价值的信息,例如应用程序中的拿一项资源最受欢迎,或者网站每天哪个时间段的访问量最大等。
LoggingFilter.class
package filter;import java.io.File;import java.io.FileNotFoundException;import java.io.IOException;import java.io.PrintWriter;import java.util.Date;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.annotation.WebFilter;import javax.servlet.annotation.WebInitParam;import javax.servlet.http.HttpServletRequest;@WebFilter(filterName = "LoggingFilter", urlPatterns = {"/*"}, initParams = {@WebInitParam(name = "logFileName", value = "log.txt"), @WebInitParam(name = "prefix", value = "URI: ")})public class LoggingFilter implements Filter{private PrintWriter logger ;private String prefix ;@Overridepublic void init(FilterConfig filterConfig) throws ServletException {prefix = filterConfig.getInitParameter("prefix") ;String logFileName = filterConfig.getInitParameter("logFileName") ;//容器的路径String appPath = filterConfig.getServletContext().getRealPath("/") ;System.out.println("logFileName:" + logFileName);System.out.println(appPath);try {logger = new PrintWriter(new File(appPath, logFileName)) ;} catch (FileNotFoundException e) {e.printStackTrace();throw new ServletException(e.getMessage()) ;}}@Overridepublic void doFilter(ServletRequest request, ServletResponse response,FilterChain filterChain) throws IOException, ServletException {System.out.println("LoggingFilter.doFilter");HttpServletRequest httpServletRequest = (HttpServletRequest)request ;logger.println(new Date() + " " + prefix + httpServletRequest.getRequestURI());logger.flush(); filterChain.doFilter(request, response);}@Overridepublic void destroy() {System.out.println("destroying filter");if(logger != null){logger.close(); }}}
例如,我输入http://localhost:8089/filter/
在tomcat的项目目录下生成一个log.txt文件并记录刚才的访问。
9.4、范例2:图片保护过滤器
本例中的ImageProtectorFilter防止通过在浏览器的地址栏中直接输入图片URL来下载图片。只有在页面中单击图片的链接时,才会显示应用程序中的图片。过滤器通过查看HTTP标头referer的值进行工作。值为空表示当前请求没有相当的引用页,换句话说,该资源是直接输入其URL进行请求的。标头referer值非空的资源,将以原始页面作为引用页。
ImageProtectorFilter.javapackage filter;import java.io.IOException;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.annotation.WebFilter;import javax.servlet.http.HttpServletRequest;@WebFilter(filterName = "ImageProtetorFilter", urlPatterns = {"*.png","*.jpg","*.gif"})public class ImageProtectorFilter implements Filter{@Overridepublic void destroy() {}@Overridepublic void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {System.out.println("ImageProtecorFilter");HttpServletRequest httpServletRequest = (HttpServletRequest)request ;String referer = httpServletRequest.getHeader("referer") ;System.out.println("referer:" + referer);if(referer != null){chain.doFilter(request, response);}else{throw new ServletException("Image not availabe") ;}}@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}}
image.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><html> <head> <title>image</title> </head> <body> <img src="image/logo.png"/> </body></html>当直接在浏览器中输入:http://localhost:8089/filter/image/logo.png
会出现错误: Image not availabe
通过访问浏览器:http://localhost:8089/filter/image.jsp可以得到图片
9.5、范例3:下载计数过滤器
本例中的下载计数过滤器可以计算某一个资源被下载了多少次。当你想要知道你的文档或者视频的受欢迎程度时,这个就很有帮助了。为了简便起见,这些数字会被保存在一个属性文件中,而不是保存在一个数据库中。资源URI做为属性文件的属性键。
DownloadCounterFilter.javapackage filter;import java.io.File;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;import java.util.Properties;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.annotation.WebFilter;import javax.servlet.http.HttpServletRequest;@WebFilter(filterName = "DownloadCounterFilter", urlPatterns = {"/*"})public class DownloadCounterFilter implements Filter{ExecutorService executorService = Executors.newSingleThreadExecutor() ;Properties downloadLog ;File logFile ;@Overridepublic void destroy() {// TODO Auto-generated method stubexecutorService.shutdown();}@Overridepublic void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {// TODO Auto-generated method stubHttpServletRequest httpServletRequest = (HttpServletRequest)request ;final String uri = httpServletRequest.getRequestURI() ;executorService.execute(new Runnable(){@Overridepublic void run() {// TODO Auto-generated method stubString property = downloadLog.getProperty(uri) ;if(property == null){downloadLog.setProperty(uri, "1") ;}else{int count = 0 ;try {count = Integer.parseInt(property) ;} catch (NumberFormatException e) {e.printStackTrace();}count ++ ;downloadLog.setProperty(uri, Integer.toString(count)) ;}try {downloadLog.store(new FileWriter(logFile), "");} catch (IOException e) {e.printStackTrace();}}});chain.doFilter(request, response);}@Overridepublic void init(FilterConfig filterConfig) throws ServletException {// TODO Auto-generated method stubSystem.out.println("DownloadCounterFilter");String appPath = filterConfig.getServletContext().getRealPath("/") ;logFile = new File(appPath, "downloadLog.txt") ;if(!logFile.exists()){try {logFile.createNewFile() ;} catch (IOException e) {e.printStackTrace();}}downloadLog = new Properties() ;try {downloadLog.load(new FileReader(logFile));} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}}
9.6、过滤器的顺序
如果多个过滤器应用于同一个资源,那么调用顺序就很重要,必须用部署描述符管理应该先调用哪一个过滤器。加入filter1必须在filter2之前调用,那么在部署描述符中,Filter1的声明就要放在Filter2的声明之前。
- 第九章_过滤器
- LINUX基础第九章笔记_压缩
- C和指针--第九章_问题
- Android开发艺术探索_第九章
- 《Apache MINA 2.0 用户指南》第九章:编解码器过滤器
- 《Apache MINA 2.0 用户指南》第九章:编解码器过滤器
- MC9S12XEP100RMV10打印_第九章_安全加密
- 多线程并发实践_笔记_第九章
- C++primer_第九章_顺序容器_学习跟踪
- 读书笔记_大话数据结构第九章_排序
- 行为模式_过滤器
- 【web】赵雅智_过滤器
- AngularJS(六)_过滤器 |
- 第九章 Java多线程机制 05_线程同步_ 12_总结
- 黑马程序员_高新技术学习笔记第九章
- 第九章 Java多线程机制 01_线程的基本概念
- 第九章 Java多线程机制 04_举例
- 第九章 Java多线程机制 05_线程同步_1
- HDOJ 4888 Redraw Beautiful Drawings && HDOJ 4975 A simple Gaussian elimination problem
- C语言排序算法实现之插入排序
- 一个非常简单的C++内存池方案
- 转载_BlueTooth: 蓝牙基带
- java 静态代码块执行顺序
- 第九章_过滤器
- 关于shape和layer-list结合使用的一点用法
- 生成树的计数
- oracle 自动生成手机号码
- IOS ARC内存管理,提高效率避免内存泄露
- 百度提前批三面面经
- bootstrap ie6 一个实例
- 快速模糊 FastBlur
- android camera 架构浅析-------------360 图书馆