本文共 13360 字,大约阅读时间需要 44 分钟。
Decorator设计模式(装饰模式)是一种常用的设计模式,其核心思想是在不修改原有类文件的情况下,通过包装对象动态地扩展对象的功能。这种模式在Java web开发中有着广泛的应用,尤其是在Servlet应用中,对request和response对象进行功能增强。
Decorator模式的主要思想是通过创建一个包装对象(Decorator),来对目标对象(Target)进行功能增强。这种模式的主要优势在于:
在Servlet开发中,request和response对象是由容器动态创建的,其具体实现类并非公开的。因此,为了对这些对象进行功能增强,开发人员通常会采用Decorator模式对其进行包装。
编写一个用于解决中文乱码的过滤器 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标签的过滤器 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 ListdirtyWords; @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; } }}
编写一个用于对响应内容进行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 MapresourceCache; 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/