关于struts2中prepare接口实现数据准备

      之前做过不少的项目,所有的action只实现了一个execute()方法,也用到过Preparable接口,并没注意到它的具体用法。随着项目的需 求的增加,按照以前的方法,每一个功能都需要一个action,这样势必会造成action类的大规模膨胀。所以决定采取action!method的形 式,这样在一个action中可以包含很多方法,减少了action类的数量,也便于维护。

     把crud方法放在一个action类中,就必定会涉及到一些数据准备的事情,所以用Preparable接口就再合适不过了,实现这个接口的 prepare()方法,这个方法会在action类的所有方法执行前执行,另外我们也可以按照它的规则来写一些其它形式的prepare方法,例如 aciton中有一个方法叫input(),那么我们可以实现一个prepareInput方法,这样在input()执行前,会执行 prepareInput()方法。

     好了,言归正传,我们有这样的一个action:

Java代码   收藏代码
  1. package  ht.gisoa.action;  
  2.   
  3. import  ht.gisoa.model.Sysconfig;  
  4. import  ht.gisoa.service.SysconfigManager;  
  5.   
  6. import  java.util.List;  
  7. import  java.util.Map;  
  8.   
  9. import  javax.servlet.http.HttpServletRequest;  
  10.   
  11. import  org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;  
  12.   
  13. import  com.opensymphony.webwork.ServletActionContext;  
  14. import  com.opensymphony.webwork.interceptor.ServletRequestAware;  
  15. import  com.opensymphony.webwork.interceptor.SessionAware;  
  16. import  com.opensymphony.xwork.ActionSupport;  
  17. import  com.opensymphony.xwork.ModelDriven;  
  18. import  com.opensymphony.xwork.Preparable;  
  19. import  com.thoughtworks.xstream.XStream;  
  20.   
  21. public   class  SystemConfigAction  extends  ActionSupport  implements  Preparable,SessionAware,ServletRequestAware,ModelDriven{  
  22.     /**  
  23.      *   
  24.      */    
  25.       
  26.     private  Map session ;  
  27.     private  HttpServletRequest request;  
  28.   
  29.     private  NamedParameterJdbcTemplate namedParameterJdbcTemplate =  null ;  
  30.       
  31.     private  Double hignSpeed =  0.0 ;  
  32.     private  Double midSpeed =  0.0 ;  
  33.     private  Double lowSpeed =  0.0 ;  
  34.       
  35.     private   static   final   long  serialVersionUID = 1L;  
  36.     private  SysconfigManager sysconfigManager =  null ;  
  37.       
  38.       
  39.     private  Long id ;  
  40.     private  Sysconfig entity;  
  41.       
  42.     public   void  setId(Long id) {  
  43.         this .id = id;  
  44.     }  
  45.   
  46.     public  String editSpeed()  throws  Exception{  
  47.         Map<String,Sysconfig> configs = sysconfigManager.getSpeedConfig() ;  
  48.         ServletActionContext.getRequest().setAttribute("configs" , configs);  
  49.         return   this .SUCCESS;  
  50.     }  
  51.       
  52.     public  String input()  throws  Exception{  
  53.         return   "input" ;  
  54.     }  
  55.       
  56.     public  String list(){  
  57.         List<Sysconfig> speedCollection = sysconfigManager.getSpeedList();  
  58.         ServletActionContext.getRequest().setAttribute("speedCollection" , speedCollection);  
  59.         return   "list" ;  
  60.     }  
  61.       
  62.     public  String save()  throws  Exception{  
  63.         sysconfigManager.mergy(entity);  
  64.         return   "reload" ;  
  65.     }  
  66.       
  67.     public  String delete()  throws  Exception{  
  68.         sysconfigManager.delete(id);  
  69.         return   "reload" ;  
  70.     }  
  71.       
  72.     public  SysconfigManager getSysconfigManager() {  
  73.         return  sysconfigManager;  
  74.     }  
  75.     public   void  setSysconfigManager(SysconfigManager sysconfigManager) {  
  76.         this .sysconfigManager = sysconfigManager;  
  77.     }  
  78.   
  79.     public  Double getHignSpeed() {  
  80.         return  hignSpeed;  
  81.     }  
  82.   
  83.     public   void  setHignSpeed(Double hignSpeed) {  
  84.         this .hignSpeed = hignSpeed;  
  85.     }  
  86.   
  87.     public  Double getMidSpeed() {  
  88.         return  midSpeed;  
  89.     }  
  90.   
  91.     public   void  setMidSpeed(Double midSpeed) {  
  92.         this .midSpeed = midSpeed;  
  93.     }  
  94.   
  95.     public  Double getLowSpeed() {  
  96.         return  lowSpeed;  
  97.     }  
  98.   
  99.     public   void  setLowSpeed(Double lowSpeed) {  
  100.         this .lowSpeed = lowSpeed;  
  101.     }  
  102.   
  103.     public   void  setSession(Map session) {  
  104.         this .session = session;  
  105.     }  
  106.   
  107.     public   void  setServletRequest(HttpServletRequest request) {  
  108.         this .request = request;  
  109.     }  
  110.   
  111.     public   void  prepare()  throws  Exception {  
  112.           
  113.     }  
  114.       
  115.     public   void  prepareModel()  throws  Exception {  
  116.         if  (id== null ){  
  117.             System.out.println("id=null" );  
  118.             entity = new  Sysconfig();  
  119.             entity.setKeyType(1L);  
  120.         }else {  
  121.             System.out.println("id==" +id);  
  122.             entity = sysconfigManager.get(id);  
  123.         }  
  124.     }  
  125.       
  126.     public   void  prepareInput()  throws  Exception{  
  127.         prepareModel();  
  128.     }  
  129.     public   void  prepareSave()  throws  Exception {  
  130.         prepareModel();  
  131.     }  
  132.       
  133.     public  Object getModel() {  
  134.         return  entity;  
  135.     }  
  136. }  

这里要注意,要在spring中配置该action的作用域为prototype,否则,不同的方法之间会出现数据混乱的情况:

Xml代码   收藏代码
  1. < bean   id = "systemconfig"   
  2.  class = "ht.gisoa.action.SystemConfigAction"   scope = "prototype" >   
  3.  < property   name = "sysconfigManager" >   
  4.   < ref   bean = "SysconfigManager"   />   
  5.  </ property >   
  6. </ bean >   

sysconfig_input.jsp代码如下:

Jsp代码   收藏代码
  1. <%@ page language= "java"  pageEncoding= "UTF-8"  isELIgnored= "false" %>  
  2. <%@ taglib uri="http://java.sun.com/jstl/core_rt"  prefix= "c" %>  
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"   "http://www.w3.org/TR/html4/loose.dtd" >  
  4. <html>  
  5. <head>  
  6. <meta http-equiv="Content-Type"  content= "text/html; charset=UTF-8" >  
  7.   
  8. </head>  
  9. <body>  
  10. <div id="msg" >  
  11. ${msg}  
  12. </div>  
  13. <c:choose><c:when test="${ param.id == null}" >创建</c:when><c:otherwise>修改</c:otherwise></c:choose>设置  
  14. <div id="main" >  
  15. <form action="systemconfig!save.action" >  
  16.     <input type="text"  name= "model.keyName"  value= "${model.keyName}" /><br>  
  17.     <input type="text"  name= "model.keyValue"   value= "${model.keyValue}" /><br>  
  18.     <input type="hidden"  name= "model.id"   value= "${model.id}" /><br>  
  19.     <input type="hidden"  name= "model.keyType"   value= "1" /><br>  
  20.     <input type="submit"  value= "修改" />  
  21. </form>     
  22. </div>  
  23. <c:remove var="msg"  scope= "session" />  
  24. </body>  
  25. </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中相关配置如下:

Xml代码   收藏代码
  1. < action   name = "systemconfig"   class = "systemconfig" >   
  2.     < result   name = "list"   type = "dispatcher" >   
  3.         < param   name = "location" > syscfg_speed_list.jsp </ param >   
  4.     </ result >   
  5.     < result   name = "reload"   type = "redirect" >   
  6.         < param   name = "location" > systemconfig!list.action </ param >   
  7.     </ result >   
  8.     < result   name = "input"   type = "dispatcher" >   
  9.         < param   name = "location" > syscfg_speed_input.jsp </ param >   
  10.     </ result >   
  11.     < interceptor-ref   name = "paramsPrepareParamsStack"   />   
  12.     < interceptor-ref   name = "modelParamsStack" > </ interceptor-ref >   
  13. </ action >    

通过paramsPrepareParamsStack可以让流程更明确,代码更简洁,也更利于大家的交流。

      之前做过不少的项目,所有的action只实现了一个execute()方法,也用到过Preparable接口,并没注意到它的具体用法。随着项目的需 求的增加,按照以前的方法,每一个功能都需要一个action,这样势必会造成action类的大规模膨胀。所以决定采取action!method的形 式,这样在一个action中可以包含很多方法,减少了action类的数量,也便于维护。

     把crud方法放在一个action类中,就必定会涉及到一些数据准备的事情,所以用Preparable接口就再合适不过了,实现这个接口的 prepare()方法,这个方法会在action类的所有方法执行前执行,另外我们也可以按照它的规则来写一些其它形式的prepare方法,例如 aciton中有一个方法叫input(),那么我们可以实现一个prepareInput方法,这样在input()执行前,会执行 prepareInput()方法。

     好了,言归正传,我们有这样的一个action:

Java代码   收藏代码
  1. package  ht.gisoa.action;  
  2.   
  3. import  ht.gisoa.model.Sysconfig;  
  4. import  ht.gisoa.service.SysconfigManager;  
  5.   
  6. import  java.util.List;  
  7. import  java.util.Map;  
  8.   
  9. import  javax.servlet.http.HttpServletRequest;  
  10.   
  11. import  org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;  
  12.   
  13. import  com.opensymphony.webwork.ServletActionContext;  
  14. import  com.opensymphony.webwork.interceptor.ServletRequestAware;  
  15. import  com.opensymphony.webwork.interceptor.SessionAware;  
  16. import  com.opensymphony.xwork.ActionSupport;  
  17. import  com.opensymphony.xwork.ModelDriven;  
  18. import  com.opensymphony.xwork.Preparable;  
  19. import  com.thoughtworks.xstream.XStream;  
  20.   
  21. public   class  SystemConfigAction  extends  ActionSupport  implements  Preparable,SessionAware,ServletRequestAware,ModelDriven{  
  22.     /**  
  23.      *   
  24.      */    
  25.       
  26.     private  Map session ;  
  27.     private  HttpServletRequest request;  
  28.   
  29.     private  NamedParameterJdbcTemplate namedParameterJdbcTemplate =  null ;  
  30.       
  31.     private  Double hignSpeed =  0.0 ;  
  32.     private  Double midSpeed =  0.0 ;  
  33.     private  Double lowSpeed =  0.0 ;  
  34.       
  35.     private   static   final   long  serialVersionUID = 1L;  
  36.     private  SysconfigManager sysconfigManager =  null ;  
  37.       
  38.       
  39.     private  Long id ;  
  40.     private  Sysconfig entity;  
  41.       
  42.     public   void  setId(Long id) {  
  43.         this .id = id;  
  44.     }  
  45.   
  46.     public  String editSpeed()  throws  Exception{  
  47.         Map<String,Sysconfig> configs = sysconfigManager.getSpeedConfig() ;  
  48.         ServletActionContext.getRequest().setAttribute("configs" , configs);  
  49.         return   this .SUCCESS;  
  50.     }  
  51.       
  52.     public  String input()  throws  Exception{  
  53.         return   "input" ;  
  54.     }  
  55.       
  56.     public  String list(){  
  57.         List<Sysconfig> speedCollection = sysconfigManager.getSpeedList();  
  58.         ServletActionContext.getRequest().setAttribute("speedCollection" , speedCollection);  
  59.         return   "list" ;  
  60.     }  
  61.       
  62.     public  String save()  throws  Exception{  
  63.         sysconfigManager.mergy(entity);  
  64.         return   "reload" ;  
  65.     }  
  66.       
  67.     public  String delete()  throws  Exception{  
  68.         sysconfigManager.delete(id);  
  69.         return   "reload" ;  
  70.     }  
  71.       
  72.     public  SysconfigManager getSysconfigManager() {  
  73.         return  sysconfigManager;  
  74.     }  
  75.     public   void  setSysconfigManager(SysconfigManager sysconfigManager) {  
  76.         this .sysconfigManager = sysconfigManager;  
  77.     }  
  78.   
  79.     public  Double getHignSpeed() {  
  80.         return  hignSpeed;  
  81.     }  
  82.   
  83.     public   void  setHignSpeed(Double hignSpeed) {  
  84.         this .hignSpeed = hignSpeed;  
  85.     }  
  86.   
  87.     public  Double getMidSpeed() {  
  88.         return  midSpeed;  
  89.     }  
  90.   
  91.     public   void  setMidSpeed(Double midSpeed) {  
  92.         this .midSpeed = midSpeed;  
  93.     }  
  94.   
  95.     public  Double getLowSpeed() {  
  96.         return  lowSpeed;  
  97.     }  
  98.   
  99.     public   void  setLowSpeed(Double lowSpeed) {  
  100.         this .lowSpeed = lowSpeed;  
  101.     }  
  102.   
  103.     public   void  setSession(Map session) {  
  104.         this .session = session;  
  105.     }  
  106.   
  107.     public   void  setServletRequest(HttpServletRequest request) {  
  108.         this .request = request;  
  109.     }  
  110.   
  111.     public   void  prepare()  throws  Exception {  
  112.           
  113.     }  
  114.       
  115.     public   void  prepareModel()  throws  Exception {  
  116.         if  (id== null ){  
  117.             System.out.println("id=null" );  
  118.             entity = new  Sysconfig();  
  119.             entity.setKeyType(1L);  
  120.         }else {  
  121.             System.out.println("id==" +id);  
  122.             entity = sysconfigManager.get(id);  
  123.         }  
  124.     }  
  125.       
  126.     public   void  prepareInput()  throws  Exception{  
  127.         prepareModel();  
  128.     }  
  129.     public   void  prepareSave()  throws  Exception {  
  130.         prepareModel();  
  131.     }  
  132.       
  133.     public  Object getModel() {  
  134.         return  entity;  
  135.     }  
  136. }  

这里要注意,要在spring中配置该action的作用域为prototype,否则,不同的方法之间会出现数据混乱的情况:

Xml代码   收藏代码
  1. < bean   id = "systemconfig"   
  2.  class = "ht.gisoa.action.SystemConfigAction"   scope = "prototype" >   
  3.  < property   name = "sysconfigManager" >   
  4.   < ref   bean = "SysconfigManager"   />   
  5.  </ property >   
  6. </ bean >   

sysconfig_input.jsp代码如下:

Jsp代码   收藏代码
  1. <%@ page language= "java"  pageEncoding= "UTF-8"  isELIgnored= "false" %>  
  2. <%@ taglib uri="http://java.sun.com/jstl/core_rt"  prefix= "c" %>  
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"   "http://www.w3.org/TR/html4/loose.dtd" >  
  4. <html>  
  5. <head>  
  6. <meta http-equiv="Content-Type"  content= "text/html; charset=UTF-8" >  
  7.   
  8. </head>  
  9. <body>  
  10. <div id="msg" >  
  11. ${msg}  
  12. </div>  
  13. <c:choose><c:when test="${ param.id == null}" >创建</c:when><c:otherwise>修改</c:otherwise></c:choose>设置  
  14. <div id="main" >  
  15. <form action="systemconfig!save.action" >  
  16.     <input type="text"  name= "model.keyName"  value= "${model.keyName}" /><br>  
  17.     <input type="text"  name= "model.keyValue"   value= "${model.keyValue}" /><br>  
  18.     <input type="hidden"  name= "model.id"   value= "${model.id}" /><br>  
  19.     <input type="hidden"  name= "model.keyType"   value= "1" /><br>  
  20.     <input type="submit"  value= "修改" />  
  21. </form>     
  22. </div>  
  23. <c:remove var="msg"  scope= "session" />  
  24. </body>  
  25. </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中相关配置如下:

Xml代码   收藏代码
  1. < action   name = "systemconfig"   class = "systemconfig" >   
  2.     < result   name = "list"   type = "dispatcher" >   
  3.         < param   name = "location" > syscfg_speed_list.jsp </ param >   
  4.     </ result >   
  5.     < result   name = "reload"   type = "redirect" >   
  6.         < param   name = "location" > systemconfig!list.action </ param >   
  7.     </ result >   
  8.     < result   name = "input"   type = "dispatcher" >   
  9.         < param   name = "location" > syscfg_speed_input.jsp </ param >   
  10.     </ result >   
  11.     < interceptor-ref   name = "paramsPrepareParamsStack"   />   
  12.     < interceptor-ref   name = "modelParamsStack" > </ interceptor-ref >   
  13. </ action >    

通过paramsPrepareParamsStack可以让流程更明确,代码更简洁,也更利于大家的交流。

猜你喜欢

转载自88548886.iteye.com/blog/1545908