- 浏览: 21513686 次
- 性别:
博客专栏
-
跟我学spring3
浏览量:2420451
-
Spring杂谈
浏览量:3010227
-
跟开涛学SpringMVC...
浏览量:5640572
-
Servlet3.1规范翻...
浏览量:260217
-
springmvc杂谈
浏览量:1597941
-
hibernate杂谈
浏览量:250369
-
跟我学Shiro
浏览量:5860584
-
跟我学Nginx+Lua开...
浏览量:702883
-
亿级流量网站架构核心技术
浏览量:785743
文章分类
- 全部博客 (329)
- 跟我学Nginx+Lua开发 (13)
- 跟我学spring (54)
- 跟开涛学SpringMVC (34)
- spring4 (16)
- spring杂谈 (50)
- springmvc杂谈 (22)
- 跟我学Shiro (26)
- shiro杂谈 (3)
- hibernate杂谈 (10)
- java开发常见问题分析 (36)
- 加速Java应用开发 (5)
- Servlet 3.1规范[翻译] (21)
- servlet3.x (2)
- websocket协议[翻译] (14)
- websocket规范[翻译] (1)
- java web (6)
- db (1)
- js & jquery & bootstrap (4)
- 非技术 (4)
- reminder[转载] (23)
- 跟叶子学把妹 (8)
- nginx (2)
- 架构 (19)
- flume架构与源码分析 (4)
最新评论
-
xxx不是你可以惹得:
认真看错误代码,有时候重启电脑就行了 醉了 我把数据库配置写死 ...
第十六章 综合实例——《跟我学Shiro》 -
dagger9527:
holyselina 写道您前面说到能获取调用是的参数数组,我 ...
【第六章】 AOP 之 6.6 通知参数 ——跟我学spring3 -
xxx不是你可以惹得:
Access denied for user 'root'@' ...
第十六章 综合实例——《跟我学Shiro》 -
dagger9527:
只有@AspectJ支持命名切入点,而Schema风格不支持命 ...
【第六章】 AOP 之 6.5 AspectJ切入点语法详解 ——跟我学spring3 -
dagger9527:
支持虽然会迟到,但永远不会缺席!
【第四章】 资源 之 4.3 访问Resource ——跟我学spring3
第一章 Web MVC简介 —— 跟开涛学SpringMVC
第二章 Spring MVC入门 —— 跟开涛学SpringMVC
第三章 DispatcherServlet详解 ——跟开涛学SpringMVC
第四章 Controller接口控制器详解(1)——跟着开涛学SpringMVC
第四章 Controller接口控制器详解(2)——跟着开涛学SpringMVC
第四章 Controller接口控制器详解(3)——跟着开涛学SpringMVC
第四章 Controller接口控制器详解(4)——跟着开涛学SpringMVC
第四章 Controller接口控制器详解(5)——跟着开涛学SpringMVC
第四章 Controller接口控制器详解(6)——跟着开涛学SpringMVC
4.16、数据类型转换和数据验证
流程:
1、首先创建数据绑定器,在此此会创建ServletRequestDataBinder类的对象,并设置messageCodesResolver(错误码解析器);
2、提供第一个扩展点,初始化数据绑定器,在此处我们可以覆盖该方法注册自定义的PropertyEditor(请求参数——>命令对象属性的转换);
3、进行数据绑定,即请求参数——>命令对象的绑定;
4、提供第二个扩展点,数据绑定完成后的扩展点,此处可以实现一些自定义的绑定动作;
5、验证器对象的验证,验证器通过validators注入,如果验证失败,需要把错误信息放入Errors(此处使用BindException实现);
6、提供第三个扩展点,此处可以实现自定义的绑定/验证逻辑;
7、将errors传入功能处理方法进行处理,功能方法应该判断该错误对象是否有错误进行相应的处理。
4.16.1、数据类型转换
请求参数(String)——>命令对象属性(可能是任意类型)的类型转换,即数据绑定时的类型转换,使用PropertyEditor实现绑定时的类型转换。
一、Spring内建的PropertyEditor如下所示:
类名 |
说明 |
默认是否注册 |
ByteArrayPropertyEditor |
String<——>byte[] |
√ |
ClassEditor |
String<——>Class 当类没有发现抛出 |
√ |
CustomBooleanEditor |
String<——>Boolean true/yes/on/1转换为true,false/no/off/0转换为false |
√ |
CustomCollectionEditor |
数组/Collection——>Collection 普通值——>Collection(只包含一个对象) 如String——>Collection 不允许Collection——>String(单方向转换) |
√ |
CustomNumberEditor |
String<——>Number(Integer、Long、Double) |
√ |
FileEditor |
String<——>File |
√ |
InputStreamEditor |
String——>InputStream 单向的,不能InputStream——>String |
√ |
LocaleEditor |
String<——>Locale, (String的形式为[语言]_[国家]_[变量],这与Local对象的toString()方法得到的结果相同) |
√ |
PatternEditor |
String<——>Pattern |
√ |
PropertiesEditor |
String<——>java.lang.Properties |
√ |
URLEditor |
String<——>URL |
√ |
StringTrimmerEditor |
一个用于trim 的 String类型的属性编辑器 如默认删除两边的空格,charsToDelete属性:可以设置为其他字符 emptyAsNull属性:将一个空字符串转化为null值的选项。 |
× |
CustomDateEditor |
String<——>java.util.Date |
× |
二、Spring内建的PropertyEditor支持的属性(符合JavaBean规范)操作:
表达式 |
设值/取值说明 |
username |
属性username 设值方法setUsername()/取值方法getUsername() 或 isUsername() |
schooInfo.schoolType |
属性schooInfo的嵌套属性schoolType 设值方法getSchooInfo().setSchoolType()/取值方法getSchooInfo().getSchoolType() |
hobbyList[0] |
属性hobbyList的第一个元素 索引属性可能是一个数组、列表、其它天然有序的容器。 |
map[key] |
属性map(java.util.Map类型) map中key对应的值 |
三、示例:
接下来我们写自定义的属性编辑器进行数据绑定:
(1、模型对象:
package cn.javass.chapter4.model; //省略import public class DataBinderTestModel { private String username; private boolean bool;//Boolean值测试 private SchoolInfoModel schooInfo; private List hobbyList;//集合测试,此处可以改为数组/Set进行测试 private Map map;//Map测试 private PhoneNumberModel phoneNumber;//String->自定义对象的转换测试 private Date date;//日期类型测试 private UserState state;//String——>Enum类型转换测试 //省略getter/setter } package cn.javass.chapter4.model; //如格式010-12345678 public class PhoneNumberModel { private String areaCode;//区号 private String phoneNumber;//电话号码 //省略getter/setter }
(2、PhoneNumber属性编辑器
前台输入如010-12345678自动转换为PhoneNumberModel。
package cn.javass.chapter4.web.controller.support.editor; //省略import public class PhoneNumberEditor extends PropertyEditorSupport { Pattern pattern = Pattern.compile("^(\\d{3,4})-(\\d{7,8})$"); @Override public void setAsText(String text) throws IllegalArgumentException { if(text == null || !StringUtils.hasLength(text)) { setValue(null); //如果没值,设值为null } Matcher matcher = pattern.matcher(text); if(matcher.matches()) { PhoneNumberModel phoneNumber = new PhoneNumberModel(); phoneNumber.setAreaCode(matcher.group(1)); phoneNumber.setPhoneNumber(matcher.group(2)); setValue(phoneNumber); } else { throw new IllegalArgumentException(String.format("类型转换失败,需要格式[010-12345678],但格式是[%s]", text)); } } @Override public String getAsText() { PhoneNumberModel phoneNumber = ((PhoneNumberModel)getValue()); return phoneNumber == null ? "" : phoneNumber.getAreaCode() + "-" + phoneNumber.getPhoneNumber(); } }
PropertyEditorSupport:一个PropertyEditor的支持类;
setAsText:表示将String——>PhoneNumberModel,根据正则表达式进行转换,如果转换失败抛出异常,则接下来的验证器会进行验证处理;
getAsText:表示将PhoneNumberModel——>String。
(3、控制器
需要在控制器注册我们自定义的属性编辑器。
此处我们使用AbstractCommandController,因为它继承了BaseCommandController,拥有绑定流程。
package cn.javass.chapter4.web.controller; //省略import public class DataBinderTestController extends AbstractCommandController { public DataBinderTestController() { setCommandClass(DataBinderTestModel.class); //设置命令对象 setCommandName("dataBinderTest");//设置命令对象的名字 } @Override protected ModelAndView handle(HttpServletRequest req, HttpServletResponse resp, Object command, BindException errors) throws Exception { //输出command对象看看是否绑定正确 System.out.println(command); return new ModelAndView("bindAndValidate/success").addObject("dataBinderTest", command); } @Override protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception { super.initBinder(request, binder); //注册自定义的属性编辑器 //1、日期 DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); CustomDateEditor dateEditor = new CustomDateEditor(df, true); //表示如果命令对象有Date类型的属性,将使用该属性编辑器进行类型转换 binder.registerCustomEditor(Date.class, dateEditor); //自定义的电话号码编辑器 binder.registerCustomEditor(PhoneNumberModel.class, new PhoneNumberEditor()); } }
initBinder:第一个扩展点,初始化数据绑定器,在此处我们注册了两个属性编辑器;
CustomDateEditor:自定义的日期编辑器,用于在String<——>日期之间转换;
binder.registerCustomEditor(Date.class, dateEditor):表示如果命令对象是Date类型,则使用dateEditor进行类型转换;
PhoneNumberEditor:自定义的电话号码属性编辑器用于在String<——> PhoneNumberModel之间转换;
binder.registerCustomEditor(PhoneNumberModel.class, newPhoneNumberEditor()):表示如果命令对象是PhoneNumberModel类型,则使用PhoneNumberEditor进行类型转换;
(4、spring配置文件chapter4-servlet.xml
<bean name="/dataBind" class="cn.javass.chapter4.web.controller.DataBinderTestController"/>
(5、视图页面(WEB-INF/jsp/bindAndValidate/success.jsp)
EL phoneNumber:${dataBinderTest.phoneNumber}<br/> EL state:${dataBinderTest.state}<br/> EL date:${dataBinderTest.date}<br/>
视图页面的数据没有预期被格式化,如何进行格式化显示呢?请参考【第七章 注解式控制器的数据验证、类型转换及格式化】。
(6、测试:
1、在浏览器地址栏输入请求的URL,如
http://localhost:9080/springmvc-chapter4/dataBind?username=zhang&bool=yes&schooInfo.specialty=computer&hobbyList[0]=program&hobbyList[1]=music&map[key1]=value1&map[key2]=value2&phoneNumber=010-12345678&date=2012-3-18 16:48:48&state=blocked
2、控制器输出的内容:
DataBinderTestModel [username=zhang, bool=true, schooInfo=SchoolInfoModel [schoolType=null, schoolName=null, specialty=computer], hobbyList=[program, music], map={key1=value1, key2=value2}, phoneNumber=PhoneNumberModel [areaCode=010, phoneNumber=12345678], date=Sun Mar 18 16:48:48 CST 2012, state=锁定]
类型转换如图所示:
四、注册PropertyEditor
1、使用WebDataBinder进行控制器级别注册PropertyEditor(控制器独享)
如“【三、示例】”中所使用的方式,使用WebDataBinder注册控制器级别的PropertyEditor,这种方式注册的PropertyEditor只对当前控制器独享,即其他的控制器不会自动注册这个PropertyEditor,如果需要还需要再注册一下。
2、使用WebBindingInitializer批量注册
PropertyEditor
如果想在多个控制器同时注册多个相同的PropertyEditor时,可以考虑使用WebBindingInitializer。
示例:
(1、实现WebBindingInitializer
package cn.javass.chapter4.web.controller.support.initializer; //省略import public class MyWebBindingInitializer implements WebBindingInitializer { @Override public void initBinder(WebDataBinder binder, WebRequest request) { //注册自定义的属性编辑器 //1、日期 DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); CustomDateEditor dateEditor = new CustomDateEditor(df, true); //表示如果命令对象有Date类型的属性,将使用该属性编辑器进行类型转换 binder.registerCustomEditor(Date.class, dateEditor); //自定义的电话号码编辑器 binder.registerCustomEditor(PhoneNumberModel.class, new PhoneNumberEditor()); } }
通过实现WebBindingInitializer并通过binder注册多个PropertyEditor。
(2、修改【三、示例】中的DataBinderTestController,注释掉initBinder方法;
(3、修改chapter4-servlet.xml配置文件:
<!-- 注册WebBindingInitializer实现 --> <bean id="myWebBindingInitializer" class="cn.javass.chapter4.web.controller.support.initializer.MyWebBindingInitializer"/> <bean name="/dataBind" class="cn.javass.chapter4.web.controller.DataBinderTestController"> <!-- 注入WebBindingInitializer实现 --> <property name="webBindingInitializer" ref="myWebBindingInitializer"/> </bean>
(4、尝试访问“【三、示例】”中的测试URL即可成功。
使用WebBindingInitializer的好处是当你需要在多个控制器中需要同时使用多个相同的PropertyEditor可以在WebBindingInitializer实现中注册,这样只需要在控制器中注入WebBindingInitializer即可注入多个PropertyEditor。
3、全局级别注册PropertyEditor(全局共享)
只需要将我们自定义的PropertyEditor放在和你的模型类同包下即可,且你的Editor命名规则必须是“模型类名Editor”,这样Spring会自动使用标准JavaBean架构进行自动识别,如图所示:
此时我们把“DataBinderTestController”的“binder.registerCustomEditor(PhoneNumberModel.class, new PhoneNumberEditor());”注释掉,再尝试访问“【三、示例】”中的测试URL即可成功。
这种方式不仅仅在使用Spring时可用,在标准的JavaBean等环境都是可用的,可以认为是全局共享的(不仅仅是Spring环境)。
PropertyEditor被限制为只能String<——>Object之间转换,不能Object<——>Object,Spring3提供了更强大的类型转换(TypeConversion)支持,它可以在任意对象之间进行类型转换,不仅仅是String
<——>Object。
如果我在地址栏输入错误的数据,即数据绑定失败,Spring Web MVC该如何处理呢?如果我输入的数据不合法呢?如用户名输入100个字符(超长了)那又该怎么处理呢?出错了需要错误消息,那错误消息应该是硬编码?还是可配置呢?
接下来我们来学习一下数据验证器进行数据验证吧。
私塾在线学习网原创内容(http://sishuok.com)
原创内容,转载请注明私塾在线【http://sishuok.com/forum/blogPost/list/5677.html】
评论
比如这一节说的是什么 做什么用的. 以场景来带入.
在测试这里例子的时候,有几个疑问
1、在PhoneNumberModelEditor设置断点,为什么代码不会跟进去呢?
2、号码输入错误时,代码中有抛出一个异常,但是测试的日志中没有发现异常信息,只是页面上没有显示处理而已,这个是spring的容错机制吗?
3、在PhoneNumberModelEditor 中打印的语句也没有输出。
那说明没执行 仔细检查下 注册是否正确
但是验证的规则却是成功的,匹配正则表达式的正常显示,不匹配的,显示为空,断点不进。
运行你的程序4,也是一样。。。
handle方法断点有效
没明白验证为什么没有进断点。。。很奇怪。。。
用注册PropertyEditor的方式 断点可进
在测试这里例子的时候,有几个疑问
1、在PhoneNumberModelEditor设置断点,为什么代码不会跟进去呢?
2、号码输入错误时,代码中有抛出一个异常,但是测试的日志中没有发现异常信息,只是页面上没有显示处理而已,这个是spring的容错机制吗?
3、在PhoneNumberModelEditor 中打印的语句也没有输出。
那说明没执行 仔细检查下 注册是否正确
但是验证的规则却是成功的,匹配正则表达式的正常显示,不匹配的,显示为空,断点不进。
运行你的程序4,也是一样。。。
handle方法断点有效
没明白验证为什么没有进断点。。。很奇怪。。。
在测试这里例子的时候,有几个疑问
1、在PhoneNumberModelEditor设置断点,为什么代码不会跟进去呢?
2、号码输入错误时,代码中有抛出一个异常,但是测试的日志中没有发现异常信息,只是页面上没有显示处理而已,这个是spring的容错机制吗?
3、在PhoneNumberModelEditor 中打印的语句也没有输出。
那说明没执行 仔细检查下 注册是否正确
在测试这里例子的时候,有几个疑问
1、在PhoneNumberModelEditor设置断点,为什么代码不会跟进去呢?
2、号码输入错误时,代码中有抛出一个异常,但是测试的日志中没有发现异常信息,只是页面上没有显示处理而已,这个是spring的容错机制吗?
3、在PhoneNumberModelEditor 中打印的语句也没有输出。
谢谢
发表评论
-
跟我学SpringMVC目录汇总贴、PDF下载、源码下载
2012-12-22 08:05 620825扫一扫,关注我的公众号 购买地址 ... -
源代码下载——第七章 注解式控制器的数据验证、类型转换及格式化
2012-12-01 07:12 33474源代码请到附件中下载。 其他下载: ... -
SpringMVC数据验证——第七章 注解式控制器的数据验证、类型转换及格式化——跟着开涛学SpringMVC
2012-11-23 07:47 2389947.4、数据验证 7.4.1 ... -
SpringMVC数据格式化——第七章 注解式控制器的数据验证、类型转换及格式化——跟着开涛学SpringMVC
2012-11-19 19:18 890207.3、数据格式化 ... -
SpringMVC数据格式化——第七章 注解式控制器的数据验证、类型转换及格式化——跟着开涛学SpringMVC
2012-11-19 16:41 46支持一下博主:------------------ ... -
SpringMVC数据类型转换——第七章 注解式控制器的数据验证、类型转换及格式化——跟着开涛学SpringMVC
2012-11-12 20:08 1233577.1、简介 在编写可 ... -
扩展SpringMVC以支持绑定JSON格式的请求参数
2012-11-08 07:43 126077上一篇:《扩展SpringMVC以支持更精准的数据绑 ... -
扩展SpringMVC以支持更精准的数据绑定1
2012-11-06 07:38 76792最新版请点击查看FormM ... -
SpringMVC强大的数据绑定(2)——第六章 注解式控制器详解——跟着开涛学SpringMVC
2012-10-26 07:57 1528796.6.2、@RequestParam绑定单个请求参 ... -
SpringMVC强大的数据绑定(2)——第六章 注解式控制器详解——跟着开涛学SpringMVC
2012-10-23 14:45 15---------------------------- ... -
SpringMVC强大的数据绑定(1)——第六章 注解式控制器详解——跟着开涛学SpringMVC
2012-10-16 07:48 121082到目前为止,请求已经能交给我们的处理器进行处理了,接下来 ... -
Spring MVC 3.1新特性 生产者、消费者请求限定 —— 第六章 注解式控制器详解——跟着开涛学SpringMVC
2012-10-10 14:16 484976.6.5、生产者、消费者限定 6.6.5.1、基 ... -
SpringMVC3强大的请求映射规则详解 第六章 注解式控制器详解——跟着开涛学SpringMVC
2012-09-24 15:29 104893声明:本系列都是原创内容,觉得好就顶一个,让更多人知道! ... -
请求映射之URL路径映射 第六章 注解式控制器详解——跟着开涛学SpringMVC
2012-09-24 11:50 946.5.1.1、普通URL路径映射 @Request ... -
请求映射之请求方法映射限定 第六章 注解式控制器详解——跟着开涛学SpringMVC
2012-09-24 11:48 536.5.2、请求方法映射 ... -
请求映射之请求方法映射限定 第六章 注解式控制器详解——跟着开涛学SpringMVC
2012-09-24 10:47 216.5.2、请求方法映射限定 一般我们熟悉的表单 ... -
请求映射之URL路径映射 第六章 注解式控制器详解——跟着开涛学SpringMVC
2012-09-24 07:05 1636.5.1.1、普通URL路径映射 @Reques ... -
源代码下载 第六章 注解式控制器详解
2012-09-22 07:11 42058源代码请到附件中下载。 其他下载: 跟着 ... -
注解式控制器运行流程及处理器定义 第六章 注解式控制器详解——跟着开涛学SpringMVC
2012-09-20 17:47 67447声明:本系列都是原创内容,觉得好就顶一个,让更多人知道! ... -
注解式控制器运行流程及处理器定义 第六章 注解式控制器详解——跟着开涛学SpringMVC
2012-09-20 15:54 96.1、注解式控制器简介 一、Spring2. ...
相关推荐
PDF,源代码 开涛学SpringMVC 第一章源...第四章 Controller接口控制器详解 源代码下载 第五章 处理器拦截器详解——跟着开涛学SpringMVC 第六章 注解式控制器详解 第七章 注解式控制器的数据验证、类型转换及格式化
1. **MVC架构**:首先,我们需要了解MVC模式,它是一种设计模式,将应用程序分为三个主要组件——模型(Model)、视图(View)和控制器(Controller)。在SpringMVC中,模型处理业务逻辑,视图负责展示数据,而控制...
该框架通过将应用程序的不同部分——模型(Model)、视图(View)和控制器(Controller)分离,使得各个部分能够各司其职,从而提高代码的可读性和可维护性。 - **模型(Model)**:负责处理应用程序的数据逻辑,...
《基于SSM的图书馆管理系统毕业设计详解》 SSM(Spring、SpringMVC、MyBatis)是一个在Java开发领域广泛应用的开源框架组合,它在构建企业级Web应用时提供了强大的支持。本毕业设计——“基于SSM的图书馆管理系统”...
4. 支付模块:与第三方支付平台接口对接,实现在线支付功能,涉及安全支付协议。 5. 库存模块:实时更新库存信息,确保订单执行的准确性。 四、核心技术点 1. Spring框架:利用IoC容器管理对象,实现依赖注入,提升...
2. **SpringMVC**:作为Spring的Web MVC框架,处理HTTP请求和响应,通过DispatcherServlet、Controller、ModelAndView等组件实现模型-视图-控制器模式,使业务逻辑和展示层分离。 3. **MyBatis**:作为持久层框架,...
2. SpringMVC:作为Spring框架的一部分,SpringMVC是一个用于构建Web应用的模型-视图-控制器(MVC)架构。它简化了HTTP请求的处理,使得业务逻辑与表示层更易于解耦。 3. MyBatis:是一个持久层框架,它简化了SQL...
在洗衣店预约系统中,SpringMVC扮演着控制器的角色,协调各个组件的工作。 3. **MyBatis**:MyBatis是一个持久层框架,它允许开发者将SQL语句直接写在XML配置文件或注解中,与Java对象进行映射,从而简化了数据访问...
《KTV点歌系统——基于SSM框架的Java毕业设计详解》 KTV点歌系统是一种常见的娱乐场所管理系统,主要用于帮助顾客便捷地选择并播放歌曲。在这个项目中,我们将深入探讨一个基于SSM(Spring、SpringMVC、MyBatis)...
- SpringMVC:负责处理HTTP请求,通过DispatcherServlet调度控制器,与视图层进行交互,实现了Model-View-Controller的设计模式。 - MyBatis:是一个优秀的持久层框架,它支持定制化SQL、存储过程以及高级映射,...
4. 支付功能:集成第三方支付接口,如微信支付,实现在线支付功能。 5. 系统设置:管理员可以进行系统配置,如价格设定、营业时间设定等。 在开发过程中,可能会采用Maven或Gradle作为项目构建工具,确保项目的依赖...
SpringMVC则是Spring框架的一部分,专门用于处理Web请求,它通过模型-视图-控制器(Model-View-Controller,MVC)的设计模式,将业务逻辑、数据处理和用户界面分离,提升了系统的可扩展性和可测试性。 MyBatis作为...