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()+"过滤");
}
分享到:
相关推荐
标题“使用HttpServletRequestWrapper在filter修改request参数”揭示了主要知识点,即如何在过滤器中通过自定义`HttpServletRequestWrapper` 子类来动态改变请求参数。这通常用于处理如数据验证、安全过滤、参数转换...
然而,如果我们需要在上传过程中做一些额外的操作,如验证文件类型、大小限制等,可以创建一个继承自`HttpServletRequestWrapper`的子类,并覆盖相关的方法。 以下是一个简单的例子,展示如何创建一个`...
主要用于使用Request中的getParamterMap()方法生成一个实体类,其中还包括getParamterMap中字段的检查方法。详见内容!
在Spring Boot中,我们可以使用`ServletRequestWrapper`或`HttpServletRequestWrapper`来解决这个问题。`ServletRequestWrapper`是Spring对Servlet规范中的`HttpServletRequest`接口的包装类,它允许我们对原始请求...
3. **修改`getReader`方法的行为限制**:`HttpServletRequestWrapper`的子类不能修改`getReader`方法的行为。这是不正确的,子类可以通过覆盖`getReader`方法来自定义其行为。 4. **使用范围的限制**:`...
输入转义 对用户输入的所有数据进行拦截,检测是否含有XSS攻击关键字,如果... 方法是实现一个自定义的 HttpServletRequestWrapper ,然后在 Filter 里面调用它,重写getParameter, getParameterValues 函数即可。
然而,`request.getRealPath("/")`方法虽然可以获取到服务器上JSP文件的实际物理路径,如`d:\web\`,但这个方法在现代的Java Web应用中已经不再推荐使用,因为它依赖于服务器的文件系统,这在分布式和容器化的环境中...
- **Filter接口下的使用**:虽然`HttpServletRequestWrapper`可以由任何需要修改请求的对象使用,但在Servlet过滤器(实现`javax.servlet.Filter`接口的类)中特别有用,因为过滤器通常需要修改或检查请求和响应。...
解决request请求流只能读取一次的问题,我们可以使用自定义的HttpServletRequestWrapper,覆写getInputStream()和getReader()方法,从而实现流的重复读取。这可以在SpringBoot项目中使用Filter拦截器对所有请求流中...
2,此Filter为真实项目部署,在XssHttpServletRequestWrapper.java文件中的cleanSqlKeyWords方法为具体的Xss拦截逻辑,可根根据自己的需要进行完善 3,服务器白名单为单独的一个工具包,在文章最后给出 4,文章开发...
2,此Filter为真实项目部署,在XssHttpServletRequestWrapper.java文件中的cleanSqlKeyWords方法为具体的Xss拦截逻辑,可根根据自己的需要进行完善 3,服务器白名单为单独的一个工具包,在文章最后给出 4,文章开发...
在`doFilter()`方法中,可以读取原始请求参数,进行修改,然后使用`HttpServletRequestWrapper`包装修改后的参数,再继续请求链。 3. **处理逻辑内修改**:如果修改参数的逻辑比较单一,也可以选择在具体处理请求的...
这时,我们可以使用`HttpServletRequestWrapper`类来包装请求,并在需要时获取内层的原始请求。下面是一个简单的例子: ```java public class OriginalRequestWrapper extends HttpServletRequestWrapper { ...
在上述代码中,我们创建了一个`HttpServletRequestWrapper`子类,重写了`getParameterValues()`和`getParameter()`方法,以便在获取参数值时自动去除空格。 接下来,需要在Spring配置文件(如`applicationContext....
本文将详细讲解JSP内置对象`request`的常见用法。 首先,`request`对象是`HttpServletRequestWrapper`类的实例,它是`ServletRequest`接口的一个实现。`HttpServletRequest`是`ServletRequest`的唯一子接口,而`...
1. **对`HttpServletRequest`进行封装**:通过创建`HttpServletRequestWrapper`子类来包装原始请求对象,并重写`getReader()`和`getInputStream()`方法来读取请求体数据。 2. **对`HttpServletResponse`进行封装**...
我们讨论了如何在Spring Security中获取用户信息的实现代码,包括借鉴现有的Spring Security Controller自动注入参数的方法、解决默认HttpServletRequest的限制、实现HttpServletRequestWrapper和使用Filter替换原来...
在 Java 中,我们可以使用 `request.getParameterNames()` 方法来获取所有的请求参数名,然后遍历这些参数名,使用 `request.getParameter(key)` 方法来获取对应的参数值。 ```java String[] parameterNames = ...
`EncodingFilter`可能会实现`javax.servlet.Filter`接口,重写`doFilter()`方法,并使用`ServletRequest#setCharacterEncoding()`来设置请求的字符编码,同时可能也会设置响应的编码,以确保返回给客户端的内容也...