2019独角兽企业重金招聘Python工程师标准>>>

Struts2的结构

Action是Strus2的核心逻辑之一。但这并不意味着Action是复杂的,实际上Action很简单,一个普通的java类就可以作为一个Action。我们之所以可以很方便的使用Action,是因为Struts2的框架对Action做了最大的支持。就像是一个老大,手底下有一大群牛逼的小弟,所以可以整天无所事事。Action的逻辑简单,但是围绕着Action的各个组件的逻辑就复杂的不行了。上图展示了struts2中一个从请求的获取到响应的流程。

一个请求被获取后,会经过层层的Filter到达ActionMapper。ActionMapper可以判断该是否需要为该请求调用一个Action。如果是的话,这个请求会被送给ActionProxy。ActionProxy会通过配置文件和请求生成一个ActionInvocation。ActionInvocation的主要任务是根据运行对应的Action方法,并获取Result。在ActionInvocation中会先运行Interceptor,如果没有从Interceptor中获取Result,则会运行Action的方法。获取result后,会检查配置文件中Action对应的结果,并根据结果访问页面或者请求另外一个Action(Action链)。


Action的实现

Action可以通过三种方式实现:

1.一个类可以是普通的java类,但是必须有一个execute()

2.实现了Action接口,Action接口提供了execute()方法

3.继承了ActionSupport类型,ActionSupport实现了Action和其他的一些接口,提供了许多常用方法。


Action的流程

proxy应当是Action流程的开端,所以这里从Proxy开始进行分析一直到获取Result为止。

DefaultActionProxy的execute中首先会设置ActionContext,将当前请求的Context给予ActionContext。每个ActionContext都是基于ThreadLocal且静态的。也就说每个请求都会生成一个ActionContext,这个ActionContext在此次请求是可以全局调用的

接下来DefaultActionInvocation的invoke方法被调用了。在invoke方法中首先会查看拦截器,这些拦截器被存储在名为interceptors的列表中。遍历这个链表,并运行拦截器的interceptor方法,将invocation本身作为参数传递给interceptor方法。interceptor方法的最后会重新调用invocation的invoke方法,所以该方法是递归方法。拦截器会不断递归interceptor方法,直到所有的拦截器都被调用过或者在一个拦截器中获得了一个resultCode。

invoke方法代码:

public String invoke() throws Exception {String profileKey = "invoke: ";try {...if (interceptors.hasNext()) {final InterceptorMapping interceptor = interceptors.next();String interceptorMsg = "interceptor: " + interceptor.getName();UtilTimerStack.push(interceptorMsg);try {resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);}finally {UtilTimerStack.pop(interceptorMsg);}} else {resultCode = invokeActionOnly();}...if (!executed) {if (preResultListeners != null) {for (Object preResultListener : preResultListeners) {PreResultListener listener = (PreResultListener) preResultListener;...try {UtilTimerStack.push(_profileKey);listener.beforeResult(this, resultCode);}finally {UtilTimerStack.pop(_profileKey);}}}if (proxy.getExecuteResult()) {executeResult();}executed = true;}return resultCode;}finally {UtilTimerStack.pop(profileKey);}}

如果运行完所有拦截器都没有获取ResultCode,那么就会运行请求指定的Action的方法了。该方法是通过反射机制获取的。

通过反射机制获取方法代码:

protected String invokeAction(Object action, ActionConfig actionConfig) throws Exception {String methodName = proxy.getMethod();...try {UtilTimerStack.push(timerKey);boolean methodCalled = false;Object methodResult = null;Method method = null;try {method = getAction().getClass().getMethod(methodName, EMPTY_CLASS_ARRAY);} catch (NoSuchMethodException e) {...}if (!methodCalled) {methodResult = method.invoke(action, EMPTY_OBJECT_ARRAY);}return saveResult(actionConfig, methodResult);} catch (NoSuchMethodException e) {...} catch (InvocationTargetException e) {...} finally {UtilTimerStack.pop(timerKey);}}

获取到一个ResultCode后会检查PreResultListener,PreResultListener通常也是拦截器,但是不会运行interceptor方法,而是beforeResult方法。

最后会调用DefaultActionInvocation的executeResult方法。这个方法的作用是根据我们获取的resultcode,在配置中获取一个Result对象,并同过Result对象的execute方法将响应结果发送出去。


Action与ServletAPI

Action的请求参数一般可以通过“注入”的方式获取,这种方式避免了Action与ServletAPI的耦合,但是也有很多情况是需要直接访问ServletAPI获取的。Struts2也提供了许多访问ServletAPI的方法。

ActionContext

ActionContext类提供了HttpServletRequest,HttpSession,ServletContext的获取方法,它们分别对应JSP内置对象的request,session,application。但是ActionContext只能获取request内容,也就是只能从页面获取参数。

ActionContext的获取方式为 :

ActionContext actionContext = ActionContext.getContext();

ActionContext是action执行时的上下文,它存放着Action需要用到的各种对象.如:请求参数(Parameter),会话(Session),Servlet上下文(ServletContext),本地化(Locale)

每次执行Action的时候都会创建新的ActionContext,ActionContext是线程安全的,在同一个线程里ActionContext是唯一的。

ActionContext对Servlet的一些内容进行了封装,从而使Action与Serlvet解耦合。

ServletActionContext

ServletActionContext继承于ActionContext,提供了一些直接访问Serlvet的方法。SerlvetActionContext可以操作Cookie.ServletActionContext可以获取的对象有:

HttpServletRequest——请求对象

HttpServletResponse——响应对象

ServletContext——上下文信息

ApplicationContext——Http页面上下文

ActionContext与ServletActionContext都是基于WEB应用的,所以普通的java应用是无法获取ActionContext或ServletActionContext的。在运行的时候,它们的值将为NULL。ActionContext和ServletActionContext都可以获取WEB数据,但是ActionContext更偏向于值得操作而ServletActionContext更偏向Serlvet的操作。

Others

SessionAware,RequestAware,ApplicationAware,ParameterAware也可以访问页面获取的数据。要使用这些工具,Action就必须实现SessionAware,RequestAware,ApplicationAware,ParameterAware接口。并实现

Public void setSession(Map<String,Object> map);

Public void setRequest(Map<String,Object> map );

Public void setApplication(Map<String,Object> map);

Public void setParameter(Map<String,Object> map);

ServletRequestAware,ServletResponseAware可以用来获取HttpServletRequest和HttpServletResponse对象。要获取这些对象,就必须实现ServletRequestAware,ServletResponseAware接口。并实现:

Public  void setServletRequest(HttpServletRequest request);

Public void  setServletResponse(HttpServletResponse response);


参考了许多资料,也看了点代码,不过老实说还是一知半解,望高手出来指点迷津:)

转载于:https://my.oschina.net/u/241670/blog/325032

Struts2的Action相关推荐

  1. Struts2中Action接收参数

    Struts2中Action接收参数的方法主要有以下三种: Struts2中Action接收参数的方法主要有以下三种: 1.使用Action的属性接收参数:     a.定义:在Action类中定义属 ...

  2. Struts2中action接收参数的三种方法及ModelDriven跟Preparable接口结合JAVA反射机制的灵活用法...

    Struts2中action接收参数的三种方法及ModelDriven跟Preparable接口结合JAVA反射机制的灵活用法 www.MyException.Cn   发布于:2012-09-15 ...

  3. struts2学习 - action -3 动态方法调用 DMI

    Action执行的时候并不一定要执行execute方法 可以在配置文件中配置Action的时候用method=来指定执行哪个方法 也可以在url地址中动态指定(动态方法调用DMI)(推荐)   配置文 ...

  4. struts2对action的搜索规则

    跟java代码编程相似,struts2对Action类的配置也采用包(package)结构进行管理,如此固然清晰了配置文件的层次结构,提高了配置文件的可读性,然而由于各action分布于不同的包(pa ...

  5. 单元测试Struts2的Action(包含源码)

    很久没有从头搭建Struts2的环境了.最近,认真实践了单元测试Struts2.Spring等Java项目. 今天特意写的是单元测试Struts2的Action,遇到了不少问题,果然是实践出真知啊. ...

  6. struts2从action向jsp传参数

    struts2从action向jsp传参数: 1.在action类里面的成员变量域那里写上你要返回给jsp的变量和相应的get  set方法(比如list).. 在execute方法里为list填充了 ...

  7. Struts2中Action访问Servlet API的三种方法

    Struts2的Action并未直接与任何Servlet API耦合,这是Struts2的一个改良之处,因为Action类不再与Servlet API耦合,能更轻松的测试该Action.但如何访问? ...

  8. Struts2 - 在Action类中获得HttpServletResponse对象

    Struts2 - 在Action类中获得HttpServletResponse对象 在struts1.x Action类的execute方法中,有四个参数,其中两个就是 response和reque ...

  9. SpringAop对struts2的Action设置切面织入时报错java.lang.NoSuchMethodException

    学习springAop,尝试对struts2的Action层使用Aop切面实现日志的打印. 执行出现报错:java.lang.NoSuchMethodException. 查阅资料解决办法:sprin ...

  10. struts2的action从request获取参数值的几种方式

    使用jquery框架的ajax能够方便的向后台传递参数,以$.post为例,参数有2种方式字符串和键值对:$.post(url, "name=aty&age=25")和$. ...

最新文章

  1. Selenium 爬虫时遇到的问题 Selenium message:session not created
  2. 在vuejs 中使用axios不能获取属性data的解决方法
  3. 华为v9计算机在哪方面的应用,华为荣耀V9和华为Mate9区别在哪 哪款更好?
  4. ReactiveStream01
  5. SDL2 自建对话框
  6. numpy 读取txt为array 一行搞定
  7. java矩阵连乘算法_使用java写的矩阵乘法实例(Strassen算法)
  8. 利用Vulnhub复现漏洞 - JBoss JMXInvokerServlet 反序列化漏洞
  9. java的内存管理_操作系统实验——java内存管理
  10. Intellij IDEA 安装jnetpcap开发环境与 no jnetpcap in java.library.path 的解决方案
  11. python new 干什么用_详解Python中的__new__()方法的使用
  12. Pyspider 框架的用法
  13. 【c++】cout.setf(left)、cout.setf(right)详解
  14. cd短是什么意思,王者荣耀:是不是技能cd越短难度就越大?看她就明白了
  15. 录屏时如何录制麦克风声音?-QVE屏幕录制
  16. LeetCode 325. Maximum Size Subarray Sum Equals k
  17. python实现图片暗藏表白效果
  18. 栈和堆的区别是什么? 为什么说栈的速度快,堆的速度慢?
  19. 手机游戏:崇尚简单至上和零碎娱乐的永恒价值
  20. 2022年R2移动式压力容器充装操作证考试题库及模拟考试

热门文章

  1. pyramid setup(修改版)
  2. Gartner发布2011年SIEM市场分析报告(幻方图)
  3. 网络工程职业规划【转载】
  4. systemtap打点方法
  5. 给chrome手动安装github上插件
  6. 【图论】图的深度优先遍历与广度优先遍历(图文讲解)
  7. python实现简单的socket通信
  8. 杭电计算机接口实验报告,杭电新闻
  9. 笔记本屏幕出现横条纹_华为再添黑科技,手机一碰笔记本,手机页面就出现在PC屏幕上...
  10. mysql 有数据更新数据_MySQL之——实现无数据插入,有数据更新