[SpringMVC]修改源码使之能够更加智能的自动装配request请求参数

记得以前用Struts2时候,有种说法好像叫做自动装配(可能名字记错了,见谅),就是将request中的<form>表单自动组装为java对象。然而后来使用SpringMVC之后,发现SpringMVC这一点做得有些差强人意。因为Struts2能够自动组装的是<input name="obj.property"> 这种request参数名,而SpringMVC自动组装的是<input name="property"> 这种参数名,虽然仅仅少了个obj. ,但是用起来差别很大。

 

比如在管理系统中,有时候一个form表单中会涉及多个类。我最近遇到的一个form表单中有两种类,一个是辅料,一种是原料 。两种原料中都有一些同名的参数mark 。在form表单中是这样的:

Java代码   收藏代码
  1. <form>  
  2.     ......<!--省去代码若干-->  
  3.     <input type='text' name='mark'/> <!-- 原料的mark -->  
  4.     ......<!--省去代码若干-->  
  5.     <input type='text' name='mark'/> <!-- 辅料的mark -->  
  6.     ......<!--省去代码若干-->  
  7. </form>  

 这种情况下,我感觉使用SpringMVC很麻烦,或许是自己知识短浅,找不到解决办法。

 

但是我也想到了为什么SpringMVC不能像Struts2一样,可以再name标签上添加一个obj. 呢?如果可以添加obj. 的话,这种情况根本没有一点复杂的:

Java代码   收藏代码
  1. <form>  
  2.     ......<!--省去代码若干-->  
  3.     <input type='y.text' name='mark'/> <!-- 原料的mark,action中原料参数名为y -->  
  4.     ......<!--省去代码若干-->  
  5.     <input type='f.text' name='mark'/> <!-- 辅料的mark,action中辅料参数名为f -->  
  6.     ......<!--省去代码若干-->  
  7. </form>  

 

可惜, SpringMVC没有这个功能,因此,我便动了修改它源码的念头。经过一番折腾,终于完成了,现将修改方法公布出来,供大家参考:

 

需要修改的Spring类全部都在org.springframework.web.jar包中,我使用的是3.0.6版本。

 

 

第一步,修改org.springframework.web.bind.annotation.support.HandlerMethodInvoker类的

private WebDataBinder resolveModelAttribute(...)方法 :

Java代码   收藏代码
  1. private WebDataBinder resolveModelAttribute(String attrName,  
  2.         MethodParameter methodParam, ExtendedModelMap implicitModel,  
  3.         NativeWebRequest webRequest, Object handler) throws Exception {  
  4.         // .......省去若干行  
  5.     // 原Spring中为name,应将name改为methodParam.getParameterName()  
  6.     WebDataBinder binder = createBinder(webRequest, bindObject, methodParam.getParameterName());  
  7.     initBinder(handler, name, binder, webRequest);  
  8.     return binder;  
  9. }  

 

第二步,修改org.springframework.web.bind.ServletRequestParameterPropertyValues类,最后新增两个方法 :

Java代码   收藏代码
  1. /** 
  2.  * 新增的构造方法,此方法添加了一个ServletRequestDataBinder类型参数,用于获取方法arg名称 
  3.  * @param request 
  4.  * @param binder 
  5.  */  
  6. public ServletRequestParameterPropertyValues(ServletRequest request, ServletRequestDataBinder binder){  
  7.     // super(WebUtils.getParametersStartingWith(request, (prefix != null ? prefix + prefixSeparator : null)));  
  8.     super(getAvailableParams(request, binder));  
  9. }  
  10.   
  11. /** 
  12.  * 新增方法,此方法内部将target.property提取为property 
  13.  * @param request 
  14.  * @param binder 
  15.  * @return 
  16.  */  
  17. public static Map<String, Object> getAvailableParams(ServletRequest request, ServletRequestDataBinder binder){  
  18.     // 此方法内部优先提取target.property值,之后再取property值  
  19.     Map<String, Object> params = new HashMap<String, Object>();  
  20.     Enumeration<String> paramNames = request.getParameterNames();  
  21.     while (paramNames != null && paramNames.hasMoreElements()) {  
  22.         String paramName = (String) paramNames.nextElement(); // parameter名称  
  23.         String[] values = request.getParameterValues(paramName);  
  24.         // 如果是以target.开始的参数则去除target.  
  25.         if(paramName.startsWith(binder.getObjectName()+".")){  
  26.             paramName = paramName.substring(paramName.indexOf('.')+1);  
  27.         }else{  
  28.             if(params.containsKey(paramName))  
  29.                 continue;  
  30.         }  
  31.         if (values == null || values.length == 0) {  
  32.             // Do nothing, no values found at all.  
  33.         } else if (values.length > 1) {  
  34.             params.put(paramName, values);  
  35.         } else {  
  36.             params.put(paramName, values[0]);  
  37.         }  
  38.     }  
  39.     return params;  
  40. }  

 

第三步,修改org.springframework.web.bind.ServletRequestDataBinder类的

public void bind(ServletRequest request)方法 :

Java代码   收藏代码
  1. public void bind(ServletRequest request) {  
  2.         // 此处原来为new ServletRequestParameterPropertyValues(request)  
  3.     MutablePropertyValues mpvs = new ServletRequestParameterPropertyValues(request, this);  
  4.     MultipartRequest multipartRequest = WebUtils.getNativeRequest(request, MultipartRequest.class);  
  5.     if (multipartRequest != null) {  
  6.         bindMultipart(multipartRequest.getMultiFileMap(), mpvs);  
  7.     }  
  8.     doBind(mpvs);  
  9. }  

 

大功告成,此时,你便可以将form表单中的同名不同类参数修改为obj.property ,以标明同名的参数分别归哪个对象

 

现将修改之后的org.springframework.web-3.0.6.jar发布出来,如果你使用的是不同版本的Spring,可以采取上面的步骤自己重新打包使用

 

 

谢谢观看,完毕~~~~~

你可能感兴趣的:(springMVC)