Servlet API包含4个可修饰的类,用于改变Servlet Request以及Servlet Response。这种修饰允许修改 ServletRequest以及ServletResponse或者HTTP中的等价 类(即HttpServletRequest和HttpServletResponse)中的 任务方法。这种修饰遵循Decorator模式或者Wrapper模 式,因此在使用修饰前,需要了解一下该模式的内容。

一.Decorator 模式( 装饰器模式)

  Decorator模式或者Wrapper模式允许修饰或者封装 (在字面意义中,即修改行为)一个对象,即使你没有 该对象的源代码或者该对象标识为final。

   Decorator模式适用于无法继承该类(例如,对象的 实现类使用final标识)或者无法创建该类的实例,但可 以从另外的系统中可以取得该类的实现时。例如, Servlet容器方法。只有一种方法可以修改ServletRequest 或者ServletResponse行为,即在另外的对象中封装该实 例。唯一的限制是,修饰对象必须继承一个接口,然后 实现接口以封装这些方法。

  

  

  类图说明了一个Component接口以及它 的实现类ComponentImpl。Component接口定义了A的方 法。为了修饰ComponentImpl的实例,需要创建一个 Decorator类,并实现Component的接口,然后在子类中 扩展Decorator的新行为。在类图中DecoratorA就是 Decorator的一个子类。每个Decorator实例需要包含 Component的一个实例。Decorator类代码如下(注意在 构建函数中获取了Component的实例,这意味着创建 Decorator对象只能传入Component的实例):

public class Decorator implements Component {
private Component decorated;
// constructor takes a Component implementation
public Decorator(Component component) {
this.decorated = component;
}
// undecorated method
@Override
public void methodA(args) {
decorated.methodA(args);
}
// decorated method
@Override
public void methodB(args) {
decorated.methodB(args)
}
}

  在Decorator类中,有修饰的方法就是可能在子类中 需要修改行为的方法,在子类中不需要修饰的方法可以 不需要实现。所有的方法,无论是否需要修饰,都叫作 Component中的配对方法。Decorator是一个非常简单的 类,便于提供每个方法的默认实现。修改行为在它的子 类中。

  需要牢记一点,Decorator类及被修饰对象的类需要 实现相同的接口。为了实现Decorator,可以在Decorator 中封装修饰对象,并把Decorator作为Component的一个 实现。任何Component的实现都可以在Decorator中注 入。事实上,你可以把一个修饰的对象传入另一个修饰 的对象,以实现双重的修饰。

二. Servlet封装类

  Servlet API源自于4个实现类,它很少被使用,但 是十分强大:ServletRequestWrapper、 ServletResponseWrapper以及 HttpServletRequestWrapper、 HttpServletResponseWrapper。

  ServletRequestWrapper(或者其他3个Wrapper类) 非常便于使用,因为它提供了每个方法的默认实现:即 ServletRequest封闭的配置方法。通过继承 ServletRequestWrapper,只需要实现你需要变更的方法 就可以了。如果不用ServletRequestWrapper,则需要继 承ServletRequest并实现ServletRequest中所有的方法。

  图所示为Decorator模式中 ServletRequestWrapper的类图。Servlet容器在每次 Servlet服务调用时创建ServletRequest、ContainerImpl。 直接扩展ServletRequestWrapper就可以修饰 ServletRequest了。

 

三. 示例:AutoCorrect Filter

  在Web应用中,用户经常在单词的前面或者后面输 入空格,更有甚者在单词之间也加入空格。是否很想在 应用的每个Servlet中,把多余的空格删除掉呢?本节的 AutoCorrect Filter可以帮助你搞定它。该Filter包含了 HttpServletRequestWrapper子类 AutoCorrectHttpServletRequestWrapper,并重写了返回 参数值的方法:getParameter、getParameterValues及 getParameterMap。代码如下所示。

AutoCorrectFilter 类

package filter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
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.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
// urlPatterns={"/*"} 不能过滤链接
@WebFilter(filterName = "AutoCorrectFilter", urlPatterns = { "*" })
public class AutoCorrectFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
} @Override
public void destroy() {
} @Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
AutoCorrectHttpServletRequestWrapper wrapper = new AutoCorrectHttpServletRequestWrapper(httpServletRequest);
filterChain.doFilter(wrapper, response);
} class AutoCorrectHttpServletRequestWrapper extends HttpServletRequestWrapper {
private HttpServletRequest httpServletRequest; public AutoCorrectHttpServletRequestWrapper(HttpServletRequest httpServletRequest) {
super(httpServletRequest);
this.httpServletRequest = httpServletRequest;
} @Override
public String getParameter(String name) {
return autoCorrect(httpServletRequest.getParameter(name));
} @Override
public String[] getParameterValues(String name) {
return autoCorrect(httpServletRequest.getParameterValues(name));
} //用匿名内部类 重写 getParameterMap() 方法
@Override
public Map<String, String[]> getParameterMap() {
// 得到request的 parameterMap
final Map<String, String[]> parameterMap = httpServletRequest.getParameterMap();
// 重写 parameterMap
Map<String, String[]> newMap = new Map<String, String[]>() {
@Override
public int size() {
return parameterMap.size();
} @Override
public boolean isEmpty() {
return parameterMap.isEmpty();
} @Override
public boolean containsKey(Object key) {
return parameterMap.containsKey(key);
} @Override
public boolean containsValue(Object value) {
return parameterMap.containsValue(value);
} @Override
public String[] get(Object key) {
return autoCorrect(parameterMap.get(key));
} @Override
public void clear() {
// this will throw an IllegalStateException
// but let the user get the original
// exception
parameterMap.clear();
} @Override
public Set<String> keySet() {
return parameterMap.keySet();
} @Override
public Collection<String[]> values() {
return autoCorrect(parameterMap.values());
} @Override
public Set<Map.Entry<String, String[]>> entrySet() {
return autoCorrect(parameterMap.entrySet());
} @Override
public String[] put(String key, String[] value) {
// this will throw an IllegalStateException
// but let the user get the original
// exception
return parameterMap.put(key, value);
} @Override
public void putAll(Map<? extends String, ? extends String[]> map) {
// this will throw an IllegalStateException
// but let
// the user get the original exception
parameterMap.putAll(map);
} @Override
public String[] remove(Object key) {
// this will throw an IllegalStateException,
// but let
// the user get the original exception
return parameterMap.remove(key);
}
};
//返回一个新的map
return newMap;
}
} private String autoCorrect(String value) {
if (value == null) {
return null;
}
// 去除String头尾空格
value = value.trim();
int length = value.length();
StringBuilder temp = new StringBuilder();
boolean lastCharWasSpace = false;
for (int i = ; i < length; i++) {
char c = value.charAt(i);
// 如果是空格
if (c == ' ') {
// 如果是空格且是最后一个字符 就添加到temp
if (!lastCharWasSpace) {
temp.append(c);
}
lastCharWasSpace = true;
} else {
// 不是空格的字符直接添加到temp
temp.append(c);
lastCharWasSpace = false;
}
}
return temp.toString();
} private String[] autoCorrect(String[] values) {
if (values != null) {
int length = values.length;
for (int i = ; i < length; i++) {
values[i] = autoCorrect(values[i]);
}
return values;
}
return null;
} private Collection<String[]> autoCorrect(Collection<String[]> valueCollection) {
Collection<String[]> newCollection = new ArrayList<String[]>();
for (String[] values : valueCollection) {
newCollection.add(autoCorrect(values));
}
return newCollection;
} private Set<Map.Entry<String, String[]>> autoCorrect(Set<Map.Entry<String, String[]>> entrySet) {
Set<Map.Entry<String, String[]>> newSet = new HashSet<Map.Entry<String, String[]>>();
for (final Map.Entry<String, String[]> entry : entrySet) {
Map.Entry<String, String[]> newEntry = new Map.Entry<String, String[]>() {
@Override
public String getKey() {
return entry.getKey();
} @Override
public String[] getValue() {
return autoCorrect(entry.getValue());
} @Override
public String[] setValue(String[] value) {
return entry.setValue(value);
}
};
newSet.add(newEntry);
}
return newSet;
}
}

  这个Filter的doFilter方法非常简单:创建 ServletRequest的修饰实现,然后,把修饰类传给 doFilter

HttpServletRequest httpServletRequest =
(HttpServletRequest) request;
AutoCorrectHttpServletRequestWrapper wrapper = new
AutoCorrectHttpServletRequestWrapper(
httpServletRequest);
filterChain.doFilter(wrapper, response);

  在这个Filter背后的任何Servlet获得的 HttpServletRequest都将被AutoCorrectHttp ServletRequestWrapper 所封装。这个封装类很长,但很 好理解。简单地说,就是它把所有获取参数的响应都调 用了一下autoCorrect方法:

test1.jsp页面

<!DOCTYPE html>
<html>
<head>
<title>User Form</title>
</head>
<body>
<form action="test2.jsp" method="post">
<table>
<tr>
<td>Name:</td>
<td><input name="name"/></td>
</tr>
<tr>
<td>Address:</td>
<td><input name="address"/></td>
</tr>
<tr>
<td colspan="">
<input type="submit" value="Login"/>
</td>
</tr>
</table>
</form>
</body>
</html>

test2.jsp页面

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
<!DOCTYPE html>
<html>
<head>
<title>Form Values</title>
</head>
<body>
<table>
<tr>
<td>Name:</td>
<td>${param.name} (length:${fn:length(param.name)})</td>
</tr>
<tr>
<td>Address:</td>
<td>${param.address} (length:${fn:length(param.address)})</td>
</tr>
</table>
</body>
</html>

  输入一个带空格的单词,无论是前面、后面,还是 在单词之间,然后点击提交。接下来,在显示器上你将 看到这些输入单词都被修正过来

jsp 修饰 Request 及Response的更多相关文章

  1. Web jsp开发学习——终极解决jsp中request和response中文乱码的问题(加个过滤器)

    中文乱码真的很烦人的.而且每次都要写,可麻烦了,而且有时候写了还不一定管用,所以我们可以试试过滤器 1.每个jsp头上当然要写上utf8啦 <%@ page language="jav ...

  2. JSP 中的 Request 和 Response 对象

    客户端的请求信息被封装在request对象中,通过它才能了解到客户的需求,然后做出响应.它是HttpServletRequest类的实例:response对象包含了响应客户请求的有关信息,但在JSP中 ...

  3. JSP Servlet中的Request和Response的简单研究

    本文参考了几篇文章所得,参考目录如下: 1.http://www.cnblogs.com/guangshan/p/4198418.html 2.http://www.iteye.com/problem ...

  4. 关于项目在网页中运行部分jsp出现乱码(由request.getRequestDispatcher("XXX.jsp").forward(request, response)造成)的解决方法

    在写jsp的时候发现部分的jsp在浏览器预览时出现乱码,为一堆问号,如图: 当时问了同学,只有部分jsp会出现乱码,因为重新建一个jsp在运行就没有错误,可以显示出来,所以发现是jsp头部的错误,当新 ...

  5. JSP Servlet中Request与Response所有成员方法的研究

    HttpServletRequest与HttpServletResponse作为Servlet中doGet.doPost等方法中传递的参数,承接了Http请求与响应中的大部分功能,请求的解析与响应的返 ...

  6. Request 和 Response 原理

    * Request 和 Response 原理:     * request对象和response对象由服务器创建,我们只需要在service方法中使用这两个对象即可        * 继承体系结构: ...

  7. javaWeb中 servlet 、request 、response

    1.Servlet (1)Servlet是JavaEE的一个动态web资源开发技 术,就是在服务器上运行的小程序,这个小程序是由服务器调用的,服务器为了能调用这个小程序,就要求这样的程序必须实现一个S ...

  8. Java 中的 request 和response 区别

    1.response 属于重定向请求: 其地址栏的URL会改变: 会向服务器发送两次请求: 2. request 属于请求转发: 其地址栏的URL不会改变: 向服务器发送一次请求: 举一个区分它们的简 ...

  9. request 和response

    当今web程序的开发技术真是百家争鸣,ASP.NET, PHP, JSP,Perl, AJAX 等等. 无论Web技术在未来如何发展,理解Web程序之间通信的基本协议相当重要, 因为它让我们理解了We ...

随机推荐

  1. mvc中异常页面的设置

    参考原文: http://blog.csdn.net/zjlovety/article/details/48734791 这种异常处理就是说,在mvc发生未处理异常时,对用户展示的页面. 第一种能被m ...

  2. Python基础6 面向对象

    本节内容 面向对象编程介绍 为什么要面向对象开发? 面向对象的特性:封装,继承,多态 类,方法 引子 假设现在我们需要开发一款简单的游戏,譬如叫做人兽战争.我们需要简单的2个角色,一个人,一个怪兽,而 ...

  3. 832B Petya and Exam

    题意:给你两个串,第一个串里面的字母都是good 字母, 第二个串是模式串,里面除了字母还有?和*(只有一个) ?可以替换所有good字母, *可以替换所有坏字母和空格(可以是多个坏字母!!!这点卡了 ...

  4. Jedis(java操作redis数据库技术)

    Redis有什么命令,Jedis就有什么方法. 客户端无法连接时,需要考虑防火墙配置,比如6379端口是否开放,也可以直接关闭防火墙. Jedis连接池: import org.junit.Test; ...

  5. flask 连接mysql及基本操作

    #导入第三方连接库sql点金术 from flask_sqlalchemy import SQLAlchemy #建立对象 app = Flask(__name__) #载入配置文件 app.conf ...

  6. python,异常处理

    # 该例子是对文件异常和类型异常分别进行的处理 try: sum = 1+' f=open('wo.txt') print(f.read()) f.close() except OSError as ...

  7. linux 服务器下的基本操作

    1.SSH 上传: scp /path/file(这部分为本地的路径) user(远端目标用户名)@host(远端目标IP):/pathorfile(文件存储路径) 下载: scp user(远端用户 ...

  8. Python学习笔记-循环语句

    While 循环语句 flag=False name = raw_input("请输入:"); numbers=['羊爸爸','羊妈妈','羊宝','牛宝'] while len( ...

  9. P3168 [CQOI2015]任务查询系统

    题目地址:P3168 [CQOI2015]任务查询系统 主席树的模板题 更模板的在这儿:P3834 [模板]可持久化线段树 1(主席树) 形象的说,P3834是"单点修改,区间查询" ...

  10. Python内建函数-callable

    Python内建函数-callable callable(object) 中文说明:检查对象object是否可调用.如果返回True,object仍然可能调用失败:但如果返回False,调用对象ojb ...