1.Action是干什么的?翻译过来就是“动作”的意思...
传统的MVC框架中,Control层一般都是一个类似与Servlet的一个Java对象。因为从职责上讲,Control层需要完成以下的职责:
1. 接收从Web容器传递过来的参数,并做恰当的类型转化
2. 调用逻辑处理
3. 搜集数据,并返回到视图
而在这个其中的第一步和第三步,都离不开Web容器中的对象的处理。
2.struts2中Action
在Struts2中的Action,并不需要依赖于特定的Web容器。我们看不到类似HttpServletRequest,HttpServletResponse等Web容器相关的对象。
这时候问题就出来了
a.为什么Action只是一个普通的再也不能普通的类,并且不带任何的有关Web容器相关的对象,Action又是如何工作在Web容器中的?
又是如何与WEB进行通信并获取参数的?
Struts2为Action的执行,准备了完整的数据环境和执行环境。而这个执行环境,就保证了Action在Web容器中的顺利运行。
在Struts2中,每个Http的请求,会被发送到一个Filter。而这个Filter,就会针对每个请求,创建出一个代码的执行环境,并在这个基础上,
为每个执行环境配备与之对应的数据环境,这个数据环境中的内容,就来自于Web容器中的一个又一个对象。这样,就能够顺利调用Action执行代码而无需担心
它是否运行在 Web容器中了。
其中,数据环境就成为了Action获取Web容器的基础。所以,当Action需要获取Web容器的相关对象,需要通过数据环境来进行。
b.何为数据环境?何为执行环境?
--ActionContext —— 数据环境
具备以下特性:
1. ActionContext应成为Action与Web容器之间的桥梁
2. ActionContext中应该保存有针对某个请求的详细信息
3. ActionContext应该是一个线程安全的类对象
--ActionProxy —— 执行环境
既然是执行环境,那么ActionProxy就需要提供Action执行的时候一切所需要的配置、参数等等,当然,也要有进行Action调用的入口。所以让我们来看一下ActionProxy的接口:
1 public interface ActionProxy { 2 3 /** 4 * Called after all dependencies are set 5 */ 6 void prepare() throws Exception; 7 8 /** 9 * @return the Action instance for this Proxy 10 */ 11 Object getAction(); 12 13 /** 14 * @return the alias name this ActionProxy is mapped to 15 */ 16 String getActionName(); 17 18 /** 19 * @return the ActionConfig this ActionProxy is built from 20 */ 21 ActionConfig getConfig(); 22 23 /** 24 * Sets whether this ActionProxy should also execute the Result after executing the Action 25 * 26 * @param executeResult 27 */ 28 void setExecuteResult(boolean executeResult); 29 30 /** 31 * @return the status of whether the ActionProxy is set to execute the Result after the Action is executed 32 */ 33 boolean getExecuteResult(); 34 35 /** 36 * @return the ActionInvocation associated with this ActionProxy 37 */ 38 ActionInvocation getInvocation(); 39 40 /** 41 * @return the namespace the ActionConfig for this ActionProxy is mapped to 42 */ 43 String getNamespace(); 44 45 /** 46 * Execute this ActionProxy. This will set the ActionContext from the ActionInvocation into the ActionContext 47 * ThreadLocal before invoking the ActionInvocation, then set the old ActionContext back into the ThreadLocal. 48 * 49 * @return the result code returned from executing the ActionInvocation 50 * @throws Exception 51 * @see ActionInvocation 52 */ 53 String execute() throws Exception; 54 55 /** 56 * Sets the method to execute for the action invocation. If no method is specified, the method provided by 57 * in the action's configuration will be used. 58 * 59 * @param method the string name of the method to invoke 60 */ 61 void setMethod(String method); 62 63 /** 64 * Returns the method to execute, or null if no method has been specified (meaning "execute" will be invoked) 65 */ 66 String getMethod(); 67 68 }
在这其中,prepare和execute方法是用作Action调用的入口函数,其他的接口定义都与Action执行时的运行参数和配置有关。
3.实现Action类:
Struts2不要求 Action类继承任何的Struts2的基类或实现Struts2接口。(但是,我们为了方便实现Action,大多数情况下都会继承com.opensymphony.xwork2.ActionSupport类,并重写此类里的public String execute() throws Exception方法。
Struts2中通常直接使用Action来封装HTTP请求参数,因 此,Action类里还应该包含与请求参数对应的属性,并且为属性提供对应的getter和setter方法。(当然,Action类中还可以封装处理结 果,把处理结果信息当作一属性,提供对应的getter和setter方法)
例如:
package org.caijieru.web.struts2.action; import com.opensymphony.xwork2.ActionSupport; /** *@authorcaijieru *@version1.0 */ publicclass LoginAction extends ActionSupport{ private String userName; private String password; private String msg; //结果信息属性 /** *@returnthemsg */ public String getMsg() { returnmsg; } /** *@parammsgthemsgtoset */ publicvoid setMsg(String msg) { this.msg = msg; } /** *@returntheuserName */ public String getUserName() { returnuserName; } /** *@paramuserNametheuserNametoset */ publicvoid setUserName(String userName) { this.userName = userName; } /** *@returnthepassword */ public String getPassword() { returnpassword; } /** *@parampasswordthepasswordtoset */ publicvoid setPassword(String password) { this.password = password; } /** *处理用户请求的excute()方法 *@return结果导航字符串 *@throwsException */ public String execute() throws Exception{ if("test".equals(this.userName) && "test".equals(this.password)){ msg = "登录成功,欢迎" + this.userName; returnthis.SUCCESS; }else{ msg = "登录失败,用户名或密码错"; returnthis.ERROR; } } }
4.Action访问Servlet API:
public String execute() throws Exception{ if("test".equals(this.userName) && "test".equals(this.password)){ msg = "登录成功,欢迎" + this.userName; //获取ActionContext实例,通过它来访问Servlet API ActionContext context = ActionContext.getContext(); //看session中是否已经存放了用户名,如果存放了:说明已经登录了; //否则说明是第一次登录成功 if(null != context.getSession().get("uName")){ msg = this.userName + ":你已经登录过了!!!"; }else{ context.getSession().put("uName", this.userName); } returnthis.SUCCESS; }else{ msg = "登录失败,用户名或密码错"; returnthis.ERROR; } }
Struts2中通过ActionContext来访问Servlet API,让Action彻底从Servlet API 中分离出来,最大的好处就是可以脱离Web容器测试Action。