单元测试在开发中是非常重要的一个环节
程序员在写完代码时,相应的单元测试也应写完整,否则你的代码就是不能让人信服的
Struts2将Action与Servlet的API进行解耦之后,就使得单元测试变得非常容易了
比如HttpServletRequest对象,它是由Tomcat容器给我们提供的,我们自己产生不出来
若Action中充斥者ServletAPI,哪怕仅一个,那么一般意义上的JUnit单元测试便无法进行
若Action中耦合了ServletAPI,可以采用apache的Cactus对它进行测试,这要稍微麻烦些
另外也可以采用Mock,它本身是模拟的Servlet的API的一些相关的对象
然后用模拟出来的对象代替容器中产生的对象,来实现对应用程序的访问
而Struts2的Action已经脱离了ServletAPI,所以无需这两种方式,便可直接用JUnit测试


Struts2和Struts1.X中关于Action的测试
Struts1.X的Action依赖于ServletAPI,比如HttpServletRequest、HttpServletResponse对象
这些类都是和容器结合的,所以必须启动Tomcat服务器之后才能获得容器里面的对象
所以测试时比较麻烦。而Apache提供了可以捆绑到Eclipse上专门用于独立测试的项目
它为我们模拟了一系列的HttpServlet对象,使用它之后就可以脱离Tomcat独立测试
Struts2的Action不依赖容器,它和容器无关,所以能够脱离容器进行单独测试
换句话说,我们可以直接在Action里面写一个main()方法进行测试,这是没问题的
这在Struts1.X中是不可想象的,它必须要么启动Tomcat然后去测试,要么装插件再进行测试


Struts2没有与任何的Servlet API耦合
这样可以不依赖于Web容器【如Tomcat】轻松测试Action
Struts2为我们提供了三种方式,使得我们可以轻松获得Servlet的API
ActionContext
ServletActionContext
实现特定接口
由于com.opensymphony.xwork2.ActionContext已经与Servlet的API完全解耦
所以建议首选ActionContext次之采用ServletActionContext最不推荐使用接口


第一种com.opensymphony.xwork2.ActionContext类
首先通过ActionContext类的静态getContext()方法获得当前线程相关的一个ActionContext实例
然后就可以通过该实例调用它的众多方法得到Servlet的一些API
public Object get(Object key)方法,就相当于HttpServletRequest.getAttribute()
public void put(Object key, Object value)对应HttpServletRequest.setAttribute()
public Map<String, Object> getParameters()对应HttpServletRequest.getParameterMap()
public Map<String, Object> getSession()方法对应javax.servlet.http.HttpSession
session.put(Object key, Object value)对应Servlet编程中的HttpSession.setAttribute(…)
也就是说,ActionContext能够获得三个Map类型的Request, Session, Application对象
ActionContext有一个好处,就是它已经将底层的Servlet进行了转化,比如它将session转化成Map
这样在测试时,Struts2便可脱离Servlet容器进行单纯的JUnit测试


第二种org.apache.struts2.ServletActionContext类
ServletActionContext.getRequest()对应javax.servlet.http.HttpServletRequest
ServletActionContext.getResponse()对应javax.servlet.http.HttpServletResponse
ServletActionContext.getServletContext()对应javax.servlet.ServletContext
它的方法全都是static的。另外它所获得的ServletContext对象,就相当于Application
因为它的生命周期与Application生命周期是一样的,只要服务器不关闭,就都是有效的
ServletActionContext可以获得和容器绑定Request, Response, ServletContext对象
这里获得的都不是Map对象,所以在测试的时候,就必须要启动Tomcat服务器


第三种org.apache.struts2.util.ServletContextAware接口
它仅有个void setServletContext(javax.servlet.ServletContext context)方法
通过该方法获得的ServletContext就相当于Application,二者生命周期都是相同的
以及org.apache.struts2.interceptor.ServletRequestAware接口
同样有个void setServletRequest(javax.servlet.http.HttpServletRequest request)方法
以及org.apache.struts2.interceptor.ServletResponseAware接口
同样有个void setServletResponse(javax.servlet.http.HttpServletResponse response)方法
使用方式及示例代码,如下所示
此时需设置一个跟Servlet容器耦合HttpServletRequest类型request成员变量
当执行完setServletRequest()方法,成员变量就被它的HttpServletRequest参数赋值了
该方法是由Struts2自动调用的,显然这是一种非常非常典型的依赖注入DI
由Struts2自动将容器产生的HttpServletRequest对象set到我们应用中的变量上
这样成员变量request就变成了容器所产生的HttpServletRequest对象了
接下来就可以正常的使用request了,使用方法与在Servlet中的使用方式是一样的

  1. public class DecoupleAction implements ServletRequestAware {
  2. private HttpServletRequest request;
  3. public void setServletRequest(HttpServletRequest arg0) {
  4. this.request = arg0;
  5. }
  6. }
  1. public class DecoupleAction implements ServletRequestAware {
  2. private HttpServletRequest request;
  3. public void setServletRequest(HttpServletRequest arg0) {
  4. this.request = arg0;
  5. }
  6. }

补充org.apache.struts2.interceptor.RequestAware接口
示例代码如下

  1. public class DecoupleAction implements RequestAware, SessionAware, ApplicationAware {
  2. Map request;
  3. Map session;
  4. Map application;
  5. public void setRequest(Map arg0) {
  6. this.request = arg0;
  7. }
  8. public void setSession(Map arg0) {
  9. this.session = arg0;
  10. }
  11. public void setApplication(Map arg0) {
  12. this.application = arg0;
  13. }
  14. }
  1. public class DecoupleAction implements RequestAware, SessionAware, ApplicationAware {
  2. Map request;
  3. Map session;
  4. Map application;
  5. public void setRequest(Map arg0) {
  6. this.request = arg0;
  7. }
  8. public void setSession(Map arg0) {
  9. this.session = arg0;
  10. }
  11. public void setApplication(Map arg0) {
  12. this.application = arg0;
  13. }
  14. }

这里用到了IoC模式,即将三个Map变量初始化的权利交给了调用者,即容器
容器会自动的利用这三个setXxx()方法将三个Map变量的值从外面注入进来
而我们在Action中不需要new出来Map对象,也不需要做任何的初始化操作
然后就可以直接使用request, session, application三个对象了


小结
与Servlet容器解耦非IoC方法:com.opensymphony.xwork2.ActionContext类  (ActionContext )
与Servlet容器解耦的   IoC方法:RequestAware、SessionAware、ApplicationAware接口
与Servlet容器耦合非IoC方法:org.apache.struts2.ServletActionContext类 (ServletActionContext)
与Servlet容器耦合的   IoC方法:ServletRequestAware、ServletResponseAware接口 

Struts2 Action与Servlet API耦合的更多相关文章

  1. struts2 笔记01 登录、常用配置参数、Action访问Servlet API 和设置Action中对象的值、命名空间和乱码处理、Action中包含多个方法如何调用

    Struts2登录 1. 需要注意:Struts2需要运行在JRE1.5及以上版本 2. 在web.xml配置文件中,配置StrutsPrepareAndExecuteFilter或FilterDis ...

  2. struts2的action访问servlet API的三种方法

    学IT技术,就是要学习... 今天无聊看看struts2,发现struts2的action访问servlet API的三种方法: 1.Struts2提供的ActionContext类 Object g ...

  3. Struts2中获取servlet API的几种方式

    struts2是一个全新的MVC框架,如今被广大的企业和开发者所使用,它的功能非常强大.这给我们在使用servlet 纯java代码写项目的时候带来了福音.但是一般来说,我们的项目不到一定规模并不需要 ...

  4. struts2中访问servlet API

    Struts2中的Action没有与任何Servlet API耦合,,但对于WEB应用的控制器而言,不访问Servlet API几乎是不可能的,例如需要跟踪HTTP Session状态等.Struts ...

  5. Struts 2读书笔记-----Action访问Servlet API

    Action访问Servlet API Struts2中的Action并没有和任何Servlet API耦合,这样框架更具灵活性,更易测试. 对于Web应用的控制器而言,不访问ServletAPI是几 ...

  6. Action访问Servlet API的三种方法

    一.为什么要访问Servlet API ? Struts2的Action并未与Servlet API进行耦合,这是Struts2 的一个改良,从而方便了单独对Action进行测试.但是对于Web控制器 ...

  7. Struts2(八)访问Servlet API

    一.Struts2中的Servlet API 1.1.struts2的Action实现了MVC中C层的作用 针对请求用户显示不同的信息 登录后段保存用户信息 ----session 保存当前在线人数等 ...

  8. Struts2中使用Servlet API步骤

    Struts2中使用Servlet API步骤 Action类中声明request等对象 Map<String, Object> request; 获得ActionContext实例 Ac ...

  9. 笔记01 登录、常用配置参数、Action访问Servlet API 和设置Action中对象的值、命名空间和乱码处理、Action中包含多个方法如何调用

    Struts2登录 1. 需要注意:Struts2需要运行在JRE1.5及以上版本 2. 在web.xml配置文件中,配置StrutsPrepareAndExecuteFilter或FilterDis ...

随机推荐

  1. jquery------使用jQuery的委托方法

    index.jsp <div id="gallery"> <div class="photo"> <img src="a ...

  2. 大数据分析与机器学习领域Python兵器谱

    http://www.thebigdata.cn/JieJueFangAn/13317.html 曾经因为NLTK的缘故开始学习Python,之后渐渐成为我工作中的第一辅助脚本语言,虽然开发语言是C/ ...

  3. C# Attribute 特性 学习

    一.特性的概述 公共语言运行库允许您添加类似关键字的描述性声明(称为特性 (Attribute))来批注编程元素,如类型.字段.方法和属性 (Property).属性与 Microsoft .NET ...

  4. java中获取路径中的空格处理(%20)问题

    在java中获取文件路径的时候,有时候会获取到空格,但是在中文编码环境下,空格会变成“%20”从而使得路径错误. 解决办法: String path = Parameter.class.getReso ...

  5. 改变placeholder颜色

    /* WebKit browsers */ ::-webkit-input-placeholder { color: red; text-overflow: ellipsis; } /* Mozill ...

  6. 动态插入、添加删除表格行的JS代码

    <html> <head> <title>Table对象的方法</title> <script language="JavaScript ...

  7. Socket网络编程(1)

    TCP/IP 简单介绍 应用层 (Application):应用层是个很广泛的概念,有一些基本相同的系统级 TCP/IP 应用以及应用协议,也有许多的企业商业应用和互联网应用. 传输层 (Transp ...

  8. 10GE---超长距离的万兆以太网

    万兆以太网 锁定 本词条由“科普中国”百科科学词条编写与应用工作项目 审核 . 以太网标准是一个古老而又充满活力的标准.自从1982年以太网协议被IEEE采纳成为标准以后,已经历了20年的风风雨雨.在 ...

  9. 手机wifi密码的保存位置

    subjects:  adj. 受制于...的, 被统治的; n. 主题,学科, 国民 the subjects had to kneel down before the king. kneel -& ...

  10. apue第六章学习总结

    apue第六章学习总结 1.关于阴影文件与口令 在口令文件当中,常见的字段有(以root为例): root(用户名):x(加密口令):0(uid):0(gid):root(注释字段):/root(用户 ...