jsp 修饰 Request 及Response
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的更多相关文章
- Web jsp开发学习——终极解决jsp中request和response中文乱码的问题(加个过滤器)
中文乱码真的很烦人的.而且每次都要写,可麻烦了,而且有时候写了还不一定管用,所以我们可以试试过滤器 1.每个jsp头上当然要写上utf8啦 <%@ page language="jav ...
- JSP 中的 Request 和 Response 对象
客户端的请求信息被封装在request对象中,通过它才能了解到客户的需求,然后做出响应.它是HttpServletRequest类的实例:response对象包含了响应客户请求的有关信息,但在JSP中 ...
- JSP Servlet中的Request和Response的简单研究
本文参考了几篇文章所得,参考目录如下: 1.http://www.cnblogs.com/guangshan/p/4198418.html 2.http://www.iteye.com/problem ...
- 关于项目在网页中运行部分jsp出现乱码(由request.getRequestDispatcher("XXX.jsp").forward(request, response)造成)的解决方法
在写jsp的时候发现部分的jsp在浏览器预览时出现乱码,为一堆问号,如图: 当时问了同学,只有部分jsp会出现乱码,因为重新建一个jsp在运行就没有错误,可以显示出来,所以发现是jsp头部的错误,当新 ...
- JSP Servlet中Request与Response所有成员方法的研究
HttpServletRequest与HttpServletResponse作为Servlet中doGet.doPost等方法中传递的参数,承接了Http请求与响应中的大部分功能,请求的解析与响应的返 ...
- Request 和 Response 原理
* Request 和 Response 原理: * request对象和response对象由服务器创建,我们只需要在service方法中使用这两个对象即可 * 继承体系结构: ...
- javaWeb中 servlet 、request 、response
1.Servlet (1)Servlet是JavaEE的一个动态web资源开发技 术,就是在服务器上运行的小程序,这个小程序是由服务器调用的,服务器为了能调用这个小程序,就要求这样的程序必须实现一个S ...
- Java 中的 request 和response 区别
1.response 属于重定向请求: 其地址栏的URL会改变: 会向服务器发送两次请求: 2. request 属于请求转发: 其地址栏的URL不会改变: 向服务器发送一次请求: 举一个区分它们的简 ...
- request 和response
当今web程序的开发技术真是百家争鸣,ASP.NET, PHP, JSP,Perl, AJAX 等等. 无论Web技术在未来如何发展,理解Web程序之间通信的基本协议相当重要, 因为它让我们理解了We ...
随机推荐
- 用python在后端将数据写入到数据库并读取
用python在后端将数据写入到数据库: # coding:utf- import pandas as pd from sqlalchemy import create_engine # 初始化数据库 ...
- vue学习之template标签
HTML5提供的新标签,具有以下特性: 1.该元素天生display:none,同时模板元素内部内容也是隐藏的 2.位置任意,可以在<head>中,也可以在<body>或者&l ...
- renren-security旧版本 分模块 的模块之间关系浅析
Maven结构,一个父模块 六个子模块 七个pom.xml: \git\renren-security\pom.xml <modules> <module>renren-com ...
- 线程变量---ThreadLocal类
用处:保存线程的独立变量.对一个线程类(继承自Thread) 思想:如果一个资源会引起线程竞争,那就为每一个线程配置一个资源.相比于synchronized是一种空间换时间的策略 当使用ThreadL ...
- C/C++ assert()函数用法总结
1. 简介 assert宏的原型定义在<assert.h>中,其作用是如果它的条件返回错误,则终止程序执行. 原型定义: #include <assert.h>void ass ...
- C++ 读取字符串中的数字
今天真是试了各种方法,笨方法聪明方法都有了 方法1:一个字符一个字符的读取 方法2:借助strtok实现split 适用于char 方法3:借助istringstream实现split 适用于stri ...
- VC操作excel
http://www.cnblogs.com/witxjp/archive/2010/06/05/1752181.html 最近在做个数据库程序,因为有些数据用户要求导出到Excel文件显示(需要 ...
- 基于Hadoop2.7.3集群数据仓库Hive1.2.2的部署及使用
基于Hadoop2.7.3集群数据仓库Hive1.2.2的部署及使用 HBase是一种分布式.面向列的NoSQL数据库,基于HDFS存储,以表的形式存储数据,表由行和列组成,列划分到列族中.HBase ...
- MySQL的数据文件存储
MySQL的数据文件存储 MyISAM引擎分为:静态.动态和压缩MyISAM三种: 静态MyISAM:如果数据表中的各数据列的长度都是预先固定好的,服务器将自动选择这种表类型.因为数据表中每一条记录所 ...
- Linux命令之chmod、chown
一.chmod命令 chmod命令用于改变linux系统文件或目录的访问权限.用它控制文件或目录的访问权限.该命令有两种用法.一种是包含字母和操作符表达式的文字设定法:另一种是包含数字的数字设定法. ...