`

HttpServletRequestWrapper 用法

阅读更多
Servlet规范中所引入的filter令人心动不已,因为它引入了一个功能强大的拦截模式。Filter是这样一种Java对象,它能在request到达servlet的服务方法之前拦截HttpServletRequest对象,而在服务方法转移控制后又能拦截HttpServletResponse对象。你可以使用filter来实现特定的任务,比如验证用户输入,以及压缩web内容。但你拟富有成效地使用过滤器的念头却被你不能改变HttpServletRequest对象的参数的现实扫了兴,因为java.util.Map所包装的HttpServletRequest对象的参数是不可改变的。这极大地缩减了filter的应用范围。至少在一半的时间里,你希望可以改变准备传送给filter的对象。如果在HttpServletRequest对象到达Struts的action  servlet之前,我们可以通过一个filter将用户输入的多余空格去掉,难道不是更美妙吗?这样的话,你就不必等到在Struts的action表单验证方法中才进行这项工作了。
幸运的是,尽管你不能改变不变对象本身,但你却可以通过使用装饰模式来改变其状态。
现在,让我们来看看,如何编写自己的HttpServletRequest装饰类。

一个删除空白字符的Filter
本节将以上的理论投入实际使用,通过实现一个删除空白字符的filter,来演示如何使用javax.servlet.http.HttpServletRequestWrapper类来装饰HttpServletRequest对象。在本例中,这个filter将删除所传来的参数中多余的空白字符。
这在许多servlet/JSP应用中是很有用的,包括Struts及JavaServer  Faces等应用。例如,Struts通过调用HttpServletRequest对象的getParameterValues()对象来处理action表单。通过覆盖装饰类中此方法,你可以改变当前HttpServletRequest对象的状态。
要创建HttpServletRequest的装饰类,你需要继承HttpServletRequestWrapper并且覆盖你希望改变的方法。列表5中,MyRequestWrapper类将删除getParameterValues()方法返回值的多余空白字符。

列表5:HttpServerletRequest装饰类
程序代码:
package trimmer.filter;

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;
}
}
列表6演示了如何载获Http请求并装饰HttpServletRequest对象。[i]列表6:删除空白符的filter


列表6演示了如何载获Http请求并装饰HttpServletRequest对象。

[i]列表6:删除空白符的filter
程序代码:
package trimmer.filter;

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;

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);
}
}
这个程序使用了列表6所示的filter来修整用户输入。要使用这个filter,你需要在web.xml文件中如下设置filter及filter-mapping的元素。
  
<filter>
       <filter-name>TrimmerFilter</filter-name>
       <filter-class>trimmer.filter.MyFilter</filter-class>
   </filter>
   <filter-mapping>
       <filter-name>TrimmerFilter</filter-name>
       <url-pattern>*.do</url-pattern>
   </filter-mapping>


要测试这个filter,启动这个应用后,在表单中输入一些值,提交表单,看看这个filter是如何修整输入数值的。这是一个实用的装饰模式的应用。

小结
Servlet  filter可以在调用一个servlet的服务方法后,拦载或加工HTTP请求。尽管这非常诱人,但其实际使用却有所限制,因为你不能改变HttpServletRequest对象。
这时候装饰模式派上了用场。本文演示了如何通过应用装饰模式来“修改”HttpServletRequest对象,从而使你的servlet  filter更加有用。在上面filter例子中,filter改了request参数中的用户输入,而这一点,如果没有装饰request对象,你是无论如何也不可能做到的。




---------------------------------------------------------
package wrapper;  
 
import 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()+"过滤");  
 
    } 
分享到:
评论
7 楼 zifangsky 2016-09-24  
关于“继承HttpServletRequestWrapper以实现在Filter中修改HttpServletRequest的参数”,我也在我的个人博客上专门写了一篇文章来介绍这个装饰模式是怎么来实现的,感兴趣的童鞋可以来看看http://www.zifangsky.cn/677.html
6 楼 DavyJones2010 2016-03-07  
有趣.在filter里用RequestWrapper替换掉Request对象. 另外这个wrapper技巧可以用在集群环境下session共享里. http://www.sjsjw.com/104/002313MYM000506/
5 楼 孙子宸 2014-11-18  
好人,有空顶你
4 楼 lz726 2014-05-08  
三克油~
3 楼 focus2008 2014-05-03  
it's cool
2 楼 卖火柴的老特工 2013-11-29  
不错
1 楼 ie4119 2013-11-29  
真是NICE!   

相关推荐

    使用HttpServletRequestWrapper在filter修改request参数

    标题“使用HttpServletRequestWrapper在filter修改request参数”揭示了主要知识点,即如何在过滤器中通过自定义`HttpServletRequestWrapper` 子类来动态改变请求参数。这通常用于处理如数据验证、安全过滤、参数转换...

    HttpServletRequestWrapper应用(二):包装文件上传请求

    然而,如果我们需要在上传过程中做一些额外的操作,如验证文件类型、大小限制等,可以创建一个继承自`HttpServletRequestWrapper`的子类,并覆盖相关的方法。 以下是一个简单的例子,展示如何创建一个`...

    Request中的参数转实体类

    主要用于使用Request中的getParamterMap()方法生成一个实体类,其中还包括getParamterMap中字段的检查方法。详见内容!

    springboot 解决InputStream只能读取一次的问题

    在Spring Boot中,我们可以使用`ServletRequestWrapper`或`HttpServletRequestWrapper`来解决这个问题。`ServletRequestWrapper`是Spring对Servlet规范中的`HttpServletRequest`接口的包装类,它允许我们对原始请求...

    防范XSS攻击程序

    输入转义 对用户输入的所有数据进行拦截,检测是否含有XSS攻击关键字,如果... 方法是实现一个自定义的 HttpServletRequestWrapper ,然后在 Filter 里面调用它,重写getParameter, getParameterValues 函数即可。

    jsp中获得路径的两种方法和获得url路径的方法(推荐).docx

    然而,`request.getRealPath("/")`方法虽然可以获取到服务器上JSP文件的实际物理路径,如`d:\web\`,但这个方法在现代的Java Web应用中已经不再推荐使用,因为它依赖于服务器的文件系统,这在分布式和容器化的环境中...

    Killtest 免费提供 310-084 最新资料下载

    - **Filter接口下的使用**:虽然`HttpServletRequestWrapper`可以由任何需要修改请求的对象使用,但在Servlet过滤器(实现`javax.servlet.Filter`接口的类)中特别有用,因为过滤器通常需要修改或检查请求和响应。...

    完美解决request请求流只能读取一次的问题

    解决request请求流只能读取一次的问题,我们可以使用自定义的HttpServletRequestWrapper,覆写getInputStream()和getReader()方法,从而实现流的重复读取。这可以在SpringBoot项目中使用Filter拦截器对所有请求流中...

    使用Filter针对Xss攻击,sql注入,服务器访问白名单,以及csrf进行安全校验

    2,此Filter为真实项目部署,在XssHttpServletRequestWrapper.java文件中的cleanSqlKeyWords方法为具体的Xss拦截逻辑,可根根据自己的需要进行完善 3,服务器白名单为单独的一个工具包,在文章最后给出 4,文章开发...

    主要使用Filter针对Xss攻击,sql注入,服务器访问白名单,以及csrf进行安全校验

    2,此Filter为真实项目部署,在XssHttpServletRequestWrapper.java文件中的cleanSqlKeyWords方法为具体的Xss拦截逻辑,可根根据自己的需要进行完善 3,服务器白名单为单独的一个工具包,在文章最后给出 4,文章开发...

    java修改请求参数

    在`doFilter()`方法中,可以读取原始请求参数,进行修改,然后使用`HttpServletRequestWrapper`包装修改后的参数,再继续请求链。 3. **处理逻辑内修改**:如果修改参数的逻辑比较单一,也可以选择在具体处理请求的...

    在使用实现过滤器进行request包装,获取内层request的分析

    这时,我们可以使用`HttpServletRequestWrapper`类来包装请求,并在需要时获取内层的原始请求。下面是一个简单的例子: ```java public class OriginalRequestWrapper extends HttpServletRequestWrapper { ...

    RemoveSpace.rar

    在上述代码中,我们创建了一个`HttpServletRequestWrapper`子类,重写了`getParameterValues()`和`getParameter()`方法,以便在获取参数值时自动去除空格。 接下来,需要在Spring配置文件(如`applicationContext....

    详解JSP 内置对象request常见用法

    本文将详细讲解JSP内置对象`request`的常见用法。 首先,`request`对象是`HttpServletRequestWrapper`类的实例,它是`ServletRequest`接口的一个实现。`HttpServletRequest`是`ServletRequest`的唯一子接口,而`...

    java filter打印请求返回参数

    1. **对`HttpServletRequest`进行封装**:通过创建`HttpServletRequestWrapper`子类来包装原始请求对象,并重写`getReader()`和`getInputStream()`方法来读取请求体数据。 2. **对`HttpServletResponse`进行封装**...

    spring security获取用户信息的实现代码

    我们讨论了如何在Spring Security中获取用户信息的实现代码,包括借鉴现有的Spring Security Controller自动注入参数的方法、解决默认HttpServletRequest的限制、实现HttpServletRequestWrapper和使用Filter替换原来...

    java 获取request中的请求参数代码详解

    在 Java 中,我们可以使用 `request.getParameterNames()` 方法来获取所有的请求参数名,然后遍历这些参数名,使用 `request.getParameter(key)` 方法来获取对应的参数值。 ```java String[] parameterNames = ...

    Web开发 乱码过滤器.zip

    `EncodingFilter`可能会实现`javax.servlet.Filter`接口,重写`doFilter()`方法,并使用`ServletRequest#setCharacterEncoding()`来设置请求的字符编码,同时可能也会设置响应的编码,以确保返回给客户端的内容也...

Global site tag (gtag.js) - Google Analytics