热门标签 | 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和内置对象。

 


推荐阅读
  • Java中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 闭包一直是Java社区中争论不断的话题,很多语言都支持闭包这个语言特性,闭包定义了一个依赖于外部环境的自由变量的函数,这个函数能够访问外部环境的变量。本文以JavaScript的一个闭包为例,介绍了闭包的定义和特性。 ... [详细]
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
  • Week04面向对象设计与继承学习总结及作业要求
    本文总结了Week04面向对象设计与继承的重要知识点,包括对象、类、封装性、静态属性、静态方法、重载、继承和多态等。同时,还介绍了私有构造函数在类外部无法被调用、static不能访问非静态属性以及该类实例可以共享类里的static属性等内容。此外,还提到了作业要求,包括讲述一个在网上商城购物或在班级博客进行学习的故事,并使用Markdown的加粗标记和语句块标记标注关键名词和动词。最后,还提到了参考资料中关于UML类图如何绘制的范例。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 本文介绍了一些Java开发项目管理工具及其配置教程,包括团队协同工具worktil,版本管理工具GitLab,自动化构建工具Jenkins,项目管理工具Maven和Maven私服Nexus,以及Mybatis的安装和代码自动生成工具。提供了相关链接供读者参考。 ... [详细]
  • 本文由编程笔记#小编为大家整理,主要介绍了StartingzookeeperFAILEDTOSTART相关的知识,希望对你有一定的参考价值。下载路径:https://ar ... [详细]
  • 如何提高PHP编程技能及推荐高级教程
    本文介绍了如何提高PHP编程技能的方法,推荐了一些高级教程。学习任何一种编程语言都需要长期的坚持和不懈的努力,本文提醒读者要有足够的耐心和时间投入。通过实践操作学习,可以更好地理解和掌握PHP语言的特异性,特别是单引号和双引号的用法。同时,本文也指出了只走马观花看整体而不深入学习的学习方式无法真正掌握这门语言,建议读者要从整体来考虑局部,培养大局观。最后,本文提醒读者完成一个像模像样的网站需要付出更多的努力和实践。 ... [详细]
  • 本文介绍了Java中Hashtable的clear()方法,该方法用于清除和移除指定Hashtable中的所有键。通过示例程序演示了clear()方法的使用。 ... [详细]
  • 重入锁(ReentrantLock)学习及实现原理
    本文介绍了重入锁(ReentrantLock)的学习及实现原理。在学习synchronized的基础上,重入锁提供了更多的灵活性和功能。文章详细介绍了重入锁的特性、使用方法和实现原理,并提供了类图和测试代码供读者参考。重入锁支持重入和公平与非公平两种实现方式,通过对比和分析,读者可以更好地理解和应用重入锁。 ... [详细]
  • 本文介绍了GregorianCalendar类的基本信息,包括它是Calendar的子类,提供了世界上大多数国家使用的标准日历系统。默认情况下,它对应格里高利日历创立时的日期,但可以通过调用setGregorianChange()方法来更改起始日期。同时,文中还提到了GregorianCalendar类为每个日历字段使用的默认值。 ... [详细]
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社区 版权所有