Action是Struts2的核心组件,有3个作用:
1.对页面请求作出处理
2.保存页面传入和需要使用的数据
3.处理请求后返回视图
Action的实现和配置:
1.实现
Struts2的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;
}
可以看到接口定义了一些常量和一个方法execute,如果不在配置文件中指定action执行的方法,则默认执行action的execute方法,而这些常量可以很方便地用作execute方法返回值,框架内部也使用这些常量。
在Action接口的基础上,框架又提供了ActionSupport类,这个类实现了几个重要的接口,包括Action,提供了一些数据验证,资源本地化等功能。
public class ActionSupport implements Action, Validateable, ValidationAware, TextProvider, LocaleProvider, Serializable
所以一般创建Action都继承ActionSupport这个类。
2.配置
实现Action后,要访问它,还需要在Action中配置,一个标准的action配置如下:
<package name="test" extends="struts-default" namespace="/test">
<action name="checkLogin" class="com.test.LoginAction" method="checkLogin">
<result name="success">/index.jsp</result>
<result name="fail">/login.jsp</result>
</action>
</package>
package可以包含多个action,extends属性指定被继承的父包,一般package都继承struts-default,struts-default这个包定义了常用的拦截器栈。namespace指定了命名空间,在开发时会出现模块之间的action同名的情况,namespace避免了这个问题,namespace的路径会作为action访问路径的一部分。
<action>元素声明了具体的Action,name是Action名称,在form提交表单时会用到这个name,class是Action的实现类路径,method指定了要执行的Action的方法,如果不指定这个参数,则默认执行Action中的execute方法。
子元素<result>指定返回的视图,name属性和execute方法或指定method中的String返回值一致,如果找到匹配的返回值,则转向后面的页面。
下面是一个完整的示例:
jsp:
<%@ page language="java" contentType="text/html"
pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Insert title here</title>
</head>
<body>
<div style="margin:30px 50px 20px 50px;text-align:center">
<s:form action="hello" namespace="/test">
<s:textfield name="username" label="名称" />
<s:submit value="确认" />
</s:form>
</div>
</body>
</html>
Action:
public class HellowAction extends ActionSupport{
private String username;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String execute() throws Exception {
System.out.println();
return SUCCESS;
}
}
struts.xml:
<struts>
<include file="struts-default.xml" />
<package name="test" extends="struts-default" namespace="/test">
<action name="hello" class="com.test.HellowAction">
<result name="success">/success.jsp</result>
</action>
</package>
</struts>
如果action返回success,跳转的jsp:success.jsp
<%@ page language="java" contentType="text/html"
pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title></title>
</head>
<body>
<div style="text-align:center">
hello!<s:property value="username"/>
</div>
</body>
</html>
启动,访问第一个jsp,输入abc,点击确定,查看跳转页面内容:
hello!abc
可以看到,struts2会将页面表单请求的属性名和Action的属性对比,如果一直则将form值赋值到Action的属性上,这个过程是由params这个拦截器实现的,同样,在跳转后的jsp页面上,也可以访问到Action中的属性。
Action的数据转移:
如果想在Action中将接受到的表单数据赋值给另外的JavaBean,一种做法是:
public String execute() throws Exception {
User user= new User();
user.setName(getUsername());
return SUCCESS;
}
如果页面表单内容过多,需要一个一个单独接收并且赋值给新的对象,这是一个繁琐的操作,struts2提供了2种数据直接转移的方法,一种是直接提供对象作为Action属性赋值(ognl表达式方式),一种是使用ModelDriven
1.对象属性(ognl表达式)
修改上面例子的代码,
User:
public class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "name="+name;
}
}
action:
public class HellowAction extends ActionSupport{
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public String execute() throws Exception {
System.out.println(user);
return SUCCESS;
}
}
struts.xml:
<struts>
<include file="struts-default.xml" />
<package name="test" extends="struts-default" namespace="/test">
<action name="hello" class="com.test.HellowAction">
<result name="success">/success.jsp</result>
</action>
</package>
</struts>
Jsp:
<%@ page language="java" contentType="text/html"
pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Insert title here</title>
</head>
<body>
<div style="margin:30px 50px 20px 50px;text-align:center">
<s:form action="hello" namespace="/test">
<s:textfield name="user.name" label="名称" />
<s:submit value="确认" />
</s:form>
</div>
</body>
</html>
success.jsp:
<%@ page language="java" contentType="text/html"
pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title></title>
</head>
<body>
<div style="text-align:center">
hello!<s:property value="user.name"/>
</div>
</body>
</html>
第一个页面提交输入abc,success页面输出了hello!abc,观察控制台,打印:name=abc
ognl表达式访问属性的方式是对象.属性
2.ModelDriven
需要Action实现ModelDriven接口,然后在getModle方法中公开要访问的对象和属性。
与ognl方式相比只有Action代码不同
public class HellowAction extends ActionSupport implements ModelDriven<User>{
private User user = new User();
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public String execute() throws Exception {
System.out.println(user);
return SUCCESS;
}
@Override
public User getModel() {
return user;
}
}
注意到使用这种方式时,user对象必须先初始化。
在Action中获取ActionContext:
ActionContext包含了框架请求处理过程中可以访问的所有的数据,包括以下对象:
parameters,request,session,application,attr,ValuesStack
在Action中获取ActionContext的方法:
ActionContext ac = ActionContext.getContext();
获得的ActionContext实例可以通过get方法取得以上提及的对象。
在Action中访问Servlet API:
访问Servlet API有2种方法,间接和直接,通过ActionContext访问属于间接方式,直接方式有IoC和非IoC两种
1.IoC:
Struts2中通过Ioc方式将Servlet对象注入到Action中,具体实现是由一组接口决定的,要使用Ioc方式就要实现以下的一个或者多个接口:
ApplicationAware,SessionAware,CookiesAware,ParameterAware,ServletContextAware,ServletRequestAware,ServletResponseAware
下面以实现ServletRequestAware接口获取ServletRequest对象为例:
public class IocAction extends ActionSupport implements ServletRequestAware{
private HttpServletRequest request;
@Override
public String execute() throws Exception {
HttpSession session = request.getSession();
return SUCCESS;
}
@Override
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
}
2.非Ioc方式:
HttpServletRequest request = ServletActionContext.getRequest();
HttpSession session = ServletActionContext.getRequest().getSession();