二、使用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. 【论文阅读】Motion Planning through policy search

    想着CSDN还是不适合做论文类的笔记,那里就当做技术/系统笔记区,博客园就专心搞看论文的笔记和一些想法好了,[]以后中框号中间的都算作是自己的内心OS 有时候可能是问题,有时候可能是自问自答,毕竟是笔 ...

  2. SpringBoot总结之Spring Data Jpa

    一.Spring Data Jpa简介 JPA(Java Persistence API)定义了一系列对象持久化的标准,目前实现这一规范的产品有Hibernate.TopLink等. Spring D ...

  3. Easyui动态添加控件无法渲染 $.parser.parse()无效

    本文链接:https://blog.csdn.net/huangbaokang/article/details/78367553动态添加easyui控件<input class="ea ...

  4. 谷粒学院-2-mybatisplus

    一.参考文档 官网:http://mp.baomidou.com/ 参考教程:http://mp.baomidou.com/guide/ MyBatis-Plus(简称 MP)是一个 MyBatis ...

  5. map 和 unordered_map

    map就是映射. 定义 map<typename,typename> 注:map的元素是pair. 特性 map会对第一个对象自动排序. map不允许有两个相同的关键字. map可以定义迭 ...

  6. P4778 Counting Swaps 题解

    第一道 A 掉的严格意义上的组合计数题,特来纪念一发. 第一次真正接触到这种类型的题,给人感觉好像思维得很发散才行-- 对于一个排列 \(p_1,p_2,\dots,p_n\),对于每个 \(i\) ...

  7. 在java中为啥要重写toString 方法?

    在java中为啥要重写toString 方法?下面以一个简单的例子来说明. 先定义一个test5类.并写它的get,set方法. package test5; public class Test5 { ...

  8. 常见的BI软件有哪些_BI工具软件哪个好用

    世界越来越以数据的驱动.数据分析是帮助企业深入了解自身业务表现(例如正在做什么或哪块业务需要注意和改进)的重要元素.为了获得更直观的展现,数据分析软件可帮助公司通过报告.数据可视化.应用程序等从数据中 ...

  9. Fedora无法安装Qt4

    针对QT4,6安装时遇到的情况 安装平台:fedora14i686 Qt版本:4.6.2 1:解压qt的tar包 我们进行解压(tar xzvf ***.tar.gz),解压到指定目录的话后边加上: ...

  10. vue 跨域 springCloud @CrossOrigin注解

    vue 跨域  springCloud @CrossOrigin注解 一丶什么是跨域 跨域问题来源于浏览器的同源策略,浏览器为了提高网站的安全性,在发送ajax请求时,只有在当前页面地址与请求地址的协 ...