论坛首页 Java企业应用论坛

webwork与orm结合时,参数绑定的方法

浏览 12788 次
该帖已经被评为良好帖
作者 正文
   发表时间:2007-06-12   最后修改:2009-08-01
问题1.从客户端传来的id,需要转化成持久化对象,webwork默认会为我们创建出空对象,但不满足,希望webwork能按照id值绑定持久化对象.
解决办法:创建自己的转化器
    1.创建xwork-conversion.properties,内容如下
            
com.abest.common.domain.CommonEntity=com.abest.common.EntityWebworkConverter

其中CommonEntity为所有持久化实体类的超类,更详细的资料见:
http://wiki.opensymphony.com/display/XW/XWork+Conversion

    2.实现自定义转换器
public class EntityWebworkConverter extends WebWorkTypeConverter {

    public static EntityWebworkConverterDelegate delegate = null;

    public EntityWebworkConverter() {
    }

    public Object convertFromString(Map map, String[] strings, Class toClass) {
        return delegate.convertFromString(map,strings,toClass);
    }

    public String convertToString(Map map, Object o) {
        return delegate.convertToString(map,o);
    }
}



public class EntityWebworkConverterDelegate extends WebWorkTypeConverter {

    private QueryService queryService = null;

    public EntityWebworkConverterDelegate(QueryService queryService) {
        this.queryService = queryService;
    }


    public Object convertFromString(Map map, String[] strings, Class toClass) {
        if(strings.length > 0)
        {
            int id = 0;
            try {
                id = Integer.parseInt(strings[0]);
            } catch (NumberFormatException e) {
            }
            if(id > 0)
            {
                return queryService.find(toClass,id);
            }
        }

        try {
            return toClass.newInstance();
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    public void setQueryService(QueryService queryService) {
        this.queryService = queryService;
    }


    public String convertToString(Map map, Object o) {
        return null;
    }
}


在这里,因为不了解webwork有什么合适的机制对converter的创建进行控制,因此,converter使用静态属性delegate,该属性由ServletContextListener来注入

这样便可完成参数的绑定了,页面传的参数形式,譬如 foo.bar=1即可

问题2:如何绑定到列表
1.使用java5泛型,xwork..-tiger.jar
2.客户端参数形式changedList[0].id=1,changedList[0].name=name,changedList[1].id=2,changedList[1].name=name2
3.预load对象,以使得其它属性能正确的绑定到对象中.处理逻辑为"先过滤出id,对起进行参数绑定,之后,再交由webwork自带的参数拦截器去绑定其它的参数",拦截器代码如下(保留使用原有的params拦截器):

public class AnotherGridEditDataBindInterceptor extends AroundInterceptor {
    protected void after(ActionInvocation actionInvocation, String s) throws Exception {

    }

    protected void before(ActionInvocation actionInvocation) throws Exception {
        Object action = actionInvocation.getAction();
        Map map = actionInvocation.getInvocationContext().getParameters();
        Map entityIdMap = new HashMap();
        for(int i = 0;i < 200;i++)
        {
            String key = "changedList[" + i + "].id";
            String[] ids = (String[]) map.get(key);
            if(ids != null && ids.length > 0)
            {
                entityIdMap.put("changedList["+i+"]",ids);
                map.remove(key);
            }
        }
        for(int i = 0;i < 200;i++)
        {
            String key = "newList[" + i + "].id";
            String[] ids = (String[]) map.get(key);
            if(ids != null && ids.length > 0)
            {
                entityIdMap.put("newList["+i+"]",ids);
                map.remove(key);
            }
        }
        bindParametersToTarget(entityIdMap,action);

    }



    private void bindParametersToTarget(Map propertiesValue, Object target) {
        ActionContext invocationContext = ActionContext.getContext();
        OgnlValueStack stack = null;
        Object preRoot = null;
        try {
            invocationContext.put(InstantiatingNullHandler.CREATE_NULL_OBJECTS, Boolean.TRUE);
            invocationContext.put(XWorkMethodAccessor.DENY_METHOD_EXECUTION, Boolean.TRUE);
            invocationContext.put(XWorkConverter.REPORT_CONVERSION_ERRORS, Boolean.TRUE);

            if (propertiesValue != null) {
                stack = ActionContext.getContext().getValueStack();
                preRoot = stack.pop();
                stack.push(target);

                for (Iterator iterator = propertiesValue.entrySet().iterator();
                     iterator.hasNext();) {
                    Map.Entry entry = (Map.Entry) iterator.next();
                    stack.setValue(entry.getKey().toString(), entry.getValue());
                }
            }
        } finally {
            invocationContext.put(InstantiatingNullHandler.CREATE_NULL_OBJECTS, Boolean.FALSE);
            invocationContext.put(XWorkMethodAccessor.DENY_METHOD_EXECUTION, Boolean.FALSE);
            invocationContext.put(XWorkConverter.REPORT_CONVERSION_ERRORS, Boolean.FALSE);
            if (preRoot != null) {
                stack.pop();
                stack.push(preRoot);
            }
        }
    }


}


其中,changedList表示的是修改过的对象,newList表示的是新增的对象

总结:需要建立Xwork的Converter,Interceptor。servlet的ServletContextListener为converter注入orm的持久对象查找方法;orm提供find(class,id)这样的方法



  
   发表时间:2007-06-12  
好方法!提供了我另外一个思路。

我以前一直是用拦截器+特殊命名规范来做的。比如,我规定,需要绑定持久化对象的命名必须以#结尾:foo.bar#=1。由于默认的params拦截器会把带有#符号的命名过滤掉,所以这些命名正好可以进入我自己的拦截器,截断以后拼上id,再load出来。

如果用Spring的话,我直接使用WebApplicationContextUtils中的静态方法来getBean获取Service,ServletContext则直接ServletActionContext.getServletContext()得到。其实你这里如果用Spring,也可以采取这种方式,应该不需要那个static的delegate了。
0 请登录后投票
   发表时间:2007-06-12  
能不能把你的代码贴全啊.包括配置文件,以及那些用ServletContextListener注入的代码
0 请登录后投票
   发表时间:2007-06-14  
这个一般我是用ModelDriven(在params之前)了,getModel中去判断有id则取,否则新建实例,用ModelDriven好在validation/i18n都一并绑定了,
多个对象的情况是通过一个ModelSetable对象对多个对象的引用来实现的,也是在getModel中拿,通过action上的范型声明是否为ModelSetable判断,参数传递跟你的类似,不过是keys数组与modelSet.models数组的参数传递,如keys[0]=1,modelSet.models[0].name=1,
keys[1]=2,modelSet.models[1].name=2
0 请登录后投票
   发表时间:2007-06-26  
如果是Webwork2和Spring结合的话,可以把Converter直接配置到spring里面,转换的时候Webwork会取到这个Bean,名字为“com.abest.common.EntityWebworkConverter”
0 请登录后投票
   发表时间:2007-06-26  
/*
 * DocumentConventor.java
 *
 * Created on 2007?1?3?, ??11:15
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package edirectory.web.converter;

import com.opensymphony.webwork.util.WebWorkTypeConverter;
import edirectory.persistence.Document;
import edirectory.service.DocumentManager;
import java.util.Map;
import org.springframework.web.context.WebApplicationContext;

/**
 *
 * @author linqing
 */
public class DocumentConverter extends WebWorkTypeConverter {
    private DocumentManager documentManager;
    public String convertToString(Map context, Object o) {
            return ((Document)o).getId().toString();
    }

    public Object convertFromString(Map context, String[] values, Class toClass) {
        if(values[0].equals("") ) {
            return null;
        }
        Long id = Long.parseLong(values[0]);
        return documentManager.find(toClass, id);
    }

    public DocumentManager getDocumentManager() {
        return documentManager;
    }

    public void setDocumentManager(DocumentManager documentManager) {
        this.documentManager = documentManager;
    }
}
0 请登录后投票
   发表时间:2007-06-26  
    <!-- Services -->
    <bean id="documentManager"
          class="edirectory.service.impl.JpaDocumentManager"
          scope="singleton"
          autowire="byName" />
    <!-- Converters -->
    <bean id="edirectory.web.converter.DocumentConverter"
          class="edirectory.web.converter.DocumentConverter"
          scope="singleton"
          autowire="byName" />
  • 描述: 一个通用的EntityManager,整个系统是配置出来的
  • 大小: 160.5 KB
0 请登录后投票
   发表时间:2007-06-28  
我最近也在思考这个问题,之前在struts 1.3.8里面都是这样做的:
struts-config.xml 表单配置:
xml 代码
 
  1. <form-bean name="projectForm"  
  2.     type="org.apache.struts.validator.LazyValidatorForm">  
  3. </form-bean>  

struts-config.xml action-mapping配置:
xml 代码
 
  1. <action path="/project"  
  2.     type="com.bupticet.strutsinterceptor.InterceptorActionProxy"  
  3.     name="projectForm" parameter="method" scope="request"  
  4.     validate="false" cancellable="true">  
  5.     <forward name="add-success" path="/add_project.jsp" />  
  6.     <forward name="save-success"  
  7.         path="/project.do?method=view&amp;id=" redirect="true" />  
  8.     <forward name="save-cancel" path="/project.do"  
  9.         redirect="true" />  
  10.     <forward name="save-failure" path="/add_project.jsp" />  
  11.     <forward name="edit-success" path="/edit_project.jsp" />  
  12.     <forward name="view-success" path="/view_project.jsp" />  
  13.     <forward name="list-success" path="/list_project.jsp" />  
  14.     <forward name="update-failure" path="/edit_project.jsp" />  
  15.     <forward name="update-cancel" path="/project.do"  
  16.         redirect="true" />  
  17.     <forward name="update-success"  
  18.         path="/project.do?method=view&amp;id=" redirect="true" />  
  19.     <forward name="delete-success" path="/project.do?method=list" redirect="true"/>  
  20.     <forward name="search-page" path="/search_project.jsp"/>  
  21. </action>  


页面表单:
xml 代码
 
  1. <html:form action="/project?method=save" method="post">  
  2.     <tr>  
  3.         <td width='10%' nowrap class="boxHead">项目名称:</td>  
  4.         <td background="../images/leftbg2.gif"><html:text property="name" size='100' maxlength='100'/></td>  
  5.     </tr>  
  6.   
  7.     <tr>  
  8.         <td width='10%' nowrap class="boxHead">项目编号:</td>  
  9.         <td background="../images/leftbg2.gif"><html:text property="projectNo" size='50' maxlength='60'/></td>  
  10.     </tr>  
  11.   
  12.     <tr>  
  13.         <td width='10%' nowrap class="boxHead">项目类别:</td>  
  14.         <td background="../images/leftbg2.gif"><html:text property="sort" size='50' maxlength='60'/>  
  15.          <%  
  16.        String[] allExistSorts = com.bupticet.research.web.collection.ProjectCollection.getExistSorts();  
  17.         if(allExistSorts.length>0){  
  18.             pageContext.setAttribute("allExistSorts", allExistSorts);  
  19.         %>  
  20.         &nbsp;&lt;==备选项:<html:select property="existSorts" onchange="autoPopulate(this,'sort');">  
  21.         <html:option value="-1">--- 请选择 ---</html:option>  
  22.         <html:option value=""></html:option>  
  23.         <html:options name="allExistSorts" labelName="allExistSorts" />  
  24. </html:select>  
  25. <%} %>  
  26.           
  27.         </td>  
  28.     </tr>  
  29. ......  


Action代码:
java 代码
 
  1. /** 
  2.  *  
  3.  */  
  4. package com.bupticet.research.web.action;  
  5.   
  6. import java.util.Enumeration;  
  7. import java.util.HashMap;  
  8. import java.util.List;  
  9. import java.util.Map;  
  10.   
  11. import javax.servlet.http.HttpServletRequest;  
  12. import javax.servlet.http.HttpServletResponse;  
  13.   
  14. import org.apache.commons.beanutils.BeanUtils;  
  15. import org.apache.commons.beanutils.DynaBean;  
  16. import org.apache.struts.action.ActionForm;  
  17. import org.apache.struts.action.ActionForward;  
  18. import org.apache.struts.action.ActionMapping;  
  19.   
  20. import com.bupticet.base.web.struts.BaseAction;  
  21. import com.bupticet.base.web.struts.StrutsUtils;  
  22. import com.bupticet.constant.StrutsConstant;  
  23. import com.bupticet.helper.GlobalSession;  
  24. import com.bupticet.model.ClientInfo;  
  25. import com.bupticet.research.entity.Fruit;  
  26. import com.bupticet.research.entity.Project;  
  27. import com.bupticet.research.service.ProjectManager;  
  28. import com.bupticet.util.RequestUtils;  
  29. import com.bupticet.util.encode.Decoder;  
  30.   
  31. /** 
  32.  * @author lijt 
  33.  *  
  34.  */  
  35. public class ProjectAction extends BaseAction {  
  36.   
  37.     private ProjectManager projectManager;  
  38.   
  39.     /** 
  40.      * @param projectManager 
  41.      *            the projectManager to set 
  42.      */  
  43.     public void setProjectManager(ProjectManager projectManager) {  
  44.         this.projectManager = projectManager;  
  45.     }  
  46.   
  47.     /** 
  48.      *  
  49.      */  
  50.     public ProjectAction() {  
  51.     }  
  52.   
  53.     /* 
  54.      * (non-Javadoc) 
  55.      *  
  56.      * @see com.bupticet.base.web.struts.BaseAction#delete(org.apache.struts.action.ActionMapping, 
  57.      *      org.apache.struts.action.ActionForm, 
  58.      *      javax.servlet.http.HttpServletRequest, 
  59.      *      javax.servlet.http.HttpServletResponse) 
  60.      */  
  61.     @Override  
  62.     public ActionForward delete(ActionMapping mapping, ActionForm form,  
  63.             HttpServletRequest req, HttpServletResponse res) throws Exception {  
  64.         String id = req.getParameter("id");  
  65.         checkInputPara(new String[] { id });  
  66.         projectManager.removeObject( id);  
  67.         return mapping.findForward(StrutsConstant.DELETE_SUCCESS);  
  68.     }  
  69.   
  70.     /* 
  71.      * (non-Javadoc) 
  72.      *  
  73.      * @see com.bupticet.base.web.struts.BaseAction#edit(org.apache.struts.action.ActionMapping, 
  74.      *      org.apache.struts.action.ActionForm, 
  75.      *      javax.servlet.http.HttpServletRequest, 
  76.      *      javax.servlet.http.HttpServletResponse) 
  77.      */  
  78.     @Override  
  79.     public ActionForward edit(ActionMapping mapping, ActionForm form,  
  80.             HttpServletRequest req, HttpServletResponse res) throws Exception {  
  81.         String id = req.getParameter("id");  
  82.         checkInputPara(new String[] { id });  
  83.         Project p = projectManager.getObject( id);  
  84.         if (p == null) {  
  85.             this.throwEntityMissingException();  
  86.         }  
  87.         DynaBean f = (DynaBean) form;  
  88.         BeanUtils.copyProperties(f, p);  
  89.         saveToken(req);  
  90.         return mapping.findForward(StrutsConstant.EDIT_SUCCESS);  
  91.     }  
  92.   
  93.     /* 
  94.      * (non-Javadoc) 
  95.      *  
  96.      * @see com.bupticet.base.web.struts.BaseAction#list(org.apache.struts.action.ActionMapping, 
  97.      *      org.apache.struts.action.ActionForm, 
  98.      *      javax.servlet.http.HttpServletRequest, 
  99.      *      javax.servlet.http.HttpServletResponse) 
  100.      */  
  101.     @Override  
  102.     public ActionForward list(ActionMapping mapping, ActionForm form,  
  103.             HttpServletRequest req, HttpServletResponse res) throws Exception {  
  104.         int pageNum = RequestUtils.getIntParameter(req, "pageNum"1);  
  105.         boolean isAsc = RequestUtils.getBooleanParameter(req, "isAsc"false);  
  106.         String orderField = RequestUtils.getStringParameter(req, "orderField",  
  107.                 "project0.BEGIN_DATE");  
  108.         req.setAttribute("list", projectManager.getObjectsForPage(  
  109.                  pageNum, 20, orderField, isAsc));  
  110.         return mapping.findForward(StrutsConstant.LIST_SUCCESS);  
  111.     }  
  112.   
  113.     /* 
  114.      * (non-Javadoc) 
  115.      *  
  116.      * @see com.bupticet.base.web.struts.BaseAction#save(org.apache.struts.action.ActionMapping, 
  117.      *      org.apache.struts.action.ActionForm, 
  118.      *      javax.servlet.http.HttpServletRequest, 
  119.      *      javax.servlet.http.HttpServletResponse) 
  120.      */  
  121.     @Override  
  122.     public ActionForward save(ActionMapping mapping, ActionForm form,  
  123.             HttpServletRequest req, HttpServletResponse res) throws Exception {  
  124.         if (isCancelled(req)) {  
  125.             return mapping.findForward(StrutsConstant.SAVE_CANCEL);  
  126.         }  
  127.         checkAndClearToken(req);  
  128.         saveToken(req);  
  129.         if (!this.validateForm(mapping, form, req)) {  
  130.             return mapping.findForward(StrutsConstant.SAVE_FAILURE);  
  131.         }  
  132.         DynaBean f = (DynaBean) form;  
  133.         if (null != projectManager.checkName((String) f.get("name"))) {  
  134.             this.saveErrors(req,  
  135.                     addError("projectForm.error.existSameNameProject"));  
  136.             return mapping.findForward(StrutsConstant.SAVE_FAILURE);  
  137.         }  
  138.         if (null != projectManager.checkNo((String) f.get("projectNo"))) {  
  139.             this.saveErrors(req,  
  140.                     addError("projectForm.error.existSameNoProject"));  
  141.             return mapping.findForward(StrutsConstant.SAVE_FAILURE);  
  142.         }  
  143.         GlobalSession globalSession = (GlobalSession) req.getSession(true)  
  144.                 .getAttribute("globalSession");  
  145.   
  146.         Project project = new Project();  
  147.         BeanUtils.copyProperties(project, f);  
  148.         project.setEnterorId(globalSession.getUserID());  
  149.         projectManager.saveObject( project);  
  150.         return StrutsUtils.getExtForward(mapping, StrutsConstant.SAVE_SUCCESS,  
  151.                 project.getId());  
  152.     }  
  153.   
  154.     /* 
  155.      * (non-Javadoc) 
  156.      *  
  157.      * @see com.bupticet.base.web.struts.BaseAction#update(org.apache.struts.action.ActionMapping, 
  158.      *      org.apache.struts.action.ActionForm, 
  159.      *      javax.servlet.http.HttpServletRequest, 
  160.      *      javax.servlet.http.HttpServletResponse) 
  161.      */  
  162.     @Override  
  163.     public ActionForward update(ActionMapping mapping, ActionForm form,  
  164.             HttpServletRequest req, HttpServletResponse res) throws Exception {  
  165.         if (isCancelled(req)) {  
  166.             return mapping.findForward(StrutsConstant.UPDATE_CANCEL);  
  167.         }  
  168.         checkAndClearToken(req);  
  169.         saveToken(req);  
  170.         if (!this.validateForm(mapping, form, req)) {  
  171.             return mapping.findForward(StrutsConstant.UPDATE_FAILURE);  
  172.         }  
  173.         DynaBean f = (DynaBean) form;  
  174.         String id = (String) f.get("id");  
  175.         String existId = projectManager.checkName((String) f.get("name"));  
  176.         if (existId != null && !id.equals(existId)) {  
  177.             this.saveErrors(req,  
  178.                     addError("projectForm.error.existSameNameProject"));  
  179.             return mapping.findForward(StrutsConstant.UPDATE_FAILURE);  
  180.         }  
  181.         existId = projectManager.checkNo((String) f.get("projectNo"));  
  182.         if (existId != null && !id.equals(existId)) {  
  183.             this.saveErrors(req,  
  184.                     addError("projectForm.error.existSameNoProject"));  
  185.             return mapping.findForward(StrutsConstant.UPDATE_FAILURE);  
  186.         }  
  187.         Project project = projectManager.getObject(  
  188.                 (String) f.get("id"));  
  189.         BeanUtils.copyProperties(project, f);  
  190.         projectManager.saveObject( project);  
  191.         return StrutsUtils.getExtForward(mapping,  
  192.                 StrutsConstant.UPDATE_SUCCESS, project.getId());  
  193.     }  
  194.   
  195.     /* 
  196.      * (non-Javadoc) 
  197.      *  
  198.      * @see com.bupticet.base.web.struts.BaseAction#view(org.apache.struts.action.ActionMapping, 
  199.      *      org.apache.struts.action.ActionForm, 
  200.      *      javax.servlet.http.HttpServletRequest, 
  201.      *      javax.servlet.http.HttpServletResponse) 
  202.      */  
  203.     @Override  
  204.     public ActionForward view(ActionMapping mapping, ActionForm form,  
  205.             HttpServletRequest req, HttpServletResponse res) throws Exception {  
  206.         String id = req.getParameter("id");  
  207.         checkInputPara(new String[] { id });  
  208.         Project p = projectManager.getObject( id);  
  209.         if (p == null) {  
  210.             this.throwEntityMissingException();  
  211.         }  
  212.         List<Fruit> fruits = projectManager.getFruitsOfProject(p.getId());  
  213.         req.setAttribute("fruits", fruits);  
  214.         req.setAttribute("info", p);  
  215.         return mapping.findForward(StrutsConstant.VIEW_SUCCESS);  
  216.     }  
  217.   
  218.     /** 
  219.      * @param mapping 
  220.      * @param form 
  221.      * @param req 
  222.      * @param res 
  223.      * @return 
  224.      * @throws Exception 
  225.      */  
  226.     public ActionForward audit(ActionMapping mapping, ActionForm form,  
  227.             HttpServletRequest req, HttpServletResponse res) throws Exception {  
  228.         req.setAttribute("auditFlag"new Boolean(true));  
  229.         return this.edit(mapping, form, req, res);  
  230.     }  
  231.   
  232.     /** 
  233.      * @param mapping 
  234.      * @param form 
  235.      * @param req 
  236.      * @param res 
  237.      * @return 
  238.      * @throws Exception 
  239.      */  
  240.     public ActionForward goSearch(ActionMapping mapping, ActionForm form,  
  241.             HttpServletRequest req, HttpServletResponse res) throws Exception {  
  242.         return mapping.findForward("search-page");  
  243.     }  
  244.   
  245.     /** 
  246.      * @param mapping 
  247.      * @param form 
  248.      * @param req 
  249.      * @param res 
  250.      * @return 
  251.      * @throws Exception 
  252.      */  
  253.     @SuppressWarnings("unchecked")  
  254.     public ActionForward search(ActionMapping mapping, ActionForm form,  
  255.             HttpServletRequest req, HttpServletResponse res) throws Exception {  
  256.         Map<String, String> p = new HashMap<String, String>();  
  257.         for(Enumeration<String> e = req.getParameterNames();e.hasMoreElements();){  
  258.             String key = e.nextElement();  
  259.             String value = req.getParameter(key);  
  260.             if (value != null && !"".equals(value)) {  
  261.                 p.put(key, Decoder.customDecode(value));  
  262.             }  
  263.         }  
  264.         int pageNum = RequestUtils.getIntParameter(req, "pageNum"1);  
  265.         boolean isAsc = RequestUtils.getBooleanParameter(req, "isAsc"false);  
  266.         String orderField = RequestUtils.getStringParameter(req, "orderField",  
  267.                 "project0.BEGIN_DATE");  
  268.         req.setAttribute("list", projectManager.search(p, pageNum, 20,  
  269.                 orderField, isAsc));  
  270.         req.setAttribute("search""true");  
  271.         return mapping.findForward(StrutsConstant.LIST_SUCCESS);  
  272.     }  
  273.   
  274. }  
0 请登录后投票
   发表时间:2007-06-28  
主要是利用DynaBean,从客户端提交的数据都保存导DynaBean里面,然后再通过beanutils拷贝到实体对象里面去, 现在准备用struts2,正打算实现一个拦截器,将客户端表单提交过来的数据保存到DynaBean对象里面,然后再手动拷贝导实体对象。
0 请登录后投票
   发表时间:2007-06-28  
不过感觉楼上几位思路更好,这样最简单。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics