热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

开发笔记:StrutsActioncontext和ServletConfigInterceptor的原理分析

篇首语:本文由编程笔记#小编为大家整理,主要介绍了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和内置对象。

 


推荐阅读
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 在重复造轮子的情况下用ProxyServlet反向代理来减少工作量
    像不少公司内部不同团队都会自己研发自己工具产品,当各个产品逐渐成熟,到达了一定的发展瓶颈,同时每个产品都有着自己的入口,用户 ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • Activiti7流程定义开发笔记
    本文介绍了Activiti7流程定义的开发笔记,包括流程定义的概念、使用activiti-explorer和activiti-eclipse-designer进行建模的方式,以及生成流程图的方法。还介绍了流程定义部署的概念和步骤,包括将bpmn和png文件添加部署到activiti数据库中的方法,以及使用ZIP包进行部署的方式。同时还提到了activiti.cfg.xml文件的作用。 ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • PHP图片截取方法及应用实例
    本文介绍了使用PHP动态切割JPEG图片的方法,并提供了应用实例,包括截取视频图、提取文章内容中的图片地址、裁切图片等问题。详细介绍了相关的PHP函数和参数的使用,以及图片切割的具体步骤。同时,还提供了一些注意事项和优化建议。通过本文的学习,读者可以掌握PHP图片截取的技巧,实现自己的需求。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文讨论了在Spring 3.1中,数据源未能自动连接到@Configuration类的错误原因,并提供了解决方法。作者发现了错误的原因,并在代码中手动定义了PersistenceAnnotationBeanPostProcessor。作者删除了该定义后,问题得到解决。此外,作者还指出了默认的PersistenceAnnotationBeanPostProcessor的注册方式,并提供了自定义该bean定义的方法。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 标题: ... [详细]
  • 本文介绍了如何使用C#制作Java+Mysql+Tomcat环境安装程序,实现一键式安装。通过将JDK、Mysql、Tomcat三者制作成一个安装包,解决了客户在安装软件时的复杂配置和繁琐问题,便于管理软件版本和系统集成。具体步骤包括配置JDK环境变量和安装Mysql服务,其中使用了MySQL Server 5.5社区版和my.ini文件。安装方法为通过命令行将目录转到mysql的bin目录下,执行mysqld --install MySQL5命令。 ... [详细]
  • web.py开发web 第八章 Formalchemy 服务端验证方法
    本文介绍了在web.py开发中使用Formalchemy进行服务端表单数据验证的方法。以User表单为例,详细说明了对各字段的验证要求,包括必填、长度限制、唯一性等。同时介绍了如何自定义验证方法来实现验证唯一性和两个密码是否相等的功能。该文提供了相关代码示例。 ... [详细]
  • Imtryingtofigureoutawaytogeneratetorrentfilesfromabucket,usingtheAWSSDKforGo.我正 ... [详细]
  • 网络请求模块选择——axios框架的基本使用和封装
    本文介绍了选择网络请求模块axios的原因,以及axios框架的基本使用和封装方法。包括发送并发请求的演示,全局配置的设置,创建axios实例的方法,拦截器的使用,以及如何封装和请求响应劫持等内容。 ... [详细]
author-avatar
手机用户2502873691
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有