`
wangtong40
  • 浏览: 252973 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Filter过滤器

阅读更多

第6章    Filter过滤器
6.1    Filter接口
Filter定义了三个方法init(),doFilter(),destory() ,分别用于初始化,运行过滤器和销毁过滤器。
1、    Init()     
public void init(FilterConfig filterConfig)
在Web应用程序启动时,Web服务器根据web.xml文件创建注册的Filter实例对象。创建实例对象后会立刻调用init方法,且只调用一次。

FilterConfig接口:Filter程序可能访问Servlet容器,Servlet将ServletContext和Filter配置参数信息封装到FilterConfig中。

FilterConfig常用方法:
getFilterName()/getServletContext()/getInitParameter()/getInitParameterNames()

2、    doFilter()
public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain)
当一个Filter对象拦截访问请求后,Servlet容器会调用该Filter对象的doFilter()。
FilterChain接口只有一个方法doFilter()用于通知Web容器吧请求交给FilterChain的下一个Filter或Servlet处理。

3、    destroy()
public void destroy()
6.2    Filter基础实例

public class FirstFilter implements Filter {
    private FilterConfig config = null;
    private String paramvalue = "";

    public void init(FilterConfig config) throws ServletException {
        this.config = config;
        paramvalue = config.getInitParameter("encoding");
}
public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        chain.doFilter(request, response);
    }
public void destroy() {
        this.config = null;
}}
 

 

<filter>
        <filter-name>FirstFilter</filter-name>
        <filter-class>filter.FirstFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>GB2312</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>FirstFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
 

6.3    阻止Servlet容器继续调用Servlet

public void doFilter(ServletRequest request, ServletResponse response, 
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpSession session = req.getSession();
if (session.getAttribute("user") == null) {
RequestDispatcher rd = req.getRequestDispatcher("/login.jsp");
rd.forward(req, resp);
} else {chain.doFilter(request, response);}}
 


6.4    修改Servlet容器传给Servlet的请求信息
下面实例是一个将Servlet的Request对象获取的请求中的HTML特殊字符进行转换。

public class ConvertSpecialCharacterServletRequestWrapper extends
HttpServletRequestWrapper {
    public ConvertSpecialCharacterServletRequestWrapper(
            HttpServletRequest request) {
        super(request);
    }
    public String getParameter(String name) {
        String value = super.getParameter(name);
        if (null != value) {
            return toHtml(value.trim());
        } else {
            return null;
        }
    }
    public String toHtml(String str) {
        if (str == null) {
            return null;
        }
        StringBuffer sb = new StringBuffer();
        int len = str.length();
        for (int i = 0; i < len; i++) {
            char c = str.charAt(i);
            switch (c) {
            case ' ':
                sb.append("&nbsp;");
                break;
            case '<':
                sb.append("&lt;");
                break;
            case '>':
                sb.append("&gt;");
                break;
            case '&':
                sb.append("&amp;");
                break;
            case '"':
                sb.append("&#34;");
                break;
            case '\\':
                sb.append("&#92;");
                break;
            default:
                sb.append(c);
            }
        }
        return sb.toString();
    }
}
 

 

public class SpecialCharacterFilter implements Filter {

    public void init(FilterConfig config) throws ServletException {
    }
    public void doFilter(ServletRequest request, ServletResponse response, 
FilterChain chain) 
throws IOException, ServletException {
HttpServletRequestWrapper requestWrapper = 
(HttpServletRequestWrapper) request;
    chain.doFilter(requestWrapper, response);
    }
    public void destroy() {}
}
 


6.5    修改Servlet回送给Servlet容器的响应结果
下例中将JSP内容通过ServletResponse打印出来

public class JSPOutputServletResponseWrapper extends HttpServletResponseWrapper {
    private MyPrintWriter tmpWriter;
    private ByteArrayOutputStream output;
    public JSPOutputServletResponseWrapper(HttpServletResponse response) {
        super(response);
        output = new ByteArrayOutputStream();
        tmpWriter = new MyPrintWriter(output);
    }
    public void finalize() throws Throwable {
        super.finalize();
        output.close();
        tmpWriter.close();
    }
    public String getContent() {
        try {
tmpWriter.flush(); // 刷新该流的缓冲
            String s = tmpWriter.getByteArrayOutputStream().toString("UTF-8");
            // 此处可根据需要进行对输出流以及Writer的重置操作
            // 比如tmpWriter.getByteArrayOutputStream().reset()
            return s;
        } catch (UnsupportedEncodingException e) {
            return "UnsupportedEncoding";
        }
    }

    // 覆盖getWriter()方法,使用我们自己定义的Writer
    public PrintWriter getWriter() throws IOException {
        return tmpWriter;
    }

    public void close() throws IOException {
        tmpWriter.close();
    }

    // 自定义PrintWriter,为的是把response流写到自己指定的输入流当中
    // 而非默认的ServletOutputStream
    private static class MyPrintWriter extends PrintWriter {
        ByteArrayOutputStream myOutput; // 此即为存放response输入流的对象
        public MyPrintWriter(ByteArrayOutputStream output) {
            super(output);
            myOutput = output;
        }
        public ByteArrayOutputStream getByteArrayOutputStream() {
            return myOutput;
        }
    }
}
 


6.6    使用Filter压缩HTML正文

public class CompressionResponseStream extends ServletOutputStream {
    protected int compressionThreshold = 0;// 是否启用压缩的临界值
    protected byte[] buffer = null;// 临时容纳写入的数据的缓冲区
    protected int bufferCount = 0; // 缓冲区实际写入的数据量
    protected GZIPOutputStream gzipstream = null;
    protected boolean closed = false;// 对当前流对象是否处于关闭状态
    protected int length = -1;
    protected HttpServletResponse response = null;
    protected ServletOutputStream output = null;
    public CompressionResponseStream(HttpServletResponse response)
            throws IOException {
        super();
        closed = false;
        this.response = response;
        this.output = response.getOutputStream();
    }
    protected void setBuffer(int threshold) {
        compressionThreshold = threshold;
        buffer = new byte[compressionThreshold];
    }
    public void close() throws IOException {
        if (closed) {
        throw new IOException("This output stream has already been closed");
        }
        /*
         * 根据gzipstream是否为null,就可以判断写入的内容是否达到
         * 启用压缩的临界值,因为到达临界值时,write方法会自动创建gzipstream对象
         */
        if (gzipstream != null) {
            flushToGZip();
            gzipstream.close();
            gzipstream = null;
        } else {
            if (bufferCount > 0) {
                output.write(buffer, 0, bufferCount);
                bufferCount = 0;
            }
        }
        output.close();
        closed = true;
    }
    public void flush() throws IOException {
        if (closed) {
            throw new IOException("Can't flush a closed output stream");
        }
        if (gzipstream != null) {
            gzipstream.flush();
        }
    }
    /**
     * 将buffer缓冲区中的数据写入到gzipstream中
     *
     * @throws IOException
     */
    public void flushToGZip() throws IOException {
        if (bufferCount > 0) {
            writeToGZip(buffer, 0, bufferCount);
            bufferCount = 0;
        }
    }

    @Override
    public void write(int b) throws IOException {
        if (closed) {
            throw new IOException("Can't write to a closed output stream");
        }

        /*
         * 当写入的数据达到启用压缩的临界值时, 则先将buffer缓冲区的数据写入到gzipstream对象中
         */
        if (bufferCount >= buffer.length) {
            flushToGZip();
        }
        buffer[bufferCount++] = (byte) b;
    }

    public void write(byte b[]) throws IOException {
        write(b, 0, b.length);
    }

    public void write(byte[] b, int off, int len) throws IOException {
        if (closed) {
            throw new IOException("Can't write to a closed output stream");
        }
        if (len == 0) {
            return;
        }
        /*
         * 如果buffer缓冲区中剩余的空间能够容纳要写入的数据, 则先将这些数据写入到buffer缓冲区中
         */
        if (len <= (buffer.length - bufferCount)) {
            System.arraycopy(b, off, buffer, bufferCount, len);
            bufferCount += len;
            return;
        }
        /*
         * 如果buffer缓冲区剩余的空间不能容纳要写入的数据, 则先将buffer缓冲区的原有数据写入到gzipstream对象中
         */
        flushToGZip();

        /*
         * 腾空buffer缓冲区数据后,判断整个buffer缓冲区是否能够容纳要写入的数据, 如果能将这些数据写入到buffer缓冲区中
         */
        if (len <= (buffer.length - bufferCount)) {
            System.arraycopy(b, off, buffer, bufferCount, len);
            bufferCount += len;
            return;
        }
        /*
         * 如果整个buffer缓冲区的空间都不能容纳要写入的数据, 则直接将这些数据写入gzipstream中
         */
        writeToGZip(b, off, len);
    }

    /**
     * 将gzipstream对象中写入数据,如果第一次写入 则还需创建gzips实体对象
     *
     * @param b
     * @param off
     * @param len
     * @throws IOException
     */
    public void writeToGZip(byte b[], int off, int len) throws IOException {
        if (gzipstream == null) {
            response.addHeader("Content-Encoding", "gzip");
            gzipstream = new GZIPOutputStream(output);
        }
        gzipstream.write(b, off, len);
    }
}
public class CompressionServletResponseWrapper extends
        HttpServletResponseWrapper {

    protected HttpServletResponse origResponse = null;
    protected static final String info = "CompressionServletResponseWrapper";
    protected ServletOutputStream stream = null;
    protected PrintWriter writer = null;
    protected int threshold = 0;
    protected String contentType = null;

    public CompressionServletResponseWrapper(HttpServletResponse response) {
        super(response);
        origResponse = response;
    }

    public void setContentType(String contentType) {
        this.contentType = contentType;
        origResponse.setContentType(contentType);
    }

    public void setCompressionThreshold(int threshold) {
        this.threshold = threshold;
    }

    /**
     * 创建自定义response对象包括输出流对象
     *
     * @return
     * @throws IOException
     */
    public ServletOutputStream createOutputStream() throws IOException {
        CompressionResponseStream stream = new CompressionResponseStream(
                origResponse);
        stream.setBuffer(threshold);
        return stream;
    }

    /**
     * 为了防止目标Servlet没有关闭输出流对象,Filter调用该方法 以便自动关闭输出流对象
     */
    public void finishResponse() {
        try {
            if (writer != null) {
                writer.close();
            } else {
                if (stream != null) {
                    stream.close();
                }
            }
        } catch (Exception e) {
            // TODO: handle exception
        }
    }
    /**
     * 覆盖flushBuffer方法
     */
    public void flushBuffer() throws IOException {
        ((CompressionResponseStream) stream).flush();
    }
    /**
     * 覆盖getOutputStream方法
     */
    public ServletOutputStream getOutputStream() throws IOException {
        if (writer != null) {
            throw new IllegalStateException(
                    "getWriter() has already been called for this resposne");
        }
        if (stream == null) {
            stream = createOutputStream();
        }
        return stream;
    }

    public PrintWriter getWriter() throws IOException {
        if (writer != null) {
            return writer;
        }
        if (stream != null) {
            throw new IllegalStateException(
                    "getOutputStream() has already been called for this resposne");
        }
        stream = createOutputStream();

        String charEnc = origResponse.getCharacterEncoding();
        if (charEnc != null) {
            writer = new PrintWriter(new OutputStreamWriter(stream, charEnc));
        } else {
            writer = new PrintWriter(stream);
        }
        return writer;
    }
}
public class CompressionFilter implements Filter {
    private FilterConfig config = null;
    private int minThreshold = 128;
    protected int compressionThreshold;
    public void init(FilterConfig filterConfig) throws ServletException {
        this.config = filterConfig;
        if (filterConfig != null) {
            String str = filterConfig.getInitParameter("compressionThreshold");
            if (compressionThreshold != 0 & compressionThreshold < minThreshold) {
                compressionThreshold = minThreshold;
            } else {
                // 不对响应信息的实体内容进行压缩
                compressionThreshold = 0;
            }
        } else {
            compressionThreshold = 0;
        }
    }
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        /*
         * 不对响应信息的实体内容进行压缩
         */
        if (compressionThreshold == 0) {
            chain.doFilter(request, response);
        }
        /*
         * 检测客户端浏览器是否支持gzip数据压缩格式
         */
        boolean supportCompression = false;
        if (request instanceof HttpServletRequest) {
            Enumeration<String> e = ((HttpServletRequest) request)
                    .getHeaders("Accept-Encoding");
            while (e.hasMoreElements()) {
                String name = e.nextElement();
                if (name.indexOf("gzip") != -1) {
                    supportCompression = true;
                }
            }
        }
        if (!supportCompression) {
            chain.doFilter(request, response);
            return;
        } else {
            if (response instanceof HttpServletResponse) {
                /*
                 * 创建自定义的Response对象
                 */
CompressionServletResponseWrapper wrapperResponse = new 
CompressionServletResponseWrapper((HttpServletResponse) response);
    wrapperResponse.setCompressionThreshold(compressionThreshold);
                try {
                    chain.doFilter(request, wrapperResponse);
                } finally {
                    wrapperResponse.finishResponse();
                }
            }
            return;
        }
    }
    public void destroy() {
        this.config = null;
    }
}
 

 

分享到:
评论

相关推荐

    java 中如何使用filter过滤器

    本文将详细介绍如何在Java中使用Filter过滤器,以及如何配置相关的配置文件,让你一目了然。 ### 1. Filter接口与生命周期 Filter是Servlet API中的一个接口,位于`javax.servlet`包下。它定义了三个关键方法: -...

    Filter过滤器(分类讨论,分类讲解)

    ### Filter过滤器(分类讨论,分类讲解) #### 一、Filter概述 在Java Web开发中,`Filter`是一种非常重要的技术,它可以在请求到达目标资源(如Servlet或JSP页面)之前进行预处理,或者在响应返回客户端之前进行...

    SpringBoot的filter过滤器(源代码)

    SpringBoot的filter过滤器 一、过滤器的作用和概述 1.1 简述 1.2 使用场景 二、自定义过滤的两种方式 2.1 第一种方式 2.1.1 启动类增加注解@ServletComponentScan 2.1.2 定义一个filter类 2.1.3. 测试 2.2 第二种...

    ffmpeg filter过滤器基础实例以及全面解析

    FFmpeg Filter 过滤器是FFmpeg项目中用于音视频数据处理的一个重要组件,通过libavfilter库提供丰富的视频和音频过滤功能。这些过滤器可以在不同阶段对媒体数据进行操作,包括但不限于格式转换、帧率调整、大小缩放...

    如何配置Filter过滤器处理JSP中文乱码

    【如何配置Filter过滤器处理JSP中文乱码】 在开发Java Web应用时,尤其是在处理包含中文字符的请求时,可能会遇到中文乱码的问题。解决这个问题的一种常见方法是使用Filter过滤器。以下是配置Filter过滤器处理JSP...

    PHP Filter过滤器全面解析

    PHP Filter过滤器是PHP中用于处理和验证非安全来源数据的工具,特别是在处理用户输入时。这些过滤器有助于确保应用程序接收到的是预期的数据类型,从而提高应用的安全性和稳定性。过滤器扩展使得数据过滤过程变得...

    filter过滤器的简单使用.rar

    在标题提到的"filter过滤器的简单使用.rar"压缩包中,很显然包含了一个关于如何在Maven项目和Spring Boot项目中使用Filter的示例。下面将详细介绍Filter的基本概念、工作原理以及如何在两种项目环境中应用。 **...

    filter过滤器防止恶意注入

    在Java Web开发中,`Filter`过滤器是一个关键的安全组件,用于拦截并处理HTTP请求和响应。本示例中的`URLfilter`类就是一个简单的过滤器,它的主要目的是防止SQL注入攻击,这是一种常见的恶意攻击手段,攻击者试图...

    YII Framework的filter过滤器用法分析

    YII框架中的filter过滤器是该框架提供的一个强大功能,它允许开发者在控制器动作执行之前或之后执行一段自定义的代码,用以完成如访问控制、性能监控、数据验证等任务。过滤器的实现方式可以是通过控制器类中的特定...

    jsp filter 过滤器判断用户是否登录

    下面我们就通过分析一个具体的示例代码来详细了解如何使用JSP Filter过滤器来判断用户是否已经登录。 #### 示例代码分析 首先,我们来看一下示例中的过滤器类`RightFilter`: ```java import javax.servlet....

    java filter过滤器

    【Java Filter过滤器详解】 Java Filter是Java Servlet技术的一部分,它允许开发者在Servlet容器中对HTTP请求和响应进行拦截处理,实现数据过滤、权限控制、日志记录等多种功能。Filter的生命周期包括三个主要方法...

    Socket通信,封包处理, Filter过滤器处理

    Filter过滤器处理则是在数据传输或处理流程中添加的一层逻辑,用于拦截、修改或者增强数据。 首先,我们来深入理解Socket通信。Socket可以视为网络上的两个程序之间的一个连接点,通过这个连接点,数据可以在它们...

    Filter过滤器1

    Filter 过滤器 Filter 过滤器是 JavaWeb 的一个重要组件,对请求和响应进行拦截,实现一些特殊的功能。Filter 程序是一个实现 Filter 接口的 Java 类,类似于 Servlet 程序,由 Servlet 容器进行调用和执行。需要在...

    filter 过滤器 解释 MultipartHttpServletRequest表单

    filter 过滤器 解释 MultipartHttpServletRequest表单

    STRUTS:filter过滤器

    ### STRUTS:filter过滤器 #### 概述 在Java Web开发中,过滤器(Filter)是一种重要的组件,用于拦截客户端发送至服务器的请求或服务器返回至客户端的响应。Struts框架作为Java Web开发中的一种流行框架,利用了...

    Filter过滤器的概念和使用

    ### Filter过滤器的概念 在Java Web开发中,`Filter`是一种功能强大的机制,它能够拦截客户端请求,并在请求到达目标资源(如Servlet)之前或之后进行处理。这为开发者提供了极大的灵活性来添加诸如编码处理、登录...

    15_尚硅谷_Filter过滤器_王振国 - 课堂笔记1

    Filter 过滤器详解 Filter 过滤器是 JavaWeb 的三大组件之一,另外两个组件是 Servlet 程序和 Listener 监听器。Filter 过滤器是一个接口,它的作用是拦截请求,过滤响应。常见的应用场景有权限检查、日记操作、...

    filter过滤器流程及中文乱码解决和客户端IP地址控制

    【filter过滤器流程】 在Java Web开发中,Filter(过滤器)是用于处理HTTP请求和响应的重要组件。它遵循Servlet规范中的Filter接口,允许开发者在请求到达目标Servlet或JSP之前以及响应离开Servlet之后进行拦截和...

    MVCFilter过滤器.rar

    "MVCFilter过滤器.rar"这个压缩包可能包含了一些关于如何在ASP.NET MVC中使用过滤器的示例或文档。 过滤器主要分为四类: 1. **授权过滤器(Authorization Filters)**:这类过滤器用于验证用户是否有权限访问某个...

    Lucene5学习之Filter过滤器

    《深入理解Lucene5:Filter过滤器的奥秘》 在全文搜索引擎的开发过程中,Lucene作为一款强大的开源搜索引擎库,扮演着至关重要的角色。它提供了丰富的功能,使得开发者能够快速构建高效的搜索系统。其中,Filter...

Global site tag (gtag.js) - Google Analytics