Struts2实现了MVC模式:模型、视图、控制器,视图与控制器之间怎样传递数据—回显数据。Action通过继承ModelDriven接口,使Jsp回显Action中绑定到属性或者对象上的数据。
一、回显方式
1、方式一 :所有属性使用set方法将需要内容设置到Javabean(实体类)中
action:
public class roleTestAction implements ModelDriven<Role> {
private Long id;
private String name;
private String description;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@Resource
private RoleService roleService;
/** 添加 */
public String save() throws Exception {
Role role=new Role();
Role.setId="123";
Role.setName="人事部";
Role.setDescription="电话:1234556666";
roleService.save(role);
return "toList";
}
}</span>
</span>
jsp:
<s:iterator value="#roleList">
<tr class="TableDetail1 template">
<td>${name} </td>
<td>${description} </td>
<td>
<s:a action="role_delete?id=%{id}" onclick="return confirm('确定要删除吗?')">删除</s:a>
<s:a action="role_editUI?id=%{id}">修改</s:a>
<a href="setPrivilegeUI.html">设置权限</a>
</td>
</tr>
</s:iterator>
<span style="font-size:14px;">
</span>
特点:所有的属性都需要get、set方法进行设置,无法合理的应对复杂的业务。
2、方式二:根据业务将公共属性抽象出JavaBean,直接将JavaBean设置为一个属性,前台通过get方法获取
抽象JavaBean:
public class Role implements java.io.Serializable {
private Long id;
private String name;
private String description;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
action:
public class roleTestAction implements ModelDriven<Role> {
@Resource
private RoleService roleService;
private Role role;
//get和set方法
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
/** 添加 */
public String save() throws Exception {
roleService.save(role);
return "toList";
}
}
jsp: <s:iterator value="#roleList">
<tr class="TableDetail1 template">
<td>${user.name} </td>
<td>${user.description} </td>
<td>
<s:a action="role_delete?id=%{user.id}" onclick="return confirm('确定要删除吗?')">删除</s:a>
<s:a action="role_editUI?id=%{user.id}">修改</s:a>
<a href="setPrivilegeUI.html">设置权限</a>
</td>
</tr>
</s:iterator>
特点:
action还是需要设置对象的get、set方法,而且Jsp中获取对象时,必须加上对象的前缀
适合有特殊需求的业务,不需要使用对象模型,只是需要简单获取简单几个属性
3、方式三:ModelDriven,直接操作应用程序中的领域对象,已经封装了属性的所有get、set方法
抽象的JavaBean:
public class Role implements java.io.Serializable {
private Long id;
private String name;
private String description;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
action: public class roleTestAction implements ModelDriven<Role> {
@Resource
private RoleService roleService;
private Role model = new Role();
public Role getModel() {
return model;
}
/** 添加 */
public String save() throws Exception {
roleService.save(model);
return "toList";
}
}
}
jsp: <s:iterator value="#roleList">
<tr class="TableDetail1 template">
<td>${name} </td>
<td>${description} </td>
<td>
<s:a action="role_delete?id=%{id}" onclick="return confirm('确定要删除吗?')">删除</s:a>
<s:a action="role_editUI?id=%{id}">修改</s:a>
<a href="setPrivilegeUI.html">设置权限</a>
</td>
</tr>
</s:iterator>
特点:
modelDriven封装了所有的对象,不需要使用get和set方法;Jsp也只需要对象的属性名即可
二、ModelDriven
(1)模型驱动的Action必须实现ModelDriven接口,而且要提供相应的泛型
(2)实现ModelDriven的getModel方法,其实就是简单的返回泛型的一个对象
(3)在Action提供一个泛型的私有对象,就是定义一个对象,并提供相应的getter与setter。
三、原理(ValueStack)
MoldenDriven的实现,介绍一下拦截器ModelDrivenInterceptor,ModelDrivenInterceptor主要做的事就是调用Action的getModel()方法然后把返回的model压入值栈。下面是该拦截器intercept方法
源码:
@Override
public String intercept(ActionInvocation invocation) throws Exception {
//获取当前正在执行的Action
Object action = invocation.getAction();
//如果Action实现了ModelDriven接口
if (action instanceof ModelDriven) {
ModelDriven modelDriven = (ModelDriven) action;
ValueStack stack = invocation.getStack();
//通过getModel方法获取model
Object model = modelDriven.getModel();
//如果model不为null则把model压入值栈
if (model != null) {
stack.push(model);
}
if (refreshModelBeforeResult) {
//在执行Result之前是否要更新model对象,默认为false
invocation.addPreResultListener(
new RefreshModelBeforeResult(modelDriven, model));
}
}
return invocation.invoke();//调用下一个拦截器
}
此方法就是把getModel方法返回的结果压入值栈,我们一般实现这个接口是利用压入值栈的model对象接收从页面提交过来的数据,因为Action也是在值栈中,而struts2在赋值参数的时候是在值栈从栈顶往栈底寻找有相应setter方法的对象,而这时model压入了值栈,它是处于栈顶的,所以从页面提交过来的参数也就被model对象接收了。
注意:
每次action请求对Javabean赋值,反复赋值,会将旧对象的信息覆盖
三、实例
使用ModelDriven的方式。该action继承ModelDriven接口,实现getModel()方法,方法只返回一个模型对象,默认转换Object。
ModelDriven接口只有一个方法
public Object getModel() {
return null;
}
该方法返回一个用于接收用户输入数据的对象模型,在这个模型对象中的属性可以直接通过(属性名)userName来访问,而不需要使用(对象名.属性名)user.userName这种格式来访问了,在action也不需要对对象提供getter和setter方法了,但是必须要在action中进行new操作
如下
//对ModelDriven使用泛型进行抽象
public class RoleAction extends ActionSupport implements ModelDriven<Role> {
@Resource
private RoleService roleService;
//实例化要回显的兑现
private Role model = new Role();
//实现接口方法
public Role getModel() {
return model;
}
/** 修改页面 */
public String editUI() throws Exception {
// 准备回显的数据
Role role = roleService.getById(model.getId());
//将回显对象放入栈顶
ActionContext.getContext().getValueStack().push(role);
return "saveUI";
}
}
四、总结
ModelDriven直接把实体类当成页面数据的收集对象,将实体对象压入栈顶。简化操作,提高效率。