之前做过不少的项目,所有的action只实现了一个execute()方法,也用到过Preparable接口,并没注意到它的具体用法。随着项目的需 求的增加,按照以前的方法,每一个功能都需要一个action,这样势必会造成action类的大规模膨胀。所以决定采取action!method的形 式,这样在一个action中可以包含很多方法,减少了action类的数量,也便于维护。
把crud方法放在一个action类中,就必定会涉及到一些数据准备的事情,所以用Preparable接口就再合适不过了,实现这个接口的 prepare()方法,这个方法会在action类的所有方法执行前执行,另外我们也可以按照它的规则来写一些其它形式的prepare方法,例如 aciton中有一个方法叫input(),那么我们可以实现一个prepareInput方法,这样在input()执行前,会执行 prepareInput()方法。
好了,言归正传,我们有这样的一个action:
- package ht.gisoa.action;
- import ht.gisoa.model.Sysconfig;
- import ht.gisoa.service.SysconfigManager;
- import java.util.List;
- import java.util.Map;
- import javax.servlet.http.HttpServletRequest;
- import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
- import com.opensymphony.webwork.ServletActionContext;
- import com.opensymphony.webwork.interceptor.ServletRequestAware;
- import com.opensymphony.webwork.interceptor.SessionAware;
- import com.opensymphony.xwork.ActionSupport;
- import com.opensymphony.xwork.ModelDriven;
- import com.opensymphony.xwork.Preparable;
- import com.thoughtworks.xstream.XStream;
- public class SystemConfigAction extends ActionSupport implements Preparable,SessionAware,ServletRequestAware,ModelDriven{
- /**
- *
- */
- private Map session ;
- private HttpServletRequest request;
- private NamedParameterJdbcTemplate namedParameterJdbcTemplate = null ;
- private Double hignSpeed = 0.0 ;
- private Double midSpeed = 0.0 ;
- private Double lowSpeed = 0.0 ;
- private static final long serialVersionUID = 1L;
- private SysconfigManager sysconfigManager = null ;
- private Long id ;
- private Sysconfig entity;
- public void setId(Long id) {
- this .id = id;
- }
- public String editSpeed() throws Exception{
- Map<String,Sysconfig> configs = sysconfigManager.getSpeedConfig() ;
- ServletActionContext.getRequest().setAttribute("configs" , configs);
- return this .SUCCESS;
- }
- public String input() throws Exception{
- return "input" ;
- }
- public String list(){
- List<Sysconfig> speedCollection = sysconfigManager.getSpeedList();
- ServletActionContext.getRequest().setAttribute("speedCollection" , speedCollection);
- return "list" ;
- }
- public String save() throws Exception{
- sysconfigManager.mergy(entity);
- return "reload" ;
- }
- public String delete() throws Exception{
- sysconfigManager.delete(id);
- return "reload" ;
- }
- public SysconfigManager getSysconfigManager() {
- return sysconfigManager;
- }
- public void setSysconfigManager(SysconfigManager sysconfigManager) {
- this .sysconfigManager = sysconfigManager;
- }
- public Double getHignSpeed() {
- return hignSpeed;
- }
- public void setHignSpeed(Double hignSpeed) {
- this .hignSpeed = hignSpeed;
- }
- public Double getMidSpeed() {
- return midSpeed;
- }
- public void setMidSpeed(Double midSpeed) {
- this .midSpeed = midSpeed;
- }
- public Double getLowSpeed() {
- return lowSpeed;
- }
- public void setLowSpeed(Double lowSpeed) {
- this .lowSpeed = lowSpeed;
- }
- public void setSession(Map session) {
- this .session = session;
- }
- public void setServletRequest(HttpServletRequest request) {
- this .request = request;
- }
- public void prepare() throws Exception {
- }
- public void prepareModel() throws Exception {
- if (id== null ){
- System.out.println("id=null" );
- entity = new Sysconfig();
- entity.setKeyType(1L);
- }else {
- System.out.println("id==" +id);
- entity = sysconfigManager.get(id);
- }
- }
- public void prepareInput() throws Exception{
- prepareModel();
- }
- public void prepareSave() throws Exception {
- prepareModel();
- }
- public Object getModel() {
- return entity;
- }
- }
这里要注意,要在spring中配置该action的作用域为prototype,否则,不同的方法之间会出现数据混乱的情况:
- < bean id = "systemconfig"
- class = "ht.gisoa.action.SystemConfigAction" scope = "prototype" >
- < property name = "sysconfigManager" >
- < ref bean = "SysconfigManager" />
- </ property >
- </ bean >
sysconfig_input.jsp代码如下:
- <%@ page language= "java" pageEncoding= "UTF-8" isELIgnored= "false" %>
- <%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix= "c" %>
- <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" >
- <html>
- <head>
- <meta http-equiv="Content-Type" content= "text/html; charset=UTF-8" >
- </head>
- <body>
- <div id="msg" >
- ${msg}
- </div>
- <c:choose><c:when test="${ param.id == null}" >创建</c:when><c:otherwise>修改</c:otherwise></c:choose>设置
- <div id="main" >
- <form action="systemconfig!save.action" >
- <input type="text" name= "model.keyName" value= "${model.keyName}" /><br>
- <input type="text" name= "model.keyValue" value= "${model.keyValue}" /><br>
- <input type="hidden" name= "model.id" value= "${model.id}" /><br>
- <input type="hidden" name= "model.keyType" value= "1" /><br>
- <input type="submit" value= "修改" />
- </form>
- </div>
- <c:remove var="msg" scope= "session" />
- </body>
- </html>
我们编辑完信息,提交后,会执行action中的save方法,按道理,表单提交后,会将action中的model填充好数据,但是save方法 之前又会执行prepareSave方法,从数据库里获取一次数据,这样不就把之前填充好的数据冲掉了吗?仔细想想也确实是这样的.
那么该如何解决这种矛盾呢,立即使出google大法,查了一下关于interceptor的资料,有这样的一个 interceptor:paramsPrepareParamsStack,paramsPrepareParamsStack主要解决了 ModelDriven和Preparable的配合问题,从字面上理解来说,这个stack的拦截器调用的顺序为:首先params,然后 prepare,接下来modelDriven,最后再params。Struts 2.0的设计上要求modelDriven在params之前调用,而业务中prepare要负责准备model,准备model又需要参数,这就需要在 prepare之前运行params拦截器设置相关参数,这个也就是创建paramsPrepareParamsStack的原因。流程如下:
1. params拦截器首先给action中的相关参数赋值,如id
2. prepare拦截器执行prepare方法,prepare方法中会根据参数,如id,去调用业务逻辑,设置model对象
3. modelDriven拦截器将model对象压入value stack,这里的model对象就是在prepare中创建的
4. params拦截器再将参数赋值给model对象
5. action的业务逻辑执行
我的xwork.xml中相关配置如下:
- < action name = "systemconfig" class = "systemconfig" >
- < result name = "list" type = "dispatcher" >
- < param name = "location" > syscfg_speed_list.jsp </ param >
- </ result >
- < result name = "reload" type = "redirect" >
- < param name = "location" > systemconfig!list.action </ param >
- </ result >
- < result name = "input" type = "dispatcher" >
- < param name = "location" > syscfg_speed_input.jsp </ param >
- </ result >
- < interceptor-ref name = "paramsPrepareParamsStack" />
- < interceptor-ref name = "modelParamsStack" > </ interceptor-ref >
- </ action >
通过paramsPrepareParamsStack可以让流程更明确,代码更简洁,也更利于大家的交流。
之前做过不少的项目,所有的action只实现了一个execute()方法,也用到过Preparable接口,并没注意到它的具体用法。随着项目的需 求的增加,按照以前的方法,每一个功能都需要一个action,这样势必会造成action类的大规模膨胀。所以决定采取action!method的形 式,这样在一个action中可以包含很多方法,减少了action类的数量,也便于维护。
把crud方法放在一个action类中,就必定会涉及到一些数据准备的事情,所以用Preparable接口就再合适不过了,实现这个接口的 prepare()方法,这个方法会在action类的所有方法执行前执行,另外我们也可以按照它的规则来写一些其它形式的prepare方法,例如 aciton中有一个方法叫input(),那么我们可以实现一个prepareInput方法,这样在input()执行前,会执行 prepareInput()方法。
好了,言归正传,我们有这样的一个action:
- package ht.gisoa.action;
- import ht.gisoa.model.Sysconfig;
- import ht.gisoa.service.SysconfigManager;
- import java.util.List;
- import java.util.Map;
- import javax.servlet.http.HttpServletRequest;
- import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
- import com.opensymphony.webwork.ServletActionContext;
- import com.opensymphony.webwork.interceptor.ServletRequestAware;
- import com.opensymphony.webwork.interceptor.SessionAware;
- import com.opensymphony.xwork.ActionSupport;
- import com.opensymphony.xwork.ModelDriven;
- import com.opensymphony.xwork.Preparable;
- import com.thoughtworks.xstream.XStream;
- public class SystemConfigAction extends ActionSupport implements Preparable,SessionAware,ServletRequestAware,ModelDriven{
- /**
- *
- */
- private Map session ;
- private HttpServletRequest request;
- private NamedParameterJdbcTemplate namedParameterJdbcTemplate = null ;
- private Double hignSpeed = 0.0 ;
- private Double midSpeed = 0.0 ;
- private Double lowSpeed = 0.0 ;
- private static final long serialVersionUID = 1L;
- private SysconfigManager sysconfigManager = null ;
- private Long id ;
- private Sysconfig entity;
- public void setId(Long id) {
- this .id = id;
- }
- public String editSpeed() throws Exception{
- Map<String,Sysconfig> configs = sysconfigManager.getSpeedConfig() ;
- ServletActionContext.getRequest().setAttribute("configs" , configs);
- return this .SUCCESS;
- }
- public String input() throws Exception{
- return "input" ;
- }
- public String list(){
- List<Sysconfig> speedCollection = sysconfigManager.getSpeedList();
- ServletActionContext.getRequest().setAttribute("speedCollection" , speedCollection);
- return "list" ;
- }
- public String save() throws Exception{
- sysconfigManager.mergy(entity);
- return "reload" ;
- }
- public String delete() throws Exception{
- sysconfigManager.delete(id);
- return "reload" ;
- }
- public SysconfigManager getSysconfigManager() {
- return sysconfigManager;
- }
- public void setSysconfigManager(SysconfigManager sysconfigManager) {
- this .sysconfigManager = sysconfigManager;
- }
- public Double getHignSpeed() {
- return hignSpeed;
- }
- public void setHignSpeed(Double hignSpeed) {
- this .hignSpeed = hignSpeed;
- }
- public Double getMidSpeed() {
- return midSpeed;
- }
- public void setMidSpeed(Double midSpeed) {
- this .midSpeed = midSpeed;
- }
- public Double getLowSpeed() {
- return lowSpeed;
- }
- public void setLowSpeed(Double lowSpeed) {
- this .lowSpeed = lowSpeed;
- }
- public void setSession(Map session) {
- this .session = session;
- }
- public void setServletRequest(HttpServletRequest request) {
- this .request = request;
- }
- public void prepare() throws Exception {
- }
- public void prepareModel() throws Exception {
- if (id== null ){
- System.out.println("id=null" );
- entity = new Sysconfig();
- entity.setKeyType(1L);
- }else {
- System.out.println("id==" +id);
- entity = sysconfigManager.get(id);
- }
- }
- public void prepareInput() throws Exception{
- prepareModel();
- }
- public void prepareSave() throws Exception {
- prepareModel();
- }
- public Object getModel() {
- return entity;
- }
- }
这里要注意,要在spring中配置该action的作用域为prototype,否则,不同的方法之间会出现数据混乱的情况:
- < bean id = "systemconfig"
- class = "ht.gisoa.action.SystemConfigAction" scope = "prototype" >
- < property name = "sysconfigManager" >
- < ref bean = "SysconfigManager" />
- </ property >
- </ bean >
sysconfig_input.jsp代码如下:
- <%@ page language= "java" pageEncoding= "UTF-8" isELIgnored= "false" %>
- <%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix= "c" %>
- <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" >
- <html>
- <head>
- <meta http-equiv="Content-Type" content= "text/html; charset=UTF-8" >
- </head>
- <body>
- <div id="msg" >
- ${msg}
- </div>
- <c:choose><c:when test="${ param.id == null}" >创建</c:when><c:otherwise>修改</c:otherwise></c:choose>设置
- <div id="main" >
- <form action="systemconfig!save.action" >
- <input type="text" name= "model.keyName" value= "${model.keyName}" /><br>
- <input type="text" name= "model.keyValue" value= "${model.keyValue}" /><br>
- <input type="hidden" name= "model.id" value= "${model.id}" /><br>
- <input type="hidden" name= "model.keyType" value= "1" /><br>
- <input type="submit" value= "修改" />
- </form>
- </div>
- <c:remove var="msg" scope= "session" />
- </body>
- </html>
我们编辑完信息,提交后,会执行action中的save方法,按道理,表单提交后,会将action中的model填充好数据,但是save方法 之前又会执行prepareSave方法,从数据库里获取一次数据,这样不就把之前填充好的数据冲掉了吗?仔细想想也确实是这样的.
那么该如何解决这种矛盾呢,立即使出google大法,查了一下关于interceptor的资料,有这样的一个 interceptor:paramsPrepareParamsStack,paramsPrepareParamsStack主要解决了 ModelDriven和Preparable的配合问题,从字面上理解来说,这个stack的拦截器调用的顺序为:首先params,然后 prepare,接下来modelDriven,最后再params。Struts 2.0的设计上要求modelDriven在params之前调用,而业务中prepare要负责准备model,准备model又需要参数,这就需要在 prepare之前运行params拦截器设置相关参数,这个也就是创建paramsPrepareParamsStack的原因。流程如下:
1. params拦截器首先给action中的相关参数赋值,如id
2. prepare拦截器执行prepare方法,prepare方法中会根据参数,如id,去调用业务逻辑,设置model对象
3. modelDriven拦截器将model对象压入value stack,这里的model对象就是在prepare中创建的
4. params拦截器再将参数赋值给model对象
5. action的业务逻辑执行
我的xwork.xml中相关配置如下:
- < action name = "systemconfig" class = "systemconfig" >
- < result name = "list" type = "dispatcher" >
- < param name = "location" > syscfg_speed_list.jsp </ param >
- </ result >
- < result name = "reload" type = "redirect" >
- < param name = "location" > systemconfig!list.action </ param >
- </ result >
- < result name = "input" type = "dispatcher" >
- < param name = "location" > syscfg_speed_input.jsp </ param >
- </ result >
- < interceptor-ref name = "paramsPrepareParamsStack" />
- < interceptor-ref name = "modelParamsStack" > </ interceptor-ref >
- </ action >
通过paramsPrepareParamsStack可以让流程更明确,代码更简洁,也更利于大家的交流。