Spring Validation校验框架@Validated注解常规校验,分组校验的使用,以及搭配全局异常处理器一起使用。

时间:2025-03-11 07:20:24

注:Sring Validation验证框架对参数的校验机制提供了@Validated(Spring JSR-303规范,是标准JSR-303的一个变种),javax提供了@Valid(标准JSR-303规范),配合BindingResult可以直接提供参数验证结果。

    @Validated配合BindingResult使用个人觉得比较死板,如果不做处理测试校验结果只能校验出有数据不符合制定的规则,并不能校验哪个数据出现了异常。而前端需要拿到你返回的异常信息,所以不能在不作处理的情况下直接给他,不然前端会砍你的。所以后面会提到搭配全局异常处理器使用。

注解说明

空校验	针对类型	说明
@Null	任何类型	校验对象必须为空
@NotNull	任何类型	校验对象不为空,不能校验字符串长度为0的对象
@NotBlank	字符串	只对字符串有效,校验字符串去掉前后空格后长度不为0
@NotEmpty	字符串、集合、数组	校验对象不能为空 (字符串长度不为0、集合大小不为0)


boolean校验	针对类型	说明
@AssertTrue	布尔	校验boolean类型必须为true
@AssertFalse	布尔	校验boolean类型必须为false


数值校验	针对类型	说明
@Min	数字类型	校验必须是一个数字,其值必须大于或等于指定的最小值
@Max	数字类型	校验必须是一个数字,其值必须小于或等于指定的最大值
@DecimalMin	数字类型	校验必须是一个数字,其值必须大于或等于指定的最小值
@DecimalMax	数字类型	校验必须是一个数字,其值必须小于或等于指定的最大值
@Digits(integer=,fraction=)	数字类型	校验必须是一个数字,interger指定整数精度,fraction指定小数精度
@Range(min =,max = )	数字类型、字符串	校验对象的值在min和max区间内
@Length(min =,max = )	字符串	校验对象的值的长度在min和max区间内
@Size(min =,max = )	字符串、集合、数组	校验对象的值在min和max区间内,如字符长度、集合大小


其他校验	针对类型	说明
@Email	字符串	校验对象的值必须是Email类型,也可以通过regexp和flag指定自定义的email格式
@Pattern	字符串	校验对象的值必须符合指定的正则表达式
@CreditCardNumber	数字类型、字符串	校验对象的值必须是信用卡类型
@URL	字符串	校验对象的值必须是URL地址

springboot项目已经默认导入了基础包,所以无需另行导包,直接使用即可。

1.首先安排一个实体类,下面是在工作时写功能测试用的,今天就用它。

import ;
import ;

import ;
import ;
import ;
import ;
import ;
import ;
import ;

import ;
import ;
import ;
import ;

/**
 * 文件压缩记录表
 * 
 * @author XRJ
 * @email 1033835209@
 * @date 2020-04-06 20:46:31
 */
@Data
@Valid
@TableName("hostconfiguration")
public class HostconfigurationEntity implements Serializable {
	private static final long serialVersionUID = 1L;

	/**
	 * 主键id
	 */
	@TableId
	@NotNull(groups = {})
	private int id;

	/**
	 * 服务器ip
	 */
	@NotNull(groups = {})
	@Pattern(groups = {, , }, regexp = "((2[0-4]\\d|25[0-5]|1?[1-9]?\\d)\\.){3}(2[0-4]\\d|25[0-5]|1?[1-9]?\\d)", message = "请输入合法的IP地址")
	private String localhostIp;

	/**
	 * 服务器账号
	 */
	@NotBlank(groups = {})
	@Pattern(groups = {, }, regexp = "\\w{1,32}", message = "用户名只能[a-zA-Z0-9_]中字符,长度不能超过32位")
	private String localhostUsername;

	/**
	 * 服务器密码
	 */
	@NotBlank(groups = {})
	@Length(groups = {, }, min = 1, max = 32)
	private String localhostPassword;

	/**
	 * 端口号
	 */
	@NotNull(groups = {})
	private Integer localhostPort;

	/**
	 * 需压缩文件路径
	 */
	@NotBlank(groups = {})
	private String localhostDirectory;

	/**
	 * 天数,压缩几天前的日志文件
	 */
	@NotNull(groups = {})
	private Integer numTime;

	/**
	 * 创建时间
	 */
	private Date createTime;
	/**
	 * 是否成功,0失败,1成功
	 */
	private Integer isSuccess;

}

上边groups = {,,,}属于分组校验,分别对应增删改查。在controller层使用@Validated(,,,),则会启用相应校验。

层代码如下

package ;

import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import .*;
import ;
import ;
import ;
import ;


/**
 * 文件压缩记录表
 *
 * @author XRJ
 * @email 1033835209@
 * @date 2020-04-06 20:46:31
 */
@RestController
@RequestMapping("/hostconfiguration")
public class HostconfigurationController {
    @Autowired
    private HostconfigurationService hostconfigurationService;

    @PostMapping(value = "/add",produces = "application/json;charset=UTF-8")
    public Result<Integer> insert(@RequestBody @Validated() HostconfigurationEntity hostconf){
        return (hostconf);
    }
}

目前还没有配合全局异常捕获器,先用postman测试一下,下面是我模拟的数据

{
	"localhostPort":22,
	"localhostPassword":"",
	"localhostUsername":"",
	"localhostDirectory":"",
	"localhostIp":"192.156.124.90",
	"numTime":3
}

这是返回的结果,很明显,把整个异常信息带回来了,不知道是哪个属性异常了,这时候全局异常处理器来了:

{"timestamp":1587890386937,"status":400,"error":"Bad Request","errors":[{"codes":["","","","Length"],"arguments":[{"codes":["","localhostPassword"],"arguments":null,"defaultMessage":"localhostPassword","code":"localhostPassword"},32,1],"defaultMessage":"长度需要在1和32之间","objectName":"hostconfigurationEntity","field":"localhostPassword","rejectedValue":"","bindingFailure":false,"code":"Length"},{"codes":["","","","NotBlank"],"arguments":[{"codes":["","localhostPassword"],"arguments":null,"defaultMessage":"localhostPassword","code":"localhostPassword"}],"defaultMessage":"不能为空","objectName":"hostconfigurationEntity","field":"localhostPassword","rejectedValue":"","bindingFailure":false,"code":"NotBlank"},{"codes":["","","","Pattern"],"arguments":[{"codes":["","localhostUsername"],"arguments":null,"defaultMessage":"localhostUsername","code":"localhostUsername"},[],{"defaultMessage":"\\w{1,32}","arguments":null,"codes":["\\w{1,32}"]}],"defaultMessage":"用户名只能[a-zA-Z0-9_]中字符,长度不能超过32位","objectName":"hostconfigurationEntity","field":"localhostUsername","rejectedValue":"","bindingFailure":false,"code":"Pattern"},{"codes":["","","","NotBlank"],"arguments":[{"codes":["","localhostUsername"],"arguments":null,"defaultMessage":"localhostUsername","code":"localhostUsername"}],"defaultMessage":"不能为空","objectName":"hostconfigurationEntity","field":"localhostUsername","rejectedValue":"","bindingFailure":false,"code":"NotBlank"},{"codes":["","","","NotBlank"],"arguments":[{"codes":["","localhostDirectory"],"arguments":null,"defaultMessage":"localhostDirectory","code":"localhostDirectory"}],"defaultMessage":"不能为空","objectName":"hostconfigurationEntity","field":"localhostDirectory","rejectedValue":"","bindingFailure":false,"code":"NotBlank"}],"message":"Validation failed for object='hostconfigurationEntity'. Error count: 5","path":"/compress/hostconfiguration/add"}

校验框架配合全局异常处理器,全局异常处理器代码如下:

package ;

import ;
import ;
import ;
import ;
import ;
import ;
import ;

import ;
import ;
import ;
import ;

/**
 * description : 全局异常处理器
 */
@ControllerAdvice
public class GlobalExceptionHandler {

//    private static final SystemLogger LOGGER = ();

    /**
     * 方法入参支持:Exception、SessionAttribute、@RequestAttribute、HttpServletRequest、HttpServletResponse、HttpSession
     * 方法返回支持: ModelAndView、@ResponseBody、ResponseEntity
     */
    @ExceptionHandler()
    @ResponseBody
    public Result<String> error(HttpServletResponse response, Exception e) {
        ("application/json;charset=UTF-8");
        ("UTF-8");
//        ("全局异常捕获", e);
        try {
            ().print(((Code.SC_INTERNAL_SERVER_ERROR.getState(), Code.SC_INTERNAL_SERVER_ERROR.getDescription(), ())));
        } catch (IOException exc) {
//            ("全局异常捕获响应失败", exc);
        }
        return null;
//        return new Result<>(Code.SC_INTERNAL_SERVER_ERROR, ());
    }

    @ExceptionHandler()
    @ResponseBody
    public String handleMethodArgumentNotValid(HttpServletResponse response, Exception e) {
        ("application/json;charset=UTF-8");
        ("UTF-8");
        MethodArgumentNotValidException ex = (MethodArgumentNotValidException) e;
        BindingResult bindingResult = ();
        Map<String, Object> map = new HashMap<>();
        for (FieldError error : ()) {
            String field = ();
            String msg = ();
//            Object value = ();
//            (field, ("{'value':'%s','errorMsg','%s'}", value, msg));
            (field, msg);
        }
        try {
            ().print(((Code.SC_PRECONDITION_FAILED.getState(), Code.SC_PRECONDITION_FAILED.getDescription(), map)));
        } catch (IOException exc) {
//            ("统一参数异常处理响应失败", exc);
        }
        return null;
//        return new Result<>(Code.SC_PRECONDITION_FAILED, map);
    }
}

使用之前的数据再一次请求接口,返回数据如下:

{
    "code": 412,
    "data": {
        "localhostPassword": "长度需要在1和32之间",
        "localhostUsername": "用户名只能[a-zA-Z0-9_]中字符,长度不能超过32位",
        "localhostDirectory": "不能为空"
    },
    "message": "客户端请求信息的先决条件错误"
}

如此一来,可以很清楚的看到,请求体中是哪个属性出现了异常,这就是全局异常处理器,可以好好研究一下,由于公司的编码要求严格,数据返回格式做了统一,大家可以自定义。

Sring Validation验证框架就到此结束,后面会逐个更新springcloud核心组件的配置与使用当做个人的云笔记本,觉得不错的小伙伴点个关注哈哈。。。