springMVC整理05--数据校验、格式化 & 其他注解 & 数据绑定流程
1. 数据校验、数据格式化
参考博客 http://www.importnew.com/19477.html
1.1 数据校验
使用 spring 数据校验,先要导入校验器的 jar:
<!--数据校验-->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.2.Final</version>
</dependency>
此处使用的 hibernate 校验器
JSR 规范:
在实体类的属性上添加注解,可以完成数据校验:
@Null 被注释的元素必须为 null
@NotNull 被注释的元素必须不为 null
@AssertTrue 被注释的元素必须为 true
@AssertFalse 被注释的元素必须为 false
@Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max=, min=) 被注释的元素的大小必须在指定的范围内
@Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past 被注释的元素必须是一个过去的日期
@Future 被注释的元素必须是一个将来的日期
@Pattern(regex=,flag=) 被注释的元素必须符合指定的正则表达式
------------------------------
Hibernate Validator 附加的注解
@NotBlank(message =) 验证字符串非 null,且长度必须大于 0
@Email 被注释的元素必须是电子邮箱地址
@Length(min=,max=) 被注释的字符串的大小必须在指定的范围内
@NotEmpty 被注释的字符串的必须非空
@Range(min=,max=,message=) 被注释的元素必须在合适的范围内
如 Employee 实体类中:
public class Employee { {
private Integer id;
@NotEmpty( message = " " 用户名不能为空" ")
@Size( min = 3 3, max = 6 6, message = " " 姓名长度应在 {min}- - {max}")
private String name;
@Min( value = 2700, message = " " 工资不能少于 {value}")
@Max( value = 10000, message = " " 工资不能超过 {value}")
private Float salary;
在 springMVC-servlet.xml 中配置校验器:
<!-- 配置校验器 -->
<bean id="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<!-- 校验器,使用 hibernate 校验器 -->
<property name="providerClass"
value="org.hibernate.validator.HibernateValidator"/>
</bean>
1.1.1 简单的数据校验
新建 ValidateController
@Controller
public class ValidateController { {
@RequestMapping( "/val1.html")
public M M odelAndView validate1( @Validated Employee emp, BindingResult result) { {
if ( result. hasErrors()) { { // 如果验证错误
FieldError nameError = result. getFieldError( "name");
FieldError salaryError = result. getFieldError( "salary");
ModelAndView view = new ModelAndView();
view.setViewName( "/validate.jsp"); // 如果 有错就 返回原页面
if ( nameError != null) { {
view.addObject( "nameError", nameError.getDefaultMessage());
} }
if ( salaryError != null) { {
view.addObject( "salaryError", salaryError.getDefaultMessage());
} }
return view;
} }
// 验证成功去首页
return new ModelAndView( "/index.jsp");
} }
} }
@Validated 修饰的参数会被按照规则校验。BindingResult 会存放校验信息。在需要校验的 pojo 前边添加@Validated,在需要校验的 pojo 后边添加 BindingResultbindingResult 接收校验出错信息注意:@Validated 和 BindingResult bindingResult 是配对出现,并且形参顺序是固定的(一前一后)
页面 validate.jsp
<form action="/val1.html" method="post">
name:<input type="text" name="name"/>${nameError}<br/>
salary:<input type="text" name="salary"/>${salaryError}<br/>
<input type="submit" value="提交"/>
</form>
运行结果:
提交后:
1.1.2 使用@ModelAttribute 和<form:>
spring 有自定义的表单标签,<form:>冒号后面的是生成 html 的标签名,如<form:input>就会生成一个<input>:
<form:form modelAttribute="empModel" method="post" action="/val2.html">
name:<form:input path="name" /><br/>
<!--输出 name 的校验信息-->
<form:errors path="name"></form:errors><br/>
salary:<form:input path="salary" /><br/>
<form:errors path="salary"></form:errors><br/>
<input type="submit" value="Submit" /><br/>
<!--输出所有错误信息-->
<form:errors path="*"></form:errors>
</form:form>
使用这个标签需要在 jsp 页面中引入头文件:
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<form:>标签将的 modelAttribute 与 action 对应的方法上@ModelAttribute 修饰的对象对应。要想进入这个页面,首先要经过一个 Controller 的方法,在 Model 中添加对应的属性:
@RequestMapping( "/goVal2.html")
public String goVal2(Model model) { {
if (! ! model. containsAttribute( "empModel")) { {
l //empModel 与页面中的 <form:form modelAttribute="empModel"> 对应
model. addAttribute( "empModel", new Employee());
} }
return "/validate.jsp";
} }
如果不经过 Controller 或者 Controller 中没有放 empModel 这个属性,那么页面就会报错:
提交表单验证的方法:
@RequestMapping( "/val2.html")
public String test( @Validated @ModelAttribute( "empModel") Employee emp,
BindingResult result, Model model) { {
// 如果有验证错误 返回到 m form 页面
if ( result. hasErrors()) { {
// 经过 2 goVal2 方法的目的是为了设置 l empModel 属性
// 如果 l empModel 属性没有设置,页面就报错了
return goVal2( model);
} }
return "/index.jsp";
} }
1.1.3 数据校验信息国际化
国际化就是根据浏览器默认语言的不同,显示不同的提示信息:
在 Employee 中,给 id 字段添加验证信息:
public class Employee { {
@NotNull( message= "{NotNull.emp.id}")
private Integer
{NotNull.emp.Id}是从 properties 文件中读取属性值
在 resources 目录下创建两个文件,一个用来存放中文提示信息,一个存放英文提示信息:
注意文件的命名,xx.properties 对应的英文配置文件是 xx_en_US.properties
i18n.properties
NotNull.emp.id=id 不能为空
i18n_en_US.properties
NotNull.emp.id=userId can not be null
两个文件的 key 是对应的,值是不同的语言
springMVC-servlet.xml 中配置,其中 id=validator 的 bean 前面已经配置过了,这里再添加一个属性即可
<!-- 配置校验器 -->
<bean id="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<!-- 校验器,使用 hibernate 校验器 -->
<property name="providerClass"
value="org.hibernate.validator.HibernateValidator"/>
<!--这里添加一个校验信息的数据源-->
<property name="validationMessageSource" ref="messageSource" />
</bean>
<!--自动装配校验器-->
<mvc:annotation-driven validator="validator"/>
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<!-- 在 web 环境中一定要定位到 classpath 否则默认到当前 web 应用下找 -->
<value>classpath:i18n</value>
<value>classpath:org/hibernate/validator/ValidationMessages</value>
</list>
</property>
</bean>
使用 1.1.2 节中的测试代码,运行结果:
将浏览器语言切换成英文,刷新页面:
1.2 数据格式化
1.2.1使用注解格式化
springMVC 在映射 Date 类型的属性时会报错:
如果属性是封装在实体类中的,可以使用@DateTimeFormat 注解,如 Employee 中的 hireDate属性。
@DateTimeFormat( pattern = "yyyy- - MM- - dd")
private Date hireDate;
12.2.2 initBinder 实现格式化
@DateTimeFormat 是在实体类中格式化日期类型的属性,所有的 Controller 中用到该实
体类都会自动使用注解定义的格式是格式化数据。除此之外,还可以使用@InitBinder 在
Controller 中自定义格式化:
@Controller
public class DateFormatController { {
// 自定义格式化
@InitBinder
public void initBinder( ServletRequestDataBinder binder) { {
SimpleDateFormat dateFormat = new SimpleDateFormat( "yyyy- - MM- - dd");
binder.registerCustomEditor( Date. class,
new CustomDateEditor( dateFormat, true));
} }
@RequestMapping( "/date.html")
public String date( Date date) { {
System. out .println( date);
return "/format.jsp";
} }
} }
@InitBinder 定义的格式化规则对当前 Controller 有效。
1.2.3 自定义格式化
springMVC 有多种方式实现自定义数据格式化,假设现在输入一个电话号码,格式是010-12345678,我们有一个实体类,把区号和电话号码分开:
public class PhoneNumModel { {
private String areaCode; // 区号
private String phoneNumber; // 电话号码
//getter/setter 方法略
} }
当请求中传入一个 String 类型的参数“010-12345678”,通过 springMVC 的数据格式化,可以把 String 转换成实体类 PhoneNumModel
第一种方式:定义一个转换工具类,继承 PropertyEditorSupport
public class PhoneNumConverter implements Converter< < String, PhoneNumModel > {
// 正则表达式,定义数据规则
Pattern pattern = = Pattern.compile( "^(\\ d{3,4})- -( (\\ d{7,8})$");
@Override
public PhoneNumModel convert( String s s) { {
if ( s == null || !StringUtils.hasLength(s s)) { {
return null; // 如果没值,设值为 null
} }
Matcher matcher = pattern.matcher(s s);
if ( matcher.matches()) { {
PhoneNumModel phoneNumber = new PhoneNumModel();
phoneNumber.setAreaCode( matcher.group(1 1));
phoneNumber.setPhoneNumber( matcher.group(2 2));
return phoneNumber;
} else { {
throw new IllegalArgumentException( String.format(" " 类型转换失败,需要格
式 [010- - 12345678] ,但格式是 [%s]", s s));
} }
} }
} }
Controller 中使用@InitBinder 注册自定义转换器:
@Controller
public class MyBinderController { {
// 自定义格式化
@InitBinder
public void initBinder( WebDataBinder binder) { {
binder.registerCustomEditor( PhoneNumModel. class, new PhoneNumEditor());
} }
@RequestMapping( "/phone.html") // 注意一定要写 @RequestParam
public ModelAndView phone( @RequestParam( "phone") PhoneNumModel phone) { {
// 绑定成功时可以看到输出
System. out .println( phone.getAreaCode());
System. out .println( phone.getPhoneNumber());
return new ModelAndView( "/format.jsp", "phone", phone);
} }
} }
测试分 url:
http://localhost:8080/phone.html?phone=010-1234567
通过@InitBinder 的方式,数据绑定规则只对当前 Controller 有效
在 Spring4.2 之后提出了一种新的转换方式,工具类实现 Converter 接口:
public class PhoneNumConverter implements Converter< < String, PhoneNumModel > {
// 正则表达式,定义数据规则
Pattern pattern = Pattern.compile( "^(\\ d{3,4})- -( (\\ d{7,8})$");
@Override
public PhoneNumModel convert( String s s) { {
if ( s == null || !StringUtils.hasLength(s s)) { {
return null; // 如果没值,设值为 null
} }
Matcher matcher = pattern.matcher(s s);
if ( matcher.matches()) { {
PhoneNumModel phoneNumber = new PhoneNumModel();
phoneNumber.setAreaCode( matcher.group(1 1));
phoneNumber.setPhoneNumber( matcher.group(2 2));
return phoneNumber;
} else { {
throw new IllegalArgumentException( String.format(" " 类型转换失败,需要格
式 [010- - 12345678] ,但格式是 [%s]", s s));
} }
} }
} }
在 springMVC 配置文件中注册自定义转换器:
<!-- 需要将转换器设置给注解驱动 -->
<mvc:annotation-driven conversion-service="conversionServiceFactoryBean"/>
<bean id="conversionServiceFactoryBean"
class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="util.PhoneNumConverter"></bean>
</set>
</property>
</bean>
Controller 中不需要写@InitBinder 了。这个配置对所有 Controller 都生效。
2. 其它注解
2.1 @CookieValue
@RequestMapping( "cookie.html")
public String cookie( @CookieValue( value = "JSESSIONID", defaultValue = "mysession")
String jsessionId) { {
System. out .println( jsessionId);
return "/index.jsp";
} }
@CookieValue 用于获取 cookie 信息。value 用于指定 cookie 的名字,defaultValue 是当对应的 cookie 为空时系统设置的默认值。required 设置为 true 表示必须。
上面的代码如果浏览器中没有 cookie,会输出 mysession。再次刷新页面,就会打印出当前的 jsesessionid,如:
2.2 @Value
@Value 可以实现从配置文件中读取数据并注册给 Controller 在 springMVC 配置文件种加载 properties 文件:
<context:property-placeholder location="classpath:*.properties"/>
测试代码,这里读取的是 12.1.3 中配置文件中的 key
// 从配置文件中读取属性
@Value( "${NotNull.emp.id}")
private String NOT_NULL_ID;
@RequestMapping( "value.html")
public String value() { {
System. out .println( NOT_NULL_ID);
return "/index.jsp";
} }
3. 数据绑定流程
- ApplicationContext 初始化时建立所有 url 和 controller 类的对应关系(用 Map 保存);
- 根据请求url找到对应的controller,并从controller中找到处理请求的方法
- Spring MVC 主框架将 ServletRequest 对象及目标方法的入参实例传递给 WebDataBinderFactory 实例,以创建 DataBinder 实例对象
- DataBinder 是数据绑定的核心部件,调用装配在 Spring MVC 上下文中的 ConversionService 组件进行数据类型转换、数据格式化工作。将 Servlet中的请求信息填充到入参对象中
- 调用 Validator 组件对已经绑定了请求消息的入参对象进行数据合法性校验,并最终生成数据绑定结果 BindingData 对象
- Spring MVC 抽取 BindingResult 中的入参对象和校验错误对象,将它们赋给处理方法的响应入参。
springMVC整理05--数据校验、格式化 & 其他注解 & 数据绑定流程的更多相关文章
- SpringMvc中的数据校验
SpringMvc中的数据校验 Hibernate校验框架中提供了很多注解的校验,如下: 注解 运行时检查 @AssertFalse 被注解的元素必须为false @AssertTrue 被注解的元素 ...
- 【SpringMVC学习06】SpringMVC中的数据校验
这一篇博文主要总结一下springmvc中对数据的校验.在实际中,通常使用较多是前端的校验,比如页面中js校验,对于安全要求较高的建议在服务端也要进行校验.服务端校验可以是在控制层conroller, ...
- springMVC使用JSR303数据校验
JSR303注解 hibernate validate是jsr 303的一个参考实现,除支持所有的标准校验注解外,他还支持扩展注解 spring4.0拥有自己独立的数据校验框架,同时支持jsr 303 ...
- SpringMvc数据校验@Valid等注解的使用与工具类抽取
最近在重构老项目的代码,发现校验入参占用了很多代码,之前我对这一块的认识局限于使用StringUtils等工具来多个if块进行判断,代码是没什么问题,但是总写这些令人生烦,毕竟写代码也要讲究优雅的嘛, ...
- Spring MVC—数据绑定机制,数据转换,数据格式化配置,数据校验
Spring MVC数据绑定机制 数据转换 Spring MVC处理JSON 数据格式化配置使用 数据校验 数据校验 Spring MVC数据绑定机制 Spring MVC解析JSON格式的数据: 步 ...
- 用spring的@Validated注解和org.hibernate.validator.constraints.*的一些注解在后台完成数据校验
这个demo主要是让spring的@Validated注解和hibernate支持JSR数据校验的一些注解结合起来,完成数据校验.这个demo用的是springboot. 首先domain对象Foo的 ...
- SpringBoot入门 (十一) 数据校验
本文记录学习在SpringBoot中做数据校验. 一 什么是数据校验 数据校验就是在应用程序中,对输入进来得数据做语义分析判断,阻挡不符合规则得数据,放行符合规则得数据,以确保被保存得数据符合我们得数 ...
- SpringMVC框架下数据的增删改查,数据类型转换,数据格式化,数据校验,错误输入的消息回显
在eclipse中javaEE环境下: 这儿并没有连接数据库,而是将数据存放在map集合中: 将各种架包导入lib下... web.xml文件配置为 <?xml version="1. ...
- SpringMVC 数据转换 & 数据格式化 & 数据校验
数据绑定流程 1. Spring MVC 主框架将 ServletRequest 对象及目标方法的入参实例传递给 WebDataBinderFactory 实例,以创建 DataBinder 实例对象 ...
随机推荐
- MemSQL与MySQL不兼容问题总结
1.数据行Update更新数据行时,如果数据行没有变化,MySQL返回受影响的数据行数为1,但MemSQL返回的数据行数为0. 2.MemSQL不支持唯一约束 3.MemSQL不支持外键约束
- 剑指offer--2.替换空格
题目: 请实现一个函数,将一个字符串中的每个空格替换成“%20”.例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy. 思路:可以使用replace或者 ...
- rest-framework的权限组件
权限组件 写在开头: 首先要在models表中添加一个用户类型的字段: class User(models.Model): name=models.CharField(max_length=32) p ...
- 【转】linux下查看磁盘分区的文件系统格式
https://www.cnblogs.com/youbiyoufang/p/7607174.html
- Migrate MySQL database using dump and restore
kaorimatz/mysqldump-loader: Load a MySQL dump file using LOAD DATA INFILEhttps://github.com/kaorimat ...
- PHP导出CSV文件出现乱码的解决方法
在做项目时碰到使用外语的情况下,我们就会使用UTF-8编码.但是,在用PHP导出CSV文件时,如果写入的数据是使用UTF-8编码的日语.韩语之类的外文,就会出现乱码. 要解决PHP生成CSV文件的乱码 ...
- Python PEP8 编码规范中文版
原文链接:https://legacy.python.org/dev/peps/pep-0008/ 参考:https://blog.csdn.net/ratsniper/article/details ...
- react初入门
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- php 对象赋值后改变成员变量影响赋值对象
话不多说看代码 打印结果 对obj1的操作 直接影响了obj2 , 对obj2的操作 直接影响了obj1
- laravel创建项目
composer create-project --prefer-dist laravel/laravel=5.5.* blog