Spring MVC中基于自定义Editor的表单数据处理技巧分享

面向对象的编程方式极大地方便了程序员在管理数据上所花费的精力。在基于Spring MVC的Web开发过程当中,可以通过对象映射的方式来管理表单提交上来的数据,而不用去一个一个地从request中提取出来。另外,这一功能还支持基本数据类型的映射。例如in、long、float等等。这样我们就能从传统单一的String类型中解脱出来。然而,应用是灵活的。我们对数据的需求是千变万化的。有些时候我们需要对表单的数据进行兼容处理。

例如日期格式的兼容:

中国的日期标注习惯采用yyyy-MM-dd格式,欧美习惯采用MM/dd/yyyy。虽然两种格式都是日期的标注方法,但是往往我们要想达到兼容的目的必须做繁琐的转换。

例如价格的兼容:

价格无非就是一串数字,我们经常用的就是0.00这种表达形式,而对于金额较大的价格我们还习惯采用0,000.00这样带有逗号分隔的价格表述形式。

其实Spring MVC中已经考虑到了这个问题,在Controller中可以在初始化绑定的时候注册一个编辑器。当表单提交过来的数据映射到某一特定类型(甚至是特定参数)时可以按照自定义的方法进行转换。(除二进制方式传输过来的数据以外,通常我们认为所有传过来的参数不论是什么内容,一律认为是字符串)

下面我虚构了一个需求:

我有一个表单,里面需要填写用户名、生日和积分。这分别代表了String类型、Date类型和Long类型。下面是表单内容:


代码如下:

<form action="getObj.do" method="post">
 <table>
  <tr>
   <td>用户名:</td>
   <td><input type="text" name="userName" value="Name Test" /></td>
   <td>*普通字符串</td>
  </tr>
  <tr>
   <td>生日:</td>
   <td><input type="text" name="birthday" value="2013-3-7" /></td>
   <td>*支持格式: yyyy-MM-dd 或 MM/dd/yyyy</td>
  </tr>
  <tr>
   <td>积分:</td>
   <td><input type="text" name="score" value="1,000" /></td>
   <td>*支持纯数字或带逗号分隔的数字</td>
  </tr>
  <tr>
   <td colspan="3"><input type="submit" value="提交" /></td>
  </tr>
 </table>
</form>

这里根据表单,我们映射了如下的一个表单对象,这里对象的属性名称要和上面表单的字段name一致:


代码如下:

package blog.csdn.net.chaijunkun.formObjs;

import java.util.Date;

public class UserInfo {

private String userName;

private Date birthday;

private Long score;

//getters and setters...

}

那么我们想接收这样一个表单数据,可以写一个对表单处理的方法:


代码如下:

package blog.csdn.net.chaijunkun.controller;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import blog.csdn.net.chaijunkun.formObjs.UserInfo;

@Controller
public class ObjController {

private static Logger logger= Logger.getLogger(ObjController.class);

public ObjController(){
  logger.info("对象映射控制器初始化");
 }

@RequestMapping(value="/getObj.do")
 public String modifyUser(HttpServletRequest request,
   HttpServletResponse response,Map<String, Object> model,
   UserInfo userInfo){
  logger.info("收集对象信息");
  model.put("userInfo", userInfo);  
  return "user";
 }

}

如果仅仅是这么写,当然还不能做到多格式兼容。我们需要写一个针对日期和Long型的格式兼容编辑器。编辑器需要至少继承自类:java.beans.PropertyEditorSupport。当然,也可以继承Spring内置的一些编辑器,例如:org.springframework.beans.propertyeditors.CustomNumberEditor,这个是专门用来处理数字转换的。无论是继承哪一个,方法都是一样的:

第一步:重写公有的void setAsText(String text)方法;

第二步:将转换好的数据调用setValue(Object obj)进行写入。

下面我们先实现一个日期兼容的编辑器:


代码如下:

package blog.csdn.net.chaijunkun.editors;

import java.beans.PropertyEditorSupport;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class MyDateEditor extends PropertyEditorSupport {

@Override
 /**
  * text是表单传入的数据内容
  */
 public void setAsText(String text){
  Date value= null;
  SimpleDateFormat sdf= new SimpleDateFormat();
  sdf.applyPattern("yyyy-MM-dd");
  try{
   value= sdf.parse(text);
  }catch(ParseException e1){
   sdf.applyPattern("MM/dd/yyyy");
   try {
    value= sdf.parse(text);
   } catch (ParseException e2) {
    value= null;
   }
  }
  //这一步将转换好的数据写入到对象映射的属性中
  setValue(value);
 }

}

然后我们再来写一个针对Long型的编辑器,可以支持带逗号分隔和不带逗号分隔的数值表达形式:


代码如下:

package blog.csdn.net.chaijunkun.editors;

import org.springframework.beans.propertyeditors.CustomNumberEditor;

public class MyLongEditor extends CustomNumberEditor  {

public MyLongEditor(){
  super(Long.class, true);
 }

@Override
 public void setAsText(String text){
  if ((text== null) || text.trim().equals("")){
   setValue(null);
  }else{
   Long value= null;
   try{
    //按照标准的数字格式尝试转换
    value= Long.parseLong(text);
   }catch(NumberFormatException e){
    //尝试去除逗号 然后再转换
    text= text.replace(",", "");
    value= Long.parseLong(text);
   }
   //转好之后将值返给被映射的属性
   setValue(value);   
  }
 }

}

好了,这两个编辑器写好了,如何让它们发挥作用呢?这需要在Controller内加一个数据转换时的绑定方法:


代码如下:

@InitBinder
public void initBinder(HttpServletRequest request, ServletRequestDataBinder binder){
 binder.registerCustomEditor(Date.class, new MyDateEditor());
 binder.registerCustomEditor(Long.class, new MyLongEditor());
}

上面的代码作用就是:当接收到表单数据,Spring发现参数名能够与对象属性相对应,而转换的类型恰好也是在上述代码中注册过的类似,则会将数据内容按照指定的编辑器来做转换。

我们来试一下:

如下图所示:

同样,数据被正确识别了。

通过以上方法,我们成功地兼容了多种数据格式。

写在后面:

其实针对日期格式,我开始的时候想写成下面代码那样来实现兼容:


代码如下:

@InitBinder
public void initBinder(HttpServletRequest request, ServletRequestDataBinder binder){
 binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
 binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("MM/dd/yyyy"), true));
}

后来我发现,这样写之后只支持MM/dd/yyyy格式的日期,提交yyyy-MM-dd格式的日期后会抛出异常。看来,对于同一类型,在一个控制器里只能注册一个编辑器,而且是最后一个被注册的才起作用。

另外,在文章刚开始的时候写到,不仅可以按类型,甚至是某一类型的某个属性都可以按照自己的要求定制编辑器,同时不影响其它同类型的属性。这个很容易,在registerCustomEditor方法中还有一个重载的方法,第二个参数可以指定具体的属性名称。这样就很容易控制细粒度了。

(0)

相关推荐

  • SpringMVC处理Form表单实例

    Spring MVC 表单处理例子下面的例子说明了如何编写一个简单的基于 web 的应用程序,它利用了使用 Spring 的 Web MVC 框架的 HTML 表单. 一 测试项目搭建 (1)新建Java Web项目,并引入几个SpringMVC项目所需要的jar包,项目结构和所需要的jar包如下: ①web.xml: <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3

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

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

  • Spring学习笔记2之表单数据验证、文件上传实例代码

    在上篇文章给大家介绍了Spring学习笔记1之IOC详解尽量使用注解以及java代码,接下来本文重点给大家介绍Spring学习笔记2之表单数据验证.文件上传实例代码,具体内容,请参考本文吧! 一.表单数据验证 用户注册时,需要填写账号.密码.邮箱以及手机号,均为必填项,并且需要符合一定的格式.比如账号需要32位以内,邮箱必须符合邮箱格式,手机号必须为11位号码等.可以采用在注册时验证信息,或者专门写一个工具类用来验证:来看下在SpringMVC中如何通过简单的注释实现表单数据验证. 在javax

  • [Spring MVC] -简单表单提交实例

    Spring MVC自带的表单标签比较简单,很多时候需要借助EL和JSTL来完成. 下面是一个比较简单的表单提交页面功能: 1.User model package com.my.controller.bean; import java.util.Date; import java.util.List; import javax.validation.constraints.Future; import javax.validation.constraints.Max; import javax

  • Spring MVC---数据绑定和表单标签详解

    数据绑定和表单标签 数据绑定 数据绑定是将用户输入绑定到领域模型的一种特性,在Spring MVC的controller和view数据传递中,基于HTTP请求的特性,所有HTTP请求参数的类型均为字符串,如果模型领域需要绑定的类型为double或int,则需要手动进行类型转换,而有了数据绑定后,就不需要手动将HTTP请求中的String类型转换为模型需要的类型了,数据绑定的另一个好处是,当输入验证失败时,会重新生成一个HTML表单,无需重新填写输入字段. 表单标签库 表单标签库中包含了可以用在J

  • Spring MVC中基于自定义Editor的表单数据处理技巧分享

    面向对象的编程方式极大地方便了程序员在管理数据上所花费的精力.在基于Spring MVC的Web开发过程当中,可以通过对象映射的方式来管理表单提交上来的数据,而不用去一个一个地从request中提取出来.另外,这一功能还支持基本数据类型的映射.例如in.long.float等等.这样我们就能从传统单一的String类型中解脱出来.然而,应用是灵活的.我们对数据的需求是千变万化的.有些时候我们需要对表单的数据进行兼容处理. 例如日期格式的兼容: 中国的日期标注习惯采用yyyy-MM-dd格式,欧美

  • Spring MVC中自定义拦截器的实例讲解

    1. 引言 拦截器(Interceptor)实现对每一个请求处理前后进行相关的业务处理,类似于Servlet的Filter. 我们可以让普通的Bean实现HandlerIntercpetor接口或继承HandlerInterceptorAdapter类来实现自定义拦截器. 通过重写WebMvcConfigurerAdapter的addIntercetors方法来注册一个计算每一次请求的处理时间的拦截器. 2. 自定义拦截器的实现 2.1 定义拦截器 新建LogInterceptor类,并继承Ha

  • 详解Http请求中Content-Type讲解以及在Spring MVC中的应用

    详解Http请求中Content-Type讲解以及在Spring MVC中的应用 引言: 在Http请求中,我们每天都在使用Content-type来指定不同格式的请求信息,但是却很少有人去全面了解content-type中允许的值有多少,这里将讲解Content-Type的可用值,以及在spring MVC中如何使用它们来映射请求信息. 1.  Content-Type MediaType,即是Internet Media Type,互联网媒体类型:也叫做MIME类型,在Http协议消息头中,

  • Spring MVC 中 短信验证码功能的实现方法

    在外部网站中短信的验证很有必要,比如在实现注册.验证用户信息等的情况下.在SpringMVC中的实现如下: 短信接口 短信接口,有些企业会购买的有移动的短信平台接口.如果是个人或者是小企业可以使用一些云服务的.比如百度的API Store上面的. 我使用的是:http://apistore.baidu.com/apiworks/servicedetail/1018.html 当然短信接口肯定都是要付费的,而且是基于模板的,具体的使用说明可以看这个网址里面的使用说明. 前端界面 前端的界面,可能如

  • Spring MVC中处理ajax请求的跨域问题与注意事项详解

     前言 有时候前后台做数据交互,会遇到烦人的跨域请求问题,如果你还是一枚编程小白来说,无疑来说是很痛苦的事. 当然网上也肯定会有一些解决方法.但自身实力有限,不一定会看的懂,能把问题解决了.所以下面这篇文章就来给大家总结介绍在Spring MVC中处理ajax请求的跨域问题与一些注意事项,话不多说了,来一起看看详细的介绍吧. 为何跨域 简单的说即为浏览器限制访问A站点下的js代码对B站点下的url进行ajax请求.假如当前域名是www.abc.com,那么在当前环境中运行的js代码,出于安全考虑

  • spring mvc中的@PathVariable动态参数详解

    目录 spring mvc @PathVariable动态参数 spring mvc是如何做到根据参数名动态绑定参数的? 反射获取参数名 -parameters参数 -g参数 ASM SpringMVC的处理方式 总结 spring mvc @PathVariable动态参数 spring mvc中的@PathVariable是用来获得请求url中的动态参数的,十分方便 @Controller public class TestController { @RequestMapping(value

  • Spring MVC中的Controller进行单元测试的实现

    目录 导入静态工具方法 初始化MockMvc 执行测试 测试GET接口 测试POST接口 测试文件上传 定义预期结果 写在最后 对Controller进行单元测试是Spring框架原生就支持的能力,它可以模拟HTTP客户端发起对服务地址的请求,可以不用借助于诸如Postman这样的外部工具就能完成对接口的测试.具体来讲,是由Spring框架中的spring-test模块提供的实现,详见MockMvc. 如下将详细阐述如何使用MockMvc测试框架实现对“Spring Controller”进行单

  • spring mvc中的@ModelAttribute注解示例介绍

    前言 本文介绍在spring mvc中非常重要的注解@ModelAttribute.这个注解可以用在方法参数上,或是方法声明上.这个注解的主要作用是绑定request或是form参数到模型对象.可以使用保存在request或session中的对象来组装模型对象.注意,被@ModelAttribute注解的方法会在controller方法(@RequestMapping注解的)之前执行.因为模型对象要先于controller方法之前创建. 请看下面的例子 ModelAttributeExample

  • Spring MVC中Ajax实现二级联动的简单实例

    今天写项目遇到了二级联动,期间遇到点问题,写个博客记录一下. 后台Controller: @RequestMapping("/faultType") @ResponseBody public Map<String,Object> faultType(int id,HttpServletRequest request)throws IOException { String ReturnMessage = ""; //获取所有子类故障类型 List<F

  • MVC中基于Ajax和HTML5实现文件上传功能

    引言 在实际编程中,经常遇到实现文件上传并显示上传进度的功能,基于此目的,本文就为大家介绍不使用flash 或任何上传文件的插件来实现带有进度显示的文件上传功能. 基本功能:实现带有进度条的文件上传功能 高级功能:通过拖拽文件的操作实现多个文件上传功能 背景 HTML5提供了一种标准的访问本地文件的方法--File API规格说明,通过调用File API 能够访问文件信息,也可以利用客户端来验证上传文件的类型和大小是否规范. 该规格说明包含以下几个接口来使用文件: File接口:具有文件的"读

随机推荐