SpringMvc 注解 @InitBinder 表单多对象精准绑定接收
@InitBinder用于在@Controller中标注于方法,表示为当前控制器注册一个属性编辑器或者其他,只对当前的Controller有效。
在使用SpringMVC的时候,经常会遇到表单中的日期字符串和JavaBean的Date类型的转换,而SpringMVC默认不支持这个格式的转换,需要手动配置自定义数据的绑定才能解决这个问题。
在需要日期转换的Controller中使用SpringMVC的注解@initbinder和Spring自带的WebDateBinder类来操作。
WebDataBinder是用来绑定请求参数到指定的属性编辑器. 由前台传到controller里的值是String类型的,当往Model里Set这个值的时候,如果set的这个属性是个对象,Spring就会去找到对应的editor进行转换,然后再SET进去。
-----------------------------------我是分隔线-----------------------------------
一. 问题描述: 一张表单中提交多个对象,并在后台Controller 中精准的绑定。可对象中的参数名有的相同,后台接收入参时无法像struts那样jsp表单中使用Object.Param形式对表单进行精准绑定入参(struts2默认就是这种方案),因为struts2采用了OGNL,并通过栈(根对象)进行操作,栈中默认有action实例,所以无此问题。但 Struts用这种方式绑定入参牺牲了性能。
现在以前台表单提交两个对象为例。
User.java 和 Addr.java
public class User implements Serializable{
String id;
String name;
//get..set....
}
public class Addr implements Serializable{
String id;
String name;//set..get...
}
前台JSP
<form action="/test/test" method="post">
<input type="text" name="user.id" value="huo_user_id">
<input type="text" name="user.name" value="huo_user_name">
<input type="text" name="addr.id" value="huo_addr_id">
<input type="text" name="addr.name" value="huo_addr_name">
<input type="submit" value="提交">
</form>
此时 springMVC 直接进行入参,是不能接收到参数的。
二. 解决思路
用 @InitBinder 注解作参数绑定。前台表单中name属性仍然使用Object.Param形式传入。
(另一种解决思路:扩展spring的HandlerMethodArgumentResolver以支持自定义的数据绑定方式。)
@InitBinder("user")
public void initBinderUser(WebDataBinder binder) {
binder.setFieldDefaultPrefix("user.");
}
@InitBinder() 的value,用于指定命令/表单属性或请求参数的名字,符合该名字的将使用此处的DataBinder,如我们的@ModelAttribute("user1") User user1 将使用@InitBinder("user1")指定的DataBinder绑定;如果不指定value值,那么所有的都将使用。
DataBinder.setFieldDefaultPrefix 是设置参数的前缀,如我们的是"user1.",此处不能少了".",
此方式的缺点:
1、不支持Path variable的绑定,如/test1/{user1.id}这种情况的绑定;
2、不支持如集合/数组的绑定;
三 问题解决
@Controller
@RequestMapping("/test")
public class TestController {
// 绑定变量名字和属性,参数封装进类
@InitBinder("user")
public void initBinderUser(WebDataBinder binder) {
binder.setFieldDefaultPrefix("user.");
}
// 绑定变量名字和属性,参数封装进类
@InitBinder("addr")
public void initBinderAddr(WebDataBinder binder) {
binder.setFieldDefaultPrefix("addr.");
}
@RequestMapping("/test")
@ResponseBody
public Map<String,Object> test(HttpServletRequest request,@ModelAttribute("user") User user,@ModelAttribute("addr") Addr addr){
Map<String,Object> map=new HashMap<String,Object>();
map.put("user", user);
map.put("addr", addr);
return map;
}
就一个@InitBinder 就可以解决了。
另外可以通过DataBinder完成如下几件事情:
1、binder.setAllowedFields("id") : 设置允许的字段,比如我只想设置id,那么可以调用这个方法,那么其他属性会忽略;
2、binder.setDisallowedFields("id") : 设置不允许的自动,比如我不想设置id,那么可以调用此方法,这个属性将不设置;
3、binder.setRequiredFields() : 表示哪些字段是必填的;
4、binder.setValidator() :设置自定义的验证器,如果如JSR-303不适合,可以使用这个。
完整例子:
两个对象
public class User implements Serializable{
String id;
String name;
//get..set....
}
public class Addr implements Serializable{
String id;
String name;//set..get...
}
jsp
<form action="/test/test" method="post">
<input type="text" name="user.id" value="huo_user_id">
<input type="text" name="user.name" value="huo_user_name">
<input type="text" name="addr.id" value="huo_addr_id">
<input type="text" name="addr.name" value="huo_addr_name">
<input type="submit" value="提交">
</form>
Controller
@Controller
@RequestMapping("/test")
public class TestController {
// 绑定变量名字和属性,参数封装进类
@InitBinder("user")
public void initBinderUser(WebDataBinder binder) {
binder.setFieldDefaultPrefix("user.");
}
// 绑定变量名字和属性,参数封装进类
@InitBinder("addr")
public void initBinderAddr(WebDataBinder binder) {
binder.setFieldDefaultPrefix("addr.");
}
@RequestMapping("/test")
@ResponseBody
public Map<String,Object> test(HttpServletRequest request,@ModelAttribute("user") User user,@ModelAttribute("addr") Addr addr){
Map<String,Object> map=new HashMap<String,Object>();
map.put("user", user);
map.put("addr", addr);
return map;
}
--------------------- 转自:
https://blog.csdn.net/qq_24505127/article/details/54236583
https://blog.51cto.com/simplelife/1919597
另关于类型转换见另一文章: SpringMVC注解 @initbinder 解决类型转换问题
- 使用angular4和asp.net core 2 web api做个练习项目(四)
- list.add(),向List集合插入对象报空指针异常
- 使用angular4和asp.net core 2 web api做个练习项目(三)
- 即学即用系列一:纯函数
- Java之StringBuffer,StringBuilder,Math,Date,SimpleDateFormat,UUID,File
- React编程思想
- 前台分页,以及类别选择
- 使用angular4和asp.net core 2 web api做个练习项目(二), 这部分都是angular
- 数据库 105道题目整理与吐血总结
- 使用angular4和asp.net core 2 web api做个练习项目(一)
- =.=
- JavaScript经典面试题之for循环click
- 学习docker on windows (1): 为什么要使用docker
- 使用VS Code开发asp.net core (下)
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- Android仿微信发送语音消息的功能及示例代码
- 详解Android studio ndk配置cmake开发native C
- Android编程实现禁止状态栏下拉的方法详解
- Android进度条ProgressBar的实现代码
- Android画画板的制作方法
- Android实现bitmap指定区域滑动截取功能
- Android开发实现应用层面屏蔽状态栏的方法小结
- Android实现实时搜索框功能
- 浅谈Android轻量级的数据缓存框架RxCache
- Android开发实现消除屏幕锁的方法
- Android中js和原生交互的示例代码
- 浅谈android获取设备唯一标识完美解决方案
- Android开发实现长按返回键弹出关机框功能
- Android View 完美实现EditText 在软键盘上边的示例
- Android蓝牙通信之搜索蓝牙设备