Action是Struts2应用的核心,用于处理用户的请求,因此Action也被称为业务控制器。每个Action都是一个工作单元,而Struts2框架则负责将用户的请求与相应的Action匹配。匹配成功则使用相应的Action处理用户的请求,匹配的规则在struts.xml中进行设置。
实现Action有三种方式:
1.普通的POJO类,该类包含一个无参数的execute()方法,返回值为String。
2.实现Action接口。
3.继承ActionSupport类。
1.POJO实现方式
在(一)Struts2实现第一个案例这篇文章里,写的那个UserAction就是POJO的实现方式,这里就不再说了,以后文章尽量精简一点,不然看着疲惫,写的也累。
运行tomcat,打开网页输入账户名密码地址后,点击提交,结果如下
运行结果
2.实现Action接口方式
Action接口的定义如下
public 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 String execute() throws Exception;
}
通过实现Action接口,我们就可以使用里面的常量值作为execute()方法的返回值。
package com.codeliu.action;
import com.opensymphony.xwork2.Action;
/**
* 通过实现Action接口来创建一个action
* @author liu
*/
public class LoginAction2 implements Action {
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;
}
@Override
public String execute() throws Exception {
if("admin".equals(username) && "admin".equals(password)) {
// Action接口中的静态常量,返回成功界面
return SUCCESS;
} else {
// 返回失败界面
return ERROR;
}
}
}
在struts.xml中增加一个Action,同时修改表单的action
<!-- 通过实现Action接口来实现一个action -->
<action name="login2" class="com.codeliu.action.LoginAction2">
<result name="success">/success.jsp</result>
<result name="error">/error.jsp</result>
</action>
运行结果和上面一样。
3.继承ActionSupport类方式
ActionSupport是Struts2默认的Action处理类,如果在struts.xml中配置Action时,省略了class属性,则默认调用ActionSupport类对作为Action的处理类,对用户的请求进行处理。编写Action时继承ActionSupport类能简化Action的开发,提高效率。
/**
* 通过继承ActionSupport来实现一个action
* @author liu
*/
@SuppressWarnings("serial")
public class LoginAction3 extends ActionSupport {
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;
}
@Override
public String execute() throws Exception {
System.out.println("用户名:" + username);
System.out.println("密码:" + password);
if("admin".equals(username) && "admin".equals(password)) {
return SUCCESS;
} else {
return ERROR;
}
}
@Override
/**
* 重写validate方法,可以在execute方法执行之前执行,对用户输入的数据进行验证
*/
public void validate() {
if(username == null || "".equals(username)) {
// 将错误信息写到ActionSupport类的FieldErrors中,此时Struts2框架自动返回input页面
this.addFieldError(username, "用户名不能为空");
System.out.println("用户名为空");
}
if(password == null || password.length() < 6) {
this.addFieldError(password, "密码不能为空且长度要大于6");
System.out.println("密码为空或长度小于6");
}
}
}
在上面的代码中,我们重写了ActionSupport类中的validate方法,该方法是在execute方法之前执行的,可以对用户输入的数据进行一些合法性的判断,如果不符合要求,则会自动跳转到输入页面。
其实Struts2有完整的验证框架,可以通过配置文件的方式对需要验证的内容进行配置,更加灵活,便于维护,这会在后面系列文章中讲到。
同样在struts.xml中增加一条一个Action,同时修改表单的action
<!-- 通过继承ActionSupport类来实现一个action -->
<action name="login3" class="com.codeliu.action.LoginAction3">
<result name="success">/success.jsp</result>
<result name="error">/error.jsp</result>
<result name="input">/index.jsp</result>
</action>
我们新增了一条result,对应的是validate方法,如果不符合要求,则跳转到index.jsp。
运行后如果输入符合要求,则结果和上面的一样,如果不符合要求,比如密码为空,则会在控制台打印输出密码为空或长度小于6,同时界面跳转到index.jsp。
4.通过ActionContext类间接获取Servlet API
Struts2相比于Struts1一个很大的不同是Action进行了解耦,提高了代码的复用率,但如果我们要获取Servlet API,还是得通过Struts2提供的一些类。比如ActionContext类。
ActionContext类提供了一些方法读写Servlet中HttpServletRequest、HttpSession和ServletContext中的数据,常用方法如下
方法 | 功能描述 |
---|---|
Object get(Object key) | 获取属性值,与HttpServletRequest的getAttribute(String name)方法类似 |
Map getApplication() | 返回一个对象,该对象模拟了web应用对象的ServletContext对象 |
static ActionContext getContext() | 静态方法,用于获取系统的ActionContext对象 |
Map getParameters() | 获取所有的请求参数,类似于调用HttpServletRequest的getParameterMap()方法 |
Map getSession() | 返回一个Map对象,该对象模拟了HttpSession实例 |
void setApplication(Map application) | 直接传入一个Map对象,将该Map对象中的键/值对转换成application的属性值和属性名 |
void setSession(Map session) | 直接传入一个Map对象,将该对象里的键/值对转成session的属性名和属性值 |
下面看看代码
@SuppressWarnings("serial")
public class ClickNumAction extends ActionSupport {
@Override
public String execute() throws Exception {
// 获取一个ActionContext实例对象
ActionContext act = ActionContext.getContext();
// 获取application中num的值
Integer num = (Integer)act.getApplication().get("num");
// 第一次获取时为null
if(num == null) {
num = 1;
} else {
num++;
}
// 设置的num的值
act.getApplication().put("num", num);
return SUCCESS;
}
}
上面通过ActionContext的静态方法getContext()获取一个ActionContext实例,然后通过getApplication()方法获取ServletContext对应的Map对象,调用put/get方法进行数据的读写操作。
再写一个clickNum.jsp来看看效果
<body>
<form action="click.action" method="post">
<input type = "submit" value="click">
</form>
<!-- 通过EL表达式获取applicationScope中的num值 -->
点击按钮
${empty applicationScope.num ? 0:applicationScope.num}次
</body>
记得在struts.xml中增加一个Action的配置
<!-- 通过ActionContext类获取Servlet API -->
<action name="click" class="com.codeliu.action.ClickNumAction">
<result name="success">/clickNum.jsp</result>
</action>
启动tomcat运行后,效果如下
5.通过某些接口直接获取Servlet API
虽然通过ActionContext类能获取,但毕竟不是直接获取,好多方法我们还是不能用,局限性太大,Struts2还提供了其他一系列的接口来直接获取Servlet API
接口名 | 描述 |
---|---|
ServletContextAware | 实现该接口的Action可以直接访问Web应用的ServletContext实例 |
ServletRequestAware | 实现该接口的Action可以直接访问Web应用的HttpServletRequest实例 |
ServletResponseAware | 实现该接口的Action可以直接访问Web应用的HttpServletResponse实例 |
以ServletRequestAware为例,源代码如下
public interface ServletRequestAware {
public void setServletRequest(HttpServletRequest request);
}
里面只有一个方法,实现该接口的同时实现这个方法就能获取HttpServletRequest 实例。代码如下
public class LoginAction4 extends ActionSupport implements ServletRequestAware {
private HttpServletRequest request;
@Override
/**
* 重写ServletRequestAware接口中的方法,获取HttpServletRequest实例
*/
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
@Override
public String execute() throws Exception {
if("admin".equals(username) && "admin".equals(password)) {
// 获取session对象
HttpSession session = request.getSession();
session.setAttribute("username", username);
return SUCCESS;
} else {
return ERROR;
}
}
}
上面都是些重复的代码,我就删了,只留了些主要的,可以通过直接创建一个HttpServletRequest 的变量,然后传给setServletRequest方法就可以获取到HttpServletRequest的实例,之后就可以使用它的所有功能。
可以去struts.xml新增一条Action的配置,试一试,我就不试了。
ServletContextAware、ServletResponseAware和ServletRequestAware的使用方法基本一致。
除此之外,Struts2还提供了一个ServletActionContext工具类,里面有一些静态方法。
方法 | 描述 |
---|---|
static PageContext getPageContext() | 获取web应用的pageContext对象 |
static HttpServletRequest getRequest() | 获取web应用的HttpServletRequest 对象 |
static HttpServletResponse getResponse() | 获取web应用的HttpServletResponse 对象 |
static ServletContext getServletContext() | 获取web应用的ServletContext 对象 |
总结:因为Struts2的特点就是Action不与任何Servlet API耦合,所以我们推荐使用ActionContext来间接获取Servlet API,也可以使用ServletActionContext工具类,以更简单的方式获取Servlet API。
网友评论