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 = 0; 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 = 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[]>() {
                @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="2">
<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>
复制代码

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

posted @   江期玉  阅读(511)  评论(0编辑  收藏  举报
编辑推荐:
· 聊一聊 C#前台线程 如何阻塞程序退出
· 几种数据库优化技巧
· 聊一聊坑人的 C# MySql.Data SDK
· 使用 .NET Core 实现一个自定义日志记录器
· [杂谈]如何选择:Session 还是 JWT?
阅读排行:
· 一个.NET开源、易于使用的屏幕录制工具
· 【经验】几种数据库优化技巧
· C#中 Task 结合 CancellationTokenSource的妙用
· Superpower:一个基于 C# 的文本解析工具开源项目
· 反微服务架构(A Macro Services Framework)
点击右上角即可分享
微信分享提示