研磨Struts2 之 第五章 Action【私塾在线原创】
视频配套PPT,视频地址【 研磨Struts2视频课程】
一般一个Action代表一次请求或调用,每个请求的动作都对应于一个相应的
Action,一个Action是一个独立的工作单元和控制命令。在Struts2中,一般Action
类需要实现Action接口,或者直接继承基础类ActionSupport。它要实现默认的
execute方法,并返回一个在配置文件中定义的Result(也就是一个自定义的字符串
而已)。
当然,Action也可以只是一个POJO(普通Java对象),不用继承任何类也不用实
现任何接口。Action是一次请求的控制器,同时也充当数据模型的角色,强烈建议
不要将业务逻辑放在Action中。
一般一个Action只需要配置名称和对应的类,把这两部分添加到struts.xml
中,从而建立一个action的映射。
示例如下:
<action name="hello" class="cn.javass.s2.MyHelloWorld“/>
当然,除了使用<s:action/>标签这种极少数情况,没有result的action是没有
什么作用的。在没有建立action和result的映射之前,action无法为用户显示任何
内容。
一:为action提供别名
为相同的action提供不同的result或者interceptor,称为action别名。Struts2
还提供另外一种强大的方式:为action别名指定action类中非execute()的其他方
法,为action指定method属性,示例如下:
<action name="test" class="cn.javass.s2.MyHelloWorld" method="myMethod">
二:不需要配置的别名
Struts2还支持不用配置,直接在访问的时候写成:Action名!方法名.action,这相当于访问Action名.action,只是调用的方法是指定的方法名的方法。
三:使用参数自定义action
使用<param>标签,可以为action传递初始化参数,此时action的属性必须按照JavaBean样式的setter方法。
另外一种是扩展com.opensymphony.xwork2.ActionSupport类。ActionSupport实
现了除Action以外的其他几个接口,主要的几个接口是:
com.opensymphony.xwork2.Validateable:
提供validate()方法来为Action增加验证的功能
com.opensymphony.xwork2.Validateaware:
提供方法来保存和恢复action或field级的错误信息
com.opensymphony.xwork2.TextProvider:
提供获取本地信息文本的功能
com.opensymphony.xwork2.LocaleProvider:
提供getLocale()方法来获取本地消息
这些接口主要提供给拦截器使用,接口配合拦截器可以实现AOP功能
ActionSupport的示例非常简单,基本上就是把MyHelloWorld的实现Action改写
成继承ActionSupport类就可以了。
1:先是执行validate()方法,如果有错误,直接添加到addFieldError中,同时回到输入页面
2:通过了validate过后,进如execute()方法,如果检测数据有错误,也是添加addFieldError,同时需要return INPUT。
3:这个时候的错误信息都放到fieldError里面了,回到页面上怎么显示呢?使用Struts2的标签来实现输出错误信息,如下:
java代码:
<s:if test="hasFieldErrors()">
<s:iterator value="fieldErrors">
<s:property value="value[0]"/>
</s:iterator>
</s:if>
示例如下:
java代码:
Action类:
package cn.javass.s2;
import com.opensymphony.xwork2.ActionSupport;
public class MyHelloWorld extends ActionSupport{
public String id,name;
@Override
public String execute(){
System.out.println("the id="+id+",name="+name);
return SUCCESS;
}
@Override
public void validate(){
if(id==null || id.trim().length()==0){
this.addFieldError("id","id不允许为空");
}
}
}
Struts2.xml配置:
java代码:
<package name="myHello" extends="struts-default">
<action name="hello" class="cn.javass.s2.MyHelloWorld">
<result name="success " >
<param name="location">/t2.jsp</param>
</result>
<result name="input">/t1.jsp</result>
</action>
</package>
t1.jsp:
<%@ page contentType="text/html; charset=gb2312"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<s:if test="hasFieldErrors()">
<s:iterator value="fieldErrors">
<s:property value="value[0]"/>
</s:iterator>
</s:if>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=gb2312">
</head>
<form action="/s2/hello.action" method="post">
编号:<input type="text" name="id">
<br>姓名:<input type="text" name="name">
<br><input type="submit" value="提交">
</form>
有时在显示错误信息的时候,需要读取本地配置的信息,Struts2提供很简单的
实现方式。
1:在Action类的路径下建立一个同名的properties文件,然后添加如下行:my.message.test=Name can not be null
2:然后修改validate()方法
java代码:
public void validate(){
//数据检测的逻辑,当然这里只是做个示意
if(name == null || name.trim().length() == 0){
this.addFieldError("name",this.getText("my.message.test"));
}
}
Field-Driven(字段驱动的)Action
Action将直接用自己的字段来充当域数据属性的功能,我们前面的例子就是使用这种方式。它一般用在页面表单比较简单的情况使用,而且可以直接用域对象作为Action的字段,这样就不用在另写FormBean,减少了重复代码。
前面演示的直接使用public属性的字段,或者是使用另外的UserModel的情况都属于Field-Dirven Action
全面的数据是直接匹配到Action里面的public属性上面去的,通常会另外建立域
对象对数据进行封装,然后在Action里面使用。
1:先建立一个UserModel
2:注意Action里面下列写法:
java代码:
private UserModel um;
public void setUm(UserModel um){
this.um = um;
}
public UserModel getUm(){return this.um;}
3:以前直接访问id和name的地方,全部改成用um去访问
4:注意对应的web页面中的下列写法:
id:<input type=“text” name=“um.id”> 中间的um.id,以前都是直接写id的,这种用法在后面表达式语言的时候讲。
Model-Driven(模型驱动的)Action
它很像Struts的FormBean,但在Struts2中,只要普通Java对象就可以充当模型部分。模型驱动的Action要求Action实现ModelDriven接口,它有一个方法:Object getModel();,我们用这个方法返回我们的模型对象就可以了。
1:使Action类实现ModelDriven接口,并实现getModel方法
2:去掉原来的getUm和setUm方法,现在统一从getMedel走
3:对应的Jsp页面也不需要再写um.id了,直接写成id就可以了,因为这个时候Struts2知道这个id是谁的id,当我们采用Model-Driven(模型驱动的)Action时,它将取得模型对象保存在值堆栈中。“name=“id"”就是代表直接调用模型对象的setId()方法。
4:在struts.xml中配置<interceptor-ref name=“modelDriven”/> ,它的作用就是将模型对象保存到值堆栈中。
注意 : 为了保证一致性,不应该在请求过程中改变getModel返回的值,getModel方法 会先于execute方法被执行。
包<package>的namespace属性用来将Action的配置分成逻辑相关的模块,避免了同名Action之间的冲突。每个包都用namespace属性指定它自己URL的前缀。
包可以分成三种
默认包:没有namespace属性,<package name=“package1”>
根包:namespace属性为”/”,<package name=“package1” namespace=“/”>
具体包:namespace属性为其他具体值”/s2”,<package name=“package1” namespace=“/s2”>
Struts2还支持在name属性(URL)中定义通配符,并在以后的class属性、method属性和<result>元素中使用。
ame属性定义通配符,其他部分使用通配符。
java代码:
<action name="*_*_*_*" class="cn.javass.action.{1}Action" method="{2}">
<result name="{3}">/{4}.jsp</result>
</action>
Struts2 为每个请求都重新初始化一个 Action 的实例。
稍稍改造代码来验证一下:
1、加上public无参构造方法测试其初始化时机。
public HelloWorldAction(){
System.out.println("HelloWorldAction被初始化");
}
2、在execute方法中打印this,以观察起hashCode()方法的返回值。
public String execute() throws Exception {
System.out.println(this);
。。。
return "toWelcome";
}
在项目的classpath根目录下必须要有struts.xml(放置整个项目通用的配置),而其他配置文件如struts-hotel.xml(饭店模块的所有Action)等,需要在struts.xml进行引用。
struts.xml的内容。
java代码:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.devMode" value="true" />
<constant name="struts.locale" value="zh_CN"></constant>
<constant name="struts.i18n.encoding" value="gb2312"></constant>
<include file="struts-hotel.xml"></include>
</struts>
struts-hotel.xml的内容。
java代码:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="hotel" namespace="/hotel" extends="struts-default">
<action name="bookingAction" class="cn.javass.hotel.action.HotelBookingAction">
<result name="success">/hotel/booking.jsp</result>
</action>
<action name="queryAction" class="cn.javass.hotel.action.QueryAction">
<result name="success">/hotel/query.jsp</result>
</action>
</package>
</struts>
视频配套PPT,视频地址【 研磨Struts2视频课程】
浙公网安备 33010602011771号