第十二章_请求和响应的装饰

12.1、Decorator模式

即使没有某一个对象的类的源代码,甚至即便这个类是声明为final的,Decorator模式和Wrapper模式都允许装饰或包装这个对象。

Decorator模式适用于无法使用继承的情况(比如,所指对象的类为final),或者你不想亲自创建对象,而是想从另一个子系统中获取。例如,Servlet容器创建了一个ServletRequest和一个ServletResponse,并将他们传给Servlet的service方法。改变ServletRequest和ServletResponse行为的唯一方法是将他们包在其他对象中。唯一必须满足的条件是,被装饰对象的类要实现一个接口,并且要包装的方法必须从这个接口处继承。

12.2、Servlet Wrapper类

Servlet API中提供了4个类,他们很少用到,但是功能非常强大,分别是:ServletRequestWrapper、ServletResponseWrapper,以及HttpServletRequestWrapper和HttpServletResponseWrapper。

ServletRequestWrapper使用起来非常方便,由于它为调用被包装ServletRequest中的对等方法的每一个方法都提供了默认实现。通过继承则只好直接实现ServletRequest,并为接口中的每一个方法都提供实现。

12.3、范例:AutoCorrect过滤器

在web应用程序中,用户经常会在输入值时,在其前面或者后面添加一些空格,甚至在词与词之间也会有多余空格。你又不想到应用程序的逐个Servlet中进行检查并删除多余的空格。那么本届介绍的AutoCorrect过滤器的特性就可以帮你完成这些工作。这个过滤器中包含一个HttpServletRequestWrapper的子类,命名为AutoCorrectHttpServletRequestWrapper,并覆盖返回一个或多个参数值的下列方法:getParameter、getParameterValues和getParameterMap。

AutoCorrectFilter.java

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;
@WebFilter(filterName = "AutoCorrectFilter", urlPatterns = {"/*"})
public class AutoCorrectFilter implements Filter{

	@Override
	public void destroy() {
		// TODO Auto-generated method stub

	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {
		// TODO Auto-generated method stub

	}

	@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) {
			// TODO Auto-generated method stub
			return autoCorrect(httpServletRequest.getParameterValues(name));
		}
		@Override
		public Map<String, String[]> getParameterMap() {
			// TODO Auto-generated method stub
			final Map<String, String[]> parameterMap = httpServletRequest.getParameterMap() ;
			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 String[] put(String key, String[] value) {
					return parameterMap.put(key, value);
				}

				@Override
				public String[] remove(Object key) {
					return parameterMap.remove(key);
				}

				@Override
				public void putAll(Map<? extends String, ? extends String[]> m) {
					parameterMap.putAll(m);
				}

				@Override
				public void clear() {
					parameterMap.clear();
				}

				@Override
				public Set<String> keySet() {
					return parameterMap.keySet();
				}

				@Override
				public Collection<String[]> values() {
					return autoCorrect(parameterMap.values());
				}

				@Override
				public Set<java.util.Map.Entry<String, String[]>> entrySet() {
					return autoCorrect(parameterMap.entrySet());
				}

			} ;
			return newMap ;
		}

	}
	private String autoCorrect(String value){
		if(value == null){
			return null ;
		}
		value = value.trim() ;
		int length = value.length() ;
		StringBuilder temp = new StringBuilder() ;
		boolean lastCharWasSpace = false ;
		for(int i = 0; i<length; i++){
			char c = value.charAt(i) ;
			if(c == ' '){
				if(!lastCharWasSpace){
					temp.append(c) ;
				}
				lastCharWasSpace = true ;
			}else{
				temp.append(c) ;
				lastCharWasSpace = false ;
			}
		}
		return temp.toString() ;
	}
	private String[] autoCorrect(String[] values){
		if(values != null){
			int length = values.length ;
			for(int i=0; i<length; i++){
				values[i] = autoCorrect(values[i]) ;
			}
			return values ;
		}
		return null ;
	}
	@SuppressWarnings("unused")
	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 ;
	}
}

test1.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">

    <title>User Form</title>

	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">
	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
	<meta http-equiv="description" content="This is my page">
	<!--
	<link rel="stylesheet" type="text/css" href="styles.css">
	-->

  </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="2">
  					<input type="submit" value="Login"/>
  				</td>
  			</tr>
  		</table>
  	</form>
  </body>
</html>

test2.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">

    <title>Form Values</title>

	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">
	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
	<meta http-equiv="description" content="This is my page">
	<!--
	<link rel="stylesheet" type="text/css" href="styles.css">
	-->

  </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>

运行结果:

时间: 2024-11-05 15:57:23

第十二章_请求和响应的装饰的相关文章

第十二章 映射请求到Servlet(JavaTM Servlet 规范3.1 )

Mapping Requests to Servlets 映射请求到 Servlet The mapping techniques described in this chapter are required for Web containers mapping client requests to servlets. Web 容器需要使用本章描述的映射技术将客户端请求映射到 servlet. 12.1 Use of URL Paths 使用 URL 路径 Upon receipt of a c

我的学习之路_第二十二章_事务

JDBC事务 [事务] 作用: 保证多条SQL语句,要么都执行成功,要么都执行失败. mysql数据库,执行SQL语句,自动开启事务,提交事务,回滚事务,把数据永久保存 oracle数据库,执行SQL语句,手动开始会务,提交事务,回滚事务,把数据永久保存. Connection接口中和事务有关的方法: 无返回值 setAutoCommit(boolean autoCommit) 将此连接的自动提交模式设置为给定状态. 参数:autoCommit : true表示自动提交模式, false表示禁用

第二十二章 TCP/IP层的实现

                      第二十二章    TCP/IP层的实现        我比较喜欢先难后易,如果把GPU显示管理.和网络管理拿下后:我会从头整理.改写一遍APO操作系统.这样,就会形成APO操作系统的锥形.也获得了全局观.内核CPU线路.和用户CPU线路,你可以将它们看成是独立的2个32位CPU核:内核CPU主要任务是实时处理.硬件中断,256个实时线程包含了一些中断程序的后半部.用户CPU主要是动态优先级进程.线程调度,各种应用程序的运行:2个核之间是通过消息交互.句

Java学习笔记—第十二章 Java网络编程入门

第十二章  Java网络编程入门 Java提供的三大类网络功能: (1)URL和URLConnection:三大类中最高级的一种,通过URL网络资源表达方式,可以很容易确定网络上数据的位置.利用URL的表示和建立,Java程序可以直接读入网络上所放的数据,或把自己的数据传送到网络的另一端. (2)Socket:又称"套接字",用于描述IP地址和端口(在Internet中,网络中的每台主机都有一个唯一的IP地址,而每台主机又通过提供多个不同端口来提供多种服务).在客户/服务器网络中,当客

[CSAPP笔记][第十二章并发编程]

第十二章 并发编程 如果逻辑控制流在时间上是重叠,那么它们就是并发的(concurrent).这种常见的现象称为并发(concurrency). 硬件异常处理程序,进程和Unix信号处理程序都是大家熟悉的例子. 我们主要将并发看做是一种操作系统内核用来运行多个应用程序的机制. 但是,并发不仅仅局限于内核.它也可以在应用程序中扮演重要的角色. 例如 Unix信号处理程序如何允许应用响应异步事件 例如:用户键入ctrl-c 程序访问虚拟存储器的一个未定义的区域 其他情况 访问慢速I/O设备 当一个应

【.NET Core项目实战-统一认证平台】第十二章 授权篇-深入理解JWT生成及验证流程

原文:[.NET Core项目实战-统一认证平台]第十二章 授权篇-深入理解JWT生成及验证流程 [.NET Core项目实战-统一认证平台]开篇及目录索引 上篇文章介绍了基于Ids4密码授权模式,从使用场景.原理分析.自定义帐户体系集成完整的介绍了密码授权模式的内容,并最后给出了三个思考问题,本篇就针对第一个思考问题详细的讲解下Ids4是如何生成access_token的,如何验证access_token的有效性,最后我们使用.net webapi来实现一个外部接口(本来想用JAVA来实现的,

JavaScript DOM编程艺术-学习笔记(第十二章)

第十二章 1.本章是综合前面章节的所有东西的,一个综合实例 2.流程:①项目简介:a.获取原始资料(包括文本.图片.音视频等) b.站点结构(文件目录结构) c.页面(文件)结构 ②设计(切图) ③css -  base.css用于引入使用的css文件 color.css  - 用于设置样式 layout.css - 用于设置布局 Typography.css - 用于设置版式 3.题外话:①在实际开发中,即使是一个空白项目也往往不会从一无所有做起,而借助的平台一般会提供目录结构,所以需要把自己

第十二章 APO编程语言

第十二章      APO编程语言 APO编程语言是基于汇编语言和面向对象编程.基本指令只有7种:赋值指令.COPY指令.BTX(位X测试为1.或0转移)指令.查表跳转指令switch(RN){-.}.移位与循环指令S.三操作数运算指令.调用与返回指令.所有的指令大小.除了32位立即数赋值是2字外:其它都是32位,一个字. 指令执行时间,除了32位立即数赋值是2ns.COPY指令取决于拷贝的长度外:其它指令都是1ns. 应用程序只能使用R0-R4,R8-R15的21个寄存器作为高速的寄存器局部变

第十二章 并发编程 学习笔记

第十二章 并发编程 进程是程序级并发,线程是函数级并发. 三种基本的构造并发程序的方法: 进程:每个逻辑控制流是个一个进程,由内核进行调度和维护. I/O多路复用:应用程序在一个进程的上下文中显式地调度他们自己的逻辑流. 线程:运行在单一进程上下文中的逻辑流,由内核进行调度. 12.1 基于进程的并发编程 构造并发程序最简单的方法就是用进程. 使用大家都很熟悉的函数例如: fork exec waitpid 关于在父.子进程间共享状态信息:共享文件表,但不共享用户地址空间. 进程又独立的地址空间