springMVC参数绑定

默认支持的参数类型

处理器形参中添加如下类型的参数处理注解适配器会默认识别并进行赋值。 1 HttpServletRequest 通过request对象获取请求信息 2 HttpServletResponse 通过response处理响应信息 3 HttpSession 通过session对象得到session中存放的对象 4 Model 通过model向页面传递数据,如下: //调用service查询商品信息 Items item = itemService.findItemById(id); model.addAttribute("item", item); 页面通过${item.XXXX}获取item对象的属性值。 model也可以通过modelMap或map将数据传到页面(这是因为底层就是这个类型,具体可以看看底层代码)。

参数绑定介绍

注解适配器对RequestMapping标记的方法进行适配,对方法中的形参会进行参数绑定,早期springmvc采用PropertyEditor(属性编辑器)进行参数绑定将request请求的参数绑定到方法形参上,3.X之后springmvc就开始使用Converter进行参数绑定。

1@RequestParam:用于绑定单个请求参数。

value:参数名字,即入参的请求参数名字,如value=“item_id”表示请求的参数区中的名字为item_id的参数的值将传入;

注意:如果请求参数中没有item_id将跑出异常:HTTP Status 500 - Required Integer parameter 'item_id' is not present required:是否必须,默认是true,表示请求中一定要有相应的参数,否则将报;TTP Status 400 - Required Integer parameter 'XXXX' is not present

defaultValue:默认值,表示如果请求中没有同名参数时的默认值(即使required=true也可以不传item_id参数值)

定义如下: public String editItem(@RequestParam(value="item_id",required=true) String id) { } 如果request请求的参数名和controller方法的形参数名称一致,适配器自动进行参数绑定(不需要手动进行绑定了)。 如果不一致可以通过@RequestParam 指定request请求的参数名绑定到哪个方法形参上。

简单类型

当请求的参数名称和处理器形参名称一致时会将请求参数与形参进行绑定。 整型 public String editItem(Model model,Integer id) throws Exception{ } 字符串 例子略 单精度/双精度 例子略 布尔型 处理器方法:     public String editItem(Model model,Integer id,Boolean status) throws Exception 请求url: http://localhost:8080/springmvc_mybatis/item/editItem.action?id=2&status=false 说明:对于布尔类型的参数,请求的参数值为true或false。 需要注意的是,如果Controller方法参数中定义的是基本数据类型,但是从页面提交过来的数据为null或者”"的话,会出现数据转换的异常。也就是必须保证表单传递过来的数据不能为null或”",所以,在开发过程中,对可能为空的数据,最好将参数数据类型定义成包装类型,具体参见下面的例子。  @RequestMapping("saysth.do") public void test(Integer count) { } } 表单代码: <form action="saysth.do" method="post"><input name="count" value="10"type="text"/> ...... </form> 和基本数据类型基本一样,不同之处在于,表单传递过来的数据可以为null或”",以上面代码为例,如果表单中count为”"或者表单中无count这个input,那么,Controller方法参数中的count值则为null。

简单pojo 简单pojo类型只包括简单类型的属性。 将pojo对象中的属性名与传递进来的属性名对应,如果传进来的参数名称和对象中的属性名称一致则将参数值设置在pojo对象中。 页面定义如下; <input type="text" name="name"/> <input type="text" name="price"/> Contrller方法定义如下: @RequestMapping("/editItemSubmit") public String editItemSubmit(Items items)throws Exception{     System.out.println(items); 请求的参数名称和pojo的属性名称一致,会自动将请求参数赋值给pojo的属性。 包装pojo 问题: 如果controller方法形参中有多个pojo且pojo中有重复的属性,使用简单pojo绑定无法有针对性的绑定, 比如:方法形参有items和User,pojo同时存在name属性,从http请求过程的name无法有针对性的绑定到items或user。 这个时候需要将pojo对象作为一个包装对象的属性,action中以该包装对象作为形参。 包装对象定义(包装的pojo里边包括了pojo如下: Public class QueryVo { private Items items; } 页面定义: <input type="text" name="items.name" /> <input type="text" name="items.price" /> Controller方法定义如下: public String useraddsubmit(Model model,QueryVo  queryVo)throws Exception{ System.out.println(queryVo.getItems()); 数组 页面定义如下: 页面选中多个checkbox向controller方法传递 <input type="checkbox" name="item_id" value="001"/> <input type="checkbox" name="item_id" value="002"/> <input type="checkbox" name="item_id" value="002"/> 传递到controller方法中的格式是:001,002,003 Controller方法中可以用String[]接收,定义如下: public String deleteitem(String[] item_id)throws Exception{         System.out.println(item_id); }

 List绑定: List需要绑定在对象上,而不能直接写在Controller方法的参数中。 Model代码: public class User {      private String firstName;      private String lastName;  } public class UserListForm {      private List<User> users;  } Controller代码: @RequestMapping("saysth.do")  public void test(UserListForm userForm) {  for (User user : userForm.getUsers()) { System.out.println(user.getFirstName() 

System.out.println(user.getFirstName() + " - " + user.getLastName()); } } } } 表单代码:

<input name="users[0].firstName" value="aaa" />

<input name="users[0].lastName" value="bbb" />

<input name="users[1].firstName" value="ccc" />

<input name="users[1].lastName" value="ddd" />

在表单中需要指定List的下标。值得一提的是,Spring会创建一个以最大下标值为size的List对象,所以,如果表单中有动态添加行、删除行的情况,就需要特别注意,譬如一个表格,用户在使用过程中经过多次删除行、增加行的操作之后,下标值就会与实际大小不一致,这时候,List中的对象,只有在表单中对应有下标的那些才会有值,否则会为null,看个例子: 表单代码:

<input name="users[0].firstName" value="aaa" />

<input name="users[0].lastName" value="bbb" />

<input name="users[1].firstName" value="ccc" />

<input name="users[1].lastName" value="ddd" />

<input name="users[20].firstName" value="eee" />

<input name="users[20].lastName" value="fff" /> 这个时候,Controller中的userForm.getUsers()获取到List的size为21,而且这21个User对象都不会为null,但是,第2到第19的User对象中的firstName和lastName都为null。打印结果: aaa - bbb ccc - ddd null - null null - null ...... null - null null - null eee - fff 6. Set绑定: Set和List类似,也需要绑定在对象上,而不能直接写在Controller方法的参数中。但是,绑定Set数据时,必须先在Set对象中add相应的数量的模型对象。 Model代码: public class User {  private String firstName;  private String lastName;  } public class UserSetForm {  private Set<User> users = new HashSet<User>();  }

Controller代码: @RequestMapping("saysth.do")  public void test(UserSetForm userForm) {  for (User user : userForm.getUsers()) { System.out.println(user.getFirstName()  System.out.println(user.getFirstName() + " - " + user.getLastName()); } } } } 表单代码:

<input name="users[0].firstName" value="aaa" />

<input name="users[0].lastName" value="bbb" />

<input name="users[1].firstName" value="ccc" />

<input name="users[1].lastName" value="ddd" />

<input name="users[2].firstName" value="eee" />

<input name="users[2].lastName" value="fff" /> 基本和List绑定类似。 需要特别提醒的是,如果最大下标值大于Set的size,则会抛出org.springframework.beans.InvalidPropertyException异常。所以,在使用时有些不便。 7. Map绑定: Map最为灵活,它也需要绑定在对象上,而不能直接写在Controller方法的参数中。 Model代码: public class User {  private String firstName;  private String lastName;  } public class UserMapForm {  private Map<String, User> users;  } Controller代码: @RequestMapping("saysth.do")  public void test(UserMapForm userForm) {  for (Map.Entry<String, User> entry : userForm.getUsers().entrySet()) { System.out.println(entry.getKey()  System.out.println(entry.getKey() + ": " + entry.getValue().getFirstName() + " - " + entry.getValue().getLastName()); } } 表单代码: <input name="users['x'].firstName" value="aaa" />

<input name="users['x'].lastName" value="bbb" />

<input name="users['y'].firstName" value="ccc" />

<input name="users['y'].lastName" value="ddd" />

<input name="users['z'].firstName" value="eee" />

<input name="users['z'].lastName" value="fff" /> 打印结果: x: aaa - bbb y: ccc - ddd z: eee - fff 1.1.1 自定义参数绑定 1.1.1.1 需求 根据业务需求自定义日期格式进行参数绑定。springmvc没有提供默认的对日期类型的绑定,需要自定义日期类型的绑定。 1.1.1.2 propertyEditor(了解) 1.1.1.2.1使用WebDataBinder  在controller方法中通过@InitBinder标识方法为参数绑定方法,通过WebDataBinder注册属性编辑器,问题是此方法只能在单个controller类中注册。 /**注册属性编辑器(字符串转换为日期)*/ @InitBinder public void initBinder(WebDataBinder binder) throws Exception {        binder.registerCustomEditor(Date.classnew CustomDateEditor(newSimpleDateFormat("yyyy-MM-dd"),true));     } 1.1.1.2.2使用WebBindingInitializer 如果想多个controller需要共同注册相同的属性编辑器,可以实现PropertyEditorRegistrar接口,并注入webBindingInitializer中。 如下: 编写CustomPropertyEditor: public class CustomPropertyEditorimplements PropertyEditorRegistrar { public void registerCustomEditors(PropertyEditorRegistry registry) {        registry.registerCustomEditor(Date.classnewCustomDateEditor(new                SimpleDateFormat("yyyy-MM-dd HH-mm-ss"),true));     } } 配置如下: <!-- 注册属性编辑器 --> <beanid="customPropertyEditor"class="cn.itcast.ssm.propertyeditor.CustomPropertyEditor"></bean> <!-- 自定义webBinder --> <bean id="customBinder" class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer"> <property name="propertyEditorRegistrars"> <list> <ref bean="customPropertyEditor"/> </list> </property> </bean> <!--注解适配器 --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"> <property name="webBindingInitializer"ref="customBinder"></property> </bean>

Converter转换器(架构师掌握) 自定义Converter public class CustomDateConverter implements Converter<String, Date> { public Date convert(String source) { try {            SimpleDateFormat simpleDateFormat = newSimpleDateFormat("yyyy-MM-dd HH-mm-ss"); return simpleDateFormat.parse(source);        } catch (Exception e) {            e.printStackTrace();        } return null;     } }

配置方式1 <!--注解适配器 --> <!-- conversionService --> <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <!-- 转换器 --> <property name="converters"> <list> <beanclass="cn.itcast.ssm.controller.converter.CustomDateConverter"/> </list> </property> </bean> 配置方式2 <mvc:annotation-driven conversion-service="conversionService"> </mvc:annotation-driven> <!-- conversionService --> <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <!-- 转换器 --> <property name="converters"> <list> <beanclass="cn.itcast.ssm.controller.converter.CustomDateConverter"/> </list> </property> </bean>

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java学习之路

05 Spring框架 依赖注入(二)

上一节我们讲了三种信息的注入,满足一个类的属性信息的注入,但是如果我们需要向一个实例中注入另一个实例呢?就像我们创建一个学生类,里边有:姓名,性别,年龄,成绩等...

2845
来自专栏Java学习之路

02 Spring框架 简单配置和三种bean的创建方式

整理了一下之前学习Spring框架时候的一点笔记。如有错误欢迎指正,不喜勿喷。 上一节学习了如何搭建SpringIOC的环境,下一步我们就来讨论一下如何利...

3215
来自专栏栗霖积跬步之旅

创建Task的多种方法

Gradle的Project从本质上说只是含有多个Task的容器,一个Task与Ant的Target相似,表示一个逻辑上的执行单元。 我们可以通过多种方式定义T...

3016
来自专栏成长道路

spark提交任务,参数的形式是JSON

spark提交任务,参数的形式是JSON 比如:spark2-submit --class com.iflytek.test.Jcseg_HiveDemo  s...

2100
来自专栏py+selenium

[笨方法学python]习题51自动化测试笔记

本节自动化测试部分看不大懂,自己每步都打印出来,帮助理解。(代码标红部分为自己加入调试为打印变量值所用)

1892
来自专栏大内老A

yield在WCF中的错误使用——99%的开发人员都有可能犯的错误[上篇]

在定义API的时候,对于一些返回集合对象的方法,很多人喜欢将返回类型定义成IEnumerable<T>,这本没有什么问题。这里要说的是另一个问题:对于返回类型为...

1818
来自专栏java一日一条

50个常见的 Java 错误及避免方法(第二部分)

System.out.println("Whatdo you want to do?");

1103
来自专栏java达人

jsp中的JSTL与EL表达式用法及区别(一)

对于JSTL和EL之间的关系,这个问题对于初学JSP的朋友来说,估计是个问题,下面来详细介绍一下JSTL和EL表达式他们之间的关系,以及JSTL和EL一些相关概...

2175
来自专栏LEo的网络日志

go常见错误总结

2715
来自专栏小樱的经验随笔

C/C++中int128的那点事

最近群友对int128这个东西讨论的热火朝天的。讲道理的话,编译器的gcc是不支持__int128这种数据类型的,比如在codeblocks 16.01/Dev...

2721

扫码关注云+社区