参数绑定,简单来说就是客户端发送请求,而请求中包含一些数据,那么这些数据怎么到达 Controller ?这在实际项目开发中也是用到的最多的,那么 SpringMVC 的参数绑定是怎么实现的呢?下面我们来详细的讲解。

1、SpringMVC 参数绑定

  在 SpringMVC 中,提交请求的数据是通过方法形参来接收的。从客户端请求的 key/value 数据,经过参数绑定,将 key/value 数据绑定到 Controller 的形参上,然后在 Controller 就可以直接使用该形参。

  

  这里涉及到参数绑定组件,那么什么是参数组件,这里可以先理解为将请求的数据转换为我们需要的数据称为参数绑定组件,也就是参数绑定转换器。SpringMVC 内置了很多参数转换器,只有在极少数情况下需要我们自定义参数转换器。

2、默认支持的类型

  SpringMVC 有支持的默认参数类型,我们直接在形参上给出这些默认类型的声明,就能直接使用了。如下:

  ①、HttpServletRequest 对象

  ②、HttpServletResponse 对象

  ③、HttpSession 对象

  ④、Model/ModelMap 对象 

  Controller 代码:

  1. @RequestMapping("/defaultParameter")
  2. public ModelAndView defaultParameter(HttpServletRequest request,HttpServletResponse response,
  3. HttpSession session,Model model,ModelMap modelMap) throws Exception{
  4. request.setAttribute("requestParameter", "request类型");
  5. response.getWriter().write("response");
  6. session.setAttribute("sessionParameter", "session类型");
  7. //ModelMap是Model接口的一个实现类,作用是将Model数据填充到request域
  8. //即使使用Model接口,其内部绑定还是由ModelMap来实现
  9. model.addAttribute("modelParameter", "model类型");
  10. modelMap.addAttribute("modelMapParameter", "modelMap类型");
  11.  
  12. ModelAndView mv = new ModelAndView();
  13. mv.setViewName("view/success.jsp");
  14. return mv;
  15. }

  表单代码:(截取主要代码)

  1. <body>
  2. request:${requestParameter}
  3. session:${sessionParameter}
  4. model:${modelParameter}
  5. modelMap:${modelMapParameter}
  6. </body>

  然后访问,页面显示如下:

  

  这里我们重点说一下 Model/ModelMap,ModelMap是Model接口的一个实现类,作用是将Model数据填充到request域,即使使用Model接口,其内部绑定还是由ModelMap来实现

3、基本数据类型的绑定

  哪些是基本数据类型,我们这里重新总结一下: 

  1. 一、byte,占用一个字节,取值范围为 -128-127,默认是“\u0000”,表示空
  2. 二、short,占用两个字节,取值范围为 -32768-32767
  3. 三、int,占用四个字节,-2147483648-2147483647
  4. 四、long,占用八个字节,对 long 型变量赋值时必须加上"L"或“l”,否则不认为是 long
  5. 五、float,占用四个字节,对 float 型进行赋值的时候必须加上“F”或“f”,如果不加,会产生编译错误,因为系统
  6. 自动将其定义为 double 型变量。double转换为float类型数据会损失精度。float a = 12.23产生编译错误的,float a = 12是正确的
  7. 六、double,占用八个字节,对 double 型变量赋值的时候最好加上“D”或“d”,但加不加不是硬性规定
  8. 七、char,占用两个字节,在定义字符型变量时,要用单引号括起来
  9. 八、boolean,只有两个值“true”和“false”,默认值为false,不能用0或非0来代替,这点和C语言不同

  我们以 int 类型为例:

  JSP 页面代码:

  1. <form action="basicData" method="post">
  2. <input name="username" value="10" type="text"/>
  3. <input type="submit" value="提交">
  4. </form>

  Controller 代码:

  1. @RequestMapping("/basicData")
  2. public void basicData(int username){
  3. System.out.println(username);//10
  4. }

  结果是 打印出了表单里面的 value 的值。

  注意:表单中input的name值和Controller的参数变量名保持一致,就能完成数据绑定。那么如果不一致呢?我们使用 @RequestParam 注解来完成,如下:

  JSP页面代码不变,<input name="username">保持原样,Controller 代码如下

  

  使用注解 @RequestParam ,我们可以使用任意形参,但是注解里面的 value 属性值要和表单的name属性值一样。

  问题:我们这里的参数是基本数据类型,如果从前台页面传递的值为 null 或者 “”的话,那么会出现数据转换的异常,就是必须保证表单传递过来的数据不能为null或”",所以,在开发过程中,对可能为空的数据,最好将参数数据类型定义成包装类型,具体参见下面的例子。

4、包装数据类型的绑定

  包装类型如Integer、Long、Byte、Double、Float、Short,(String 类型在这也是适用的)这里我们以 Integer 为例

  Controller 代码为:

  

  和基本数据类型基本一样,不同之处在于,表单传递过来的数据可以为null或”",以上面代码为例,如果表单中num为”"或者表单中无num这个input,那么,Controller方法参数中的num值则为null。

5、POJO(实体类)类型的绑定

  User.java

  1. package com.ys.po;
  2.  
  3. import java.util.Date;
  4.  
  5. public class User {
  6. private Integer id;
  7.  
  8. private String username;
  9.  
  10. private String sex;
  11.  
  12. private Date birthday;
  13.  
  14. public Integer getId() {
  15. return id;
  16. }
  17.  
  18. public void setId(Integer id) {
  19. this.id = id;
  20. }
  21.  
  22. public String getUsername() {
  23. return username;
  24. }
  25.  
  26. public void setUsername(String username) {
  27. this.username = username == null ? null : username.trim();
  28. }
  29.  
  30. public String getSex() {
  31. return sex;
  32. }
  33.  
  34. public void setSex(String sex) {
  35. this.sex = sex == null ? null : sex.trim();
  36. }
  37.  
  38. public Date getBirthday() {
  39. return birthday;
  40. }
  41.  
  42. public void setBirthday(Date birthday) {
  43. this.birthday = birthday;
  44. }
  45. }

  JSP页面:注意输入框的 name 属性值和上面 POJO 实体类的属性保持一致即可映射成功。

  1. <form action="pojo" method="post">
  2. 用户id:<input type="text" name="id" value="2"></br>
  3. 用户名:<input type="text" name="username" value="Marry"></br>
  4. 性别:<input type="text" name="sex" value="女"></br>
  5. 出生日期:<input type="text" name="birthday" value="2017-08-25"></br>
  6. <input type="submit" value="提交">
  7. </form>

  注意看:这里面我们数据都写死了,直接提交。有Integer类型的,String类型的,Date类型的。

  Controller :

  1. @RequestMapping("/pojo")
  2. public void pojo(User user){
  3. System.out.println(user);
  4. }

  我们在上面代码打个断点,然后输入URL,进入到这个Controller中:

  上面是报错了,User.java 的birthday 属性是 Date 类型的,而我们输入的是字符串类型,故绑定不了

  那么问题来了,Date 类型的数据绑定失败,如何解决这样的问题呢?这就是我们前面所说的需要自定义Date类型的转换器。

  ①、定义由String类型到 Date 类型的转换器

  1. package com.ys.util;
  2.  
  3. import java.text.ParseException;
  4. import java.text.SimpleDateFormat;
  5. import java.util.Date;
  6.  
  7. import org.springframework.core.convert.converter.Converter;
  8.  
  9. //需要实现Converter接口,这里是将String类型转换成Date类型
  10. public class DateConverter implements Converter<String, Date> {
  11.  
  12. @Override
  13. public Date convert(String source) {
  14. //实现将字符串转成日期类型(格式是yyyy-MM-dd HH:mm:ss)
  15. SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  16. try {
  17. return dateFormat.parse(source);
  18. } catch (ParseException e) {
  19. // TODO Auto-generated catch block
  20. e.printStackTrace();
  21. }
  22. //如果参数绑定失败返回null
  23. return null;
  24. }
  25.  
  26. }

  ②、在 springmvc.xml 文件中配置转换器

  1. <mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
  2.  
  3. <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
  4. <property name="converters">
  5. <!-- 自定义转换器的类名 -->
  6. <bean class="com.ys.util.DateConverter"></bean>
  7. </property>
  8. </bean>

  输入 URL,再次查看Controller的形参:

  

6、复合POJO(实体类)类型的绑定

  这里我们增加一个实体类,ContactInfo.java

  1. package com.ys.po;
  2.  
  3. public class ContactInfo {
  4. private Integer id;
  5.  
  6. private String tel;
  7.  
  8. private String address;
  9.  
  10. public Integer getId() {
  11. return id;
  12. }
  13.  
  14. public void setId(Integer id) {
  15. this.id = id;
  16. }
  17.  
  18. public String getTel() {
  19. return tel;
  20. }
  21.  
  22. public void setTel(String tel) {
  23. this.tel = tel == null ? null : tel.trim();
  24. }
  25.  
  26. public String getAddress() {
  27. return address;
  28. }
  29.  
  30. public void setAddress(String address) {
  31. this.address = address == null ? null : address.trim();
  32. }
  33. }

  然后在上面的User.java中增加一个属性 private ContactInfo contactInfo

  

  JSP 页面:注意属性name的命名,User.java 的复合属性名.字段名

   

      

  Controller

  

  User对象中有ContactInfo属性,但是,在表单代码中,需要使用“属性名(对象类型的属性).属性名”来命名input的name。

7、数组类型的绑定

  需求:我们查询出所有User 的信息,并且在JSP页面遍历显示,这时候点击提交按钮,需要在 Controller 中获得页面中显示 User 类的 id 的所有值的数组集合。

  JSP 页面:注意用户id的name值定义为 userId

  

  Controller.java

  

8、List类型的绑定

  需求:批量修改 User 用户的信息

  第一步:创建 UserVo.java,封装 List<User> 属性

  1. package com.ys.po;
  2.  
  3. import java.util.List;
  4.  
  5. public class UserVo {
  6.  
  7. private List<User> userList;
  8. public List<User> getUserList() {
  9. return userList;
  10. }
  11. public void setUserList(List<User> userList) {
  12. this.userList = userList;
  13. }
  14. }

  第二步:为了简化过程,我们直接从 Controller 中查询所有 User 信息,然后在页面显示

  Controller

  1. @RequestMapping("selectAllUserAndList")
  2. public ModelAndView selectAllUserAndList(){
  3. List<User> listUser = userService.selectAllUser();
  4. ModelAndView mv = new ModelAndView();
  5. mv.addObject("listUser", listUser);
  6. mv.setViewName("list.jsp");
  7. return mv;
  8. }

  JSP 页面

  第三步:修改页面的值后,点击提交

  

  由于我们在 JSP 页面 input 输入框定义的name属性名是 userList[${status.index}].id 这种形式的,这里我们直接用 UserVo 就能获取页面批量提交的 User信息

8、Map类型的绑定

  首先在 UserVo 里面增加一个属性 Map<String,User> userMap

  

  第二步:JSP页面,注意看 <input >输入框 name 的属性值

  

  第三步:Controller 中获取页面的属性

9、遇到的问题

  ①、form表单无法提交input输入框属性设置为 disabled 的内容

  比如:

  1. <input type="text" disabled="disabled" name="metadataName" maxlength="50" placeholder="这里输入模型英文名称" title="模型英文名称" "/>

  具有 disabled="disabled" 的属性,提交到 Controller后,metadataName 的值为null

  解决办法:改为 readonly="readonly"

  readonly:针对input(text / password)和textarea有效,在设置为true的情况下,用户可以获得焦点,但是不能编辑,在提交表单时,输入项会作为form的内容提交。

  disabled:针对所有表单元素(select,button,input,textarea等),在设置为disabled为true的情况下,表单输入项不能获得焦点,用户的所有操作无意义,在提交表单时,表单输入项不会被提交。

SpringMVC详解(五)------参数绑定的更多相关文章

  1. SpringMVC详解------参数绑定

    SpringMVC详解------参数绑定  转载于:https://blog.csdn.net/swebin/article/details/92795422 目录 1.SpringMVC 参数绑定 ...

  2. SpringMVC详解一、@RequestMapping注解与Controller接收参数

    SpringMVC详解一.@RequestMapping注解与Controller接收参数 https://blog.csdn.net/mxcsdn/article/details/80719258 ...

  3. 第5章—构建Spring Web应用程序—SpringMVC详解

    SpringMVC详解 5.1.跟踪Springmvc的请求 SpringMVC的核心流程如下: 具体步骤: 第一步:发起请求到前端控制器(DispatcherServlet) 第二步:前端控制器请求 ...

  4. pika详解(五)登录认证及connectionParameters

    pika详解(五)登录认证及connectionParameters 本文链接:https://blog.csdn.net/comprel/article/details/94662916 版权 pi ...

  5. .NET DLL 保护措施详解(五)常规条件下的破解

    为了证实在常规手段破解下能有效保护程序核心功能(演示版本对AES加解密算法及数据库的密钥(一段字符串)进行了保护),特对此DLL保护思路进行相应的测试,包含了反编译及反射测试,看是否能得到AES加解密 ...

  6. 转:Windows下的PHP开发环境搭建——PHP线程安全与非线程安全、Apache版本选择,及详解五种运行模式。

    原文来自于:http://www.ituring.com.cn/article/128439 Windows下的PHP开发环境搭建——PHP线程安全与非线程安全.Apache版本选择,及详解五种运行模 ...

  7. python设计模式之迭代器与生成器详解(五)

    前言 迭代器是设计模式中的一种行为模式,它提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示.python提倡使用生成器,生成器也是迭代器的一种. 系列文章 python设计模 ...

  8. SSM框架之SpringMVC(2)参数绑定及自定义类型转换

    SpringMVC(2)参数绑定及自定义类型转换 1.请求参数的绑定 1.1. 请求参数的绑定说明 1.1.1.绑定机制 表单提交的数据都是k=v格式的 username=haha&passw ...

  9. nginx的proxy模块详解以及参数

    文章来源 运维公会:nginx的proxy模块详解以及参数 使用nginx配置代理的时候,肯定是要用到http_proxy模块.这个模块也是在安装nginx的时候默认安装.它的作用就是将请求转发到相应 ...

随机推荐

  1. RabbitMQ系列教程之七:RabbitMQ的 C# 客户端 API 的简介

    今天这篇博文是我翻译的RabbitMQ的最后一篇文章了,介绍一下RabbitMQ的C#开发的接口.好了,言归正传吧. Net/C# 客户端 API简介1.主要的命名空间,接口和类  定义核心的API的 ...

  2. CJOJ 1071 【Uva】硬币问题(动态规划)

    CJOJ 1071 [Uva]硬币问题(动态规划) Description 有n种硬币,面值分别为v1, v2, ..., vn,每种都有无限多.给定非负整数S,可以选用多少个硬币,使得面值之和恰好为 ...

  3. Iterator、for..of,for...in和自定义遍历器**

    Iterator.for..of,for...in和自定义遍历器 Iterator: var arr = [1,2,3,4,5]; var ite = arr[Symbol.iterator](); ...

  4. cocos2dx 图片压缩工具 推荐

    随着版本的第二次迭代,包体越来越大;随之而来的也就是下载量会有所影响;毕竟每增大一点包体大小,下载的玩家就会损失一小批; 但是我们的图片都经过美术压缩打包,依然包体不小; 最后发现是因为把图片都打包成 ...

  5. 没写完。。51nod_1630: B君的竞技场(期望 概率)

    题目链接 根据 你可以认为B君的水平是在所有人中的等概率随机 ,设 每场中B君获胜的概率为p~U(0,1),在给定的x,y下至游戏结束B君的获胜场数为f(p) (这是一个关于p的函数), 由此

  6. nyoj_5:Binary String Matching

    简单字符串匹配 题目链接 #include<iostream> #include<cstring> using namespace std; int fun(char*aa,c ...

  7. 笔记evernote

    8542-1090-0308-5951 2786-2836-1103-4104 6835-5846-6090-5388 5443-4068-2394-0845

  8. 11.2.0.4 RAC 手动打补丁

    1. 下载补丁和最新OPatchGI PSU : p25869727_112040_Linux-x86-64.zipOPatch : p6880880_112000_Linux-x86-64.zip ...

  9. [js高手之路] es6系列教程 - 对象功能扩展详解

    第一:字面量对象的方法,支持缩写形式 //es6之前,这么写 var User = { name : 'ghostwu', showName : function(){ return this.nam ...

  10. react-router 离开路由前确认

    react路由在做离开前确认时,有两种方法 第一种是我们写的是动态路由,可以做一个简单的离开前确认 path: '/association/administration', component: Ad ...