过滤器 监听器

【学习笔记】

一、过滤器

 

【定义】:部署在web服务器与客户端中间的机制,主要功能是处理中文乱码和简单的权限控制

 

【生命周期】:在容器【启动时】实例化,在客户端发送请求后过滤器的doFilter()方法会对接受到的

FilterChain对象和请求对象(servletrequest),响应对象(servletresponse)当对请求对象

处理完成后,可以通过FilterChain对象的doFilter()方法进行放行,在容器关闭时才会销毁

过滤器,故生命周期:容器启动-请求过滤(响应过滤)-容器关闭(同时过滤器销毁(容器调用destroy方                        法))

 

【创建部署】:创建:1.创建普通java类,但必须实现Filter接口(根据容器不同接口不同)才称得上过滤器

    2.重写destroy(),doFilter(),ini()方法

       部署:web.xml部署文件

<filter>

<filter-name>*****</filter-name>

<filter-class>java类绝对路径</filter-class>

</filter>

 

<filter-mapping>

<filter-name>*****</filter-name>

<url-pattern>*</url-pattern>

</filter-mapping>

 

 

注:filter-name为映射对应名,故一对标签中filter-name必须一样

   url-pattern:为指定过滤文件夹【*】代表所有,【文件夹名/*】该文件夹下所有                                                        文件  如usercenter文件夹下所有JSP文件 /usercenter/*

   顺序:fliter-mapping 标签 自上向下顺序执行 尽量按照数据流顺序来部署

过滤器

【数据流】:当数据进入过滤器后,会通过dofilter方法,此方法里有一个FilterChain对象调用dofilter()放行                    方法,这是个数据流关键的地方,一个请求对于一个响应,放行方法上面是放行前的处理,当处理

    完成后,放行给容器,此时对容器来说是客户端的一个请求,当容器处理完成后会返回一个响应

   【此时依然会】经过过滤器处理,此时放行方法后面的代码就是代表的响应回去的处理代码段

 

注:过滤器是【单实例多线程】

 

二、监听器


  •  

    借鉴文档

     

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

     

    一、批量设置请求编码 

    Java代码 

    1. public class EncodingFilter implements Filter {   
    1.   
    1.     private String encoding = null;   
    1.   
    1.     public void destroy() {   
    1.         encoding = null;   
    1.     }   
    1.   
    2.     public void doFilter(ServletRequest request, ServletResponse response,   
    1.             FilterChain chain) throws IOException, ServletException {   
    1.         String encoding = getEncoding();   
    2.         if (encoding == null){   
    3.             encoding = "gb2312";   
    4.         }   
    5.         request.setCharacterEncoding(encoding);// 在请求里设置上指定的编码   
    6.         chain.doFilter(request, response);   
    7.     }   
    8.   
    9.     public void init(FilterConfig filterConfig) throws ServletException {   
    10.         this.encoding = filterConfig.getInitParameter("encoding");   
    11.     }   
    1.   
    1.     private String getEncoding() {   
    1.         return this.encoding;   
    1.     }   
    1.   
    1. }  

     

    Xml代码 

    1. <filter>  
    1.     <filter-name>EncodingFilter</filter-name>  
    2.     <filter-class>com.logcd.filter.EncodingFilter</filter-class>  
    1.     <init-param>  
    1.        <param-name>encoding</param-name>  
    2.        <param-value>gb2312</param-value>  
    1.     </init-param>  
    1. </filter>  
    1.   
    1. <filter-mapping>  
    1.    <filter-name>EncodingFilter</filter-name>  
    1.    <url-pattern>/*</url-pattern>  
    1. </filter-mapping>  

     

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

     

    Java代码 

    1. public void doFilter(ServletRequest request,   
    2.         ServletResponse response,   
    1.         FilterChain chain)   
    1.         throws IOException, ServletException {   
    1.   
    1.     HttpServletRequest req = (HttpServletRequest) request;   
    1.     HttpServletResponse res = (HttpServletResponse) response;   
    1.   
    1.     HttpSession session = req.getSession();   
    1.     if (session.getAttribute("username") != null) {//登录后才能访问   
    1.         chain.doFilter(request, response);   
    2.     } else {   
    1.         res.sendRedirect("../failure.jsp");   
    1.     }   
    1. }  

     

     

    Xml代码 

    1. <filter>  
    1.     <filter-name>SecurityFilter</filter-name>  
    1.     <filter-class>com.logcd.filter.SecurityFilter</filter-class>  
    1. </filter>  
    1. <filter-mapping>  
    1.     <filter-name>SecurityFilter</filter-name>  
    1.     <url-pattern>/admin/*</url-pattern>  
    1. </filter-mapping>  

     

    三、过滤链 

     

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

    执行的代码顺序是: 

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

     

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

     

    四、使用filter,结合gzip 压缩技术,解决web应用中网络传输数据量大的问题 

        gziphttp协议中使用的一种加密算法,客户端向web服务器端发出了请求后,通常情况下服务器端会将页面文件和其他资源,返回到客户端,客户端加载后渲染呈现,这种情况文件一般都比较大,如果开启Gzip ,那么服务器端响应后,会将页面,JS,CSS等文本文件或者其他文件通过高压缩算法将其压缩,然后传输到客户端,由客户端的浏览器负责解压缩与呈现。通常能节省40%以上的流量(一般都有60%左右),一些PHPJSP文件也能够进行压缩。 

    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"    
    1.    compressableMimeType="text/html,text/xml"  
    1. -->  

     

        把它们加入到你配置的<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)提取和修改输出。在调用FilterChaindoFilter方法后,原资源的输出只要利用步骤2中提供的机制就可以得到。只要对你的应用适合,就可以修改或替换它。 

    5)发送修改过的输出到客户机。因为原资源不再发送输出到客户机(这些输出已经存放到你的响应包装器中了),所以必须发送这些输出。这样,你的过滤器需要从原响应对象中获得PrintWriterOutputStream,并传递修改过的输出到该流中。 

    Java代码 

    1. /**  
    2.  * Wrapper:在内存中开辟一个ByteOutputStream,然后将拦截的响应写入byte[]  
    3.  * 写入完毕后,再将wrapperbyte[]写入真正的response对象  
    1.  * This class is used for wrapped response for getting cached data.  
    1.  */    
    2. class CachedResponseWrapper extends HttpServletResponseWrapper {   
    1.   
    1.     /**  
    1.      * Indicate that getOutputStream() or getWriter() is not called yet.  
    1.      */  
    1.     public static final int OUTPUT_NONE = 0;   
    1.   
    2.     /**  
    1.      * Indicate that getWriter() is already called.  
    1.      */  
    1.     public static final int OUTPUT_WRITER = 1;   
    1.   
    1.     /**  
    2.      * Indicate that getOutputStream() is already called.  
    3.      */  
    4.     public static final int OUTPUT_STREAM = 2;   
    5.   
    6.     private int outputType = OUTPUT_NONE;   
    7.   
    8.     private int status = SC_OK;   
    9.   
    10.     private ServletOutputStream output = null;   
    11.   
    12.     private PrintWriter writer = null;   
    13.   
    1.     private ByteArrayOutputStream buffer = null;   
    1.   
    1.     public CachedResponseWrapper(HttpServletResponse resp) throws IOException {   
    1.         super(resp);   
    1.         buffer = new ByteArrayOutputStream();   
    1.     }   
    1.   
    1.     public int getStatus() {   
    1.         return status;   
    1.     }   
    1.   
    1.     public void setStatus(int status) {   
    1.         super.setStatus(status);   
    1.         this.status = status;   
    1.     }   
    1.   
    1.     public void setStatus(int status, String string) {   
    1.         super.setStatus(status, string);   
    1.         this.status = status;   
    1.     }   
    1.   
    1.     public void sendError(int status, String string) throws IOException {   
    1.         super.sendError(status, string);   
    1.         this.status = status;   
    1.     }   
    2.   
    3.     public void sendError(int status) throws IOException {   
    4.         super.sendError(status);   
    5.         this.status = status;   
    6.     }   
    7.   
    8.     public void sendRedirect(String location) throws IOException {   
    9.         super.sendRedirect(location);   
    10.         this.status = SC_MOVED_TEMPORARILY;   
    11.     }   
    1.   
    1.     public PrintWriter getWriter() throws IOException {   
    1.         if (outputType == OUTPUT_STREAM)   
    1.             throw new IllegalStateException();   
    1.         else if (outputType == OUTPUT_WRITER)   
    1.             return writer;   
    1.         else {   
    1.             outputType = OUTPUT_WRITER;   
    2.             writer = new PrintWriter(new OutputStreamWriter(buffer,   
    1.                     getCharacterEncoding()));   
    1.             return writer;   
    1.         }   
    1.     }   
    1.   
    1.     public ServletOutputStream getOutputStream() throws IOException {   
    1.         if (outputType == OUTPUT_WRITER)   
    1.             throw new IllegalStateException();   
    1.         else if (outputType == OUTPUT_STREAM)   
    1.             return output;   
    1.         else {   
    2.             outputType = OUTPUT_STREAM;   
    1.             output = new WrappedOutputStream(buffer);   
    1.             return output;   
    1.         }   
    1.     }   
    1.   
    1.     public void flushBuffer() throws IOException {   
    1.         if (outputType == OUTPUT_WRITER)   
    1.             writer.flush();   
    1.         if (outputType == OUTPUT_STREAM)   
    1.             output.flush();   
    1.     }   
    2.   
    1.     public void reset() {   
    1.         outputType = OUTPUT_NONE;   
    1.         buffer.reset();   
    1.     }   
    1.   
    1.     /**  
    1.      * Call this method to get cached response data.  
    1.      *   
    1.      * @return byte array buffer.  
    1.      * @throws IOException  
    1.      */  
    1.     public byte[] getResponseData() throws IOException {   
    2.         flushBuffer();   
    1.         return buffer.toByteArray();   
    1.     }   
    2.   
    1.     /**  
    2.      * This class is used to wrap a ServletOutputStream and store output stream  
    3.      * in byte[] buffer.  
    4.      */  
    5.     class WrappedOutputStream extends ServletOutputStream {   
    6.   
    7.         private ByteArrayOutputStream buffer;   
    8.   
    9.         public WrappedOutputStream(ByteArrayOutputStream buffer) {   
    10.             this.buffer = buffer;   
    11.         }   
    1.   
    1.         public void write(int b) throws IOException {   
    1.             buffer.write(b);   
    1.         }   
    1.   
    1.         public byte[] toByteArray() {   
    1.             return buffer.toByteArray();   
    1.         }   
    1.     }   
    1.   
    1. }  

     

    (2).GZipFilter 

    Java代码 

    1. public class GZipFilter implements Filter {   
    1.     public void init(FilterConfig arg0) throws ServletException {   
    1.     }   
    1.   
    1.     public void doFilter(ServletRequest request, ServletResponse response,   
    1.             FilterChain chain) throws IOException, ServletException {   
    1.   
    1.         HttpServletResponse httpResponse = (HttpServletResponse) response;   
    1.         CachedResponseWrapper wrapper = new CachedResponseWrapper(httpResponse);   
    2.         // 写入wrapper:   
    1.         chain.doFilter(request, wrapper);   
    1.         // 对响应进行处理,这里是进行GZip压缩  
    1.         byte[] data = GZipUtil.gzip(wrapper.getResponseData());   
    1.         httpResponse.setHeader("Content-Encoding""gzip");   
    1.         httpResponse.setContentLength(data.length);   
    1.         ServletOutputStream output = response.getOutputStream();   
    1.         output.write(data);   
    1.         output.flush();   
    1.     }   
    1.   
    1.     public void destroy() {   
    2.   
    1.     }   
    1.   
    1. }  

     

    (3).GZipUtil 

    Java代码 

    1. public final class GZipUtil {   
    1.     /** * Do a gzip operation. */  
    1.     public static byte[] gzip(byte[] data) {   
    1.         ByteArrayOutputStream byteOutput = new ByteArrayOutputStream(10240);   
    1.         GZIPOutputStream output = null;   
    1.         try {   
    1.             output = new GZIPOutputStream(byteOutput);   
    1.             output.write(data);   
    2.         } catch (IOException e) {   
    1.             throw new RuntimeException("G-Zip failed.", e);   
    1.         } finally {   
    1.             if (output != null) {   
    1.                 try {   
    1.                     output.close();   
    1.                 } catch (IOException e) {   
    2.                 }   
    3.             }   
    4.         }   
    5.         return byteOutput.toByteArray();   
    6.     }   
    7. }  

     

    (4).web.xml中配置 GZipFilter 

    Xml代码 

    1. <filter>  
    2.    <filter-name>GZipFilter</filter-name>     
    3.    <filter-class>com.logcd.filter.GZipFilter</filter-class>     
    4. </filter>     
    1. <filter-mapping>     
    1.    <filter-name>GZipFilter</filter-name>     
    1.    <url-pattern>*.html</url-pattern>     
    1. </filter-mapping>  

     

     

     


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值