博客
关于我
javaweb学习总结(四十三)——Filter高级开发
阅读量:351 次
发布时间:2019-03-04

本文共 13044 字,大约阅读时间需要 43 分钟。

Decorator设计模式在Servlet应用中的实践应用

Decorator设计模式(装饰模式)是一种常用的设计模式,其核心思想是在不修改原有类文件的情况下,通过包装对象动态地扩展对象的功能。这种模式在Java web开发中有着广泛的应用,尤其是在Servlet应用中,对request和response对象进行功能增强。

Decorator设计模式介绍

Decorator模式的主要思想是通过创建一个包装对象(Decorator),来对目标对象(Target)进行功能增强。这种模式的主要优势在于:

  • 无需继承:无需对目标对象的类进行继承,避免了类层次结构复杂化。
  • 动态扩展:可以在运行时动态地对目标对象的功能进行扩展,而不需要重新编译目标类。
  • 透明性:对客户端来说,Decorator对象与目标对象看起来是完全透明的,无需额外的接口定义。
  • 在Servlet开发中,request和response对象是由容器动态创建的,其具体实现类并非公开的。因此,为了对这些对象进行功能增强,开发人员通常会采用Decorator模式对其进行包装。

    request对象的功能增强

    中文乱码处理

    过滤器实现

    编写一个用于解决中文乱码的过滤器 CharacterEncodingFilter。该过滤器的主要功能是确保不同请求方式(如GET、POST)下的参数能够正确编码和解码。

    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;public class CharacterEncodingFilter implements Filter {    private FilterConfig filterConfig;    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;        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;    }}class MyCharacterEncodingRequest extends HttpServletRequestWrapper {    private HttpServletRequest request;    public MyCharacterEncodingRequest(HttpServletRequest request) {        super(request);        this.request = request;    }    @Override    public String getParameter(String name) {        String value = this.request.getParameter(name);        if (value == null) {            return null;        }        if (!this.request.getMethod().equalsIgnoreCase("get")) {            return value;        } else {            value = new String(value.getBytes("ISO-8859-1"), this.request.getCharacterEncoding());            return value;        }    }}

    配置和使用

    web.xml 中配置过滤器:

    CharacterEncodingFilter
    me.gacl.web.filter.CharacterEncodingFilter
    CharacterEncodingFilter
    /*

    HTML标签转义

    编写一个用于转义HTML标签的过滤器 HtmlFilter。该过滤器会对请求参数中的HTML标签进行转义处理。

    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;public class HtmlFilter implements Filter {    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {        HttpServletRequest request = (HttpServletRequest) req;        HttpServletResponse response = (HttpServletResponse) resp;        MyHtmlRequest requestWrapper = new MyHtmlRequest(request);        chain.doFilter(requestWrapper, response);    }}class MyHtmlRequest extends HttpServletRequestWrapper {    private HttpServletRequest request;    public MyHtmlRequest(HttpServletRequest request) {        super(request);        this.request = request;    }    @Override    public String getParameter(String name) {        String value = this.request.getParameter(name);        if (value == null) {            return null;        }        return filter(value);    }    public String filter(String message) {        if (message == null) {            return null;        }        StringBuilder sb = new StringBuilder(message.length() + 50);        for (int i = 0; i < message.length(); i++) {            switch (message.charAt(i)) {                case '&':                    sb.append("&");                    break;                case '<':                    sb.append("<");                    break;                case '>':                    sb.append(">");                    break;                case '"':                    sb.append(""");                    break;                default:                    sb.append(message.charAt(i));            }        }        return sb.toString();    }}

    敏感字符过滤

    编写一个用于过滤敏感字符的过滤器 DirtyFilter。该过滤器会对请求参数中的敏感词进行替换。

    package me.gacl.web.filter;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.util.ArrayList;import java.util.List;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;public class DirtyFilter implements Filter {    private FilterConfig filterConfig;    private List
    dirtyWords; @Override public void init(FilterConfig filterConfig) throws ServletException { this.filterConfig = filterConfig; dirtyWords = new ArrayList<>(); String dirtyWordPath = filterConfig.getInitParameter("dirtyWord"); InputStream inputStream = filterConfig.getServletContext().getResourceAsStream(dirtyWordPath); if (inputStream != null) { try { InputStreamReader is = new InputStreamReader(inputStream, "UTF-8"); BufferedReader reader = new BufferedReader(is); String line; while ((line = reader.readLine()) != null) { dirtyWords.add(line.trim()); } } catch (IOException e) { e.printStackTrace(); } } } @Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) resp; DirtyRequest dirtyRequest = new DirtyRequest(request); chain.doFilter(dirtyRequest, response); } class DirtyRequest extends HttpServletRequestWrapper { private HttpServletRequest request; public DirtyRequest(HttpServletRequest request) { super(request); this.request = request; } @Override public String getParameter(String name) { String value = this.request.getParameter(name); if (value == null) { return null; } for (String dirtyWord : dirtyWords) { if (value.contains(dirtyWord)) { System.out.println("发现敏感词:" + dirtyWord + ", 已替换为****"); value = value.replace(dirtyWord, "****"); } } return value; } }}

    response对象的功能增强

    响应内容压缩

    编写一个用于对响应内容进行GZIP压缩的过滤器 GzipFilter。该过滤器会对响应内容进行压缩处理。

    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 {        HttpServletRequest request = (HttpServletRequest) req;        HttpServletResponse response = (HttpServletResponse) resp;        BufferResponse myResponse = new BufferResponse(response);        chain.doFilter(request, myResponse);        byte[] compressedContent = myResponse.getBuffer();        System.out.println("压缩前大小:" + compressedContent.length);        ByteArrayOutputStream bout = new ByteArrayOutputStream();        GZIPOutputStream gzip = new GZIPOutputStream(bout);        gzip.write(compressedContent);        gzip.close();        byte[] gzipContent = bout.toByteArray();        System.out.println("压缩后大小:" + gzipContent.length);        response.setHeader("Content-Encoding", "gzip");        response.setContentLength(gzipContent.length);        response.getOutputStream().write(gzipContent);    }    class BufferResponse extends HttpServletResponseWrapper {        private ByteArrayOutputStream bout;        private PrintWriter pw;        public BufferResponse(HttpServletResponse response) {            super(response);        }        @Override        public ServletOutputStream getOutputStream() {            return new MyServletOutputStream(bout);        }        @Override        public PrintWriter getWriter() {            return new PrintWriter(new OutputStreamWriter(bout, response.getCharacterEncoding()));        }        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资源缓存到内存的过滤器 WebResourceCachedFilter。该过滤器会对频繁访问的页面内容进行缓存处理。

    package me.gacl.web.filter;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io OutputStreamWriter;import java.io PrintWriter;import java.util.HashMap;import java.util.Map;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 WebResourceCachedFilter implements Filter {    private Map
    resourceCache; public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) resp; String uri = request.getRequestURI(); byte[] cachedContent = resourceCache.get(uri); if (cachedContent != null) { response.getOutputStream().write(cachedContent); return; } BufferResponse myResponse = new BufferResponse(response); chain.doFilter(request, myResponse); byte[] content = myResponse.getBuffer(); resourceCache.put(uri, content); response.getOutputStream().write(content); } class BufferResponse extends HttpServletResponseWrapper { private ByteArrayOutputStream bout; private PrintWriter pw; public BufferResponse(HttpServletResponse response) { super(response); } @Override public ServletOutputStream getOutputStream() { return new MyServletOutputStream(bout); } @Override public PrintWriter getWriter() { return new PrintWriter(new OutputStreamWriter(bout, response.getCharacterEncoding())); } public byte[] getBuffer() { try { if (pw != null) { pw.close(); } return bout.toByteArray(); } 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); } }}

    总结

    通过以上实例可以看出,Decorator设计模式在Servlet开发中具有广泛的应用场景。无论是对request对象的参数处理,还是对response对象的内容输出,都可以通过包装目标对象来实现功能的增强。在实际项目中,可以根据具体需求选择性地对request和response对象进行装饰,以满足特定的功能需求。

    转载地址:http://qnkr.baihongyu.com/

    你可能感兴趣的文章
    mysql 导入 sql 文件时 ERROR 1046 (3D000) no database selected 错误的解决
    查看>>
    mysql 导入导出大文件
    查看>>
    mysql 将null转代为0
    查看>>
    mysql 常用
    查看>>
    MySQL 常用列类型
    查看>>
    mysql 常用命令
    查看>>
    Mysql 常见ALTER TABLE操作
    查看>>
    mysql 往字段后面加字符串
    查看>>
    mysql 快速自增假数据, 新增假数据,mysql自增假数据
    查看>>
    Mysql 报错 Field 'id' doesn't have a default value
    查看>>
    MySQL 报错:Duplicate entry 'xxx' for key 'UNIQ_XXXX'
    查看>>
    mysql 排序id_mysql如何按特定id排序
    查看>>
    Mysql 提示:Communication link failure
    查看>>
    mysql 插入是否成功_PDO mysql:如何知道插入是否成功
    查看>>
    Mysql 数据库InnoDB存储引擎中主要组件的刷新清理条件:脏页、RedoLog重做日志、Insert Buffer或ChangeBuffer、Undo Log
    查看>>
    mysql 数据库备份及ibdata1的瘦身
    查看>>
    MySQL 数据库备份种类以及常用备份工具汇总
    查看>>
    mysql 数据库存储引擎怎么选择?快来看看性能测试吧
    查看>>
    MySQL 数据库操作指南:学习如何使用 Python 进行增删改查操作
    查看>>
    MySQL 数据库的高可用性分析
    查看>>