您的位置:首页 > 编程语言 > Java开发

Struts2 学习系列 (5) ModelDriven 和 Preparable 拦截器

2015-11-12 20:21 537 查看
Params 拦截器

Parameters 拦截器将把表单字段映射到 ValueStack 栈的栈顶对象的各个属性中. 如果某个字段在模型里没有匹配的属性, Param 拦截器将尝试 ValueStack 栈中的下一个对象

在使用 Struts 作为前端的企业级应用程序时把 Action 和 Model 清晰地隔离开是有必要的: 有些 Action 类不代表任何Model 对象, 它们的功能仅限于提供显示服务



ModelDriven 拦截器

当用户触发 add 请求时, ModelDriven 拦截器将调用 EmployeeAction 对象的 getModel() 方法, 并把返回的模型(Employee实例)压入到 ValueStack 栈.

接下来 Parameters 拦截器将把表单字段映射到 ValueStack 栈的栈顶对象的各个属性中. 因为此时 ValueStack 栈的栈顶元素是刚被压入的模型(Employee)对象, 所以该模型将被填充. 如果某个字段在模型里没有匹配的属性, Param 拦截器将尝试 ValueStack 栈中的下一个对象

Preparable 拦截器

Struts 2.0 中的 modelDriven 拦截器负责把 Action 类以外的一个对象压入到值栈栈顶

而 prepare 拦截器负责准备为 getModel() 方法准备 model

PrepareInterceptor拦截器用方法

若 Action 实现 Preparable 接口,则 Action 方法需实现 prepare() 方法

PrepareInterceptor 拦截器将调用 prepare() 方法,prepareActionMethodName()方法 或 prepareDoActionMethodName ()方法

PrepareInterceptor 拦截器根据 firstCallPrepareDo 属性决定获取 prepareActionMethodName 、prepareDoActionMethodName的顺序。默认情况下先获取 prepareActionMethodName (), 如果没有该方法,就寻找prepareDoActionMethodName()。如果找到对应的方法就调用该方法

PrepareInterceptor 拦截器会根据 alwaysInvokePrepare 属性决定是否执行prepare()方法

给出两个个实例:

① ModelDriven单个使用即可

import com.atguigu.struts2.model.Department;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;

public class TestComplextPropertyAction extends ActionSupport
implements ModelDriven<Department>{

/**
*
*/
private static final long serialVersionUID = 1L;

@Override
public String execute() throws Exception {
System.out.println(department);
return SUCCESS;
}

private Department department;

@Override
public Department getModel() {
department = new Department();
return department;
}

}


② ModelDriven和Preparable接口配合使用
package org.andy.shop.action;

import org.andy.shop.dao.impl.UserInfoDaoImpl;
import org.andy.shop.entity.UserInfo;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.opensymphony.xwork2.ModelDriven;
import com.opensymphony.xwork2.Preparable;
import com.sun.net.httpserver.Authenticator.Success;

@Component
public class LoginAction implements ModelDriven<UserInfo>,Preparable{

private static final Logger LOGGER = Logger.getLogger(LoginAction.class);
@Autowired
private UserInfoDaoImpl userInfoDaoImpl;
/**
* 给action中的对象赋值:
* 1)可以使用ModelDriven<T>配合Preparable来使用,下面给出了实例
* 2)还可以在jsp中将input的name设置为userInfo.id来进行赋值
*/
private UserInfo userInfo;

public void setUserInfo(UserInfo userInfo) {
this.userInfo = userInfo;
}
public UserInfo getUserInfo() {
return userInfo;
}

public String saveUserInfo(){
System.out.println(this.userInfo.toString());
Integer userId = userInfoDaoImpl.save(userInfo);
System.out.println(userId);
return "success";
}

/**
* 为每一个方法定制一个prepar_MethodName,它会为saveUserInfo准备一个model对象,当ModelDriven调用getModel方法,将此对象压入栈顶中
* @author 高国藩
* @date 2015年11月4日 下午1:33:49
*/
public void prepareSaveUserInfo(){
this.userInfo = new UserInfo();
}

public void prepare() throws Exception {
System.out.println("prepare ...");
}
/**
* 为ModelDriven返回一个实例
*/
public UserInfo getModel() {
return userInfo;
}
}


在上面的类中,strust会首先执行prepareSaveUserInfo()这样一个方法,为其方法saveUserInfo()准备一个对象,在getModel()的时候用于返回,但是,strust每次都会执行prepare()这个方法,如果想要去掉该方法的执行,需要实现如下的xml配置(修改alwaysInvokePrepare 常量的值即可):

<package name="default" namespace="/" extends="struts-default">

<!-- 配置使用 paramsPrepareParamsStack 作为默认的拦截器栈 -->
<!-- 修改 PrepareInterceptor 拦截器的 alwaysInvokePrepare 属性值为 false -->
<interceptors>
<interceptor-stack name="atguigustack">
<interceptor-ref name="paramsPrepareParamsStack">
<param name="prepare.alwaysInvokePrepare">false</param>
</interceptor-ref>
</interceptor-stack>
</interceptors>

<default-interceptor-ref name="atguigustack"/>

<action name="emp-*"
class="com.atguigu.struts2.app.EmployeeAction"
method="{1}">
<result name="{1}">/emp-{1}.jsp</result>
<result name="success" type="redirectAction">emp-list</result>
</action>

<action name="emp-list"
class="com.atguigu.struts2.app.EmployeeAction"
method="list">
<result name="list">/emp-list.jsp</result>
</action>

</package>


通常我们本不是这样使用的,在页面中,我们通常会这样写这么一个form
<s:textfield name="project.id"></s:textfield>
<s:textfield name="project.name"></s:textfield>
<s:textfield name="project.age"></s:textfield>
就不需要使用上面讲述的两个借口了,更多的情况,我们会传递多个对象过去,那么页面会这样写:
private Collection<Person> persons;

public String savePs(){
for (Person person : persons) {
System.out.println(person.toString());
}
return "hello_world";
}

public Collection<Person> getPersons() {
return persons;
}

public void setPersons(Collection<Person> persons) {
this.persons = persons;
}


而在页面上我们这样写:

<form action="hello-world-default/HelloWordAction_savePs.action"
method="post">
person.id:<input type="text" name="persons[0].id"><br>
person.name:<input type="text" name="persons[0].name"><br>
<br> person.id:<input type="text" name="persons[1].id"><br>
person.name:<input type="text" name="persons[1].name"><br>
<input type="submit" value="提交">
</form>


这样子写好以后呢,当使用下一篇中的类型转换,不管是List还是Collection等,都能轻松转换,无需写额外的代码了...
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: