一、装饰器设计模式
即使没有某一个对象的类的源代码,甚至即便这个类是声明为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方法。