1.数据绑定概述
数据绑定的目的是将请求中的数据传递给处理器的参数,因此,数据绑定需要在处理器适配器调用处理器方法前完成。
数据绑定需要从ServletRequest请求对象中提取数据,通过反射机制解析处理器的形参列表,依次完成类型转换、校验等操作,最终完成处理器的参数赋值。

2.简单数据绑定
2.1 处理参数
数据绑定的目的是将ServletRequest对象中的数据赋给处理器的入参,ServletRequest对象中的数据是以“key-value”形式的Map数据格式表示。绑定时按入参名与Key是否相同,作为绑定的依据,与入参的顺序无关,Spring MVC也支持入参名与key名不同的情形,但要通过@RequestParam注解标注。
| 属性名 |
描述 |
| value |
必选属性,也是默认属性。用于指定请求域中被绑定数据的key。 |
| required |
可选属性。取true时,表示请求域必须包含该参数名,否则抛出异常。默认为true。 |
| defaultValue |
可选属性。用于设置请求参数的默认值。若设置了该值,则required属性值自动变为false。 |
一般只有单个参数需要处理时,value可以省略不写。
2.2 默认类型参数绑定
默认类型是指Web容器中内置对象类型及Spring MVC提供的类型,当处理器参数中出现默认类型时,Spring MVC能够识别这些默认类型,自动为其准备相应的实例,再赋值给处理器入参,在上一节中,我们使用到的一个类似的用例:
创建一个实体对象
1 2 3 4 5 6 7 8 9 10 11 12
| public class Book { private int bookId; private String bookName; private String isbn; private float price; private String pubDate; private String warehousingDate; private String author; private int inventory; private int pubId; }
|
创建控制器Controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| @Controller @RequestMapping(value = "/book") public class BookController { @GetMapping("to_add_book") public String toAddbook(){ return "book/add_book"; } @PostMapping("add_book_binding_default") public String addBookBindingDefault(HttpServletRequest request, Model model){ Book book = new Book(); book.setBookId(Integer.parseInt(request.getParameter("book_id"))); book.setBookName(request.getParameter("book_name")); book.setIsbn(request.getParameter("isbn")); book.setPrice(Float.parseFloat(request.getParameter("price"))); book.setPubDate(request.getParameter("pub_date")); book.setWarehousingDate(request.getParameter("warehousing_date")); book.setAuthor(request.getParameter("author")); book.setInventory(Integer.parseInt(request.getParameter("inventory"))); book.setPubId(Integer.parseInt(request.getParameter("pub_id"))); model.addAttribute("book", book); return "book/book_info"; } }
|
这里我们使用HttpServletRequest中的request对象中的getParameter来获取form表单中提交的name属性对应的值并且通过类型转换将其赋值给book对象,最后通过model.addAttribute(“book”, book);将book对象封装到一个key为book,value为book对象的键值对中return给下一个页面。
2.3 基础数据类型绑定
采用默认类型数据绑定,虽然可以将请求域中的数据传进处理器,但从HttpServletRequest对象中取数据比较麻烦。Spring MVC支持基本类型数据绑定,即使用基本类型作为处理器的参数,自动接收来自HttpServletRequest对象中的数据。在上一个Controller中添加一个映射方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| @PostMapping("/add_book_binding_basic") public String addBookBindingBasic(@RequestParam("book_id") int bookId, @RequestParam("book_name") String bookName, String isbn, float price, @RequestParam("pub_date") String pubDate, @RequestParam("warehousing_date") String warehousingDate, String author, int inventory, @RequestParam("pub_id") int pubId, Model model){ Book book = new Book(); book.setBookId(bookId); book.setBookName(bookName); book.setIsbn(isbn); book.setPrice(price); book.setPubDate(pubDate); book.setWarehousingDate(warehousingDate); book.setAuthor(author); book.setInventory(inventory); book.setPubId(pubId); model.addAttribute("book", book); return "book/book_info"; }
|
第 2~6 行是处理器 addBookBindingBasic0 的入参表,除了最后的 model 参数外,其余都是基本类型参数。当然,基本类型也可以换成对应的引用类型,如 int 和 float 可以换成 Integer 与 Float,其运行结果相同。部分请求参数名与入参名不一致,因此,用到了 @RequestParam 注解标注。由于每个基本类型参数只接收一个数据,因此,当入参很多时,会导致处理器的参数表太长。
2.3 自定义类型转换
Spring MVC提供了org.springframework.core.convert.converter.Converter接口,供开发人员定制类型转换器,同时也可以使用org.springframework.format.Formatter接口实现同样的类型转换功能。
1 2 3 4
| package org.springframework.core.convert.converter; public interface Converter<S, T> { T convert(S source); }
|
例如,我想定制一个类型 转换器实现String到Date类型的转换
1 2 3 4 5 6 7 8 9 10 11 12
| public class DateConverter implements Converter<String, Date> { @Override public Date convert(String source) { String pattern = "yyyy-MM-dd"; SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern); try { return simpleDateFormat.parse(source); }catch (ParseException e){ throw new IllegalArgumentException("日期格式无效,请使用" + pattern + "格式"); } } }
|
自定义转换器类 DateConverter 实现 Converter<> 接口,重写了 convert0方法。DateConverter类重写 convert0 方法,使自己具备了从 String 到 Date类型转换的能力,实现 Converter<> 接口自己具备了成为类型转换器的资格。接下来通过配置,使 DateConverter类进入型转工作的就绪状态,需要在配置文件 spring-mvc.xml 中添加类型转换器的配置信息:
1 2 3 4 5 6 7
| <bean name="converterService" class="org.springframework.context.support.ConversionServiceFactoryBean"> <property name="converters"> <set><bean class="com.javaee.ex07.converter.DateConverter"/></set> </property> </bean> <mvc:annotation-driven conversion-service="converterService"/>
|
ConversionServiceFactoryBean 类在实例化后,便具备了处理 Spring MVC 默认类型的转换的能力,其集合属性 converters 中可以通过配置注人多个自定义类型转换器。第7行用于装载自定义类型转换器,为了能够验证 DateConverter 类型转换器的有效性,在 BookController 控制器类中添加一个处理器addBookBindingBasicEx();
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| @PostMapping("/add_book_binding_basic_ex") public String addBookBindingBasicEx(@RequestParam("book_id") int bookId, @RequestParam("book_name") String bookName, String isbn, float price, @RequestParam("pub_date") Date pubDate, @RequestParam("warehousing_date") Date warehousingDate, String author, int inventory, @RequestParam("pub_id") int pubId, Model model) { BookEx book = new BookEx(); book.setBookId(bookId); book.setBookName(bookName); book.setIsbn(isbn); book.setPrice(price); book.setPubDate(pubDate); book.setWarehousingDate(warehousingDate); book.setAuthor(author); book.setInventory(inventory); book.setPubId(pubId); model.addAttribute("book", book); return "book/book_info"; }
|
这个代码和上个代码的差异体现19在第 1、4、5行。显然,映射路径的差异是必需的。由于形参pubDate和warehousingDate的类型由原来的String修改成 Date。
3.复杂数据绑定
3.1 pojo绑定
基本数据类型绑定简单,但是当传入的参数数量比较多的时候,形参列表的数量会比较长不利于阅读,为此可以将pojo封装成一个pojo实体类,但是在上面的book类中只包含了pubid一个属性,但是我们需要在book类中添加一个实体类Publisher实体类时。
未完待续。。。。。