• java filter


        过滤器Filter也具有生命周期:init()->doFilter()->destroy(),由部署文件中的filter元素驱动。在servlet2.4中,过滤器同样可以用于请求分派器,但须在web.xml中声明,<dispatcher>INCLUDE或FORWARD或REQUEST或ERROR</dispatcher>该元素位于filter-mapping中。 

    一、批量设置请求编码 

    Java代码  收藏代码
    1. public class EncodingFilter implements Filter {  
    2.   
    3.     private String encoding = null;  
    4.   
    5.     public void destroy() {  
    6.         encoding = null;  
    7.     }  
    8.   
    9.     public void doFilter(ServletRequest request, ServletResponse response,  
    10.             FilterChain chain) throws IOException, ServletException {  
    11.         String encoding = getEncoding();  
    12.         if (encoding == null){  
    13.             encoding = "gb2312";  
    14.         }  
    15.         request.setCharacterEncoding(encoding);// 在请求里设置上指定的编码  
    16.         chain.doFilter(request, response);  
    17.     }  
    18.   
    19.     public void init(FilterConfig filterConfig) throws ServletException {  
    20.         this.encoding = filterConfig.getInitParameter("encoding");  
    21.     }  
    22.   
    23.     private String getEncoding() {  
    24.         return this.encoding;  
    25.     }  
    26.   
    27. }  

     

    Xml代码  收藏代码
    1. <filter>  
    2.     <filter-name>EncodingFilter</filter-name>  
    3.     <filter-class>com.logcd.filter.EncodingFilter</filter-class>  
    4.     <init-param>  
    5.        <param-name>encoding</param-name>  
    6.        <param-value>gb2312</param-value>  
    7.     </init-param>  
    8. </filter>  
    9.   
    10. <filter-mapping>  
    11.    <filter-name>EncodingFilter</filter-name>  
    12.    <url-pattern>/*</url-pattern>  
    13. </filter-mapping>  


    二、用filter控制用户访问权限 

    Java代码  收藏代码
    1. public void doFilter(ServletRequest request,  
    2.         ServletResponse response,  
    3.         FilterChain chain)  
    4.         throws IOException, ServletException {  
    5.   
    6.     HttpServletRequest req = (HttpServletRequest) request;  
    7.     HttpServletResponse res = (HttpServletResponse) response;  
    8.   
    9.     HttpSession session = req.getSession();  
    10.     if (session.getAttribute("username") != null) {//登录后才能访问  
    11.         chain.doFilter(request, response);  
    12.     } else {  
    13.         res.sendRedirect("../failure.jsp");  
    14.     }  
    15. }  



    Xml代码  收藏代码
    1. <filter>  
    2.     <filter-name>SecurityFilter</filter-name>  
    3.     <filter-class>com.logcd.filter.SecurityFilter</filter-class>  
    4. </filter>  
    5. <filter-mapping>  
    6.     <filter-name>SecurityFilter</filter-name>  
    7.     <url-pattern>/admin/*</url-pattern>  
    8. </filter-mapping>  


    三、过滤链 
     
       两个过滤器,EncodingFilter负责设置编码,SecurityFilter负责控制权限,服务器会按照web.xml中过滤器定义的先后循序组装成一条链,然后一次执行其中的doFilter()方法。执行的顺序就如上图所示,执行第一个过滤器的chain.doFilter()之前的代码,第二个过滤器的chain.doFilter()之前的代码,请求的资源,第二个过滤器的chain.doFilter()之后的代码,第一个过滤器的chain.doFilter()之后的代码,最后返回响应。 
    执行的代码顺序是: 

    1. 执行EncodingFilter.doFilter()中chain.doFilter()之前的部分:request.setCharacterEncoding("gb2312");
    2. 执行SecurityFilter.doFilter()中chain.doFilter()之前的部分:判断用户是否已登录。
    3. 如果用户已登录,则访问请求的资源:/admin/index.jsp。
    4. 如果用户未登录,则页面重定向到:/failure.jsp。
    5. 执行SecurityFilter.doFilter()中chain.doFilter()之后的部分:这里没有代码。
    6. 执行EncodingFilter.doFilter()中chain.doFilter()之后的部分:这里也没有代码。


       过滤链的好处是,执行过程中任何时候都可以打断,只要不执行chain.doFilter()就不会再执行后面的过滤器和请求的内容。而在实际使用时,就要特别注意过滤链的执行顺序问题,像EncodingFilter就一定要放在所有Filter之前,这样才能确保在使用请求中的数据前设置正确的编码。 

    四、使用filter,结合gzip 压缩技术,解决web应用中网络传输数据量大的问题 
        gzip是http协议中使用的一种加密算法,客户端向web服务器端发出了请求后,通常情况下服务器端会将页面文件和其他资源,返回到客户端,客户端加载后渲染呈现,这种情况文件一般都比较大,如果开启Gzip ,那么服务器端响应后,会将页面,JS,CSS等文本文件或者其他文件通过高压缩算法将其压缩,然后传输到客户端,由客户端的浏览器负责解压缩与呈现。通常能节省40%以上的流量(一般都有60%左右),一些PHP,JSP文件也能够进行压缩。 
    1.Tomcat 直接开启Gzip 
        打开Tomcat 目录下的conf下的server.xml,并找到如下信息: 

    Xml代码  收藏代码
    1. <!-- Note : To use gzip compression you could set the following properties :  
    2.    compression="on"   
    3.    compressionMinSize="2048"   
    4.    noCompressionUserAgents="gozilla, traviata"   
    5.    compressableMimeType="text/html,text/xml"  
    6. -->  


        把它们加入到你配置的<Connector port="80" .../>中去。如果要压缩css 和 js,加入compressableMimeType="text/html,text/xml,text/css,text/javascript"。还要压缩图片,加入compressableMimeType="text/html,text/xml,text/css,text/javascript,image/gif,image/jpg"。 
        开启后重启Tomcat ,通过浏览器查看headers信息就能看到是否开启。 

    2.使用filter,在代码级别完成web应用的gzip压缩的开启。 

    (1).CachedResponseWrapper类 
        实现定制输出的关键是对HttpServletResponse 进行包装,截获所有的输出,等到过滤器链处理完毕后,再对截获的输出进行处理,并写入到真正的HttpServletResponse 对象中。JavaEE 框架已经定义了一个HttpServletResponseWrapper 类使得包装HttpServletResponse 更加容易。我们扩展这个HttpServletResponseWrapper,截获所有的输出,并保存到ByteArrayOutputStream 中。 
        定制的包装响应能方便地从帮助类 HttpServletResponseWrapper 中导出。这一类粗略地执行许多方法,允许我们简单地覆盖 getOutputStream() 方法以及 getWriter() 方法,提供了定制输出流的实例。 
        HttpServletResponseWrapper这个类的使用包括以下五个步骤: 
    1)建立一个响应包装器。扩展javax.servlet.http.HttpServletResponseWrapper。 
    2)提供一个缓存输出的PrintWriter。重载getWriter方法,返回一个保存发送给它的所有东西的PrintWriter,并把结果存进一个可以稍后访问的字段中。 
    3)传递该包装器给doFilter。此调用是合法的,因为HttpServletResponseWrapper实现HttpServletResponse。 
    4)提取和修改输出。在调用FilterChain的doFilter方法后,原资源的输出只要利用步骤2中提供的机制就可以得到。只要对你的应用适合,就可以修改或替换它。 
    5)发送修改过的输出到客户机。因为原资源不再发送输出到客户机(这些输出已经存放到你的响应包装器中了),所以必须发送这些输出。这样,你的过滤器需要从原响应对象中获得PrintWriter或OutputStream,并传递修改过的输出到该流中。 

    Java代码  收藏代码
    1. /** 
    2.  * Wrapper:在内存中开辟一个ByteOutputStream,然后将拦截的响应写入byte[], 
    3.  * 写入完毕后,再将wrapper的byte[]写入真正的response对象 
    4.  * This class is used for wrapped response for getting cached data. 
    5.  */   
    6. class CachedResponseWrapper extends HttpServletResponseWrapper {  
    7.   
    8.     /** 
    9.      * Indicate that getOutputStream() or getWriter() is not called yet. 
    10.      */  
    11.     public static final int OUTPUT_NONE = 0;  
    12.   
    13.     /** 
    14.      * Indicate that getWriter() is already called. 
    15.      */  
    16.     public static final int OUTPUT_WRITER = 1;  
    17.   
    18.     /** 
    19.      * Indicate that getOutputStream() is already called. 
    20.      */  
    21.     public static final int OUTPUT_STREAM = 2;  
    22.   
    23.     private int outputType = OUTPUT_NONE;  
    24.   
    25.     private int status = SC_OK;  
    26.   
    27.     private ServletOutputStream output = null;  
    28.   
    29.     private PrintWriter writer = null;  
    30.   
    31.     private ByteArrayOutputStream buffer = null;  
    32.   
    33.     public CachedResponseWrapper(HttpServletResponse resp) throws IOException {  
    34.         super(resp);  
    35.         buffer = new ByteArrayOutputStream();  
    36.     }  
    37.   
    38.     public int getStatus() {  
    39.         return status;  
    40.     }  
    41.   
    42.     public void setStatus(int status) {  
    43.         super.setStatus(status);  
    44.         this.status = status;  
    45.     }  
    46.   
    47.     public void setStatus(int status, String string) {  
    48.         super.setStatus(status, string);  
    49.         this.status = status;  
    50.     }  
    51.   
    52.     public void sendError(int status, String string) throws IOException {  
    53.         super.sendError(status, string);  
    54.         this.status = status;  
    55.     }  
    56.   
    57.     public void sendError(int status) throws IOException {  
    58.         super.sendError(status);  
    59.         this.status = status;  
    60.     }  
    61.   
    62.     public void sendRedirect(String location) throws IOException {  
    63.         super.sendRedirect(location);  
    64.         this.status = SC_MOVED_TEMPORARILY;  
    65.     }  
    66.   
    67.     public PrintWriter getWriter() throws IOException {  
    68.         if (outputType == OUTPUT_STREAM)  
    69.             throw new IllegalStateException();  
    70.         else if (outputType == OUTPUT_WRITER)  
    71.             return writer;  
    72.         else {  
    73.             outputType = OUTPUT_WRITER;  
    74.             writer = new PrintWriter(new OutputStreamWriter(buffer,  
    75.                     getCharacterEncoding()));  
    76.             return writer;  
    77.         }  
    78.     }  
    79.   
    80.     public ServletOutputStream getOutputStream() throws IOException {  
    81.         if (outputType == OUTPUT_WRITER)  
    82.             throw new IllegalStateException();  
    83.         else if (outputType == OUTPUT_STREAM)  
    84.             return output;  
    85.         else {  
    86.             outputType = OUTPUT_STREAM;  
    87.             output = new WrappedOutputStream(buffer);  
    88.             return output;  
    89.         }  
    90.     }  
    91.   
    92.     public void flushBuffer() throws IOException {  
    93.         if (outputType == OUTPUT_WRITER)  
    94.             writer.flush();  
    95.         if (outputType == OUTPUT_STREAM)  
    96.             output.flush();  
    97.     }  
    98.   
    99.     public void reset() {  
    100.         outputType = OUTPUT_NONE;  
    101.         buffer.reset();  
    102.     }  
    103.   
    104.     /** 
    105.      * Call this method to get cached response data. 
    106.      *  
    107.      * @return byte array buffer. 
    108.      * @throws IOException 
    109.      */  
    110.     public byte[] getResponseData() throws IOException {  
    111.         flushBuffer();  
    112.         return buffer.toByteArray();  
    113.     }  
    114.   
    115.     /** 
    116.      * This class is used to wrap a ServletOutputStream and store output stream 
    117.      * in byte[] buffer. 
    118.      */  
    119.     class WrappedOutputStream extends ServletOutputStream {  
    120.   
    121.         private ByteArrayOutputStream buffer;  
    122.   
    123.         public WrappedOutputStream(ByteArrayOutputStream buffer) {  
    124.             this.buffer = buffer;  
    125.         }  
    126.   
    127.         public void write(int b) throws IOException {  
    128.             buffer.write(b);  
    129.         }  
    130.   
    131.         public byte[] toByteArray() {  
    132.             return buffer.toByteArray();  
    133.         }  
    134.     }  
    135.   
    136. }  


    (2).GZipFilter类 

    Java代码  收藏代码
    1. public class GZipFilter implements Filter {  
    2.     public void init(FilterConfig arg0) throws ServletException {  
    3.     }  
    4.   
    5.     public void doFilter(ServletRequest request, ServletResponse response,  
    6.             FilterChain chain) throws IOException, ServletException {  
    7.   
    8.         HttpServletResponse httpResponse = (HttpServletResponse) response;  
    9.         CachedResponseWrapper wrapper = new CachedResponseWrapper(httpResponse);  
    10.         // 写入wrapper:  
    11.         chain.doFilter(request, wrapper);  
    12.         // 对响应进行处理,这里是进行GZip压缩:  
    13.         byte[] data = GZipUtil.gzip(wrapper.getResponseData());  
    14.         httpResponse.setHeader("Content-Encoding", "gzip");  
    15.         httpResponse.setContentLength(data.length);  
    16.         ServletOutputStream output = response.getOutputStream();  
    17.         output.write(data);  
    18.         output.flush();  
    19.     }  
    20.   
    21.     public void destroy() {  
    22.   
    23.     }  
    24.   
    25. }  


    (3).GZipUtil类 

    Java代码  收藏代码
    1. public final class GZipUtil {  
    2.     /** * Do a gzip operation. */  
    3.     public static byte[] gzip(byte[] data) {  
    4.         ByteArrayOutputStream byteOutput = new ByteArrayOutputStream(10240);  
    5.         GZIPOutputStream output = null;  
    6.         try {  
    7.             output = new GZIPOutputStream(byteOutput);  
    8.             output.write(data);  
    9.         } catch (IOException e) {  
    10.             throw new RuntimeException("G-Zip failed.", e);  
    11.         } finally {  
    12.             if (output != null) {  
    13.                 try {  
    14.                     output.close();  
    15.                 } catch (IOException e) {  
    16.                 }  
    17.             }  
    18.         }  
    19.         return byteOutput.toByteArray();  
    20.     }  
    21. }  


    (4).在web.xml中配置 GZipFilter 

    Xml代码  收藏代码
    1. <filter>  
    2.    <filter-name>GZipFilter</filter-name>    
    3.    <filter-class>com.logcd.filter.GZipFilter</filter-class>    
    4. </filter>    
    5. <filter-mapping>    
    6.    <filter-name>GZipFilter</filter-name>    
    7.    <url-pattern>*.html</url-pattern>    
    8. </filter-mapping>  
    魔由心生,有万境纵横,无一道清静,无量寿佛!
  • 相关阅读:
    Mybatis查询select操作
    插入排序和它的进化希尔排序
    关于c头文件的使用的小记录
    Mybatis介绍
    spring tool suite开发环境搭建
    一个简单的jsp+servlet登录界面的总结
    纠正关于线程的错误理解
    表达式语言EL简单学习
    [BZOJ 1804] Flood
    [POJ 1739] Tony's Tour
  • 原文地址:https://www.cnblogs.com/qihuan/p/4137046.html
Copyright © 2020-2023  润新知