• SpringMvc @InitBinder 表单多对象精准绑定接收


    问题出现

    要在一张表单中提交多个对象,并且还要在后台Controller 中精准的绑定接收。可是,这些对象中的参数名可能相同,后台接收入参时无法像struts那样jsp表单中使用Object.Param形式对表单进行精准绑定入参,我们都知道struts2默认就是这种方案,这是因为struts2采用了OGNL,并通过栈(根对象)进行操作的,而且栈中默认有action实例,所以很自然的没有这种问题。另一方面说,Struts用这种方式绑定入参,却牺牲了性能。虽然springmvc不能像struts那样方便的很直接的入参绑定,当然,spring多对象绑定入参也提供了方法。

    今天就以前台表单提交两个对象做实例。为了扩大影响,我让这两个对象的属性相同。

    User.Java 和Addr.java

    1. public class User implements Serializable{  
    2. String id;  
    3. String name;  
    4. //get..set....  
    5. }  
    6. public class Addr implements Serializable{  
    7.   
    8. String id;  
    9.   
    10. String name;//set..get...  
    11. }  

    前台JSP

    [html] view plain copy
     
    1. <form action="/test/test" method="post">  
    2.    <input type="text" name="user.id" value="huo_user_id">  
    3.    <input type="text" name="user.name" value="huo_user_name">  
    4.    <input type="text" name="addr.id" value="huo_addr_id">  
    5.    <input type="text" name="addr.name" value="huo_addr_name">  
    6.    <input type="submit" value="提交">  
    7. </form>  


    看到这种情况,很容易想到struts进行绑定非常方便,可是,谁让我们要使用SpringMVC呢。。。这种情况springMVC直接进行入参,是不能接收到参数的。

    问题思路


    使用 @InitBinder 注解进行绑定参数。前台表单中name属性仍然使用Object.Param形式传入。(另一种解决思路:扩展spring的HandlerMethodArgumentResolver以支持自定义的数据绑定方式。)

    [html] view plain copy
     
    1. @InitBinder("user")  
    2.     public void initBinderUser(WebDataBinder binder) {  
    3.         binder.setFieldDefaultPrefix("user.");  
    4.     }  


    此处使用@InitBinder() 中间的value,用于指定命令/表单属性或请求参数的名字,符合该名字的将使用此处的DataBinder,如我们的@ModelAttribute("user1") User user1 将使用@InitBinder("user1")指定的DataBinder绑定;如果不指定value值,那么所有的都将使用。

    DataBinder.setFieldDefaultPrefix 意思是设置参数的前缀,如我们的是"user1.",此处不能少了".",

    这种方式的缺点:

    1、不支持Path variable的绑定,如/test1/{user1.id}这种情况的绑定;

    2、不支持如集合/数组的绑定;

    问题解决

    [java] view plain copy
     
    1. @Controller  
    2. @RequestMapping("/test")  
    3. public class TestController {  
    4. // 绑定变量名字和属性,参数封装进类  
    5.     @InitBinder("user")  
    6.     public void initBinderUser(WebDataBinder binder) {  
    7.         binder.setFieldDefaultPrefix("user.");  
    8.     }  
    9.     // 绑定变量名字和属性,参数封装进类  
    10.     @InitBinder("addr")  
    11.     public void initBinderAddr(WebDataBinder binder) {  
    12.         binder.setFieldDefaultPrefix("addr.");  
    13.     }  
    14.       
    15.       
    16.     @RequestMapping("/test")  
    17.     @ResponseBody  
    18.     public Map<String,Object> test(HttpServletRequest request,@ModelAttribute("user") User user,@ModelAttribute("addr") Addr addr){  
    19.         Map<String,Object> map=new HashMap<String,Object>();  
    20.         map.put("user", user);  
    21.         map.put("addr", addr);  
    22.         return map;  
    23.     }  


    就一个@InitBinder 就可以解决了。


    另外可以通过DataBinder完成如下几件事情:

    1、binder.setAllowedFields("id")  : 设置允许的字段,比如我只想设置id,那么可以调用这个方法,那么其他属性会忽略;

    2、binder.setDisallowedFields("id") : 设置不允许的自动,比如我不想设置id,那么可以调用此方法,这个属性将不设置;

    3、binder.setRequiredFields() : 表示哪些字段是必填的;

    4、binder.setValidator() :设置自定义的验证器,如果如JSR-303不适合,可以使用这个。

    完整实例

    为了防止上面内容说的和写的模糊看不懂,我还是把较完整的代码贴出来吧,不过也是重复一遍。哈哈哈。

    两个对象

    [java] view plain copy
     
    1. public class User implements Serializable{  
    2. String id;  
    3. String name;  
    4. //get..set....  
    5. }  
    6. public class Addr implements Serializable{  
    7.   
    8. String id;  
    9.   
    10. String name;//set..get...  
    11. }  


    jsp

    [html] view plain copy
     
    1. <form action="/test/test" method="post">  
    2.    <input type="text" name="user.id" value="huo_user_id">  
    3.    <input type="text" name="user.name" value="huo_user_name">  
    4.    <input type="text" name="addr.id" value="huo_addr_id">  
    5.    <input type="text" name="addr.name" value="huo_addr_name">  
    6.    <input type="submit" value="提交">  
    7. </form>  

    Controller

    [java] view plain copy
     
      1. @Controller  
      2. @RequestMapping("/test")  
      3. public class TestController {  
      4. // 绑定变量名字和属性,参数封装进类  
      5.     @InitBinder("user")  
      6.     public void initBinderUser(WebDataBinder binder) {  
      7.         binder.setFieldDefaultPrefix("user.");  
      8.     }  
      9.     // 绑定变量名字和属性,参数封装进类  
      10.     @InitBinder("addr")  
      11.     public void initBinderAddr(WebDataBinder binder) {  
      12.         binder.setFieldDefaultPrefix("addr.");  
      13.     }  
      14.       
      15.       
      16.     @RequestMapping("/test")  
      17.     @ResponseBody  
      18.     public Map<String,Object> test(HttpServletRequest request,@ModelAttribute("user") User user,@ModelAttribute("addr") Addr addr){  
      19.         Map<String,Object> map=new HashMap<String,Object>();  
      20.         map.put("user", user);  
      21.         map.put("addr", addr);  
      22.         return map;  
      23.     }  
      24. 这是今天在查@InitBinder时找到的一个很好的讲解,弄了半天不知道怎么转发,只能拷贝了,原文地址如下,感谢原博主:
      25. http://blog.csdn.net/qq_24505127/article/details/54236583
  • 相关阅读:
    「十二省联考2019」 春节十二响
    「八省联考2018」 劈配
    斯特林数
    「POJ2505」A multiplication game [博弈论]
    [luogu2048] [bzoj2006] [NOI2010] 超级钢琴 题解
    [HNOI2002]-洛谷2234-营业额统计-Treap
    平衡树Treap模板与原理
    KMP算法讲解
    高斯消元--模板,原理
    第一篇博客!!
  • 原文地址:https://www.cnblogs.com/yuqiaopeng/p/6292669.html
Copyright © 2020-2023  润新知