为什么我们要包装 HttpServletRequest ?该 api 提供了一个 HttpServletRequestWrapper,但是我们从包装请求中获得了什么?
使用 HttpServletRequestWrapper 包装 HttpServletRequest 的目的是什么?我们从这样做中得到什么好处?
使用 HttpServletRequestWrapper 包装 HttpServletRequest 的目的是什么?我们从这样做中得到什么好处?
HttpServletRequest
是HTTP特定servlet请求的接口。通常,您可以在 servlet 过滤器或 servlet 中获取此接口的实例。
有时,您希望在某个时候调整原始请求。使用HttpServletRequestWrapper
,您可以包装原始请求并覆盖一些方法,使其行为略有不同。
例:
你有一堆 servlet 和 JSP,它们需要一些特定格式的请求参数。例如,格式的日期。yyyy-MM-dd
现在,需要以不同的格式支持日期,就像具有相同的功能一样。假设到目前为止没有中心字符串函数(它是一个继承的旧版应用程序),你必须找到servlet和JSP中的所有位置。dd.MM.yyyy
作为替代方法,您可以实现 servlet 过滤器。您可以映射过滤器,以便对 servlet 和 JSP 的所有请求都将通过此过滤器。
过滤器的目的是检查日期参数的格式,并在必要时将其重新格式化为旧格式。servlet 和 JSP 始终以预期的旧格式获取日期字段。无需更改它们。
这是过滤器的骨架:
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest adjustedRequest = adjustParamDates((HttpServletRequest) request);
chain.doFilter(adjustedRequest, response);
}
我们接受原始请求,并在方法中操作请求并将其向下传递到筛选器链中。adjustParamDates()
现在,我们将如何实现?adjustParamDates()
private HttpServletRequest adjustParamDates(HttpServletRequest req) {
// ???
}
我们需要一个新的接口实例,它的行为与原始实例完全相同。但是这四种方法, , 不应该在原始参数上工作,而应该在调整后的参数集上工作。所有其他接口方法的行为都应与原始方法类似。HttpServletRequest
req
getParameter()
getParameterMap()
getParameterNames()
getParameterValues()
HttpServletRequest
所以我们可以做这样的事情。我们创建所有方法的实例并实现所有方法。通过调用原始请求实例的相应方法,大多数方法实现都非常简单:HttpServletRequest
private HttpServletRequest adjustParamDates(final HttpServletRequest req) {
final Map<String, String[]> adjustedParams = reformatDates(req.getParameterMap());
return new HttpServletRequest() {
public boolean authenticate(HttpServletResponse response) {
return req.authenticate(response);
}
public String changeSessionId() {
return req.changeSessionId();
}
public String getContextPath() {
return req.getContextPath();
}
// Implement >50 other wrapper methods
// ...
// Now the methods with different behaviour:
public String getParameter(String name) {
return adjustedParams.get(name) == null ? null : adjustedParams.get(name)[0];
}
public Map<String, String[]> getParameterMap() {
return adjustedParams;
}
public Enumeration<String> getParameterNames() {
return Collections.enumeration(adjustedParams.keySet());
}
public String[] getParameterValues(String name) {
return adjustedParams.get(name);
}
});
}
有 50 多种方法需要实现。它们中的大多数只是原始请求的包装器实现。我们只需要四个自定义实现。但是我们必须写下所有这些方法。
因此,这里考虑了类。这是一个默认的包装器实现,它采用原始请求实例,并将接口的所有方法实现为简单的包装器方法,调用原始请求的相应方法,就像我们上面所做的那样。HttpServletRequestWrapper
HttpServletRequest
通过子类化,我们只需要用自定义行为覆盖四个参数方法。HttpServletRequestWrapper
private HttpServletRequest adjustParamDates(final HttpServletRequest req) {
final Map<String, String[]> adjustedParams = reformatDates(req.getParameterMap());
return new HttpServletRequestWrapper(req) {
public String getParameter(String name) {
return adjustedParams.get(name) == null ? null : adjustedParams.get(name)[0];
}
public Map<String, String[]> getParameterMap() {
return adjustedParams;
}
public Enumeration<String> getParameterNames() {
return Collections.enumeration(adjustedParams.keySet());
}
public String[] getParameterValues(String name) {
return adjustedParams.get(name);
}
});
}