SpringMVC的@Validated校验注解使用方法

一、SpringMVC校验注解@Validated的使用

第一步:编写国际化消息资源文件

编写国际化消息资源ValidatedMessage.properties文件主要是用来显示错误的消息定制

items.name.length.error=请输入1-30个字符的商品名称!
items.createtime.isNULL=请输入商品的日期!
items.price.isNull=请输入商品的价格!

第二步:在SpringMVC配置文件中配置LocalValidatorFactoryBean类

    <!-- 代替了上面的处理器映射器+处理器适配器 (实际开发中使用)-->
    <mvc:annotation-driven 
	    conversion-service="conversionService"
	    validator="validator">
    </mvc:annotation-driven>

	<!--
		校验器
	-->
	<bean id="validator"     class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
		<!-- hibernate校验器 -->
		<property name="providerClass" value="org.hibernate.validator.HibernateValidator"></property>
		<!-- 指定校验使用的资源文件,如果不指定则默认使用classpath下的ValidationMessages.properties -->
		<property name="validationMessageSource" ref="messageSource"></property>
	</bean>

第三步:在Pojo(实体类)中添加注解

首先介绍一下关于验证注解的类型种类:

@Null  限制只能为null
@NotNull 限制必须不为null
@AssertFalse 限制必须为false
@AssertTrue 限制必须为true
@DecimalMax(value) 限制必须为一个不大于指定值的数字
@DecimalMin(value) 限制必须为一个不小于指定值的数字
@Digits(integer,fraction)

限制必须为一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction

@Future 限制必须是一个将来的日期
@Max(value) 限制必须为一个不大于指定值的数字
@Min(value) 限制必须为一个不小于指定值的数字
@Past 验证注解的元素值(日期类型)比当前时间早
@Pattern(value) 限制必须符合指定的正则表达式
@Size(max,min) 限制字符长度必须在min到max之间
@NotEmpty 验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0)
@NotBlank 验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的空格
@Email 验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式

注意:@NotNull、@NotEmpty和@NotBlank的区别:

@NotNull://CharSequence, Collection, Map 和 Array 对象不能是 null, 但可以是空集(size = 0)。  
@NotEmpty://CharSequence, Collection, Map 和 Array 对象不能是 null 并且相关对象的 size 大于 0。  
@NotBlank://String 不是 null 且去除两端空白字符后的长度(trimmed length)大于 0。 

实体类Items:

public class Items {
    private Integer id;

    //校验名称在1-30个字符之间(分组校验)
   // @Size(min=1,max=30,message="{items.name.length.error}",groups= {ValidationGroup1.class})
    @Size(min=1,max=30,message="{items.name.length.error}",groups= {ValidationGroup1.class})
    private String name;

    //@NotNull(message="{items.price.isNull}")
    private Float price;

    private String pic;

    //非空校验
    @NotNull(message="{items.createtime.isNULL}")
    private Date createtime;
    ......

注意:其中{}相当于占位符,将min、max参数传图,同时也将消息文件中定制的错误信息传入,当然也可以直接不使用国际化文件,但是如果直接将错误信息编码进实体类,属于硬编码,不利于后期维护,因此推荐使用,方便统一与修改。

第四步:Controller层的编写

Controller层的使用,很简单。需要在相应的方法传入的Bean参数前面增加注解@Validated,还有增加BindingResult参数即可,具体请看代码示例:

​
public String editItemsSubmit(
			Model model,
			HttpServletRequest request,
			Integer id,
			@Validated ItemsCustom itemsCustom,
			BindingResult bindingResult,
			//接收商品图片
			MultipartFile items_pic 
			) throws Exception{

		//获取校验错误信息
		if(bindingResult.hasErrors()) {
			//输出错误信息
			List <ObjectError> allErrors = bindingResult.getAllErrors();
			
			for(ObjectError objectError:allErrors) {
				//输出错误信息
				System.out.println(objectError.getDefaultMessage());
			}
			//将错误信息传到页面
			model.addAttribute("allErrors",allErrors);
			
			//重新到商品修改页面
			
			return "items/editItems" ;
			
		}

​

第五步:在View层显示错误信息

<!-- 错误信息提示 -->
<c:if test="${allErrors!=null}">
	<c:forEach items="${allErrors}" var="error">
		${error.defaultMessage}<br/>
	</c:forEach>
</c:if>

二、@Validated的分组特性

使用分组验证的原因:假如对进行User表进行修改时,我们只需要验证username和password即可,不需要验证id(因为数据库中已经存在),而当我们对User表进行新增时,就需要验证id,因此字段的验证有时候分情景,这就是分组验证的目的。

第一步:创建分组接口

分组验证接口只是普通的接口,不需要写什么功能,因此并没有多大意义,只是用来标识这个属性在那种情况下被验证。

public interface ValidationGroup1 {
	//不需要定义任何方法,仅是对不同的校验规则进行分组
	//此校验只校验商品名称长度
	
}
public interface ValidationGroup2 {
	//不需要定义任何方法,仅是对不同的校验规则进行分组
	//此校验只校验商品日期
}

第二步:Controller方法参数中增加xxx.class接口

在对新增的用户进行ID验证,增加@Validated({addUser.class})接口类用来表示新增的User.getId()需要验证。

	//商品信息的提交
	@RequestMapping("/editItemsSubmit")
	//pojo绑定:页面中的input中的name和controller的pojo形参中的属性名称一致,将页面中数据绑定到pojo
	//在需要校验的pojo前面添加@Validated,在需要校验的pojo后边添加BindingResult bindingResult接校验的错误信息
	//注意:@Validated和BindingResult是成对出现的 位置固定(一前一后)
	//value= {ValidationGroup1.class}指定使用ValidationGroup1分组的校验
	public String editItemsSubmit(
			Model model,
			HttpServletRequest request,
			Integer id,
			@Validated(value= {ValidationGroup1.class}) ItemsCustom itemsCustom,
			BindingResult bindingResult,
			//接收商品图片
			MultipartFile items_pic 
			) throws Exception{

		//获取校验错误信息
		if(bindingResult.hasErrors()) {
			//输出错误信息
			List <ObjectError> allErrors = bindingResult.getAllErrors();
			
			for(ObjectError objectError:allErrors) {
				//输出错误信息
				System.out.println(objectError.getDefaultMessage());
			}
			//将错误信息传到页面
			model.addAttribute("allErrors",allErrors);
			
			//重新到商品修改页面
			
			return "items/editItems" ;
			
		}

第三步:Pojo中添加groups分组

在Items实体类中添加groups分组@Size(min=1,max=30,message="{items.name.length.error}",groups={validationGroup1.class})对应。

public class Items {
    private Integer id;

    //校验名称在1-30个字符之间(分组校验)
   // @Size(min=1,max=30,message="{items.name.length.error}",groups= {ValidationGroup1.class})
    @Size(min=1,max=30,message="{items.name.length.error}",groups= {ValidationGroup1.class})
    private String name;
    ......

分组验证到底结束,但是对于分组验证需要补充一下:

1、不分配groups分组时,默认每次都需要验证

2、通过groups分组可以对同一个变量进行多个验证,如下代码:

//对用户名进行两次不同情况的验证。
@NotEmpty(groups={First.class})
@Size(min=1,max=10,groups={Second.class})
public String username; 

3、默认情况下,不同的分组约束验证是无序的,但是在有些情况下验证的相互约束很重要(比如前一个组验证失败,后面的将不在验证等情况),所以groups分组的验证也有前后验证顺序,使用@GroupSequence注解进行排序。


/*
 * 分组顺序接口类
 */
import javax.validation.GroupSequence;
//分组序列先Frist再Second
@GroupSequence({First.class,Second.class})
public interface Group{
}
 
@Controller  
public class UserController {  
  
    @RequestMapping("/saveAdd")  
    public String saveAddUser(@Validated({Group.class}) User user, BindingResult result) {  
        if(result.hasErrors()) {  
            return "error";  
        }  
        return "success";  
}

猜你喜欢

转载自blog.csdn.net/qq_37896194/article/details/81195600