zoukankan      html  css  js  c++  java
  • ⑧javaWeb之在例子中学习(过滤器Filter)

    前言

      本系列 Servlet & JSP 学习系列[传送门]逐渐到了中期了,希望大家喜欢我写的,总结的点点滴滴-

        今天我们来讲讲过滤器

      你们的支持是我写博客的动力哦。

      最近买了两本书,觉得大二了。每个月的零花钱中买几本书,一年也能买二三十本。不亦乐乎!分享下

                  

          虽然看不懂,先看吧。至少不亏,以后温故知新.

    Fitler(过滤器)

      过滤器filter是拦截请求,并对传给请求资源的ServletRequest 或 ServletResponse 进行处理的一个对象。可以用于登录,加密和解密,会话检查,图片转换等等

      过滤器执行机制图:

          

       

      Filter API : http://docs.oracle.com/javase/6/docs/api/

    Filter详解

      Filter接口的构成:

            所有的Filter类都必须实现javax.servlet.Filter接口。这个接口含有3个过滤器类必须实现的方法:

              ①init(FilterConfig):这是Filter的初始化方法,Servlet容器创建Filter实例后将调用这个方法。在这个方法中可以读取web.xml文件中Filter的初始化参数


              ②doFilter(ServletRequest,ServletResponse,FilterChain): 这个方法完成实际的过滤操作,当客户请求访问于Filter关联的URL时,Servlet容器将先调用Filter的doFilter方法。FilterChain参数用于访问后续Filters

              ③destroy():  Servlet容器在销毁Filter实例前调用该方法,这个方法中可以释放Filter占用的资源

           配置Filter(下面例子用的是注释配置)

    <filter>  
        <filter-name>enconfigFilter</filter-name>  
        <filter-class>com.filter.EnconfigFilter</filter-class>  
        <init-param>  
            <param-name>enconfig</param-name>  
            <param-value>UTF-8</param-value>  
        </init-param>  
    </filter>  
    <filter-mapping>  
        <filter-name>enconfigFilter</filter-name>  
        <url-pattern>/*</url-pattern>  
    </filter-mapping>  

     

           其中:   

            filter-name   指定过滤器的名字
            filter-class    指定过滤器的类名
            init-param    为过滤器实例提供初始化参数,可以有多个
            url-pattern   指定和过滤器关联的URL,为”/*”表示所有URL

    图片保护过滤器

      咱们用ImageProtetorFilter来保护咱们的图片,防止地址栏中直接输入图片URL 来下载图片。

      小小的原理:

        过滤器通过查看HTTP 标头的referer的值进行工作。值为空表示当前请求没有相当的引用页。而值为空,说明请求在引用页,自然图片在jsp里面供认看与下载。

      

      小朽尝试:

        ①包结构

          

        ② ImageProtector类

          doFilter实现了,获取标头→判断→然后抛异常

        

    package sedion.jeffli.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;
    
    /**
     * 
     * @author Jeff Li
     *
     */
    @WebFilter(filterName = "ImageProtetorFilter",urlPatterns={"*.png","*.jpg","*.gif"})
    public class ImageProtector implements Filter{
    
        @Override
        public void destroy() {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response,
                FilterChain chain) throws IOException, ServletException {
            System.out.println("ImageProtetorFilter");
            HttpServletRequest httpServletR = (HttpServletRequest)request;
            String referrer = httpServletR.getHeader("referer");
            System.out.println("referrer:"+referrer);
            if(referrer != null){
                chain.doFilter(request, response);
            }else{
                throw new ServletException("Image not available");
            }
            
        }
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            // TODO Auto-generated method stub
            
        }
    
    }

        

        ③JSP 页面加入

    <img alt="logo" src="logo.jpg">

      小朽看效果说话:

        ①当直接在火狐中,打开url:http://localhost:8080/filterTest/logo.jpg

          页面出现了 HTTP Status 500 - Image not available

          打开小蜜蜂(firebug),查看网络,发现没有referer请求头信息

        ②当直接在火狐中,打开url:http://localhost:8080/filterTest/index.jsp

          页面自然出现了图片。

          打开小蜜蜂(firebug),查看网络

            

    下载过滤器

      顾名思义,计算某个资源下载了多少次,或知道某些东石受欢迎程度。自然这个必不可少。

      Question and Solving:

        我们将值保存在一个属性文件中,并且多个线程可以同时访问一个过滤器,因此就有一个线程安全性的问题需要解决。用户请求资源读取相应属性值,将它赠一个并存回新值。如果第一个线程完成任务前,又有第二个用户请求同一个资源,怎么办?同步读写值的代码似乎不是个好方法,涉及到扩展性的问题。

        我们利用Queue 和 Executor 解决这个线程的问题。所有进来的请求都在一个线程Executor队列中放置一项任务。放置任务比较快,因为这是一个异步的操作。由于只有使用一个Executor一个线程,因此消除了多线程访问该属性文件的可能。

      

      小朽尝试:

        就加个DownloadCounterFilter,启动就好。

    package sedion.jeffli.filter;
    
    import java.io.File;
    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;
    /**
     * 
     * @author Jeff Li
     *
     */
    
    @WebFilter(filterName="DownloadCounterFilter",urlPatterns={"/*"})
    public class DownloadCounterFilter implements Filter{
        
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        Properties downloadLog;
        File logFile;
    
        @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.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 (Exception e) {
                    }
                }
            });
            
            chain.doFilter(request, response);
        }
    
        @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();
            }
        }
    
    }

        

      小朽分析下:

      

      String appPath = filterConfig.getServletContext().getRealPath("/");
            logFile = new File(appPath,"downloadLog.txt");
            
            if(!logFile.exists()){
                try {
                    logFile.createNewFile();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

       项目路径下:tomcat_dir/filterTest/ 如果没有文件downloadLog.txt,初始化生成。当访问项目有关文件,则会记录到这个property文件中。

       

        小朽看效果:

        打开tomcat_dir/filterTest/downloadLog.txt

    #
    #Thu Mar 20 12:39:02 CST 2014
    /filterTest/logo.jpg=3
    /filterTest/=1
    /filterTest/index.jsp=2

      

        

      

    总结 

      

     寄读者,寄知识来源

       读者,你好!你我不相识,谢谢你们支持。只有记录点滴,我的梦想会越来越接近。共勉!

       知识来源 http://book.douban.com/doulist/3575997/

                

  • 相关阅读:
    fastjson1.2.22-1.2.24 反序列化命令执行实践测试
    Spring boot JdbcTemplate sql注入测试
    java反序列化命令执行测试实践
    SpringBoot 整合mybatis SQL注入漏洞实践
    SpringBoot整合mybatis入门
    python函数默认参数为可变对象的理解
    python笔记
    python
    python面向对象
    ICMP
  • 原文地址:https://www.cnblogs.com/Alandre/p/3613457.html
Copyright © 2011-2022 走看看