@Valid 注解 的验证之美 和验证类 异常捕获

@Valid   是JSR303 指定的标准 ,hibernate 对其做了实现

 

 

		<dependency>
			<groupId>org.hibernate.validator</groupId>
			<artifactId>hibernate-validator</artifactId>
			<version>6.0.13.Final</version>
		</dependency>

 

  

 

 

 

1 使用 只要在 需要验证的 类 ,字段 方法,写上 验证注解,

 

 

 

 

 

2 然后在需要使用的地方加上 @Valid 就可以了

 

 

 

 

 

 

 

 

 

验证注解 解释:

需要注意的是 @NotNull 通用 ,@NotBlank 只能修饰String,@NotEmpty 只能修饰集合数组

  

 

 

限制说明
@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格式

 

 

 

 

 

 

 

 

 

 

备注:@Valid 目前默认只在 SpringMvc 的 控制器有效,并且这样写也是无效的 。

 

 

1 controller  非顶层方法,也无效

 

 

 

2 service 层也是无效的。

 

 

 

 

使用验证的一些注意事项

1 @Valid 和  @Validated 效果类似,但是有写时候不一样

2 在对象里面如果对象属性没有验证,而属性的属性需要验证,需要用 @Valid ,不然验证会中断

3 @NotNull 修饰方法参数的时候,需要在参数方法所在类上标注 @Validated 修饰,这时候 @Valid 不起作用

4 在标注方法参数的时候 @NotNull ,@NotBlank @NotEmpty 都一样,只是判断是否空

package com.lomi.controller;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import com.alibaba.fastjson.JSONObject;
import com.lomi.entity.in.validate.UserIn;
import com.lomi.entity.in.validate.UserPakeageIn;
import com.lomi.entity.out.FormatOut;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

/**
 * 1 @Valid 和  @Validated 效果类似,但是有写时候不一样
 * 2 在对象里面如果对象属性没有验证,而属性的属性需要验证,需要用 @Valid ,不然验证会中断
 * 3 @NotNull 修饰方法参数的时候,需要在参数方法所在类上标注 @Validated 修饰,这时候  @Valid 不起作用
 * 4 在标注方法参数的时候 @NotNull ,@NotBlank @NotEmpty 都一样,只是判断是否空
 * 
 * 
 * @author ZHANGYUKUN
 *
 *
 */
@Api(tags="Validate测试")
@RestController
@RequestMapping(value = "/valid")
@Validated
public class ValidateController extends BaseController {
	private static final Logger logger = LoggerFactory.getLogger(ValidateController.class);

	
	
	
	@ApiOperation(value = "单参数")
	@RequestMapping(value = "t1", method = { RequestMethod.POST })
	@ResponseBody
	public FormatOut t1(@NotBlank  String  s) throws Exception {
		
		System.out.println( JSONObject.toJSONString( s ) );
		
		return null;
	}
	
	@ApiOperation(value = "对象")
	@RequestMapping(value = "t2", method = { RequestMethod.POST })
	@ResponseBody
	public String t2(@RequestBody @Validated UserIn  in) throws Exception {
		
		System.out.println( JSONObject.toJSONString( in ) );


		return "OK";
	}
	
	
	@ApiOperation(value = "2层对象")
	@RequestMapping(value = "t3", method = { RequestMethod.POST })
	@ResponseBody
	public FormatOut t2(  @Valid UserPakeageIn  in) throws Exception {
		
		System.out.println( JSONObject.toJSONString( in ) );
		
		return null;
	}
	
	
	
	
	
	
}

  

 下面是验证类

package com.lomi.entity.in.validate;

import java.util.List;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

public class UserPakeageIn {
	
	

	@NotNull(message = "UserPakeageIn-id不能是null")
	private Long id;
	
	@NotBlank(message = "UserPakeageIn-name不能是null")
	private String name;

	//标注向下传递验证
	@Valid
	private UserIn user;
	
	//@Valid 标记验证向下传递,但是自己不验证
	//@Valid
	private List<UserIn> users;

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public UserIn getUser() {
		return user;
	}

	public void setUser(UserIn user) {
		this.user = user;
	}

	public List<UserIn> getUsers() {
		return users;
	}

	public void setUsers(List<UserIn> users) {
		this.users = users;
	}

		
	
}

  

package com.lomi.entity.in.validate;

import java.util.List;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;

public class UserIn {
	
	@NotNull(message = "UserIn-id不能是null")
	private Long id;
	
	@NotBlank(message = "UserIn-name不能是null")
	private String name;
	
	@NotEmpty(message = "UserIn-skill不能是null")
	private List<String> skill;
	
	public Long getId() {
		return id;
	}
	public void setId(Long id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public List<String> getSkill() {
		return skill;
	}
	public void setSkill(List<String> skill) {
		this.skill = skill;
	}
	
	
	

}

  

 

验证框架 异常验证是在进入请求方法之前,需要使用 @ControllerAdvice 而不是  @Component

并且还要标注  @ExceptionHandler(value = Throwable.class) 才能拦截到异常(如果拦截验证类的异常不需要)

package com.lomi.context;

import org.springframework.stereotype.Component;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 *
 * 1 @Component 这种写法,没法处理 @Valid 的验证的异常,原因是 验证类异常出现在进入方法之前
 * 2 如果需要拦截 验证异常需要 @ControllerAdvice ,可以拦截到进入,并且需要指定@ExceptionHandler(value = Throwable.class)
 *
 * 简单的统一异常处理
 * @author ZHANGYUKUN
 *
 */
//@Component
@ControllerAdvice
public class GlobalExceptionResolver implements HandlerExceptionResolver {

    /**
     *{"msg":true}
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @return
     */
    @Override
    @ExceptionHandler(value = Throwable.class)
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        System.out.println( "异常:" + ex );

        String  exMsg = null;
        if( ex instanceof MethodArgumentNotValidException){
            exMsg = ((MethodArgumentNotValidException)ex).getBindingResult().getFieldErrors().get(0).getDefaultMessage();
        }else{
            exMsg = ex.getMessage();
        }

        try {
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json; charset=utf-8");

            PrintWriter writer = response.getWriter();
            writer.write("{\"exMsg\":\""+  exMsg +"\"}" );
            writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }

        //不能返回null,不要spring或默认返回一个
        return new ModelAndView();
        //return null;
    }
}

  

 

posted on 2020-03-03 16:40  zhangyukun  阅读(520)  评论(0编辑  收藏  举报

导航