热门标签 | 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 Web开发中的JSP:三大指令、九大隐式对象与动作标签详解
    在Java Web开发中,JSP(Java Server Pages)是一种重要的技术,用于构建动态网页。本文详细介绍了JSP的三大指令、九大隐式对象以及动作标签。三大指令包括页面指令、包含指令和标签库指令,它们分别用于设置页面属性、引入其他文件和定义自定义标签。九大隐式对象则涵盖了请求、响应、会话、应用上下文等关键组件,为开发者提供了便捷的操作接口。动作标签则通过预定义的动作来简化页面逻辑,提高开发效率。这些内容对于理解和掌握JSP技术具有重要意义。 ... [详细]
  • 在探讨C语言编程文本编辑器的最佳选择与专业推荐时,本文将引导读者构建一个基础的文本编辑器程序。该程序不仅能够打开并显示文本文件的内容及其路径,还集成了菜单和工具栏功能,为用户提供更加便捷的操作体验。通过本案例的学习,读者可以深入了解文本编辑器的核心实现机制。 ... [详细]
  • 【并发编程】全面解析 Java 内存模型,一篇文章带你彻底掌握
    本文深入解析了 Java 内存模型(JMM),从基础概念到高级特性进行全面讲解,帮助读者彻底掌握 JMM 的核心原理和应用技巧。通过详细分析内存可见性、原子性和有序性等问题,结合实际代码示例,使开发者能够更好地理解和优化多线程并发程序。 ... [详细]
  • 通过在项目中引用 NuGet 包 `ExcelDataReader`,可以实现高效地读取和导入 Excel 文件中的数据。具体方法是在项目中执行 `Install-Package ExcelDataReader` 命令,然后通过定义一个 `LeadingIn` 方法并传入上传文件的路径来完成数据导入。该方法不仅简化了代码逻辑,还显著提升了数据处理的效率和可靠性。 ... [详细]
  • 在 Vbox 和 Hbox 布局中,当用户点击容器添加一个矩形时,系统会自动为该矩形分配坐标并打印其位置信息。此外,在按键事件触发时,系统仅打印当前矩形的坐标值。这两种布局在特定的交互场景下,能够动态地管理和更新子组件的位置。 ... [详细]
  • 本文详细探讨了OpenCV中人脸检测算法的实现原理与代码结构。通过分析核心函数和关键步骤,揭示了OpenCV如何高效地进行人脸检测。文章不仅提供了代码示例,还深入解释了算法背后的数学模型和优化技巧,为开发者提供了全面的理解和实用的参考。 ... [详细]
  • Java集合框架特性详解与开发实践笔记
    Java集合框架特性详解与开发实践笔记 ... [详细]
  • 本文详细解析了JSONP(JSON with Padding)的跨域机制及其工作原理。JSONP是一种通过动态创建``标签来实现跨域请求的技术,其核心在于利用了浏览器对``标签的宽松同源策略。文章不仅介绍了JSONP的产生背景,还深入探讨了其具体实现过程,包括如何构造请求、服务器端如何响应以及客户端如何处理返回的数据。此外,还分析了JSONP的优势和局限性,帮助读者全面理解这一技术在现代Web开发中的应用。 ... [详细]
  • 本文介绍了Android动画的基本概念及其主要类型。Android动画主要包括三种形式:视图动画(也称为补间动画或Tween动画),主要通过改变视图的属性来实现动态效果;帧动画,通过顺序播放一系列预定义的图像来模拟动画效果;以及属性动画,通过对对象的属性进行平滑过渡来创建更加复杂的动画效果。每种类型的动画都有其独特的应用场景和实现方式,开发者可以根据具体需求选择合适的动画类型。 ... [详细]
  • 解决基于XML配置的MyBatis在Spring整合中出现“无效绑定语句(未找到):com.music.dao.MusicDao.findAll”问题的方法
    在将Spring与MyBatis进行整合时,作者遇到了“无效绑定语句(未找到):com.music.dao.MusicDao.findAll”的问题。该问题主要出现在使用XML文件配置DAO层的情况下,而注解方式配置则未出现类似问题。作者详细分析了两个配置文件之间的差异,并最终找到了解决方案。本文将详细介绍问题的原因及解决方法,帮助读者避免类似问题的发生。 ... [详细]
  • Android 图像色彩处理技术详解
    本文详细探讨了 Android 平台上的图像色彩处理技术,重点介绍了如何通过模仿美图秀秀的交互方式,利用 SeekBar 实现对图片颜色的精细调整。文章展示了具体的布局设计和代码实现,帮助开发者更好地理解和应用图像处理技术。 ... [详细]
  • Spring框架入门指南:专为新手打造的详细学习笔记
    Spring框架是Java Web开发中广泛应用的轻量级应用框架,以其卓越的功能和出色的性能赢得了广大开发者的青睐。本文为初学者提供了详尽的学习指南,涵盖基础概念、核心组件及实际应用案例,帮助新手快速掌握Spring框架的核心技术与实践技巧。 ... [详细]
  • C#编程指南:实现列表与WPF数据网格的高效绑定方法 ... [详细]
  • 深入解析Gradle中的Project核心组件
    在Gradle构建系统中,`Project` 是一个核心组件,扮演着至关重要的角色。通过使用 `./gradlew projects` 命令,可以清晰地列出当前项目结构中包含的所有子项目,这有助于开发者更好地理解和管理复杂的多模块项目。此外,`Project` 对象还提供了丰富的配置选项和生命周期管理功能,使得构建过程更加灵活高效。 ... [详细]
  • 如何使用 net.sf.extjwnl.data.Word 类及其代码示例详解 ... [详细]
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社区 版权所有