HttpServletRequestWrapper
Filter能在request到达servlet的服务方法之前拦截HttpServletRequest对象,而在服务方 法转移控制后又能拦截HttpServletResponse对象。
你可以使用filter来实现特定的任务,比如验证用户输入,以及压缩web内容。但HttpServletRequest对象的参数是不可改变的,这极大地缩减了filter的应用范围。至少在一半的时间里,你希望可以改变准备传送给 filter的对象。
幸运的是,尽管你不能改变不变对象本身,但你却可以通过使用装饰模式来改变其状态。
Example1:
一个删除空白字符的Filter
HttpServerletRequest装饰类
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletRequestWrapper;
- public final class MyRequestWrapper extends HttpServletRequestWrapper {
- public MyRequestWrapper(HttpServletRequest servletRequest) {
- super(servletRequest);
- }
- public String[] getParameterValues(String parameter) {
- String[] results = super.getParameterValues(parameter);
- if (results == null) {
- return null;
- }
- int count = results.length;
- String[] trimResults = new String[count];
- for (int i = 0; i < count; i++) {
- trimResults[i] = results[i].trim();
- }
- return trimResults;
- }
- }
如何载获Http请求并装饰HttpServletRequest对象
- public class MyFilter implements Filter {
- private FilterConfig filterConfig;
- public void init(FilterConfig filterConfig) throws ServletException {
- System.out.println("Filter initialized");
- this.filterConfig = filterConfig;
- }
- public void destroy() {
- System.out.println("Filter destroyed");
- this.filterConfig = null;
- }
- public void doFilter(ServletRequest request, ServletResponse response,
- FilterChain chain) throws IOException, ServletException {
- chain.doFilter(new MyRequestWrapper((HttpServletRequest) request),
- response);
- }
- }
Example2:
通过HttpServletRequestWrapper(装饰模式的应用)来解决中文乱码问题
自定义请求包装器包装请求,将字符编码转换的工作添加到getParameter()方法中
- mport java.io.UnsupportedEncodingException;
- import java.net.URLDecoder;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletRequestWrapper;
- public class GetHttpServletRequestWrapper extends HttpServletRequestWrapper {
- private String charset = "UTF-8";
- public GetHttpServletRequestWrapper(HttpServletRequest request) {
- super(request);
- }
- /**
- * 获得被装饰对象的引用和采用的字符编码
- * @param request
- * @param charset
- */
- public GetHttpServletRequestWrapper(HttpServletRequest request,
- String charset) {
- super(request);
- this.charset = charset;
- }
- /**
- * 实际上就是调用被包装的请求对象的getParameter方法获得参数,然后再进行编码转换
- */
- public String getParameter(String name) {
- String value = super.getParameter(name);
- value = value == null ? null : convert(value);
- return value;
- }
- public String convert(String target) {
- System.out.println("编码转换之前:" + target);
- try {
- return new String(target.trim().getBytes("ISO-8859-1"), charset);
- } catch (UnsupportedEncodingException e) {
- return target;
- }
- }
- }
- public void doFilter(ServletRequest request, ServletResponse response,
- FilterChain chain) throws IOException, ServletException {
- //设置请求响应字符编码
- request.setCharacterEncoding(charset);
- response.setCharacterEncoding(charset);
- //新增加的代码
- HttpServletRequest req = (HttpServletRequest)request;
- if(req.getMethod().equalsIgnoreCase("get"))
- {
- req = new GetHttpServletRequestWrapper(req,charset);
- }
- System.out.println("----请求被"+config.getFilterName()+"过滤");
- //传递给目标servlet或jsp的实际上时包装器对象的引用,而不是原始的HttpServletRequest对象
- chain.doFilter(req, response);
- System.out.println("----响应被"+config.getFilterName()+"过滤");
- }
这样一来,在servlet中调用包装器的getParameters方法来获取参数,就已经完成了字符编码的转换过程,我们就不需要在每次获取参数时来进行字符编码转换了。