请求和响应的装饰——装饰器设计模式

2023-10-27

一、装饰器设计模式

即使没有某一个对象的类的源代码,甚至即便这个类是声明为final的,Decorator模式和Wrapper模式都允许装饰或者包装(说白了,就是修改)这个对象的行为。

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

二、Decorator模式的UML


解释:

Component接口就好比ServletRequest

ConcreteComponent就好比HttpServletRequest

Decorator就好比ServletRequestWrapper

而ConcreterDecorator就好比HttpServletRequestWraper

其中Operation()方法是在Component接口中定义的方法。

因此呢,可以在HttpServletRequestWrapper中对其公有方法进行修改


三、具体实例:自动校验过滤器

功能描述:该过滤器能够对用户输入的变量进行检验,过滤掉字符串开始和结束部分的空白字符。

四、源代码:

package com.tanjie.decorator;

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;

/**
 * Servlet Filter implementation class AutoCorrectFilter
 */
public class AutoCorrectFilter implements Filter {

    /**
     * Default constructor. 
     */
    public AutoCorrectFilter() {
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see Filter#destroy()
	 */
	public void destroy() {
		// TODO Auto-generated method stub
	}

	/**
	 * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
	 */
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		HttpServletRequest httpServletRequest = (HttpServletRequest)request;
		AutoCorrectHttpServletRequestWrapper wrapper = new AutoCorrectHttpServletRequestWrapper(httpServletRequest);
		chain.doFilter(wrapper, response);
	}

	/**
	 * @see Filter#init(FilterConfig)
	 */
	public void init(FilterConfig fConfig) throws ServletException {
		// TODO Auto-generated method stub
	}

}

package com.tanjie.decorator;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;


public class AutoCorrectHttpServletRequestWrapper extends HttpServletRequestWrapper {
	HttpServletRequest httpServletRequest;

	public AutoCorrectHttpServletRequestWrapper(HttpServletRequest httpServletRequest) {
		super(httpServletRequest);
		this.httpServletRequest = httpServletRequest;
	}
	
	public String getParameter(String name){
		return autoCorrect(httpServletRequest.getParameter(name));
	}
	public String[] getParameterValues(String name){
		return autoCorrect(httpServletRequest.getParameterValues(name));
	}
	public Map<String, String[]> getParameterMap(){
		final Map<String, String[]> parameterMap = httpServletRequest.getParameterMap();
		Map<String, String[]> newMap = new Map<String, String[]>(){

			public int size() {
				return parameterMap.size();
			}

			public boolean isEmpty() {
				// TODO Auto-generated method stub
				return parameterMap.isEmpty();
			}

			public boolean containsKey(Object key) {
				return parameterMap.containsKey(key);
			}

			public boolean containsValue(Object value) {
				return parameterMap.containsValue(value);
			}

			public String[] get(Object key) {
				return autoCorrect(parameterMap.get(key));
			}

			public String[] remove(Object key) {
				// TODO Auto-generated method stub
				return null;
			}

			public void putAll(Map<? extends String, ? extends String[]> map) {
				
				parameterMap.putAll(map);
			}
			
			public void clear() {
				// TODO Auto-generated method stub
				parameterMap.clear();
			}

			public Set<String> keySet() {
				// TODO Auto-generated method stub
				return parameterMap.keySet();
			}

			public Collection<String[]> values() {
				// TODO Auto-generated method stub
				return autoCorrect(parameterMap.values());
			}	

			public Set<java.util.Map.Entry<String, String[]>> entrySet() {
				// TODO Auto-generated method stub
				return autoCorrect(parameterMap.entrySet());
			}
			
			public String[] put(String key, String[] value){
				return parameterMap.put(key, value);
			}
			
		};
		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);
				}else{
					lastCharWasSpace = true;
				}	
			}else{
				temp.append(c);
				lastCharWasSpace = false;
			}
		}*/
		//return temp.toString();
		return value;
	}
	
	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;
	} 
	
	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[]>() {

				public String getKey() {
					// TODO Auto-generated method stub
					return entry.getKey();
				}

				public String[] getValue() {
					// TODO Auto-generated method stub
					return autoCorrect(entry.getValue());
				}

				public String[] setValue(String[] value) {
					// TODO Auto-generated method stub
					return entry.setValue(value);
				}
			};
			newSet.add(newEntry);
		}
		return newSet;	
	}
}

	

五、总结

ServletAPI中提供了4个包装类,分别是ServletRequestWrapper、ServletResponseWrapper、HttpServletRequestWrapper、HttpServletResponseWrapper。可以使用继承它们来装饰Servlet请求和Servlet响应。之后,可以利用过滤器或者监听器创建一个包装类,并将它传递给Servlet的service方法。


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

请求和响应的装饰——装饰器设计模式 的相关文章

  • C# 中集合作为装饰器

    在设计集合基础设施时 我们遇到了一个非常 明显 的问题 假设您需要实现许多 子 类型的集合 其中一个方面是存储相关 list array等等 而另一个是行为相关 ordered 仅删除 可观察到的 每次更改时都会触发一个事件 等 显然 再次
  • WEKA 的重采样过滤器 - 如何解释结果

    我目前正在努力解决机器学习问题 而我必须处理大量不平衡的数据集 也就是说 有六个类 1 2 6 不幸的是有例如对于 1 类 有 150 个示例 实例 对于 2 有 90 个实例 对于 3 类 只有 20 个实例 所有其他类都无法 训练 因为
  • 代理模式和装饰者模式的区别

    你能给出任何好的解释吗 Proxy and 装饰者 我看到的主要区别是 当我们假设Proxy uses 作品 and 装饰者 uses 聚合那么似乎很清楚 通过使用多个 一个或多个 装饰器您可以修改 添加功能到预先存在的实例 装饰 而Pro
  • 使用组合框过滤文本框

    好吧 我必须创建一个表单 它获取文件夹的内容并将其列出在文本框中 是的 文本框不是列表框 然后 我必须使用包含文件夹所有扩展名的组合框来过滤此文本框 例如 如果我在组合框中选择 txt 则文本框应过滤以仅显示所有文本文件 除了让组合框过滤文
  • php 如何使用 getimagesize() 检查上传时的图像类型[重复]

    这个问题在这里已经有答案了 可能的重复 GetImageSize 在应该返回 FALSE 时没有返回 FALSE https stackoverflow com questions 10464948 getimagesize not ret
  • 如何根据列表中的先前值过滤Haskell中的列表元素?

    我正在努力在 Haskell 中创建一个函数 该函数根据列表中前一个元素的条件过滤列表的数字 Example 前一个数字是 2 的倍数 myFunction 1 2 5 6 3 expected output 5 3 我知道如何申请filt
  • 如何在java中的组合框之间使用过滤器?

    我的数据库中有两个表 分别是学期表和课程表 学期表中有学期 ID 课程 ID 课程名称和 Sdepartment 部门名称 课程表有课程 ID 和课程名称 我的 jframe 有两个组合框 第一个用于选择部门 第二个用于选择课程 我想选择所
  • 如何通过单击按钮从反应状态挂钩数组中删除对象

    我正在尝试制作一个按钮 根据传递的索引从数组 即状态 中删除一个对象 我已经尝试了很多 但我的方法都不起作用 所以这是代码 希望我可以找人帮忙 state const items setItems useState name quantit
  • 将“-Filter”与变量一起使用

    我尝试过滤掉这样的东西 Get ADComputer Filter name like chalmw dm and Enabled eq true 这就像一个魅力 并且得到了我想要的 现在我想要 类似名称 部分作为变量 如下所示 Get A
  • 装饰器功能不起作用(意外标记)

    刚刚尝试在 React 中使用装饰器 import React from react import Fade from Transitions Fade import withVisible from withVisible withVis
  • 使用 TextBox 过滤 Datagridview 行

    我有一个绑定的 datagridView 我想使用 TextBox 值对其进行过滤 我使用了这段代码 private void ChercheStextBox TextChanged object sender EventArgs e tr
  • 仅为一个通用命令处理程序注册 Autofac 装饰器

    我们有很多通用命令处理程序 它们由 Autofac 以开放通用方式注册 我们有几个装饰器来装饰所有的手柄 现在我需要仅为一个命令处理程序注册一个装饰器 而不影响所有其他命令处理程序 这是我的尝试 但我似乎没有正确注册 这是与我们的代码类似的
  • 使用 ASP.NET MVC Linq To SQL 进行验证:如何避免编辑生成的源?

    我正在阅读一些关于验证的文档ASP NET MVC 忽略那些建议重新发明轮子编写自己的验证逻辑的人 大多数文章提倡使用xVal或数据注释验证器 两者都允许通过装饰模型的属性 进行声明性验证 我想我会去xVal 因为它似乎是最受建议的 因此
  • 使用 fopen() 包装器创建 ZIP 文件

    如何使用以下命令创建 ZIP 文件fopen 包装器 http es php net manual en wrappers compression php 这显然是not道路
  • & 在 XML 代码中导致错误的符号

    我有以下 XML 代码 用于过滤我的 Crm Dynamics 表单中的查找字段 该过滤器根据输入帐户字段的数据使用 但是 帐户字段可以包含 符号 当出现时 会发生错误 表明 XML 格式不正确 有人有解决问题的办法吗 function a
  • Scala 程序中三元运算符的用法[关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 我有一个需要应用过滤器的对象数组 val filteredList list filter l gt pid true l Pro
  • 动态过滤 pandas 数据框

    我正在尝试使用三列的阈值来过滤 pandas 数据框 import pandas as pd df pd DataFrame A 6 2 10 5 3 B 2 5 3 2 6 C 5 2 1 8 2 df df loc df A gt 0
  • 使用动画过滤 UITableViewCells - iPhone 开发

    这看起来很简单 但到目前为止我还无法找到解决方案 基本上我有一个带有两个选项的分段控件 第一个是默认值 加载时自动显示 选择后会在表视图中显示所有行 第二个是限制显示行的过滤器 这与 iPhone 电话应用程序的 最近 选项卡上使用的设置完
  • 使用powershell计算子文件夹中具有特定名称的文件数量

    因此 我开始解决一个问题 我需要知道某个名称的子文件夹中有多少个文件 这些文件在整个目录中重复多次 我想要计算的所有文件夹都具有相同的名称 例如 Main Folder Subfolder Folder I want to count Fo
  • 在Excel中过滤后打印可见区域的宏

    我有一个根据过滤表的宏column A价值观 现在我想打印only过滤器后的可见行 但遗憾的是它打印了所有行 包括过滤期间隐藏的顶部和底部行 在我的工作表中 有来自的数据Column A I 但打印区域只能是Columns C I 过滤后的

随机推荐