JSR-330校验器的使用

作用

在平常客户端提交表单参数的时候,可以在客户端进行校验参数。但是利用postman也可以模拟表单提交功能。这时候就需要在服务端进行参数校验。这时候就需要用到jsr了。

使用

引入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

给bean添加校验注解

/**
* logo地址
*/
@NotBlank(message = "logo地址不能为空")
@URL(message = "LOGO地址不合法")
private String logo;

告诉SpringMvc字段需要校验 @Valid

/**
* 保存
*/
@RequestMapping("/save")
public R save(@Valid @RequestBody BrandEntity brand) {
   brandService.save(brand);

   return R.ok();
}

获取校验结果

BindingResult 实体类包含异常信息

/**
 * 保存
 */
@RequestMapping("/save")
public R save(@Valid @RequestBody BrandEntity brand, BindingResult result) {
    if (result.hasErrors()) {
        Map<String, String> map = new HashMap<>();
        //1、获取校验的错误结果
        result.getFieldErrors().forEach((item) -> {
            //FieldError 获取到错误提示
            String message = item.getDefaultMessage();
            //获取错误的属性的名字
            String field = item.getField();
            map.put(field, message);
        });
        return R.error(400, "提交的数据不合法").put("data", map);
    } else {
        brandService.save(brand);
    }
    return R.ok();
}

分组校验的功能(多场景的复杂校验)

实体类上使用groups

/**
* 品牌id
 */
@NotNull(message = "修改必须指定品牌id",groups = {UpdateGroup.class})
@Null(message = "新增不能指定id",groups = {AddGroup.class})
@TableId
private Long brandId;

比如在上述代码中,添加时候不需要ID,修改的时候需要Id ,这时候就需要使用分组校验了。

定义分组标识

/**
 * 添加分组
 */
public interface AddGroup {
}
/**
 * 修改分组
 */
public interface UpdateGroup {
}

controller使用分组注解

/**
 * 保存
 */
@RequestMapping("/save")
public R save(@Validated({ AddGroup.class }) @RequestBody BrandEntity brand) {
    brandService.save(brand);
    return R.ok();
}

自定义校验

编写一个自定义的校验注解 例 @ListValue

/**
 * 显示状态[0-不显示;1-显示]
 */
@NotNull(message = "显示状态不能为空", groups = { AddGroup.class, UpdateGroup.class })
@ListVal(vals = { 0, 1 }, message="显示状态只能是0或者1", groups = { AddGroup.class, UpdateGroup.class })
private Integer showStatus;

编写一个自定义注解类

validatedBy 后面的类是下面需要实现的类

@Documented
@Constraint(validatedBy = { ListValueConstraintValidator.class })
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
public @interface ListValue {
    String message() default "{显示状态只能为[0-不显示;1-显示]}";

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

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

    int[] vals() default { };
}

编写一个自定义的校验器

public class ListValValidator implements ConstraintValidator<ListVal, Integer> {

    private Set<Integer> set = new HashSet<Integer>();
    /**
     * 初始化方法
     * @param constraintAnnotation
     */
    public void initialize(ListVal constraintAnnotation) {
        int[] vals = constraintAnnotation.vals();
        for(int val : vals){
            set.add(val);
        }
    }

    public boolean isValid(Integer value, ConstraintValidatorContext context) {
        return set.contains(value);
    }
}

将这个类与上面自定义的注解进行关联

@Constraint(validatedBy = { ListValueConstraintValidator.class })

补充

上面在控制器中获取校验的异常信息时,不需要在每个方法里面写。可以将这个异常单独提出来,写在全局的异常捕获类中。
校验异常是抛出的MethodArgumentNotValidException

/** 集中处理异常
 * @Author: wanyong
 * @Date: 2020/8/11 18:17
 */
@ControllerAdvice(basePackages = "com.yong.gulimall.product.controller")
@ResponseBody
public class MallExceptionControllerAdvice {

    /**
     * 捕获校验结果集出现的异常
     * @param e
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public R handlerValidException(MethodArgumentNotValidException e){
        BindingResult result = e.getBindingResult();
        Map<String,Object> map = new HashMap<>(20);
        if(result.hasErrors()){
            result.getFieldErrors().forEach(item -> {
                String message = item.getDefaultMessage();
                String field = item.getField();
                map.put(field, message);
            });
        }
        //BizCodeEnum枚举类型
        return R.error(BizCodeEnum.VAILD_EXCEPTION.getCode(),BizCodeEnum.VAILD_EXCEPTION.getMsg()).put("data", map);
    }

    /**
     * 捕获其他异常
     * @param e
     * @return
     */
    @ExceptionHandler(Throwable.class)
    public R handlerOtherException(Throwable e) {
        return R.error(BizCodeEnum.UNKNOW_EXCEPTION.getCode(), BizCodeEnum.UNKNOW_EXCEPTION.getMsg()).put("data", e.getMessage());
    }
}

jsr大体的功能就这些!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值