作者:手机用户2502873691 | 来源:互联网 | 2023-09-25 19:40
篇首语:本文由编程笔记#小编为大家整理,主要介绍了StrutsActioncontext和ServletConfigInterceptor的原理分析相关的知识,希望对你有一定的参考价值。
篇首语:本文由编程笔记#小编为大家整理,主要介绍了Struts Actioncontext 和ServletConfigInterceptor的原理分析相关的知识,希望对你有一定的参考价值。
最近你在做网上商城的项目时对Struts的Actioncontext的原理产生的疑问,于是通过查找资料最后有了一定理解,在此写下随笔为自己的思路做整理。
web.xml代码:
1
2 struts2
3 class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilterclass>
4
5
6 struts2
7 /*
8
在web.xml配置文件中我们都有配置StrutsPrepareAndExecuteFilter这就意味着StrutsPrepareAndExecuteFilter拦截器在tomcat启动之时就比加载,并且拦截所有的action请求。
StrutsPrepareAndExecuteFilter中的doFilter如下:
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)res;
try {
if(this.excludedPatterns != null && this.prepare.isUrlExcluded(request, this.excludedPatterns)) {
chain.doFilter(request, response);
} else {
this.prepare.setEncodingAndLocale(request, response);
this.prepare.createActionContext(request, response);
this.prepare.assignDispatcherToThread();
request = this.prepare.wrapRequest(request);
ActionMapping mapping = this.prepare.findActionMapping(request, response, true);
if(mapping == null) {
boolean handled = this.execute.executeStaticResourceRequest(request, response);
if(!handled) {
chain.doFilter(request, response);
}
} else {
this.execute.executeAction(request, response, mapping);
}
}
} finally {
this.prepare.cleanupRequest(request);
}
}
在StrutsPrepareAndExecuteFilter的dofilter方法中我们可以看到一个一行 this.prepare.createActionContext(request, response); 这样的代码其中传入了 HttpServletRequest和HttpServletResponse。我们继续往createActionContext 方法看。
PrepareOperations类中createActionContext方法代码:
public ActionContext createActionContext(HttpServletRequest request, HttpServletResponse response) {
Integer counter = Integer.valueOf(1);
Integer oldCounter = (Integer)request.getAttribute("__cleanup_recursion_counter");
if(oldCounter != null) {
counter = Integer.valueOf(oldCounter.intValue() + 1);
}
ActionContext oldContext = ActionContext.getContext();
ActionContext ctx;
if(oldContext != null) {
ctx = new ActionContext(new HashMap(oldContext.getContextMap()));
} else {
// 创建值栈
ValueStack stack = ((ValueStackFactory)this.dispatcher.getContainer().getInstance(ValueStackFactory.class)).createValueStack();
// 把后面所获取到的map赋值到值栈的Map中
stack.getContext().putAll(this.dispatcher.createContextMap(request, response, (ActionMapping)null));
// 把值栈的map存储到ActionContext中一份
ctx = new ActionContext(stack.getContext());
}
request.setAttribute("__cleanup_recursion_counter", counter);
ActionContext.setContext(ctx);
return ctx;
}
在上面的方法中首先判断是否有ActionContext 如果没有的话就创建一个,如果有的话就创建一个值栈并且把后面所获取到的map赋值到值栈的Map中。最后又把值栈的map存储到ActionContext中一份
进一步分析creatContextMap方法:
public Map createContextMap(HttpServletRequest request, HttpServletResponse response, ActionMapping mapping) {
// 封装内置request对象
RequestMap requestMap = new RequestMap(request);
// 封装内置的request对象的参数
HashMap params = new HashMap(request.getParameterMap());
SessionMap session = new SessionMap(request);
ApplicationMap application = new ApplicationMap(this.servletContext);
HashMap extraContext = this.createContextMap(requestMap, params, session, application, request, response);
if(mapping != null) {
extraContext.put("struts.actionMapping", mapping);
}
return extraContext;
}
在这个方法中封装了传入的各个内置对象并把各个内置对象和map传给了createContextMap方法
public HashMap createContextMap(Map requestMap, Map parameterMap, Map sessionMap, Map applicationMap, HttpServletRequest request, HttpServletResponse response) {
// 存储了所有的map和内置对象,最后次map被返回
HashMap extraContext = new HashMap();
extraContext.put("com.opensymphony.xwork2.ActionContext.parameters", new HashMap(parameterMap));
extraContext.put("com.opensymphony.xwork2.ActionContext.session", sessionMap);
extraContext.put("com.opensymphony.xwork2.ActionContext.application", applicationMap);
Locale locale;
if(this.defaultLocale != null) {
locale = LocalizedTextUtil.localeFromString(this.defaultLocale, request.getLocale());
} else {
locale = request.getLocale();
}
extraContext.put("com.opensymphony.xwork2.ActionContext.locale", locale);
extraContext.put("com.opensymphony.xwork2.dispatcher.HttpServletRequest", request);
extraContext.put("com.opensymphony.xwork2.dispatcher.HttpServletResponse", response);
extraContext.put("com.opensymphony.xwork2.dispatcher.ServletContext", this.servletContext);
extraContext.put("request", requestMap);
extraContext.put("session", sessionMap);
extraContext.put("application", applicationMap);
extraContext.put("parameters", parameterMap);
AttributeMap attrMap = new AttributeMap(extraContext);
extraContext.put("attr", attrMap);
// 返回给ActionConetext和值栈。
return extraContext;
}
综上:
在项目启动时的时候Struts的过滤器把相应的内置对象和内置对象的相应的map存入ActionContest和值栈中。
如果实现了***Aware接口,就会从ActionContest中获取map并传入,该功能主要有servletConfig拦截器实现:
public String intercept(ActionInvocation invocation) throws Exception {
Object action = invocation.getAction();
ActionContext context = invocation.getInvocationContext();
HttpServletRequest servletContext;
if(action instanceof ServletRequestAware) {
servletContext = (HttpServletRequest)context.get("com.opensymphony.xwork2.dispatcher.HttpServletRequest");
((ServletRequestAware)action).setServletRequest(servletContext);
}
if(action instanceof ServletResponseAware) {
HttpServletResponse servletContext1 = (HttpServletResponse)context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse");
((ServletResponseAware)action).setServletResponse(servletContext1);
}
if(action instanceof ParameterAware) {
((ParameterAware)action).setParameters(context.getParameters());
}
if(action instanceof ApplicationAware) {
((ApplicationAware)action).setApplication(context.getApplication());
}
if(action instanceof SessionAware) {
((SessionAware)action).setSession(context.getSession());
}
if(action instanceof RequestAware) {
((RequestAware)action).setRequest((Map)context.get("request"));
}
if(action instanceof PrincipalAware) {
servletContext = (HttpServletRequest)context.get("com.opensymphony.xwork2.dispatcher.HttpServletRequest");
if(servletContext != null) {
((PrincipalAware)action).setPrincipalProxy(new ServletPrincipalProxy(servletContext));
}
}
if(action instanceof ServletContextAware) {
ServletContext servletContext2 = (ServletContext)context.get("com.opensymphony.xwork2.dispatcher.ServletContext");
((ServletContextAware)action).setServletContext(servletContext2);
}
return invocation.invoke();
}
通过判断是否实现相应的接口来获取相应的map和内置对象。