您现在的位置:首页 >> 前端 >> 内容

三个实例带你走进web过滤器

时间:2017/4/8 9:24:06 点击:

  核心提示:web过滤器过滤器是指拦截请求,并对传给被请求资源的ServletRequest或ServletResponse进行处理的一个对象。过滤器可用于登录、加密和解密、对话检查、图片转换等待。过滤器可以配置...

web过滤器

过滤器是指拦截请求,并对传给被请求资源的ServletRequest或ServletResponse进行处理的一个对象。

过滤器可用于登录、加密和解密、对话检查、图片转换等待。过滤器可以配置拦截一个或者多个资源

1.Filter API

过滤器必须实现javax.servret.Filter接口,这个接口暴露三个生命周期方法:init,doFilter,destroy

当过滤器启动服务时,Servlet容器就会调用init方法。这个方法指调用一次

void init(FilterConfig filterConfig)

filterConfig可用于获取ServletContext对象,或者获取初始化属性(getInitParameter)

doFilter方法时过滤器核心

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

可以在ServletRequest 中添加属性,或者在ServletResponse添加一个标头

也可以获取HttpServletRequest对象

doFilter方法实现中的最后一行代码应该时调用FilterChain中的doFilter(request,response)方法

表示放行,通常会引发下一个过滤器被调用。

void destroy()

这个方法在过滤器即将终止服务之前,有servlet容器调用

2.过滤器的配置

确定要拦截哪些资源 (urlPatterns value)

要传给init方法的启动初始值(initParams) 可通过getParameterNames 和getParameter方法来获取

给过滤器七个名字(filterName)

可以通过@webFilter注解 和部署描述符中声明

下面通过三个实例来带你了解神秘的过滤器

实例一:日志过滤器

通过一个过滤器,用于在一个文本文件中记录请求的URI。从日志中 可以推断出一些有价值的信息,例如

应用程序中哪一项资源最受欢迎,获知网站每天哪个时间段的访问量最多

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 String prefix;

private PrintWriter logger;

@Override

public void destroy() {

// TODO Auto-generated method stub

System.out.println("destroying filter");

if(logger!=null){

logger.close();

}

}

@Override

public void doFilter(ServletRequest arg0, ServletResponse arg1,

FilterChain arg2) throws IOException, ServletException {

// TODO Auto-generated method stub

System.out.println("LoggingFilter.doFilter");

HttpServletRequest httpServletRequest=(HttpServletRequest) arg0;

logger.println(new Date()+" "+prefix+

httpServletRequest.getRequestURL());

logger.flush();

arg2.doFilter(arg0, arg1);

}

@Override

public void init(FilterConfig arg0) throws ServletException {

// TODO Auto-generated method stub

prefix=arg0.getInitParameter("prefix");

String logFileName=arg0.getInitParameter("logFileName");

String appPath=arg0.getServletContext().getRealPath("/");//利用FilterConfig获取servletContext对象的getRealPath方法来获取应用程序的绝对路径

System.out.println("logFileName:"+logFileName);

try{

logger=new PrintWriter(new File(appPath,logFileName));

}catch(FileNotFoundException e){

e.printStackTrace();

throw new ServletException(e.getMessage());

}

}

}

实例2:图片保护过滤器

本例防止通过在浏览器的地址栏直接输入url来下载图片。只有当在页面中点击图片的链接时,图片才会下载

过滤器通过查看HTTP标头referer的值来判断,只有当标头不为空时,才放行

标头为空时表示请求没有相当的引用页

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="ImageProtectorFilter",urlPatterns={"*.png","*.jpg","*.gif"})

public class ImageProtectorFilter implements Filter {

@Override

public void destroy() {

// TODO Auto-generated method stub

}

@Override

public void doFilter(ServletRequest arg0, ServletResponse arg1,

FilterChain arg2) throws IOException, ServletException {

// TODO Auto-generated method stub

System.out.println("imageProtextFilter doFilter");

HttpServletRequest httpServletRequest=(HttpServletRequest) arg0;

String referrer=httpServletRequest.getHeader("referer");

System.out.println("referer:"+referrer);

if(referrer!=null){

arg2.doFilter(arg0, arg1);

}else{

throw new ServletException("Image not available");

}

}

@Override

public void init(FilterConfig arg0) throws ServletException {

// TODO Auto-generated method stub

}

}

实例3:下载计数过滤器

本例的下载计数过滤器可以计算某一个资源被下载了多少次。当你想要知道你的视频的受欢迎程度或者文档的下载次数

这个就很有帮助,将这些数据保存在一个属性文件中,并且多个线程可以同时访问一个过滤器,因此需要一个线程安全性

的问题需要解决,这个例子通过利用Queue和Executor来解决这个线程安全性问题,将所有进来的请求都在一个线程的

Executor的队列中放置一个任务。放置任务为异步操作,比较快。Executor每次从队列中取出一个项目,消除了多线程

访问该属性文件的可能性

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();//ExecutorService是Executor的一个子类

Properties downloadLog; //Properties为HashTable的子类,线程安全

File logFile;

@Override

public void destroy() {

// TODO Auto-generated method stub

executorService.shutdown();

}

@Override

public void doFilter(ServletRequest request, ServletResponse response,

FilterChain chain) throws IOException, ServletException {

// TODO Auto-generated method stub

HttpServletRequest httpServletRequest=(HttpServletRequest) request;

final String uri=httpServletRequest.getRequestURI();

executorService.execute(new Runnable() {

@Override

public void run() {

// TODO Auto-generated method stub

String property=downloadLog.getProperty(uri);

if(property==null){

downloadLog.setProperty(uri, "1");

}else{

int count=0;

try{

count=Integer.parseInt(property);

}catch(NumberFormatException e){

}

count++;

downloadLog.setProperty(uri, Integer.toString(count));

}

try{

downloadLog.store(new FileWriter(logFile), "");

}catch(IOException e){

e.printStackTrace();

}

}

});

chain.doFilter(request, response);

}

@Override

public void init(FilterConfig filterConfig) throws ServletException {

// TODO Auto-generated method stub

System.out.println("DownloadCounterFilter init");

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 (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

过滤器的顺序

如果多个过滤器应用于一个资源,必须用部署描述符管理应该先调用哪个一个过滤器

filter1

class name

filter2

class name

 

作者:网络 来源:不详