二、使用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>

九:Decorator设计模式的更多相关文章

  1. Decorator设计模式浅谈

    装饰类跟基础组件都实现了目标接口,是为了匹配正确的类型.Java中的IO设计就是典型的Decorator设计模式. 装饰模式产生的初衷是, 对默认实现类的行为进行扩展. 由于装饰类的构造器接受的参数是 ...

  2. Filter学习(二)Filter使用Decorator设计模式

    在filter中可以得到代表用户请求和响应的request.response对象,因此在编程中可以使用Decorator(装饰器)模式对request.response对象进行包装,再把包装对象传给目 ...

  3. (四)Decorator设计模式解决GET/POST请求的乱码问题(转)

    一.Decorator设计模式 1.1.Decorator设计模式介绍 当某个对象的方法不适应业务需求时,通常有2种方式可以对方法进行增强: 编写子类,覆盖需增强的方法. 使用Decorator设计模 ...

  4. 常见设计模式的解析和实现(C++)之九—Decorator模式

    作用:动态地给一个对象添加一些额外的职责.就增加功能来说,Decorator模式相比生成子类更为灵活. UML结构图: 抽象基类: 1)  Component :定义一个对象接口,可以为这个接口动态地 ...

  5. 深入解析spring中用到的九种设计模式

    转载请注明出处,文章首发于:http://itxxz.com/a/javashili/tuozhan/2014/0601/7.html 设计模式作为工作学习中的枕边书,却时常处于勤说不用的尴尬境地,也 ...

  6. spring 九种设计模式

    spring中常用的设计模式达到九种,我们举例说明: 第一种:简单工厂 又叫做静态工厂方法(StaticFactory Method)模式,但不属于23种GOF设计模式之一. 简单工厂模式的实质是由一 ...

  7. Java并发程序设计(九)设计模式与并发之不变模式

    设计模式与并发之不变模式 使用不变模式的目的:除去多线程中的同步操作,提高并行程序的性能. 一个类在的内部状态创建后,在整个生命周期内都不会发生改变,该类就是不变类. /** * @author: T ...

  8. 浅谈PHP面向对象编程(九、设计模式)

    9.0 设计模式 在编写程序时经常会遇到一此典型的问题或需要完成某种特定需求,设计模式就是针对这些问题和需求,在大量的实践中总结和理论化之后优选的代码结构编程风格,以及解决问题的思考方式. 设计模式就 ...

  9. C++设计模式 之 “单一职责”模式:Decorator、Bridge

    part 1 “单一职责”模式 在软件组件的设计中,如果责任划分的不清晰,使用继承得到的结果往往是随着需求的变化,子类急剧膨胀,同时充斥着重复代码,这时候的关键是划清责任. 典型模式 Decorato ...

随机推荐

  1. Java基础00-数组9

    1. 数组定义格式 1.1 数组概述 1.2 什么是数组 1.3 数组定义格式 推荐使用第一种格式,因为第一种格式读法比较顺畅. 2. 数组初始化之动态初始化 2.1 数组初始化概述 2.2 数组初始 ...

  2. 小程序框架WePY 从入门到放弃踩坑合集

    小程序框架WePY 从入门到放弃踩坑合集 一点点介绍WePY 因为小程序的语法设计略迷, 所以x1 模块化起来并不方便, 所以x2 各厂就出了不少的框架用以方便小程序的开发, 腾讯看到别人家都出了框架 ...

  3. 简单快速安装Apache+PHP+MySql服务环境(二)—— centos使用yum安装php5.6

    使用默认方式yum install php安装的php版本为5.4,在使用某些PHP框架的时候可能会有问题,所以需要安装高版本的PHP. 通过yum list php*查看是否有自己需要安装的版本,如 ...

  4. Spring 框架中都用到了哪些设计模式

    Spring 框架中都用到了哪些设计模式? Spring 框架中使用到了大量的设计模式,下面列举了比较有代表性的: 1.代理模式-在 AOP 和 remoting 中被用的比较多. 2.单例模式:在 ...

  5. 使用Pycharm创建Django项目无法创建app.

    Python3.7使用Django1.11.7创建Django项目报以下错误时: 在使用Pycharm创建Django项目报以下错误时: Traceback (most recent call las ...

  6. 解决pip下载速度慢的问题

    解决链接:https://blog.csdn.net/u013901768/article/details/82343512 感谢这位博主的分享. 博客内容如下: 1. 安装时强制使用国内源进行安装, ...

  7. spring web.xml 标签<param-name>contextConfigLocation</param-name>

    <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</lis ...

  8. Tom_No_01 IDEA tomcat 源码环境搭建

    1.下载源码 apache-tomcat-8.5.50-src 2.下载源码 放D盘,解压后根目录新建pom.xml和catalina-home pom.xml文件中内容为 <?xml vers ...

  9. PHP imap 远程命令执行漏洞(CVE-2018-19518)

    影响版本 PHP:5.6.38 系统:Debian/ubuntu 构造数据包 成功执行命令echo '1234567890'>/tmp/test0001

  10. 痞子衡嵌入式:嵌入式Cortex-M中断向量表原理及其重定向方法

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是Cortex-M中断向量表原理及其重定向方法. 接着前文 <嵌入式Cortex-M裸机环境下临界区保护的三种实现> 继续聊, ...