扩展SpringMVC以支持更精准的数据绑定1

最新版请点击查看FormModelMethodArgumentResolver.java 

 

问题描述:

springMVC 数据绑定 多个对象 如何准确绑定?

Java代码 复制代码  收藏代码
  1. <form>   
  2.   
  3.     <input name="student.name" value="Kate" />   
  4.   
  5.     <input name="student.type" value="自费" />   
  6.   
  7.     <input name="teacher.name" value="Gavin" />   
  8.   
  9.     <input name="teacher.level" value="2" />   
  10.   
  11. </form>  
<form>

    <input name="student.name" value="Kate" />

    <input name="student.type" value="自费" />

    <input name="teacher.name" value="Gavin" />

    <input name="teacher.level" value="2" />

</form>
Java代码 复制代码  收藏代码
  1. @RequestMapping("/school.do")   
  2.   
  3. public String school(Student student, Teacher teacher) {   
  4.   
  5.      return "school";   
  6.   
  7. }  
@RequestMapping("/school.do")

public String school(Student student, Teacher teacher) {

     return "school";

}

如果还是想刚才的jsp那些写表单,是不能封装参数的,必须把“student.”和“teacher.”去掉,但是这样封装就不能准确封装了。

 

这个问题最近老是有人问,所以写一个扩展很容易解决这个问题,springmvc和spring一样,预留的扩展点足够多。

 

我们都知道struts2默认就是这种方案,这是因为struts2采用了OGNL,并通过栈(根对象)进行操作的,而且栈中默认有action实例,所以很自然的没有这种问题。

springmvc不同,没有根对象的概念,而且本身很难来解决这个问题,因此大家在使用时最好避免这种方式或者使用类似于struts1的FormBean组合对象来解决。

 

解决方案:

扩展spring的HandlerMethodArgumentResolver以支持自定义的数据绑定方式。

 

1、请下载附件的代码,放到工程中;

2、在RequestMappingHandlerAdapter添加自定义HandlerMethodArgumentResolver Bean;

Java代码 复制代码  收藏代码
  1. <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">    
  2.    <!--线程安全的访问session-->   
  3.     <property name="synchronizeOnSession" value="true"/>    
  4.     <property name="customArgumentResolvers">   
  5.        <list>   
  6.           <bean class="cn.javass.spring.mvc.method.annotation.RequestJsonParamMethodArgumentResolver"/>   
  7.           <bean class="cn.javass.spring.mvc.method.annotation.FormModelMethodArgumentResolver"/>   
  8.        </list>   
  9.     </property>   
  10. </bean>    
     <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"> 
        <!--线程安全的访问session-->
         <property name="synchronizeOnSession" value="true"/> 
         <property name="customArgumentResolvers">
            <list>
               <bean class="cn.javass.spring.mvc.method.annotation.RequestJsonParamMethodArgumentResolver"/>
               <bean class="cn.javass.spring.mvc.method.annotation.FormModelMethodArgumentResolver"/>
            </list>
         </property>
     </bean>  

 //customArgumentResolvers用于注入自定义的参数解析器,此处我们注了FormModelMethodArgumentResolver;FormModelMethodArgumentResolver我直接修改的org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor;

 

3、使用方式

Java代码 复制代码  收藏代码
  1. public String user(@FormModel("student") Student student, @FormModel("teacher") Teacher teacher)   
 public String user(@FormModel("student") Student student, @FormModel("teacher") Teacher teacher) 

 

4、测试控制器

Java代码 复制代码  收藏代码
  1. package cn.javass.chapter6.web.controller.formmodel;   
  2.   
  3. import java.util.Arrays;   
  4. import java.util.List;   
  5.   
  6. import org.springframework.stereotype.Controller;   
  7. import org.springframework.web.bind.annotation.RequestMapping;   
  8.   
  9. import cn.javass.chapter6.model.UserModel;   
  10. import cn.javass.spring.mvc.bind.annotation.FormModel;   
  11. import cn.javass.spring.mvc.util.MapWapper;   
  12.   
  13.   
  14. @Controller  
  15. @RequestMapping("/formmodel")     
  16. public class FormModelController {   
  17.   
  18.     //ok   http://localhost:9080/springmvc-chapter6/formmodel/user?user.username=zhang&user.password=123   
  19.     @RequestMapping("/user/{user.realname}")     
  20.     public String user(@FormModel("user") UserModel user) {   
  21.         System.out.println(user);   
  22.         return "redirect:/success";           
  23.     }   
  24.        
  25.     //ok   http://localhost:9080/springmvc-chapter6/formmodel/array1?array[0]=zhang&array[1]=li   
  26.     @RequestMapping("/array1")     
  27.     public String array1(@FormModel("array") String[] array) {   
  28.         System.out.println(Arrays.toString(array));   
  29.         return "redirect:/success";           
  30.     }   
  31.        
  32.     //ok   http://localhost:9080/springmvc-chapter6/formmodel/array2?array[0].username=zhang&array[0].password=123&array[1].username=li   
  33.     @RequestMapping("/array2")     
  34.     public String array2(@FormModel("array") UserModel[] array) {   
  35.         System.out.println(Arrays.toString(array));   
  36.         return "redirect:/success";           
  37.     }   
  38.        
  39.        
  40.     //ok   http://localhost:9080/springmvc-chapter6/formmodel/list1?list[0]=123&list[1]=234   
  41.     @RequestMapping("/list1")     
  42.     public String list1(@FormModel("list") List<Integer> list) {   
  43.         System.out.println(list);   
  44.         return "redirect:/success";           
  45.     }   
  46.        
  47.     //ok   http://localhost:9080/springmvc-chapter6/formmodel/list2?list[0].username=zhang&list[1].username=li   
  48.     @RequestMapping("/list2")     
  49.     public String list2(@FormModel("list") List<UserModel> list) {   
  50.         System.out.println(list);   
  51.         return "redirect:/success";           
  52.     }   
  53.        
  54.     //ok   http://localhost:9080/springmvc-chapter6/formmodel/map1?map['0']=123&map["1"]=234   
  55.     @RequestMapping("/map1")     
  56.     public String map1(@FormModel("map") MapWapper<String, Integer> map) {   
  57.         System.out.println(map);   
  58.         return "redirect:/success";           
  59.     }   
  60.   //ok   http://localhost:9080/springmvc-chapter6/formmodel/map2?map['0'].password=123&map['0'].username=123&map["1"].username=234   
  61.     @RequestMapping("/map2")     
  62.     public String map2(@FormModel("map") MapWapper<Integer, UserModel> map) {   
  63.         System.out.println(map);   
  64.         return "redirect:/success";           
  65.     }   
  66. }  
package cn.javass.chapter6.web.controller.formmodel;

import java.util.Arrays;
import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import cn.javass.chapter6.model.UserModel;
import cn.javass.spring.mvc.bind.annotation.FormModel;
import cn.javass.spring.mvc.util.MapWapper;


@Controller
@RequestMapping("/formmodel")  
public class FormModelController {

    //ok   http://localhost:9080/springmvc-chapter6/formmodel/user?user.username=zhang&user.password=123
    @RequestMapping("/user/{user.realname}")  
    public String user(@FormModel("user") UserModel user) {
        System.out.println(user);
        return "redirect:/success";        
    }
    
    //ok   http://localhost:9080/springmvc-chapter6/formmodel/array1?array[0]=zhang&array[1]=li
    @RequestMapping("/array1")  
    public String array1(@FormModel("array") String[] array) {
        System.out.println(Arrays.toString(array));
        return "redirect:/success";        
    }
    
    //ok   http://localhost:9080/springmvc-chapter6/formmodel/array2?array[0].username=zhang&array[0].password=123&array[1].username=li
    @RequestMapping("/array2")  
    public String array2(@FormModel("array") UserModel[] array) {
        System.out.println(Arrays.toString(array));
        return "redirect:/success";        
    }
    
    
    //ok   http://localhost:9080/springmvc-chapter6/formmodel/list1?list[0]=123&list[1]=234
    @RequestMapping("/list1")  
    public String list1(@FormModel("list") List<Integer> list) {
        System.out.println(list);
        return "redirect:/success";        
    }
    
    //ok   http://localhost:9080/springmvc-chapter6/formmodel/list2?list[0].username=zhang&list[1].username=li
    @RequestMapping("/list2")  
    public String list2(@FormModel("list") List<UserModel> list) {
        System.out.println(list);
        return "redirect:/success";        
    }
    
    //ok   http://localhost:9080/springmvc-chapter6/formmodel/map1?map['0']=123&map["1"]=234
    @RequestMapping("/map1")  
    public String map1(@FormModel("map") MapWapper<String, Integer> map) {
        System.out.println(map);
        return "redirect:/success";        
    }
  //ok   http://localhost:9080/springmvc-chapter6/formmodel/map2?map['0'].password=123&map['0'].username=123&map["1"].username=234
    @RequestMapping("/map2")  
    public String map2(@FormModel("map") MapWapper<Integer, UserModel> map) {
        System.out.println(map);
        return "redirect:/success";        
    }
}

 

具体使用可以下载之前springmvc第六章源代码http://jinnianshilongnian.iteye.com/blog/1683388 

将附件中的FormModel.rar解压放到src下进行测试。

 

 

支持的spring版本:

springmvc 3.1.x,暂不支持3.0。为什么不支持呢?springmvc 3.1 和 3.0 从架构上发生了变化,而且springmvc3.1更容易扩展。

 

支持绑定的数据:

模型、集合、数组、MapWapper(Map的一个包装器,通过getInnerMap获取真实Map)

 

 

缺点:

spring自定义的参数解析器会放在默认解析器之后,不能指定order,因此如果我们@FormModel("map") Map map,此map会变成Model(请参考http://jinnianshilongnian.iteye.com/blog/1698916 第六部分、Model Map ModelMap),希望未来的版本支持自定义顺序来解决这个问题;此处我们使用MapWapper解决,可以通过MapWapper.getInnerMap()拿到我们需要的Map

 

其他方案:

[SpringMVC]修改源码使之能够更加智能的自动装配request请求参数.(不建议修改源代码解决)

@rainsoft 也给出了类似的方案, http://www.iteye.com/topic/1124433#2357830

 

如果你使用的是mvc:annotation-driven,请这样配置

Java代码 复制代码  收藏代码
  1. <mvc:annotation-driven>   
  2.     <mvc:argument-resolvers>   
  3.            <bean class="com.sishuok.es.common.web.bind.method.annotation.FormModelMethodArgumentResolver"/>   
  4.        </mvc:argument-resolvers>   
  5. </mvc:annotation-driven>  
 <mvc:annotation-driven>
     <mvc:argument-resolvers>
            <bean class="com.sishuok.es.common.web.bind.method.annotation.FormModelMethodArgumentResolver"/>
        </mvc:argument-resolvers>
 </mvc:annotation-driven>

  

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值