Servlet Filter 简单示例

本文代码转载自
《Servlet、JSP和Spring MVC初学指南》
及
http://blog.csdn.net/yao752915708/article/details/9181317
http://www.cnblogs.com/gaoyoubo/articles/1766483.html


前面提到的Listener主要作用是对用到的对象的处理进行监听,
即context request session等的init 及destroy行为,有点类似于在对象的外部
执行相关的资源操作,其第二个session属性的相关例子例证了这一点,即session
对象的attribute属性的init或destroy与对象(Vector)的相关操作。


下面要提到的Filter主要是面向页面处理行为本身,而非对象。如在进行对某些页面的
访问时,我们需要做一些处理。


一般使用filter的场景要求处理过程的可持续性,即当处理过程出现 异常 时,可以
在下一次处理时“记住”已经处理过的状态(如记录访问某个网页的request的数量),
这可以通过线程池进行维护,即java.util.concurrent


由于笔者做爬虫,看到这个要求就会想到“断点爬取”这个爬虫上的需求,显然这种
“直觉”是“对”的,见如下链接,其描述了WebCollector爬虫,的应用设计
http://datahref.com/archives/7
在这里就不赘述了(其Executor描述了相应功能),仅仅先给出一个Executers的简单例子
来源于
http://blog.csdn.net/yao752915708/article/details/9181317


下面代码中java.util.concurrent.Executors.newSingleThreadExecutor()
可以创建一个大小为1的单线程线程池对应的java.util.concurrent.ExecutorService对象
,该对象可以保持在抛出异常的情况下,保持状态,下面是一个简单例子:
 
package executerTest;

/**
 * Created by admin on 2017/2/22.
 */

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Yao implements Runnable {
    public static void main(String []args){
        Yao yao = new Yao("Max");
        foo(yao);

        System.out.println(" aDog.name.equalas Max = " + yao.name.equals("Max"));
        ExecutorService eService = Executors.newSingleThreadExecutor();
        eService.execute(yao);
    }

    public String name;
    public Yao(String name){
        this.name = name;
    }

    public static void foo(Yao d){
        d = new Yao("Fifi");
    }


    @Override
    public void run(){
        int temp = 0;
        int i = 0;
        Random random = new Random();
        while(true){
            int j = random.nextInt(100);
            System.err.println("temp--------->" + temp + " i--------->" + (i++) + "   j--------->" + j);
            try{
                if(temp == 0 && j > 90)
                    temp = 7/ 0;
                Thread.currentThread().sleep(10);
            }catch (Exception e){
                e.printStackTrace();;
            }

        }

    }

}

这里变量i的打印结果表现出记录状态的情形。


下面给出三个实际使用filter的简单实例
package filter;

/**
 * Created by admin on 2017/2/22.
 */
import java.io.*;
import java.util.Properties;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;

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;

    @Override
    public void init(FilterConfig filterConfig)throws ServletException{
        System.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(IOException e){
            e.printStackTrace();
        }
    }

    @Override
    public void destroy(){
        executorService.shutdown();
    }

    @Override
    public  void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException{
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;

        final String uri = ((HttpServletRequest) request).getRequestURI();
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                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){

                }
            }
        });
            chain.doFilter(request, response);
    }

}

package filter;

/**
 * Created by admin on 2017/2/22.
 */

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 init(FilterConfig filterConfig)throws ServletException{
    }

    @Override
    public void destroy(){
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)throws IOException, ServletException{
        System.out.println("ImageProtectorFilter");
        HttpServletRequest httpServletRequest =  (HttpServletRequest) request;
        String referer = httpServletRequest.getHeader("referer");
        System.out.println("referer: " + referer);

        if(referer != null){
            filterChain.doFilter(request, response);
        }
        else{
            throw new ServletException("Image not available");
        }
    }

}

package filter;

/**
 * Created by admin on 2017/2/22.
 */

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;

import javax.servlet.*;
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;

    @Override
    public 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);
        try{
            logger = new PrintWriter(new File(appPath, logFileName));
        }catch(FileNotFoundException e){
            e.printStackTrace();
            throw new ServletException(e.getMessage());
        }

    }

    @Override
    public void destroy(){
        System.out.println("destroying filter");
        if(logger != null){
            logger.close();
        }
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)throws IOException, ServletException{
        System.out.println("LoggerFilter doFilter");
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        logger.println(new Date() + " " + prefix + httpServletRequest.getRequestURI());
        logger.flush();
        filterChain.doFilter(request, response);

    }


}

上述filter的配置基本上与WebServlet是类似的 实现的是向log打印信息,
其中 DownloadCounterfilter使用了线程池操作


对部署比较有用的是filterConfig.getServletContext().getRealPath("/");
其可以通过ServletContext对象得到本地文件路径 这对于部署应用是有用的。
(比如在访问某个页面时要运行依赖于本地文件的应用,这时至少要知道一些路径信息,
其简单应用见 
Webcollector + Spring + MVC 搭建应用初探(六)(Lenskit 推荐系统实例)
其在访问推荐系统结果页面时 启动推荐系统进行数据更新)


另一个要说明的是 这里也利用properties进行属性记录 其实基本上就是配置
文件的形式(说的玄一点 什么properties继承了Hashable接口了什么的)


对于Filter对象当结合 
javax.servlet.http.HttpServletRequestWrapper 时可以对request对象本身 做一些预处理。
在servlet外如在Filter doFilter方法的运行过程中 request的attribute是不可变的, 故
如利用Filter来对attribute进行若干预处理需要使用
HttpServletRequestWrapper  对request对象进行包装 实际上相当于对request的若干方法进行
重写 
下面是一个利用上述过程将表单提交参数的前后空白字符去掉的例子
来源于
http://www.cnblogs.com/gaoyoubo/articles/1766483.html
 
package trimmer.filter;

/**
 * Created by admin on 2017/2/23.
 */

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

public final class MyRequestWrapper extends HttpServletRequestWrapper {
    public MyRequestWrapper(HttpServletRequest httpServletRequest){
        super(httpServletRequest);
    }

    public String[] getParameterValues(String parameter){
        String []results = super.getParameterValues(parameter);
        if(results == null)
            return null;

        int count = results.length;
        String[] trimResults = new String[count];
        for(int i =0;i < count; i++){
            trimResults[i] = results[i].trim();
        }
        return trimResults;
    }
}

package trimmer.filter;

/**
 * Created by admin on 2017/2/23.
 */

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.http.HttpServletRequest;
import javax.servlet.annotation.WebFilter;

@WebFilter(
        filterName = "TrimmerFilter",
        urlPatterns = {"/call"}
)
public class MyFilter implements Filter {
    private FilterConfig filterConfig;

    @Override
    public void init(FilterConfig filterConfig){
        this.filterConfig = filterConfig;
    }

    @Override
    public void destroy(){
        this.filterConfig = null;
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)throws IOException, ServletException{
        filterChain.doFilter(new MyRequestWrapper((HttpServletRequest) request), response);
    }

}

package trimmer.filter;

/**
 * Created by admin on 2017/2/23.
 */
import java.io.IOException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;

@WebServlet(
    name = "FilterServlet",
        urlPatterns = {"/call"}
)
public class FilterServlet extends HttpServlet {
    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response)throws IOException, ServletException{
        for(String para : request.getParameterValues("name")){
            System.out.println(para);
        }
    }

}

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Filter Test</title>
</head>
<body>

<%
    request.setAttribute("names", "jack ana");
%>


<form action = "/call" method="get">
    <input type="text" name = "name"/>
    <input type="text" name = "name"/>
    <input type="submit" value="Submit"/>
</form>

</body>
</html>


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值