• 九:Decorator设计模式


    二、使用Decorator设计模式增强request对象

      Servlet API 中提供了一个request对象的Decorator设计模式的默认实现类HttpServletRequestWrapper,HttpServletRequestWrapper 类实现了request 接口中的所有方法,但这些方法的内部实现都是仅仅调用了一下所包装的的 request 对象的对应方法,以避免用户在对request对象进行增强时需要实现request接口中的所有方法。

    2.1、使用Decorator模式包装request对象解决get和post请求方式下的中文乱码问题

      编写一个用于处理中文乱码的过滤器CharacterEncodingFilter,代码如下:

    package me.gacl.web.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.http.HttpServletRequest;
    import javax.servlet.http.HttpServletRequestWrapper;
    import javax.servlet.http.HttpServletResponse;
    
    public class CharacterEncodingFilter implements Filter {
    
        private FilterConfig filterConfig = null;
        //设置默认的字符编码
        private String defaultCharset = "UTF-8";
    
        public void doFilter(ServletRequest req, ServletResponse resp,
                FilterChain chain) throws IOException, ServletException {
            
            HttpServletRequest request = (HttpServletRequest) req;
            HttpServletResponse response = (HttpServletResponse) resp;
            //得到在web.xml中配置的字符编码
            String charset = filterConfig.getInitParameter("charset");
            if(charset==null){
                charset = defaultCharset;
            }
            request.setCharacterEncoding(charset);
            response.setCharacterEncoding(charset);
            response.setContentType("text/html;charset="+charset);
            
            MyCharacterEncodingRequest requestWrapper = new MyCharacterEncodingRequest(request);
            chain.doFilter(requestWrapper, response);
        }
    
        public void init(FilterConfig filterConfig) throws ServletException {
            //得到过滤器的初始化配置信息
            this.filterConfig = filterConfig;
        }
        
        public void destroy() {
    
        }
    }
    
    class MyCharacterEncodingRequest extends HttpServletRequestWrapper{
        //定义一个变量记住被增强对象(request对象是需要被增强的对象)
        private HttpServletRequest request;
        //定义一个构造函数,接收被增强对象
        public MyCharacterEncodingRequest(HttpServletRequest request) {
            super(request);
            this.request = request;
        }
        /* 覆盖需要增强的getParameter方法
         * @see javax.servlet.ServletRequestWrapper#getParameter(java.lang.String)
         */
        @Override
        public String getParameter(String name) {
            try{
                //获取参数的值
                String value= this.request.getParameter(name);
                if(value==null){
                    return null;
                }
                //如果不是以get方式提交数据的,就直接返回获取到的值
                if(!this.request.getMethod().equalsIgnoreCase("get")) {
                    return value;
                }else{
                    //如果是以get方式提交数据的,就对获取到的值进行转码处理
                    value = new String(value.getBytes("ISO8859-1"),this.request.getCharacterEncoding());
                    return value;
                }
            }catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }

    在web.xml文件中配置CharacterEncodingFilter

    <!--配置字符过滤器,解决get、post请求方式下的中文乱码问题-->
      <filter>
          <filter-name>CharacterEncodingFilter</filter-name>
          <filter-class>me.gacl.web.filter.CharacterEncodingFilter</filter-class>
      </filter>
      
      <filter-mapping>
          <filter-name>CharacterEncodingFilter</filter-name>
          <url-pattern>/*</url-pattern>
      </filter-mapping>

    三、使用Decorator设计模式增强response对象

      Servlet  API 中提供了response对象的Decorator设计模式的默认实现类HttpServletResponseWrapper ,HttpServletResponseWrapper类实现了response接口中的所有方法,但这些方法的内部实现都是仅仅调用了一下所包装的的 response对象的对应方法,以避免用户在对response对象进行增强时需要实现response接口中的所有方法。

    3.1、response增强案例——压缩响应正文内容

      应用HttpServletResponseWrapper对象,压缩响应正文内容。

      具体思路:通过filter向目标页面传递一个自定义的response对象。在自定义的response对象中,重写getOutputStream方法和getWriter方法,使目标资源调用此方法输出页面内容时,获得的是我们自定义的ServletOutputStream对象。在我们自定义的ServletOuputStream对象中,重写write方法,使写出的数据写出到一个buffer中。当页面完成输出后,在filter中就可得到页面写出的数据,从而我们可以调用GzipOuputStream对数据进行压缩后再写出给浏览器,以此完成响应正文件压缩功能。

      编写压缩过滤器,代码如下:

    package me.gacl.web.filter;
    
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.OutputStreamWriter;
    import java.io.PrintWriter;
    import java.util.zip.GZIPOutputStream;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletOutputStream;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpServletResponseWrapper;
    
    public class GzipFilter implements Filter {
    
        public void doFilter(ServletRequest req, ServletResponse resp,
                FilterChain chain) throws IOException, ServletException {
            
            HttpServletRequest request = (HttpServletRequest) req;
            HttpServletResponse response = (HttpServletResponse) resp;
            
            BufferResponse myresponse = new BufferResponse(response);
            chain.doFilter(request, myresponse);
            //拿出缓存中的数据,压缩后再打给浏览器
            byte out[] = myresponse.getBuffer();
            System.out.println("原始大小:" + out.length);
            
            ByteArrayOutputStream bout = new ByteArrayOutputStream();
            //压缩输出流中的数据
            GZIPOutputStream gout = new GZIPOutputStream(bout);
            gout.write(out);
            gout.close();
            
            byte gzip[] = bout.toByteArray();
            System.out.println("压缩后的大小:" + gzip.length);
            
            response.setHeader("content-encoding", "gzip");
            response.setContentLength(gzip.length);
            response.getOutputStream().write(gzip);
        }
        
        public void destroy() {
            
        }
    
        public void init(FilterConfig filterConfig) throws ServletException {
            
        }
    }
    
    class BufferResponse extends HttpServletResponseWrapper{
    
        private ByteArrayOutputStream bout = new ByteArrayOutputStream();
        private PrintWriter pw;
        private HttpServletResponse response;
        public BufferResponse(HttpServletResponse response) {
            super(response);
            this.response = response;
        }
        @Override
        public ServletOutputStream getOutputStream() throws IOException {
            return new MyServletOutputStream(bout);
        }
        @Override
        public PrintWriter getWriter() throws IOException {
            pw = new PrintWriter(new OutputStreamWriter(bout,this.response.getCharacterEncoding()));
            return pw;
        }
        
        public byte[] getBuffer(){
            try{
                if(pw!=null){
                    pw.close();
                }
                if(bout!=null){
                    bout.flush();
                    return bout.toByteArray();
                }
                
                
                return null;
            }catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }
    
    class MyServletOutputStream extends ServletOutputStream{
    
        private ByteArrayOutputStream bout;
        public MyServletOutputStream(ByteArrayOutputStream bout){
            this.bout = bout;
        }
        
        @Override
        public void write(int b) throws IOException {
            this.bout.write(b);
        }
    }

    在web.xml中配置压缩过滤器

    <filter>
          <description>配置压缩过滤器</description>
          <filter-name>GzipFilter</filter-name>
          <filter-class>me.gacl.web.filter.GzipFilter</filter-class>
      </filter>
      
      <!--jsp文件的输出的内容都经过压缩过滤器压缩后才输出 -->
      <filter-mapping>
          <filter-name>GzipFilter</filter-name>
          <url-pattern>*.jsp</url-pattern>
          <!-- 配置过滤器的拦截方式-->
          <!-- 对于在Servlet中通过
              request.getRequestDispatcher("jsp页面路径").forward(request, response) 
          方式访问的Jsp页面的要进行拦截 -->
          <dispatcher>FORWARD</dispatcher>
          <!--对于直接以URL方式访问的jsp页面进行拦截,过滤器的拦截方式默认就是 REQUEST-->
          <dispatcher>REQUEST</dispatcher>
      </filter-mapping>
      <!--js文件的输出的内容都经过压缩过滤器压缩后才输出 -->
      <filter-mapping>
          <filter-name>GzipFilter</filter-name>
          <url-pattern>*.js</url-pattern>
      </filter-mapping>
      <!--css文件的输出的内容都经过压缩过滤器压缩后才输出 -->
      <filter-mapping>
          <filter-name>GzipFilter</filter-name>
          <url-pattern>*.css</url-pattern>
      </filter-mapping>
      <!--html文件的输出的内容都经过压缩过滤器压缩后才输出 -->
      <filter-mapping>
          <filter-name>GzipFilter</filter-name>
          <url-pattern>*.html</url-pattern>
      </filter-mapping>
  • 相关阅读:
    hdu1421 搬寝室(dp)
    HDU 2577(DP)
    扩展欧几里德算法
    unique函数的作用
    区间更新 zoj3911
    set的应用
    vue 事件处理器
    vue Class与style绑定
    vue的计算属性
    sass入门
  • 原文地址:https://www.cnblogs.com/deityjian/p/11062063.html
Copyright © 2020-2023  润新知