⑧javaWeb之在例子中学习(过滤器Filter) 前言

简介:

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

相关文章
|
3月前
|
Java 调度 开发者
Java线程池ExecutorService学习和使用
通过学习和使用Java中的 `ExecutorService`,可以显著提升并发编程的效率和代码的可维护性。合理配置线程池参数,结合实际应用场景,可以实现高效、可靠的并发处理。希望本文提供的示例和思路能够帮助开发者深入理解并应用 `ExecutorService`,实现更高效的并发程序。
65 10
|
3月前
|
Java 数据库连接 数据库
【潜意识Java】深度分析黑马项目《苍穹外卖》在Java学习中的重要性
《苍穹外卖》项目对Java学习至关重要。它涵盖了用户管理、商品查询、订单处理等模块,涉及Spring Boot、MyBatis、Redis等技术栈。
341 4
|
3月前
|
前端开发 Java 数据库连接
【潜意识Java】深度解读JavaWeb开发在Java学习中的重要性
深度解读JavaWeb开发在Java学习中的重要性
60 4
|
3月前
|
存储 移动开发 算法
【潜意识Java】Java基础教程:从零开始的学习之旅
本文介绍了 Java 编程语言的基础知识,涵盖从简介、程序结构到面向对象编程的核心概念。首先,Java 是一种高级、跨平台的面向对象语言,支持“一次编写,到处运行”。接着,文章详细讲解了 Java 程序的基本结构,包括包声明、导入语句、类声明和 main 方法。随后,深入探讨了基础语法,如数据类型、变量、控制结构、方法和数组。此外,还介绍了面向对象编程的关键概念,例如类与对象、继承和多态。最后,针对常见的编程错误提供了调试技巧,并总结了学习 Java 的重要性和方法。适合初学者逐步掌握 Java 编程。
73 1
|
5月前
|
Java 大数据 API
14天Java基础学习——第1天:Java入门和环境搭建
本文介绍了Java的基础知识,包括Java的简介、历史和应用领域。详细讲解了如何安装JDK并配置环境变量,以及如何使用IntelliJ IDEA创建和运行Java项目。通过示例代码“HelloWorld.java”,展示了从编写到运行的全过程。适合初学者快速入门Java编程。
|
5月前
|
监控 Java 数据管理
java会话跟踪和拦截器过滤器
本文介绍了Web开发中的会话跟踪技术——Cookie与Session,以及过滤器(Filter)和监听器(Listener)的概念和应用。Cookie通过在客户端记录信息来识别用户,而Session则在服务器端保存用户状态。过滤器用于拦截和处理请求及响应,监听器则监控域对象的状态变化。文章详细解释了这些技术的实现方式、应用场景和主要方法,帮助开发者更好地理解和使用这些工具。
90 1
|
2月前
|
存储 监控 Java
【Java并发】【线程池】带你从0-1入门线程池
欢迎来到我的技术博客!我是一名热爱编程的开发者,梦想是编写高端CRUD应用。2025年我正在沉淀中,博客更新速度加快,期待与你一起成长。 线程池是一种复用线程资源的机制,通过预先创建一定数量的线程并管理其生命周期,避免频繁创建/销毁线程带来的性能开销。它解决了线程创建成本高、资源耗尽风险、响应速度慢和任务执行缺乏管理等问题。
207 60
【Java并发】【线程池】带你从0-1入门线程池
|
17天前
|
Java 中间件 调度
【源码】【Java并发】从InheritableThreadLocal和TTL源码的角度来看父子线程传递
本文涉及InheritableThreadLocal和TTL,从源码的角度,分别分析它们是怎么实现父子线程传递的。建议先了解ThreadLocal。
53 4
【源码】【Java并发】从InheritableThreadLocal和TTL源码的角度来看父子线程传递
|
1月前
|
存储 网络协议 安全
Java网络编程,多线程,IO流综合小项目一一ChatBoxes
**项目介绍**:本项目实现了一个基于TCP协议的C/S架构控制台聊天室,支持局域网内多客户端同时聊天。用户需注册并登录,用户名唯一,密码格式为字母开头加纯数字。登录后可实时聊天,服务端负责验证用户信息并转发消息。 **项目亮点**: - **C/S架构**:客户端与服务端通过TCP连接通信。 - **多线程**:采用多线程处理多个客户端的并发请求,确保实时交互。 - **IO流**:使用BufferedReader和BufferedWriter进行数据传输,确保高效稳定的通信。 - **线程安全**:通过同步代码块和锁机制保证共享数据的安全性。
96 23
|
23天前
|
数据采集 存储 网络协议
Java HttpClient 多线程爬虫优化方案
Java HttpClient 多线程爬虫优化方案
下一篇
oss创建bucket