`
jinnianshilongnian
  • 浏览: 21504203 次
  • 性别: Icon_minigender_1
博客专栏
5c8dac6a-21dc-3466-8abb-057664ab39c7
跟我学spring3
浏览量:2418707
D659df3e-4ad7-3b12-8b9a-1e94abd75ac3
Spring杂谈
浏览量:3008815
43989fe4-8b6b-3109-aaec-379d27dd4090
跟开涛学SpringMVC...
浏览量:5639508
1df97887-a9e1-3328-b6da-091f51f886a1
Servlet3.1规范翻...
浏览量:259932
4f347843-a078-36c1-977f-797c7fc123fc
springmvc杂谈
浏览量:1597333
22722232-95c1-34f2-b8e1-d059493d3d98
hibernate杂谈
浏览量:250226
45b32b6f-7468-3077-be40-00a5853c9a48
跟我学Shiro
浏览量:5858969
Group-logo
跟我学Nginx+Lua开...
浏览量:702014
5041f67a-12b2-30ba-814d-b55f466529d5
亿级流量网站架构核心技术
浏览量:785227
社区版块
存档分类
最新评论

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

 
阅读更多

最新版请点击查看FormModelMethodArgumentResolver.java 

 

问题描述:

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

<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>
@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;

     <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、使用方式

 public String user(@FormModel("student") Student student, @FormModel("teacher") Teacher teacher) 

 

4、测试控制器

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,请这样配置

 <mvc:annotation-driven>
     <mvc:argument-resolvers>
            <bean class="com.sishuok.es.common.web.bind.method.annotation.FormModelMethodArgumentResolver"/>
        </mvc:argument-resolvers>
 </mvc:annotation-driven>

  

 

 

欢迎大家反馈问题,我会及时修正。

 

 

下一个扩展: 绑定请求参数(JSON字符串,如 deptIds=[{"deptId":4,"isPrimary":true}] ) 到 模型对象。

 

 

17
2
分享到:
评论
13 楼 在世界的中心呼喚愛 2012-11-24  
lz是怎么学习spring和hibernate?
我工作9个月了,spring和hibernate就是公司项目里面用到的,就会用,具体原理有些知道,有些不知道。
感觉学的很浅,也不知道怎么强化。特别hibernate,有些怕,现在大部分操作我都是用ibatis完成。
有本李刚的ssh书,现在敲一敲看一看。但是和公司用到的都不一样。
特别mvc框架,公司不用struts,用spring注解,url请求映射到ctr层的类名,
@Controller 
@RequestMapping("/formmodel")   
和这个很像,就是在xml里面配置下,在url请求的时候写/formmodel后面跟方法,参数

现在大部分时间都在处理业务问题,框架都标准化,无论哪个系统,基本都是那套框架使用,就是copy,copy。
但是还是感觉学的浅,很多异常没有办法自己处理。
想请教lz是怎么学习的。
12 楼 jinnianshilongnian 2012-11-15  
skzr.org 写道
我一般这么玩:
//请求:http://localhost:8080/admin/user/add?users[0].name=张三&users[0].address=地球
@RequestMapping("/user/*")
public class 
	@RequestMapping("add")
	public @ResponseBody String addUser(UserControllerParam params) {
		return "正确转换了:'" + params.getUsers();
	}
}

class UserControllerParam {
	private List<User> users;

	public List<User> getUsers() {
		return users;
	}
	public void setUsers(List<User> users) {
		this.users = users;
	}
}

恩 通过一个form model搞定
11 楼 skzr.org 2012-11-14  
我一般这么玩:
//请求:http://localhost:8080/admin/user/add?users[0].name=张三&users[0].address=地球
@RequestMapping("/user/*")
public class 
	@RequestMapping("add")
	public @ResponseBody String addUser(UserControllerParam params) {
		return "正确转换了:'" + params.getUsers();
	}
}

class UserControllerParam {
	private List<User> users;

	public List<User> getUsers() {
		return users;
	}
	public void setUsers(List<User> users) {
		this.users = users;
	}
}
10 楼 jinnianshilongnian 2012-11-14  
zoup580 写道
tao哥。。。我把你的重写formBean放到springmvc-chapter6里可以用。。。但是把相关 的代码都copy到我自己的项目 里时就用不了了。。。
<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>    是加在application的配置文件里吗?求解啊。。。

加到spring配置文件中,而且需要去除mvc:命名空间 然后使用我的配置文件中RequestMappingHandlerAdapter和另一个Mapping  最低版本要求3.1
9 楼 zoup580 2012-11-14  
tao哥。。。我把你的重写formBean放到springmvc-chapter6里可以用。。。但是把相关 的代码都copy到我自己的项目 里时就用不了了。。。
<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>    是加在application的配置文件里吗?求解啊。。。
8 楼 jinnianshilongnian 2012-11-08  
thc1987 写道
jinnianshilongnian 写道
dicmo 写道
博主哪年生人?

87 

同样87,惭愧...

  做好自己即可,我跟别的牛比也惭愧,人和人没的比,和自己比,要求自己天天进步,加油兄弟
7 楼 thc1987 2012-11-08  
jinnianshilongnian 写道
dicmo 写道
博主哪年生人?

87 

同样87,惭愧...
6 楼 jinnianshilongnian 2012-11-06  
dicmo 写道
博主哪年生人?

87 
5 楼 dicmo 2012-11-06  
博主哪年生人?
4 楼 jinnianshilongnian 2012-11-06  
7454103 写道
引用
另外一种方案     @InitBinder("account")    //---对象1
    public void initBinder1(WebDataBinder binder) {  
            binder.setFieldDefaultPrefix("acc.");  
    }  

    @InitBinder("user")   // --对象2
    public void initBinder2(WebDataBinder binder) {  
            binder.setFieldDefaultPrefix("user.");  
    }
 

这个不错  ,内置的支持 不过这个支持如集合绑定吗? 我晚上回去测试下 
3 楼 7454103 2012-11-06  
引用
另外一种方案     @InitBinder("account")    //---对象1
    public void initBinder1(WebDataBinder binder) {  
            binder.setFieldDefaultPrefix("acc.");  
    }  

    @InitBinder("user")   // --对象2
    public void initBinder2(WebDataBinder binder) {  
            binder.setFieldDefaultPrefix("user.");  
    }
 
2 楼 jinnianshilongnian 2012-11-06  
rensanning 写道

可以,这是上边我提到的FormBean(类似于struts1)

相关推荐

    扩展SpringMVC以支持绑定JSON格式的请求参数

    扩展Spring MVC以支持绑定JSON格式的请求参数,能够使我们的服务更好地与前端或API客户端进行交互。本文将深入探讨如何实现这一功能。 首先,我们需要了解Spring MVC的模型绑定机制。模型绑定是Spring MVC中的一项...

    spring MVC数据绑定大全

    Spring MVC 是一个强大的Java Web开发框架,用于构建...对于从Struts2转向Spring MVC的开发者来说,虽然初始学习曲线可能稍陡,但深入理解和实践后,你会发现Spring MVC在数据绑定上的便利性和可扩展性是其独特的优势。

    springmvc入门参数绑定ssm整合

    SpringMVC入门参数绑定SSM整合 SpringMVC是一种基于MVC模式的Web应用程序框架,它是Spring框架的一个模块,用于开发Web项目。下面是SpringMVC入门参数绑定SSM整合的知识点总结: 一、SpringMVC概述 SpringMVC是...

    Spring In Action MVC 提交表单(2)-数据绑定和数据校验

    1. **数据绑定** 数据绑定是Spring MVC中一个强大的特性,它允许我们将HTTP请求参数自动映射到控制器方法的参数上。例如,当用户提交一个HTML表单时,表单字段的值可以被自动绑定到Java对象的属性上。Spring通过`@...

    SpringMVCC.zip

    - SpringMVC支持模型属性的数据绑定,并可集成Hibernate Validator进行数据验证。 12. **上传文件**: - 使用MultipartFile接口处理文件上传,配置MultipartResolver来处理multipart请求。 13. **异常处理**: ...

    Spring+SpringMvc+MybatisPlus+Aop(自定义注解)动态切换数据源

    MybatisPlus是在Mybatis基础上扩展的轻量级ORM(对象关系映射)框架,它简化了SQL查询和实体对象的绑定,使得开发者可以更专注于业务逻辑,而不用过多地关注数据库操作的细节。在这个项目中,MybatisPlus用于执行...

    springMVC教案.rar

    SpringMVC提供了强大的数据绑定机制,可以从请求参数自动填充Bean属性。配合JSR-303/JSR-349 Bean Validation,可以在服务器端进行数据验证。 7. **异常处理**: SpringMVC允许定义全局或特定类型的异常处理器,...

    SpringMVC学习编程代码

    此外,SpringMVC支持数据绑定和验证,可以通过`@ModelAttribute`注解将请求参数绑定到Java对象,并利用`@Valid`和`Validator`接口进行数据验证。 对于异常处理,SpringMVC提供了`@ExceptionHandler`注解,可以用来...

    jetbrick-springmvc jar包(包含源码)

    4. **数据绑定**:Jetbrick-SpringMVC增强了SpringMVC的数据绑定能力,支持类型转换、验证和默认值设定,提高开发效率。 5. **异常处理**:提供了一套统一的异常处理机制,将系统异常转化为用户友好的错误页面,...

    Spring+ibatis+struts框架整合+springmvc数据接口封装含数据表可直接运行

    标题中的"Spring+ibatis+struts框架整合+springmvc数据接口封装含数据表可直接运行"揭示了这个项目是关于使用三个主流的Java Web开发框架——Spring、iBatis和Struts进行集成,并且结合Spring MVC实现了数据接口的...

    SpringMVC实现动态加表及字段并显示数据

    使用SpringMVC的ModelAndView,我们可以将后端数据绑定到视图模板,如JSP或Thymeleaf,生成动态的表单元素。JavaScript,如jQuery或Vue.js,可以实现动态交互,如表单验证、异步提交等。在前端展示数据时,可以通过...

    SpringMVC实战

    SpringMVC支持自动的数据绑定,即将HTTP请求参数自动绑定到Controller方法的参数上。同时,它还提供了JSR-303/JSR-349标准的Bean Validation,用于验证输入数据的合法性。 **7. 模板引擎与视图技术** SpringMVC可以...

    SpringMVC jar

    此外,SpringMVC还提供了数据绑定、验证、本地化和主题等功能。数据绑定允许模型数据自动绑定到表单字段,而验证机制可以确保输入数据的正确性。本地化支持根据用户的语言和区域提供不同的显示内容,主题功能则可以...

    SpringMVC框架

    在数据绑定和验证方面,SpringMVC提供了强大的数据绑定机制,支持从请求参数到对象属性的自动绑定,还提供了数据验证和格式化的支持。开发者可以利用Spring提供的数据验证器(如Hibernate Validator)对请求数据进行...

    springmvc.docx

    其优点包括但不限于:松散耦合、注解驱动、RESTful 支持、强大的数据绑定和类型转换、高效的异常处理以及可扩展的拦截器机制。通过理解并掌握 SpringMVC 的核心概念和使用方法,开发者可以更高效地构建和维护 Web ...

    SpringMVC完整使用教程

    它提供了一种模型-视图-控制器(MVC)架构,使得开发者可以更方便地处理 HTTP 请求、响应以及数据绑定。本教程将深入探讨 SpringMVC 的核心功能和使用方法。 ### 第 1 章 SpringMVC 概述 SpringMVC 旨在简化 Web ...

Global site tag (gtag.js) - Google Analytics