查看一下StrutsRequestWrapper的源代码,本人将其中的英文注释转为中文
package org.apache.struts2.dispatcher;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.util.ValueStack;
/**
*
* 所有的request请求用这个类,他提供了简单的JSTL的可达性,这是因为JSTL与请求属性与请求属性在一起工作
* 所以这个类代表值栈,除了在少数情况下需要防止无限循环的发生,即,不要让任何属性的名字中带有#,#代表了值栈,他可能导致无限循环
* 例如在这种情况下可能发生无限循环
* request.getAttribute("#attr.foo").
*/
public class StrutsRequestWrapper extends HttpServletRequestWrapper {
/**
* The constructor
* @param req The request
*/
public StrutsRequestWrapper(HttpServletRequest req) {
super(req);
}
/**
* 获取对象,如果不存在,那么在值栈中找
* @param s The attribute key
*/
public Object getAttribute(String s) {
if (s != null && s.startsWith("javax.servlet")) {
// don't bother with the standard javax.servlet attributes, we can short-circuit this
// see WW-953 and the forums post linked in that issue for more info
return super.getAttribute(s);
}
ActionContext ctx = ActionContext.getContext();
Object attribute = super.getAttribute(s);
if (ctx != null) {
if (attribute == null) {
boolean alreadyIn = false;
Boolean b = (Boolean) ctx.get("__requestWrapper.getAttribute");
if (b != null) {
alreadyIn = b.booleanValue();
}
// note: we don't let # come through or else a request for
// #attr.foo or #request.foo could cause an endless loop
if (!alreadyIn && s.indexOf("#") == -1) {
try {
// If not found, then try the ValueStack
ctx.put("__requestWrapper.getAttribute", Boolean.TRUE);
ValueStack stack = ctx.getValueStack();
if (stack != null) {
attribute = stack.findValue(s);
}
} finally {
ctx.put("__requestWrapper.getAttribute", Boolean.FALSE);
}
}
}
}
return attribute;
}
}
Wrapper是包装的意思,所以HttpServletRequestWrapper的字面意思就是对HttpServletRequest的包装。首先查看一下HttpServletRequestWrapper的源代码:
package javax.servlet.http;
import javax.servlet.ServletRequestWrapper;
import java.util.Enumeration;
/**
*
* Provides a convenient implementation of the HttpServletRequest interface that
* can be subclassed by developers wishing to adapt the request to a Servlet.
* This class implements the Wrapper or Decorator pattern. Methods default to
* calling through to the wrapped request object.
*
*
* @see javax.servlet.http.HttpServletRequest
* @since v 2.3
*
*/
public class HttpServletRequestWrapper extends ServletRequestWrapper implements HttpServletRequest {
/**
* Constructs a request object wrapping the given request.
* @throws java.lang.IllegalArgumentException if the request is null
*/
public HttpServletRequestWrapper(HttpServletRequest request) {
super(request);
}
private HttpServletRequest _getHttpServletRequest() {
return (HttpServletRequest) super.getRequest();
}
/**
* The default behavior of this method is to return getAuthType()
* on the wrapped request object.
*/
public String getAuthType() {
return this._getHttpServletRequest().getAuthType();
}
/**
* The default behavior of this method is to return getCookies()
* on the wrapped request object.
*/
public Cookie[] getCookies() {
return this._getHttpServletRequest().getCookies();
}
/**
* The default behavior of this method is to return getDateHeader(String name)
* on the wrapped request object.
*/
public long getDateHeader(String name) {
return this._getHttpServletRequest().getDateHeader(name);
}
/**
* The default behavior of this method is to return getHeader(String name)
* on the wrapped request object.
*/
public String getHeader(String name) {
return this._getHttpServletRequest().getHeader(name);
}
/**
* The default behavior of this method is to return getHeaders(String name)
* on the wrapped request object.
*/
public Enumeration getHeaders(String name) {
return this._getHttpServletRequest().getHeaders(name);
}
/**
* The default behavior of this method is to return getHeaderNames()
* on the wrapped request object.
*/
public Enumeration getHeaderNames() {
return this._getHttpServletRequest().getHeaderNames();
}
/**
* The default behavior of this method is to return getIntHeader(String name)
* on the wrapped request object.
*/
public int getIntHeader(String name) {
return this._getHttpServletRequest().getIntHeader(name);
}
/**
* The default behavior of this method is to return getMethod()
* on the wrapped request object.
*/
public String getMethod() {
return this._getHttpServletRequest().getMethod();
}
/**
* The default behavior of this method is to return getPathInfo()
* on the wrapped request object.
*/
public String getPathInfo() {
return this._getHttpServletRequest().getPathInfo();
}
/**
* The default behavior of this method is to return getPathTranslated()
* on the wrapped request object.
*/
public String getPathTranslated() {
return this._getHttpServletRequest().getPathTranslated();
}
/**
* The default behavior of this method is to return getContextPath()
* on the wrapped request object.
*/
public String getContextPath() {
return this._getHttpServletRequest().getContextPath();
}
/**
* The default behavior of this method is to return getQueryString()
* on the wrapped request object.
*/
public String getQueryString() {
return this._getHttpServletRequest().getQueryString();
}
/**
* The default behavior of this method is to return getRemoteUser()
* on the wrapped request object.
*/
public String getRemoteUser() {
return this._getHttpServletRequest().getRemoteUser();
}
/**
* The default behavior of this method is to return isUserInRole(String role)
* on the wrapped request object.
*/
public boolean isUserInRole(String role) {
return this._getHttpServletRequest().isUserInRole(role);
}
/**
* The default behavior of this method is to return getUserPrincipal()
* on the wrapped request object.
*/
public java.security.Principal getUserPrincipal() {
return this._getHttpServletRequest().getUserPrincipal();
}
/**
* The default behavior of this method is to return getRequestedSessionId()
* on the wrapped request object.
*/
public String getRequestedSessionId() {
return this._getHttpServletRequest().getRequestedSessionId();
}
/**
* The default behavior of this method is to return getRequestURI()
* on the wrapped request object.
*/
public String getRequestURI() {
return this._getHttpServletRequest().getRequestURI();
}
/**
* The default behavior of this method is to return getRequestURL()
* on the wrapped request object.
*/
public StringBuffer getRequestURL() {
return this._getHttpServletRequest().getRequestURL();
}
/**
* The default behavior of this method is to return getServletPath()
* on the wrapped request object.
*/
public String getServletPath() {
return this._getHttpServletRequest().getServletPath();
}
/**
* The default behavior of this method is to return getSession(boolean create)
* on the wrapped request object.
*/
public HttpSession getSession(boolean create) {
return this._getHttpServletRequest().getSession(create);
}
/**
* The default behavior of this method is to return getSession()
* on the wrapped request object.
*/
public HttpSession getSession() {
return this._getHttpServletRequest().getSession();
}
/**
* The default behavior of this method is to return isRequestedSessionIdValid()
* on the wrapped request object.
*/
public boolean isRequestedSessionIdValid() {
return this._getHttpServletRequest().isRequestedSessionIdValid();
}
/**
* The default behavior of this method is to return isRequestedSessionIdFromCookie()
* on the wrapped request object.
*/
public boolean isRequestedSessionIdFromCookie() {
return this._getHttpServletRequest().isRequestedSessionIdFromCookie();
}
/**
* The default behavior of this method is to return isRequestedSessionIdFromURL()
* on the wrapped request object.
*/
public boolean isRequestedSessionIdFromURL() {
return this._getHttpServletRequest().isRequestedSessionIdFromURL();
}
/**
* The default behavior of this method is to return isRequestedSessionIdFromUrl()
* on the wrapped request object.
*/
public boolean isRequestedSessionIdFromUrl() {
return this._getHttpServletRequest().isRequestedSessionIdFromUrl();
}
}
通过上面源码的了解,可以看到StrutsRequestWrapper是在struts2框架中对HttpServletRequestWrapper类的包装,以使其得到扩展,在Struts2中,扩展后的HttpServletRequest类有了一个方法
public Object getAttribute(String s)
这个方法的作用是在servlet的Request的作用域中获得属性名为s的属性值,如果Request作用域中不存在,那么将到Struts2的值栈中查找。
它们应用了设计模式中的装饰者模式。
它们之间的关系如上图所示