Spring MVC数据校验

一般来说,准许开发中的 DRY 原则,对于Java程序中的数据校验逻辑和相应的域模型会进行绑定,将代码逻辑集中管理;
Spring 在使用DataBinder 对数据进行绑定时,同时可以调用相应的框架进行数据校验工作,提供了 org.springframwork.validation 包用于支持数据校验,其中核心接口为 Validate,支持自己提供的数据校验框架,同时提供一个工厂类 LocaleValidatorFactoryBean 同时支持自身的 Validate 接口、和 JSR-303 的 Validate 接口;

启用 Spring-mvc 数据校验功能

在 spring-mvc 上下文配置中装配一个 LocaleValidatorFactoryBean ,或者直接使用<mvc:annotation-driven> 即可(会自动装配一个 LocaleValidatorFactoryBean):
<mvc:annotation-driven  />
相当于以下:
<!--装配验证器工厂-->

<bean id="validatorFactoryBean" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />

<!--自动扫 Spring mvc 数据校验框架,通知引用指定的验证器工厂-->

<mvc:annotation-driven validator="validatorFactoryBean"/>

数据校验注解

在Spring-mvc中可以直接使用JSR-303的校验注解:
@Null / @NotNull 被注解的元素必须为null / 必须不为null
@AssertTrue / @AssertFalse 被注解的元素必须为true / 必须为false
@Min(value) / @Max(value) 被注解的元素必须大于等于指定最小值 / 小于等于指定最大值
@DecimalMin(value) / @DecimalMax(value) 同上,同时被注解元素必须为一个数字
@Size(max,min) 被注解的元素必须在指定范围内
@Digits(integer,fraction) 同上,被注解的元素必须是一个数字
@Past / @Future 被注解的元素必须是一个过去的时间 / 必须是一个将来的时间
@Email 被注解的元素必须是一个Email格式
@Pattern(regexp)  被注解的元素必须通过正则表达式regexp的验证,该元素必须是一个String
hibenate validator 对于 JSR-303 提供了一个良好的实现,同时还支持了以下的拓展注解:
@NotEmpty 被注解的元素必须不为空
@Length(min,max) 被注解的元素长度必须在指定范围内,一般为 String 类型
@Range 被注解的元素必须在核实范围内;
使用JSR-303 的数据验证注解,需要引入:javax.validation:validation-api 依赖;
使用 hibernate validator 的数据验证注解,需要导入:org.hibernate:hibernate-validator 依赖;

基于注解的数据校验的基本过程

示例代码模块:
site.assad.domain.User(领域对象)
site.assad.dao.UserDao(dao对象)
site.assad.service.UserService(service对象)
site.assad.web.UserController(控制器对象)
site/assad/applicationContext.xml(spring 配置文件)
webapp/assad-servlet.xml(spring mvc 配置文件)
webapp/web.xml
webapp/WEB-INF/views/user/jsp/*(登陆相关的 jsp 页面)
在领域对象使用注解验证注解
以下是在一个领域对象中,使用注解进行属性的校验注解:
package site.assad.domain;

import org.springframework.format.annotation.DateTimeFormat;

import javax.validation.constraints.*;

public class User {

    private int userId;

    

    @NotNull(message="用户名不可为空")

    @Pattern(regexp = "\\S{2,15}",message="用户名必须包含2-15个非空字符")

    private String userName;

    @NotNull(message="用户密码不可为空")

    @Pattern(regexp = "\\w{6,30}",message="密码必须包含6-30个有字符,下划线,数字组成的字符")

    private String password;

    @Email(message="邮箱格式错误")

    private String email;

    @Past(message="必须是一个过去的日期")

    @DateTimeFormat(pattern = "yyyy-MM-dd")   //数据格式化

    private Date birthday;

    

    //省略getter,setter

}

在控制器使用@valid绑定校验模型 
在 Spring MVC 控制器的处理方法中,使用 @Valid 让Spring-mvc在数据绑定后进行数据校验,校验的结果会被绑定到 BindingResult 对象中,可以通过该对象获取校验结果的一些信息,常用的方法接口如下:
FieldError getFieldError(String field) 根据属性名获取对应的校验错误
List<FieldError> getFieldErrors() 获取所有的校验错误
Object getFieldValue(String field) 获取属性值
int getErrorCount() 获取错误数量
boolean hasError()  判断是否含有校验错误
//响应 “/register”请求,将数据绑定到“user”模型后,进行数据校验,将校验结果绑定到 BindingResult对象中

@RequestMapping("/handleRegister")

public String register( @Valid @ModelAttribute("user") User user,BindingResult bindingResult){

    if(bindingResult.hasErrors())

        return "/user/register";

    else

        return "/user/showDetail";

}

在JSP页面输出验证错误信息
在JSP中获取校验结果,由于校验错误信息是包含在隐含模型中的,隐含模型又存放在 HttpServletRequest 中,可以使用Spring 提供的<form> 标签来绑定该模型,通过获取验证结果:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

<html>

<head>

    <title>用户注册</title>

    <style> .error{color:darkred;} </style>

</head>

<body>

<jsp:useBean id="user" class="site.assad.domain.User" scope="request" />

<form:form action="/user/handleRegister" method="post" modelAttribute="user">

    

    用户名:<form:input path="userName" /><br/>

    <form:errors path="userName" cssClass="error"/><br /> 

    密码:<form:input path="password" /><br/>

    <form:errors path="password"/><br />

    Email:<form:input path="email" cssClass="error" /><br/>

    <form:errors path="email"/><br />

    生日(格式"yyyy-MM-dd"):<form:input path="birthday" /><br/>

    <form:errors path="birthday" cssClass="error"/><br />

    <input type="submit" value="提交" />

    <input type="reset" value="重置" /><br/>

</form:form>

</body>

</html>


数据校验信息的国际化

以上示例中,校验的错误信息是硬编码在领域对象中的,为了解决 i18n 问题,可以将这些信息出储存在 i18n 资源中,以下是示例代码模块:
site.assad.domain.User(领域对象)
site.assad.dao.UserDao(dao对象)
site.assad.service.UserService(service对象)
site.assad.web.UserController(控制器对象)
site/assad/applicationContext.xml(spring 配置文件)
webapp/assad-servlet.xml(spring mvc 配置文件)
webapp/i18n/message.properties(i18n 资源文件)
webapp/web.xml
webapp/WEB-INF/views/user/jsp/*(登陆相关的 jsp 页面)
首先创建资源文件 webapp/i18n/message.properties如下:
#标准验证标签信息

register.userName.notNull=用户名必须不为空

register.userName.pattern=用户名必须包含2-15个非空字符

register.password.pattern=密码必须包含6-30个有字符,下划线,数字组成的字符

register.email=邮箱格式错误

register.birthday.past=必须是一个过去的日期

在Spring mvc上下文中装配i18n资源,绑定校验器工厂,assad-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>

<beans ....>

    <!--自动注入 site.assad.web 包的 bean-->

    ...

    <!--配置视图解析器,映射逻辑视图名的解析-->

     ...

    <!--装配验证其信息使用的 i18n 资源-->

    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"

          p:defaultEncoding="UTF-8"

          p:basename="i18n/message"/>

    <!--装配验证器工厂-->

    <bean id="validatorFactoryBean" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"

          p:validationMessageSource-ref="messageSource" />

    <!--自动扫 Spring mvc 数据校验框架,通知引用指定的验证器工厂(装配了i18n资源的验证器工厂)-->

    <mvc:annotation-driven validator="validatorFactoryBean"/>

</beans>

更改领域对象中的校验错误信息为相应的 i18n 资源:
public class User {

    private int userId;

    @NotNull(message="{register.userName.notNull}")

    @Pattern(regexp = "\\S{2,15}",message="{register.userName.pattern}")

    private String userName;

    @Pattern(regexp = "\\w{6,30}",message="{register.password.pattern}")

    private String password;

    @Email(message="{register.email}")

    private String email;

    @Past(message="{register.birthday.past}")

    @DateTimeFormat(pattern = "yyyy-MM-dd")

    private Date birthday;

    

    //省略 getter,setter

}


编写自定义数据校验代码

以上的过程都是基于Spring已经提供的数据校验标签来进行数据校验的,有几种主要的方法:

1)直接在处理方法中进行数据校验

可以直接在控制器处理方法代码块中,获取绑定对象,对绑定对象的属性进行数据校验,再将结果重新绑定到 BindingResult 或 Errors 对象中可以通过以下2种方法绑定校验错误信息:
BindingResult#rejectValue(String field,String errorCode); //向BindingResult对象注入值

ValidationUtils.rejectIfEmptyOrWhitespace(BindingResult bindingResult,String field,String errorCode)  //通过校验器工具向 Bindingresult 注入值,同时提供了空值检验的便捷方法

如以下代码对注册表单提交的绑定对象user的userName进行校验,如果数据库中存在该userName,校验失败:
package site.assad.web;

@Controller

@RequestMapping("/user")

public class UserController {

    @Autowired

    private UserService userService;

    //只负责路由转换

    @RequestMapping("/register")

    public String register(){

        return "/user/jsp/register";

    }

    //相应表单提交页面的路由请求,进行数据校验;

    @RequestMapping(value="/handleRegister",method=RequestMethod.POST)

    public String register1(@Valid @ModelAttribute("user") User user, BindingResult bindingResult,Model model){

        if(bindingResult.hasErrors()){

            return "/user/jsp/register";

        }

        boolean flag = userService.registerUser(user);

        if(flag){

            user = userService.getUserByName(user.getUserName());

            model.addAttribute("user",user);

            return "/user/jsp/userDetail";

        }else{

             //当userName在数据库中已经存在,返回注册页面,同时向 BindingResult 注入“userName”的校验失败信息

            bindingResult.rejectValue("userName","repeated"); 

            return "/user/jsp/register";

        }

    }

}

其中 bindingResult.rejectValue("userName","repeated");  即向 BindingResult 对象的 userName 注入一个值,该值的 i18n 错误码为 “repeated”,包括绑定资源文件中的以下键值:
  • repeated.user.userName
  • repeated.userName
  • repeated.java.lang.String
  • repeated
BindingResult 会按照以上顺序在对应的资源文件中查找值,直到第一个找到的值;
以下是对应的资源文件:webapp/i18n/message.properties
#自定义验证信息

repeated.userName=用户名已经存在

同时需要在 Spring mvc上下文中配置 i18n 资源:
 <!--装配验证其信息使用的 i18n 资源-->

 <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"

        p:defaultEncoding="UTF-8"

        p:basename="i18n/message"/>

<!--自动扫 Spring mvc 数据校验/数据转化/数据格式化框架-->

 <mvc:annotation-driven />

2)通过自定义实现的校验器

以上方式是直接在处理方法中编写校验逻辑,但对于某个command对象含有比较复杂的校验逻辑,可以把这些代码抽取出来,通过继承Validator接口,实现该command对象的自定义校验器,以维持代码的分层;
实现 User 对象的校验器UserValidator:
package site.assad.web.validator;

import org.springframework.validation.Errors;

import org.springframework.validation.Validator;

//针对 User 的校验器

public class UserValidator implements Validator {

    @AutoWired

    private UserService userService;

    

    //判断需要需要校验的类

    public boolean supports(Class<?> clazz) {

        return User.class.equals(clazz);

    }

    //校验逻辑

    public void validate(Object target, Errors errors) {

        if (target instanceof User) {

            User user = (User) target;

            if (userService.getUserByName(user).getUserId != 0) {

                errors.rejectValue("userName", "repeated");     //向错误对象中写入i18n资源中对应的错误码,同上

            }

        }

    }

}

控制器中 UserController 中绑定该自定义校验器
public class UserController{

    @InitBinder

    public void initBinder(WebDataBinder binder){

            binder.setValidator(new UserValidator());   //在进行数据绑定是使用自定义校验器

    }

    

    @RequestMapping("/handleRegister")

    public String register( @Valid @ModelAttribute("user") User user,BindingResult bindingResult,Model model){

        if(bindingResult.hasErrors()){

            return "/user/register";

        }else{

            user = userService.getUserByName(user.getUserName());

            model.addAttribute("user",user);

            return "/user/showDetail";

        }

    }

}

以上仅仅是在 UserController 控制器中局部启用自定义校验器 UserValidator,如果要在全局启用该校验器,可以在spring mvc上下文如如下配置:
<bean id="userValidator" class="site.assad.validator.UserValidator"/>

<mvc:annotation-driven validator="userValidator"/>

Spring MVC(4):数据校验相关推荐

  1. spring mvc响应数据方式

    目录 1. 页面跳转 2. 回写数据@ResponseBody注解 1. 页面跳转 转发,如果有视图解析器,要写全路径/pages/success.jsp @RequestMapping(" ...

  2. Spring MVC 响应数据、作用域对象

    紧耦方式完成响应: 使用:在单元方法的形参中声明request对象或者response对象,使用request对象完成转发,使用response对象完成直接响应或者重定向. 注意:使用这两种方式,单元 ...

  3. Spring MVC JSON数据交互(附带实例)

    Spring MVC 在数据绑定的过程中需要对传递数据的格式和类型进行转换,它既可以转换 String 等类型的数据,也可以转换 JSON 等其他类型的数据.本节将针对 Spring MVC 中 JS ...

  4. 【Spring Boot】数据校验

    文章目录 2. 数据校验 1. Hibernate Validator 2. JavaBean参数校验 3. URL参数校验 4. JavaBean 对象级联校验 5.分组校验 6. 声明自定义校验注 ...

  5. Spring Boot数据校验

    数据校验是一个相当重要的环节,使用Spring Boot 进行数据校验. 添加校验依赖 全部依赖文件如下 <?xml version="1.0" encoding=" ...

  6. Spring MVC 实践 - Base

    Spring MVC 实践 标签 : Java与Web Spring Web MVC Spring-Web-MVC是一种基于请求驱动的轻量级Web-MVC设计模式框架, Spring MVC使用MVC ...

  7. Spring MVC的处理流程详解

    本文来说下Spring MVC 的处理流程是怎样的 文章目录 Spring MVC概述 Spring MVC的处理流程 曾经的王者-Servlet 想要更进一步 Spring MVC-两级控制器方式 ...

  8. 面试官:Spring MVC的处理流程是怎样的?

    提起Spring MVC,你的第一印象是什么?一个简化Web开发的轻量级框架?实际上,现代开发过程中,开发流程与开发效率的不断提高,同时伴随着Restful与Json相结合的方式的兴起,使得多个设备跨 ...

  9. Spring MVC JSR-303验证框架之Hibernate-Validator

    对于 JSR 303 验证,目前有两个实现,一个是 Hibernate Validator,一个是 Apache BVal.本教程采用的是 Hibernate Validator,注意它和 Hiber ...

  10. Spring MVC框架——Web开发框架

    1.MVC设计模式 一般指MVC框架,M(Model)数据模型层,V(View)视图层,C(Controller)控制层. Controller层:获取用户的请求,处理相关业务逻辑,并成功跳转页面,负 ...

最新文章

  1. 【深度学习之美】卷地风来忽吹散,积得飘零美如画(入门系列之十)
  2. IIS 500错误报service unavailable解决方案之一
  3. 阿里Druid数据库连接池配置解释
  4. 长沙望城:以“速”大干一百天,以“质”实现双过半
  5. Android 绑定远程服务出现 Not Allowed to bind service
  6. CodeForces-999D Equalize the Remainders (贪心+神奇的STL)
  7. Scrapy框架的介绍和基本使用
  8. 商城后台管理系统Vue+Vue-Router+Element-UI+Axios+Echarts 黑马程序员视频笔记
  9. capslock键英语怎么读_电脑键盘上的那些英文键怎么读?
  10. 2020年过去了,我很怀念它
  11. BeanPostProcessor由浅入深
  12. [转]XPO 条件相关类
  13. vue的entries和nextTick
  14. 【毕业设计】51-基于Multisim的篮球比赛24秒倒计时计时器的设计(仿真工程+相关芯片资料+答辩论文)
  15. 微信6.5.10版 android,安卓版微信6.5.10版发布:这些新功能你都知道么?
  16. 批量提取excel中包含特定关键字的单元格内容
  17. Android开发宇视监控播放,宇视科技视频监控(EZPlayer)
  18. mvbox6.1官方版 7.1.0.4
  19. js php通讯录,基于aotu.js实现微信自动添加通讯录中的联系人功能
  20. 辨析 关键路径、关键链、缩短工期方法

热门文章

  1. 算法岗面试常见问题大集合
  2. 考研英语文字材料大作文(议论文)
  3. Word2010中怎样更改和恢复默认字体
  4. 区块链之java(五) eth
  5. 一起来学SpringBoot(十二)发送邮件
  6. Unity3D 关于模型变形技术代码实现
  7. html a标签 left,offcanvas-drag-left.html手机web a标签触屏失效
  8. Google+BenQ=Google Inside
  9. iPhone/iPad在越狱时出现“需要网络连接以在这台iPhone/ipad上验证……”的问题
  10. 常见web安全漏洞及修复建议