Struts2框架中的Action是业务控制器,是Struts2框架的核心。用户提交的所有请求,都是通过Action进行业务逻辑处理的。在Struts2框架中,Action是实现企业应用的关键部分。
一、 Action实现类
1. Struts2最大的特点是实现了Action与Servlet API的分离,Struts2中的Action就是一个普通的Java类
(POJO),该类通常包含一个execute()方法,该方法没有任何参数,只是返回一个字符串类型值。
例如:用户登录Action
package ch02;
import com.opensymphony.xwork2.ActionSupport;
public class UserLogin extends ActionSupport{
/**
*
*/
private static final long serialVersionUID = 1L;
private String userName;
private String password;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String execute() throws Exception{
if(userName!=null&&getPassword().equals(("123")&&!getUserName().trim().equals("")){
return SUCCESS;
}
else{
return INPUT;
}
}
}
2. 那么Struts2的Action是如何获得用户Http请求中的参数的?
通常情况下,Struts2框架中的Action会直接封装Http请求参数,一般的Action会包含与请求参数对应的属性,并提供该属性的getter和setter方法。
1. 比如上面的UserLogin是Action的实现类,该类中定义了userName、password两个属性,分别对应用户提交的form表单中的参数值。
2. 同时UserLogin类为每个属性设置了getter和setter方法。
注意: 1. 并不是Action必须要定义一个与用户Form中名字相同的属性,但是一定要有对应Form参数值的getter和setter方法。
2. Action不但可以设置与Http请求参数对应的属性,也可以定义Http参数中没有的属性,而用户可以访问这些属性。
说明: 对于Struts2框架来说,不会区分Action的属性是否为传入的还是传出的,Struts2提供了一个类似“仓库”的机制,Action可以使用getter和setter方法从“仓库”中存入或者取出属性值,只要包含用户Http请求参数的getter和setter方法即可。用户的Http也是通过post向“仓库”中传入值或者从“仓库”中取出值。
二、 Action接口和ActionSupport工具类
1. 为了规范用户开发Action的实现类,Struts2框架提供了一个Action接口,该接口提供了一个通用的规范。如下所示:Action接口
public abstract interface Action{
//定义静态常量
public static final String SUCCESS="success";
public static final String NONE="none";
public static final String ERROR="error";
public static final String INPUT="input";
public static final String LOGIN="login";
//定义抽象接口
public abstract String execute() throws Exception;
}
说明:1. Action接口很简单,定义了SUCCESS、NONE、ERROR、INPUT和LOGIN常量,开发者在编写自己的Action类时,实现Action接口,就可以在execute()方法中返回SUCCESS、NONE、ERROR、INPUT和LOGIN,而不是自己随意书写字符串,这样就规范了代码。
2. Action接口声明了一个抽象execute()方法,Action类需要对该方法进行重新编写,实现自己的业务控制逻辑。
2. Struts2预设了一个工具类ActionSupport,该类已经实现了Action接口,并定义了execute()方法和数据校验validate()方法;除此之外,还包含了很多如异常处理、国际化等一些常用的方法。
说明: 开发者在编写自己的Action时,只要继承ActionSupport类就可以了,这样可以更加方便、快
捷地实现业务控制器。
三、 Action访问ActionContext
Struts2框架的Action强调的是与Servlet API完全分离,这种非耦合性给开发者的测试提高了便利。但是,Struts2的Action不访问Servlet API是不能实现业务逻辑的,用户请求中的参数值,对业务逻辑的实现有着至关重要的意义,例如访问Session、Application状态等。
1. 一般Web应用中,需要访问的Servlet API就是HttpServlet、HttpSession和ServletContext,这三个类就包含了JSP内置对象中所对应的Request、Session和Application。 Struts2框架中有一个ActionContext类,该类中包含了所有将会访问的数据,Struts2框架的Action可以通过访问ActionContext来获得Servlet API,如下图所示:
ActionContext是一个Action执行的上下文,Action执行期间所用到的对象都保存在ActionContext中,例如Session、参数等数据。
说明:ActionContext是一个局部线程,这意味着每个线程中的ActionContext内容都是唯一的。所以不用担心Action的线程安全。
2. 访问ActionContext
1. 开发者可以使用下面的代码访问ActionContext:
ActionContext ctx=ActionContext.getContext();
2. 下面是该类的常用方法:
- public static ActionContext getContext() :获得当前Action的ActionContext实例。
- public Object get(Object key) :此方法类似于调用HttpServletRequest的getAttribute(String name)方法。
- public void put(Object key, Object value):此方法类似于调用 HttpServletRequestsetAttribute(String name, Object o)。
- public Map getParameters() :获取所有的请求参数。类似于调用HttpServletRequest对象的getParameterMap() 方法。
- public Map getSession() :返回一个Map对象,该Map对象模拟了HttpSession实例。
- public void setSession(Map session) : 直接传入一个Map实例,将该Map实例里的key-value对转换成session的属性名-属性值对。
- public Map getApplication() :返回一个Map对象,该对象模拟了该应用的ServletContext实例。
- public void setApplication(Map application) :直接传入一个Map实例,将该Map实例里的key-value对转换成application的属性名-属性值对。
四、 Action直接访问ServletAPI
1. Struts2框架的Action可以通过ActionContext来访问Servlet,除此之外,Struts2框架还提供了
ServletActionContext辅助类来帮助开发者获得ServletAPI。 可以通过下面的方式获得:
HttpServletRequest request=ServletActionContext.getRequest();
HttpServletResponse response=ServletActionContext.getResponse();
HttpSession session=request.getSession();
说明:使用ActionContext类和ServletActionContext辅助类来访问ServletAPI都属于非IoC(Inversion of
Control)方式,Struts2框架还提供了IoC方式来访问ServletAPI。
2. 使用IoC方式访问Servlet API,Action必须要实现下面的接口:
1:ServletContextAware:实现该接口的类可以直接访问Web应用的ServletContext实例。
该接口中定义了一个void setServletContext(ServletContext context)方法,实现该接口的类必须实现void
setServletContext(ServletContext context)方法。
2:ServletRequestAware:实现该接口的类可以直接访问用户请求的HttpServletRequest实例。该接口定义
了一个void setServeltRequest(HttpServletRequest request)方法,实现接口的类必须实现 void
setServeltRequest(HttpServletRequest request)方法。
3:ServletResponseAware:实现该接口的类可以直接访问服务器响应的HttpServletResponse实例。该接口
中定义了void setServletResponse(HttpServletResponse response)方法,实现该接口的类必须实现void
setServletResponse(HttpServletResponse response)方法。
五、 Action的配置
Action配置模块就是Web项目的“模块”,正是通过struts.xml文件或者其包含的配置文件来实现Action的配置的。在Struts2框架中每一个Action都是一个工作单元。Action负责将一个请求对应到一个Action处理上去,每当一个Action类匹配一个请求的时候,这个Action类就会被Struts2框架调用。下面给出一个Action的配置示例:
<action name="Regist" class="struts.HelloWorld.Regist">
<result name="success">/success.jsp</result>
<result name="input">/regist.jsp</result>
</action>
说明:1. 每一个Action可以配置多个result、多个ExceptionHandler、多个拦截器Interceptor,但是只能有一个name,这个name和package的namespace来唯一区别一个Action。
2. 每当Struts2框架接受到一个请求的时候,会去掉Host、Application和后缀等信息,得到Action的名字。
六、 Action的动态方法调用
1. 在Struts2框架中,可以使用DMI(Dynamic Method Invocation,动态方法)来调用同一个Action中的不同
业务逻辑方法,一般需要在JSP的表单属性中指定具体的调用方法,一般格式如下:
<form method=" post " action="Action名称!方法名称.action">
……
</form>
注意:1. 使用Action的动态方法调用,需要将Struts2框架的相应常量struts.enable.DynamicMethodInvocation设置为true,这样框架才支持动态方法调用。Struts2中该常量的默认值就是true。
2. Action中建立不同的业务逻辑方法,规范与execute()是完全一样的,也是一个没有参数的方法,返回值也是字符串类型。实际上,一般Action都是继承ActionSupport类,但是ActionSupport类并不强制其子类必须实现execute()方法。
2. Struts2框架还提供了另外一种方式来实现动态方法调用,就是修改配置文件,定义多个Action名称,不同的方法对应不同的Action配置。要配置不同的Action名对应一个Action类的不同方法,必须配置method属性。
例如:将Bank类的“存款”和“转账”两个业务逻辑配置成两个Action,并在配置中指定method值。配置文件代码如下:
<action name="Bank_saving" class="ch02.Bank" method="saving">
<result name="success">/success.jsp</result>
</action>
<action name="Bank_transfer" class="ch02.Bank" method="transfer">
<result name="success">/success.jsp</result>
</action>
注意:这种增加Action配置的方式访问Action动态方法会导致Struts2框架中的配置文件内容增加,如果应用项目开发量大,那么会给配置文件的管理带来很大的麻烦。
七、 通配符配置
前面的示例中Bank_saving和Bank_transfer配置中,如果使用通配符Bank_*来配置那会更加方便。 Struts2框架为开发者提供了非常好的通配符配置支持。在Action配置中,一般需要指定name、class和method属性,Struts2框架支持这三个属性使用通配符来定义。
示例:
<action name="Bank_*" class="ch02.Bank" method="{1}">
<result name="success">/success.jsp</result>
</action>
该配置使用了通配符,定义了一系列Action,只要用户请求为Bank_*.action,就可以找到相应的Action。这一系列Action都指向了类ch02.Bank,该类中有对应的不同方法。method={1}指的是用户请求Bank_*.action中的第一个参数。 例如:如果用户请求为Bank_saving.action,那么method=saving;如果用户请求为Bank_transfer.action,那么method=transfer。
说明:Struts2框架的配置文件中可以指定多个通配符,例如可以配置为:
<action name="Bank_*_*" class="ch02.Bank{1}Action" method="{2}">
<result name="success">/success.jsp</result>
</action>
如果用户请求为Bank_transfer_ccb.action,Struts2框架会将Action配置“翻译”为:
<action name="Bank_transfer_ccb" class="ch02.BanktransferAction" method="ccb">