JSR303校验与统一异常处理

JSR303校验的使用

1.给bean的属性添加校验注解并自定义校验提示信息
更多校验注解参考javax.validation.constraints包;

BrandEntity.java

	@NotBlank(message = "不能为空")
	private String name;
	// 品牌logo地址
	@URL(message = "logo必须是一个合法的url地址")
	private String logo;
	//使用正则表达式定义校验规则
	@Pattern(regexp = "^[a-zA-Z]$",message = "检索首字母不能为空")
	@NotEmpty
	//最小值为0
	@Min(value = 0,message = "排序必须大于等于0")
	private Integer sort;

2.@Valid标注在参数上告诉springmvc开启校验功能
BrandController.java

    @RequestMapping("/save")
//    @RequiresPermissions("product:brand:save")
    public R save(@Valid @RequestBody BrandEntity brand){
		brandService.save(brand);

        return R.ok();
    }

3.在被校验的bean后紧跟一个BindingResult ,就可以获取校验的结果(这里的R是我业务统一要求的返回规范)

@RequestMapping("/save")
//    @RequiresPermissions("product:brand:save")
    public R save(@Valid @RequestBody BrandEntity brand, BindingResult result){
        HashMap<String, String> stringMap = new HashMap<>();
        //获取校验错误结果
        if(result.hasErrors()){
            result.getFieldErrors().forEach((error)->{
                //获取并封装校验错误属性与错误信息
                stringMap.put(error.getField(),error.getDefaultMessage());
            });
            return R.error(400,"提交数据不合法").put("data",stringMap);
        }else {
            brandService.save(brand);
            return R.ok();
        }

当然在实际项目中我们不建议以上的写法,代码的复用性极低,推荐使用springboot的统一异常处理机制

使用枚举在公共模块中创建异常状态码枚举

package com.walkwind.common.exception;

/**
 * @Author walkwind
 * @Description 错误状态码
 * @Date 2020-5-10-18:21
 **/
public enum BizCodeEnum {
    UNKONW_EXCEPTION(10000, "系统位置错误"),
    VALID_EXCEPTION(10001, "参数格式校验失败");

    private Integer code;
    private String msg;

    BizCodeEnum(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }
//省略getter/setter方法..
}

创建exception类使用@ControllerAdvice用来处理请求

@ControllerAdvice   //全局异常处理,全局数据绑定,全局数据预处理
public class WwmallProductExceptionCcontrollerAdvice {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public R handlerVaildException(MethodArgumentNotValidException e) {
        HashMap<String, String> stringMap = new HashMap<>();
        //获取校验错误结果
        e.getBindingResult().getFieldErrors().forEach((error) -> {
            //获取并封装校验错误属性与错误信息
            stringMap.put(error.getField(), error.getDefaultMessage());
        });
        return R.error(BizCodeEnum.VALID_EXCEPTION.getCode(),BizCodeEnum.VALID_EXCEPTION.getMsg()).put("data", stringMap);
    }
}

这样话我们在数据校验层就不必每次都捕捉数据校验异常,有异常直接throw我们的异常处理器会自动捕捉

public R save(@Valid @RequestBody BrandEntity brand){
     brandService.save(brand);
     return R.ok();
}

JSR303分组校验

我们在新增时和修改时想要校验的字段,校验规则一般是不同的,例:新增时需要校验排序字段是否为空,而我们修改时就不会涉及到排序字段的修改,所以我们使用分组校验

在common中新建两个接口AddGroup,UpdateGroup这两个接口只起到标识作用,不需要有任何实现。

在这里插入图片描述

使用group属性给校验注解标注什么情况下需要校验,所有被校验的属性必须全部指定group

	@NotBlank(message = "不能为空" ,groups = {AddGroup.class, UpdateGroup.class})
	private String name;
	
	@NotEmpty(message = "不能为空",groups = {AddGroup.class, UpdateGroup.class})
	@Min(value = 0,message = "排序必须大于等于0",groups = {AddGroup.class})
	private Integer sort;

使用@validated({gruop.class})标注在被校验的参数上即可

public R save(@Validated(AddGroup.class) @RequestBody BrandEntity brand){
     brandService.save(brand);
     return R.ok();
}

注: 没有指定分组的校验注解,分组校验时不生效

自定义校验规则

需求:校验show_status的值只能为0或1
自定义校验注解

@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {ListValueConstraintValidator.class })
public @interface ListValue {

    //校验错误默认信息读取位置
    String message() default "{com.walkwind.common.valid.ListValue.message}";

    Class<?>[] groups() default { };

    Class<? extends Payload>[] payload() default { };

    int[] values() default { };
}

自定义校验器
引入依赖

 <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>2.0.1.Final</version>
        </dependency>

在resources文件夹下新建文件ValidationMessages.properties设置默认message

com.walkwind.common.valid.ListValue.message=必须提交指定值

校验器

public class ListValueConstraintValidator implements ConstraintValidator<ListValue,Integer> {

    private Set<Integer> set = new HashSet<>();
    //初始化方法
    @Override
    public void initialize(ListValue constraintAnnotation) {
        int[] values = constraintAnnotation.values();
        for (int value:values) {
            set.add(value);
        }
    }

    @Override
    //校验方法
    public boolean isValid(Integer integer, ConstraintValidatorContext constraintValidatorContext) {
         return set.contains(integer);
    }
}

自定义校验注解关联自定义校验器

@Constraint(validatedBy = {ListValueConstraintValidator.class })

使用自定义注解

	@ListValue(values = 0,groups = {AddGroup.class,UpdateGroup.class})
	private Integer showStatus
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值