SpringMVC 数据绑定实例详解

SpringMVC 数据绑定

查看spring源码可以看出spring支持转换的数据类型:

org.springframework.beans.PropertyEditorRegistrySupport:

/**
 * Actually register the default editors for this registry instance.
 */
private void createDefaultEditors() {
  this.defaultEditors = new HashMap<Class, PropertyEditor>(64); 

  // Simple editors, without parameterization capabilities.
  // The JDK does not contain a default editor for any of these target types.
  this.defaultEditors.put(Charset.class, new CharsetEditor());
  this.defaultEditors.put(Class.class, new ClassEditor());
  this.defaultEditors.put(Class[].class, new ClassArrayEditor());
  this.defaultEditors.put(Currency.class, new CurrencyEditor());
  this.defaultEditors.put(File.class, new FileEditor());
  this.defaultEditors.put(InputStream.class, new InputStreamEditor());
  this.defaultEditors.put(InputSource.class, new InputSourceEditor());
  this.defaultEditors.put(Locale.class, new LocaleEditor());
  this.defaultEditors.put(Pattern.class, new PatternEditor());
  this.defaultEditors.put(Properties.class, new PropertiesEditor());
  this.defaultEditors.put(Resource[].class, new ResourceArrayPropertyEditor());
  this.defaultEditors.put(TimeZone.class, new TimeZoneEditor());
  this.defaultEditors.put(URI.class, new URIEditor());
  this.defaultEditors.put(URL.class, new URLEditor());
  this.defaultEditors.put(UUID.class, new UUIDEditor()); 

  // Default instances of collection editors.
  // Can be overridden by registering custom instances of those as custom editors.
  this.defaultEditors.put(Collection.class, new CustomCollectionEditor(Collection.class));
  this.defaultEditors.put(Set.class, new CustomCollectionEditor(Set.class));
  this.defaultEditors.put(SortedSet.class, new CustomCollectionEditor(SortedSet.class));
  this.defaultEditors.put(List.class, new CustomCollectionEditor(List.class));
  this.defaultEditors.put(SortedMap.class, new CustomMapEditor(SortedMap.class)); 

  // Default editors for primitive arrays.
  this.defaultEditors.put(byte[].class, new ByteArrayPropertyEditor());
  this.defaultEditors.put(char[].class, new CharArrayPropertyEditor()); 

  // The JDK does not contain a default editor for char!
  this.defaultEditors.put(char.class, new CharacterEditor(false));
  this.defaultEditors.put(Character.class, new CharacterEditor(true)); 

  // Spring's CustomBooleanEditor accepts more flag values than the JDK's default editor.
  this.defaultEditors.put(boolean.class, new CustomBooleanEditor(false));
  this.defaultEditors.put(Boolean.class, new CustomBooleanEditor(true)); 

  // The JDK does not contain default editors for number wrapper types!
  // Override JDK primitive number editors with our own CustomNumberEditor.
  this.defaultEditors.put(byte.class, new CustomNumberEditor(Byte.class, false));
  this.defaultEditors.put(Byte.class, new CustomNumberEditor(Byte.class, true));
  this.defaultEditors.put(short.class, new CustomNumberEditor(Short.class, false));
  this.defaultEditors.put(Short.class, new CustomNumberEditor(Short.class, true));
  this.defaultEditors.put(int.class, new CustomNumberEditor(Integer.class, false));
  this.defaultEditors.put(Integer.class, new CustomNumberEditor(Integer.class, true));
  this.defaultEditors.put(long.class, new CustomNumberEditor(Long.class, false));
  this.defaultEditors.put(Long.class, new CustomNumberEditor(Long.class, true));
  this.defaultEditors.put(float.class, new CustomNumberEditor(Float.class, false));
  this.defaultEditors.put(Float.class, new CustomNumberEditor(Float.class, true));
  this.defaultEditors.put(double.class, new CustomNumberEditor(Double.class, false));
  this.defaultEditors.put(Double.class, new CustomNumberEditor(Double.class, true));
  this.defaultEditors.put(BigDecimal.class, new CustomNumberEditor(BigDecimal.class, true));
  this.defaultEditors.put(BigInteger.class, new CustomNumberEditor(BigInteger.class, true)); 

  // Only register config value editors if explicitly requested.
  if (this.configValueEditorsActive) {
    StringArrayPropertyEditor sae = new StringArrayPropertyEditor();
    this.defaultEditors.put(String[].class, sae);
    this.defaultEditors.put(short[].class, sae);
    this.defaultEditors.put(int[].class, sae);
    this.defaultEditors.put(long[].class, sae);
  }
}

下面挑选一些常用的数据类型,举例说明它们的绑定方式

1. 基本数据类型(以int为例,其他类似):

    Controller代码:

@RequestMapping("test.do")
public void test(int num) { 

}

    JSP表单代码:

<form action="test.do" method="post">
  <input name="num" value="10" type="text"/>
  ......
</form>

表单中input的name值和Controller的参数变量名保持一致,就能完成基本数据类型的数据绑定,如果不一致可以使用@RequestParam标注实现。值得一提的是,如果Controller方法参数中定义的是基本数据类型,但是从jsp提交过来的数据为null或者""的话,会出现数据转换的异常。也就是说,必须保证表单传递过来的数据不能为null或"",所以,在开发过程中,对可能为空的数据,最好将参数数据类型定义成包装类型,具体参见下面的第二条。

2. 包装类型(以Integer为例,其他类似):

    Controller代码:

@RequestMapping("test.do")
public void test(Integer num) { 

}

   JSP表单代码:

<form action="test.do" method="post">
  <input name="num" value="10" type="text"/>
  ......
</form>

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

3. 自定义对象类型:

    Model代码:

public class User { 

  private String firstName; 

  private String lastName; 

  public String getFirstName() {
    return firstName;
  } 

  public void setFirstName(String firstName) {
    this.firstName = firstName;
  } 

  public String getLastName() {
    return lastName;
  } 

  public void setLastName(String lastName) {
    this.lastName = lastName;
  } 

}

    Controller代码:

@RequestMapping("test.do")
public void test(User user) { 

}

    JSP表单代码:

<form action="test.do" method="post">
  <input name="firstName" value="张" type="text"/>
  <input name="lastName" value="三" type="text"/>
  ......
</form>

非常简单,只需将对象的属性名和input的name值一一对应即可。

4. 自定义复合对象类型:

    Model代码:

public class ContactInfo { 

  private String tel; 

  private String address; 

  public String getTel() {
    return tel;
  } 

  public void setTel(String tel) {
    this.tel = tel;
  } 

  public String getAddress() {
    return address;
  } 

  public void setAddress(String address) {
    this.address = address;
  } 

} 

public class User { 

  private String firstName; 

  private String lastName; 

  private ContactInfo contactInfo; 

  public String getFirstName() {
    return firstName;
  } 

  public void setFirstName(String firstName) {
    this.firstName = firstName;
  } 

  public String getLastName() {
    return lastName;
  } 

  public void setLastName(String lastName) {
    this.lastName = lastName;
  } 

  public ContactInfo getContactInfo() {
    return contactInfo;
  } 

  public void setContactInfo(ContactInfo contactInfo) {
    this.contactInfo = contactInfo;
  } 

}

    Controller代码:

@RequestMapping("test.do")
public void test(User user) {
  System.out.println(user.getFirstName());
  System.out.println(user.getLastName());
  System.out.println(user.getContactInfo().getTel());
  System.out.println(user.getContactInfo().getAddress());
}

    JSP表单代码:

<form action="test.do" method="post">
  <input name="firstName" value="张" /><br>
  <input name="lastName" value="三" /><br>
  <input name="contactInfo.tel" value="13809908909" /><br>
  <input name="contactInfo.address" value="北京海淀" /><br>
  <input type="submit" value="Save" />
</form>

User对象中有ContactInfo属性,Controller中的代码和第3点说的一致,但是,在jsp代码中,需要使用“属性名(对象类型的属性).属性名”来命名input的name。

5. List绑定:

List需要绑定在对象上,而不能直接写在Controller方法的参数中。

    Model代码:

public class User { 

  private String firstName; 

  private String lastName; 

  public String getFirstName() {
    return firstName;
  } 

  public void setFirstName(String firstName) {
    this.firstName = firstName;
  } 

  public String getLastName() {
    return lastName;
  } 

  public void setLastName(String lastName) {
    this.lastName = lastName;
  } 

} 

    public class UserListForm { 

  private List<User> users; 

  public List<User> getUsers() {
    return users;
  } 

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

}

    Controller代码:

@RequestMapping("test.do")
public void test(UserListForm userForm) {
  for (User user : userForm.getUsers()) {
    System.out.println(user.getFirstName() + " - " + user.getLastName());
  }
}

    JSP表单代码:

<form action="test.do" method="post">
  <table>
   <thead>
     <tr>
      <th>First Name</th>
      <th>Last Name</th>
     </tr>
   </thead>
   <tfoot>
     <tr>
      <td colspan="2"><input type="submit" value="Save" /></td>
     </tr>
   </tfoot>
   <tbody>
     <tr>
      <td><input name="users[0].firstName" value="aaa" /></td>
      <td><input name="users[0].lastName" value="bbb" /></td>
     </tr>
     <tr>
      <td><input name="users[1].firstName" value="ccc" /></td>
      <td><input name="users[1].lastName" value="ddd" /></td>
     </tr>
     <tr>
      <td><input name="users[2].firstName" value="eee" /></td>
      <td><input name="users[2].lastName" value="fff" /></td>
     </tr>
   </tbody>
  </table>
</form>

其实,这和第4点User对象中的contantInfo数据的绑定有点类似,但是这里的UserListForm对象里面的属性被定义成List,而不是普通自定义对象。所以,在JSP中需要指定List的下标。值得一提的是,Spring会创建一个以最大下标值为size的List对象,所以,如果JSP表单中有动态添加行、删除行的情况,就需要特别注意,譬如一个表格,用户在使用过程中经过多次删除行、增加行的操作之后,下标值就会与实际大小不一致,这时候,List中的对象,只有在jsp表单中对应有下标的那些才会有值,否则会为null,看个例子:

    JSP表单代码:

<form action="test.do" method="post">
  <table>
   <thead>
     <tr>
      <th>First Name</th>
      <th>Last Name</th>
     </tr>
   </thead>
   <tfoot>
     <tr>
      <td colspan="2"><input type="submit" value="Save" /></td>
     </tr>
   </tfoot>
   <tbody>
     <tr>
      <td><input name="users[0].firstName" value="aaa" /></td>
      <td><input name="users[0].lastName" value="bbb" /></td>
     </tr>
     <tr>
      <td><input name="users[1].firstName" value="ccc" /></td>
      <td><input name="users[1].lastName" value="ddd" /></td>
     </tr>
     <tr>
      <td><input name="users[20].firstName" value="eee" /></td>
      <td><input name="users[20].lastName" value="fff" /></td>
     </tr>
   </tbody>
  </table>
</form>

这个时候,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
null - null
null - null
null - null
null - null
null - null
null - null
null - null
null - null
null - null
null - null
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 String getFirstName() {
    return firstName;
  } 

  public void setFirstName(String firstName) {
    this.firstName = firstName;
  } 

  public String getLastName() {
    return lastName;
  } 

  public void setLastName(String lastName) {
    this.lastName = lastName;
  } 

} 

public class UserSetForm { 

  private Set<User> users = new HashSet<User>(); 

  public UserSetForm(){
    users.add(new User());
    users.add(new User());
    users.add(new User());
  } 

  public Set<User> getUsers() {
    return users;
  } 

  public void setUsers(Set<User> users) {
    this.users = users;
  } 

}

Controller代码:

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

    JSP表单代码:

<form action="test.do" method="post">
  <table>
   <thead>
     <tr>
      <th>First Name</th>
      <th>Last Name</th>
     </tr>
   </thead>
   <tfoot>
     <tr>
      <td colspan="2"><input type="submit" value="Save" /></td>
     </tr>
   </tfoot>
   <tbody>
     <tr>
      <td><input name="users[0].firstName" value="aaa" /></td>
      <td><input name="users[0].lastName" value="bbb" /></td>
     </tr>
     <tr>
      <td><input name="users[1].firstName" value="ccc" /></td>
      <td><input name="users[1].lastName" value="ddd" /></td>
     </tr>
     <tr>
      <td><input name="users[2].firstName" value="eee" /></td>
      <td><input name="users[2].lastName" value="fff" /></td>
     </tr>
   </tbody>
  </table>
</form>

基本和List绑定类似。

需要特别提醒的是,如果最大下标值大于Set的size,则会抛出org.springframework.beans.InvalidPropertyException异常。所以,在使用时有些不便。暂时没找到解决方法,如果有网友知道,请回帖共享你的做法。

5. Map绑定:

Map最为灵活,它也需要绑定在对象上,而不能直接写在Controller方法的参数中。

    Model代码:

public class User { 

  private String firstName; 

  private String lastName; 

  public String getFirstName() {
    return firstName;
  } 

  public void setFirstName(String firstName) {
    this.firstName = firstName;
  } 

  public String getLastName() {
    return lastName;
  } 

  public void setLastName(String lastName) {
    this.lastName = lastName;
  } 

} 

public class UserMapForm { 

  private Map<String, User> users; 

  public Map<String, User> getUsers() {
    return users;
  } 

  public void setUsers(Map<String, User> users) {
    this.users = users;
  } 

}

    Controller代码:

@RequestMapping("test.do")
public void test(UserMapForm userForm) {
  for (Map.Entry<String, User> entry : userForm.getUsers().entrySet()) {
    System.out.println(entry.getKey() + ": " + entry.getValue().getFirstName() + " - " +
                 entry.getValue().getLastName());
  }
}

  JSP表单代码:

<form action="test.do" method="post">
  <table>
   <thead>
     <tr>
      <th>First Name</th>
      <th>Last Name</th>
     </tr>
   </thead>
   <tfoot>
     <tr>
      <td colspan="2"><input type="submit" value="Save" /></td>
     </tr>
   </tfoot>
   <tbody>
     <tr>
      <td><input name="users['x'].firstName" value="aaa" /></td>
      <td><input name="users['x'].lastName" value="bbb" /></td>
     </tr>
     <tr>
      <td><input name="users['y'].firstName" value="ccc" /></td>
      <td><input name="users['y'].lastName" value="ddd" /></td>
     </tr>
     <tr>
      <td><input name="users['z'].firstName" value="eee" /></td>
      <td><input name="users['z'].lastName" value="fff" /></td>
     </tr>
   </tbody>
  </table>
</form>

打印结果:

x: aaa - bbb
y: ccc - ddd
z: eee - fff 

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

(0)

相关推荐

  • SpringMVC实现数据绑定及表单标签

    首先理解数据绑定 为什么要使用数据绑定 基于HTTP特性,所有的用户输入的请求参数类型都是String,比如下面表单: 但我们提交后,为了将请求信息映射到模型中,还需要手动进行格式转换,此外还借助了一个中转对象productForm,其字段名称和Product一模一样,只是类型为String. @RequestMapping(value = "/product_save",method = RequestMethod.POST) public String saveProduct(Pr

  • SpringMVC 数据绑定实例详解

    SpringMVC 数据绑定 查看spring源码可以看出spring支持转换的数据类型: org.springframework.beans.PropertyEditorRegistrySupport: /** * Actually register the default editors for this registry instance. */ private void createDefaultEditors() { this.defaultEditors = new HashMap<

  • SpringMVC+Mysql实例详解(附demo)

    一直用的是ssh,因为公司要用到SpringMVC,以前也没接触过,所以今天来和大家一起学习一下这个框架,以便工作需要. 首先我们先来了解一下什么是模式,模式就是解决某一类问题的方法论,把解决这类问题的解决方法归总到理论的高度,这就是模式.模式是一种指导,在一个良好的指导下,有助于开发人员完成任务.做出一个优秀的设计方案,能达到事半功倍的效果.而且会得到解决问题的最佳办法. mvc模式起源于Smalltalk语言,mvc是Model-View-Controller的简写.mvc减弱了业务逻辑接口

  • Angularjs中数据绑定的实例详解

    Angularjs中数据绑定的实例详解 这是一个最简单的angularjs的例子,关于数据绑定的,大家可以执行一下,看看效果 <html ng-app> <head> <title>angularjs-include</title> <script type="text/javascript" src="js/angular/angular.min.js"></script> </head

  • Springmvc ajax跨域请求处理方法实例详解

    上次给一个网站写网站  前后端分离 最后跪在ajax跨域上面了  自己在网上找了个方法  亲试可用  记录一下 写一个类  继承HandlerInterceptorAdapter package com.util; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.handler.Ha

  • SpringMVC自定义属性编辑器详解及实例

    SpringMVC自定义属性编辑器详解及实例 自定义springMVC的属性编辑器主要有两种方式,一种是使用@InitBinder标签在运行期注册一个属性编辑器,这种编辑器只在当前Controller里面有效:还有一种是实现自己的 WebBindingInitializer,然后定义一个AnnotationMethodHandlerAdapter的bean,在此bean里面进行注册 ,这种属性编辑器是全局的. 第一种方式: import java.beans.PropertyEditorSupp

  • springmvc与mybatis集成配置实例详解

    简单之美,springmvc,mybatis就是一个很好的简单集成方案,能够满足一般的项目需求.闲暇时间把项目配置文件共享出来,供大家参看: 1.首先我们来看下依赖的pom: <!-- spring --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.ve

  • SpringMVC下获取验证码实例详解

    SpringMVC下获取验证码实例详解 前言: 1.用户一开始登录的时候, 不建议出现验证码, 这一点在很多网站上已经体现的很好了, 只有当用户连续输错三次或者以上才会要求用户输入验证码. 2.记录用户输错次数最好不要使用 session 来记录, 因为 session 是跟客户端浏览器会话有关的, 如果用重启浏览器或者换新的浏览器再来登录或者试错, 就是新的回话了, 原来记录的错误次数就失效了. 建议此处采用缓存机制来实现, 简单处理就是采用 Map<用户登录id, 错误次数> 来实现, 如

  • 实例详解SpringMVC入门使用

    MVC模式(Model-View-Controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model),视图(View)和控制器(Controller).通过分层使开发的软件结构更清晰,从而达到开发效率的提高,可维护性和扩展性得到提高.Spring提供的MVC框架是在J2EE Web开发中对MVC模式的一个实现,本文通过实例讲解一下Spring MVC 的使用. 先来看一个HTTP request在Spring的MVC框架是怎么被处理的:(图片来源于Spring

  • Angular.js之作用域scope'@','=','&'实例详解

    什么是scope AngularJS 中,作用域是一个指向应用模型的对象,它是表达式的执行环境.作用域有层次结构,这个层次和相应的 DOM 几乎是一样的.作用域能监控表达式和传递事件. 在 HTML 代码中,一旦一个 ng-app 指令被定义,那么一个作用域就产生了,由 ng-app 所生成的作用域比较特殊,它是一个根作用域($rootScope),它是其他所有$Scope 的最顶层. 除了用 ng-app 指令可以产生一个作用域之外,其他的指令如 ng-controller,ng-repeat

  • 基于Spring + Spring MVC + Mybatis 高性能web构建实例详解

    一直想写这篇文章,前段时间痴迷于JavaScript.NodeJs.AngularJS,做了大量的研究,对前后端交互有了更深层次的认识. 今天抽个时间写这篇文章,我有预感,这将是一篇很详细的文章,详细的配置,详细的注释,看起来应该很容易懂. 用最合适的技术去实现,并不断追求最佳实践.这就是架构之道. 希望这篇文章能给你们带来一些帮助,同时希望你们可以为这个项目贡献你的想法. 源码地址:https://github.com/Eliteams/quick4j 点击打开 源码地址:https://gi

随机推荐