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

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

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-5.7.18安装
    查看>>
    MySQL-Buffer的应用
    查看>>
    mysql-cluster 安装篇(1)---简介
    查看>>
    mysql-connector-java各种版本下载地址
    查看>>
    mysql-EXPLAIN
    查看>>
    mysql-group_concat
    查看>>
    MySQL-redo日志
    查看>>
    MySQL-【1】配置
    查看>>
    MySQL-【4】基本操作
    查看>>
    Mysql-丢失更新
    查看>>
    Mysql-事务阻塞
    查看>>
    Mysql-存储引擎
    查看>>
    mysql-开启慢查询&所有操作记录日志
    查看>>
    MySQL-数据目录
    查看>>
    MySQL-数据页的结构
    查看>>
    MySQL-架构篇
    查看>>
    MySQL-索引的分类(聚簇索引、二级索引、联合索引)
    查看>>
    Mysql-触发器及创建触发器失败原因
    查看>>
    MySQL-连接
    查看>>
    mysql-递归查询(二)
    查看>>