JSR303校验,项目实战使用

概述:

​ 项目当中,需要对数据进行数据校验,否则就会传入不符合要求的数据。在客户端做出了校验后服务端也要做出校验,因为用户可以绕过客户端给服务端发送请求。

在实体类中加上JSR303注解,详细JSR303注解可以自行百度搜索,这里只演示校验注解的用法。

message: 说明不符合参数要求显示的信息

groups: 分组校验,用来进行不同场景下的不同校验

因为在项目中,新增不能有id,修改必须有id,此时可以用分组校验来实现此功能

	@NotNull(message = "id不能为空",groups = {UpdateGroup.class}) 
	@Null(message = "id必须为空",groups = {AddGroup.class})
	private Long id;

	@NotBlank(message = "名字不能为空")
	private String name;

Controller层:

用@Valid标注需要参数校验的实体类,用BindingResult接口来接收参数格式不正确时出现的返回信息

 	@RequestMapping("/save")
    public R save(@Valid @RequestBody BrandEntity brand,BindingResult bindingResult){
      // 创建收集信息的map
       Map<String, String> map = new HashMap<>();
      // 获取参数错误时的返回信息
        bindingResult.getFieldErrors().stream().forEach((fieldError)->{
          // getField(): 参数校验失败的字段
          // getDefaultMessage() : 参数校验失败的信息
            map.put(fieldError.getField(),fieldError.getDefaultMessage());
        });
		brandService.save(brand);

        return R.ok().put("data",map);
    }

出现的问题:

@Valid注解无法指定参数在什么场景下需要使用什么样的数据校验,比如新增方法不能有id,修改方法得有id。这个时候需要使用@Validated注解并且指定分组。

并且这样写的话每个映射器都需要写收集信息的代码,这样会造成代码冗余,可以写一个全局异常处理类,来进行捕获处理。

分组校验:

创建对应的分组接口

新增分组

public interface AddGroup {
}

修改分组

public interface UpdateGroup {
}

解决:

Controller层

@Validated(AddGroup.class) 指定是新增分组,和实体类中的分组校验对应该校验才会生效,不对应不会生效。

	@RequestMapping("/save")
    public R save(@Validated(AddGroup.class) @RequestBody BrandEntity brand){
       
		brandService.save(brand);

        return R.ok().;
    }

统一处理异常返回接口

@RestControllerAdvice : 统一异常处理接口 basePackages : 指定哪个包下需要统一处理异常

MethodArgumentNotValidException : 该类是参数校验失败具体的异常信息类,可以使用该类来获取数据校验失败后返回的信息。

@RestControllerAdvice(basePackages = "com.xhy.qaq.product.controller")
@Slf4j
public class ExceptionControllerAdvice {

    // 统一异常处理
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public R exception(MethodArgumentNotValidException e){
      	// e.getBindingResult():获取BindingResult
        BindingResult bindingResult = e.getBindingResult();
        HashMap<String, String> map = new HashMap<>();
      	// 收集数据校验失败后的信息
        bindingResult.getFieldErrors().stream().forEach((fieldError)->{
            map.put(fieldError.getField(),fieldError.getDefaultMessage());
        });
        log.info(e.getMessage());
      // 响应给前端
      return R.error().put("data",map);
    } 
}

自定义注解:

在实际中,JSR303的常用注解肯定是不够用的,这个时候需要自定义注解,就比如某个参数只能为1或者0,在JSR303中没有此注解,需要自定义

@ListValid(values = {0,1},groups = {AddGroup.class})
private Integer Status;

自定义注解步骤:

1.创建数据校验注解,注解必须要有三个属性,以及其他JSR303上面有的注解

String message() default “参数格式不正确”;

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

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

@Documented
@Constraint(
  		// 数据校验的具体实现
        validatedBy = {ListValueConstraintValidator.class}
)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ListValid {
	
  	// 数据校验失败时返回的信息
    String message() default "参数格式不正确";

  	// 分组需要
    Class<?>[] groups() default {};
  
	// payload
    Class<? extends Payload>[] payload() default {};
	
  	// 自定义需要校验的属性
    int[] values() default {};
}

2.创建数据校验具体实现类并且实现ConstraintValidator接口

ConstraintValidator<ListValid,Integer> ListValid:自定义注解, Integer : 需要校验的数据类型

public class ListValueConstraintValidator implements ConstraintValidator<ListValid,Integer> {

    private Set<Integer> set = new HashSet<>();
    /**
     *  初始化方法
     * @param constraintAnnotation : 自定义注解中的参数
     */
    @Override
    public void initialize(ListValid constraintAnnotation) {
      // 获取自定义数据校验注解中指定符合要求的数据
        int[] values = constraintAnnotation.values();
        for (int vas:values){
            set.add(vas);
        }
    }

    /**
     *  校验方法
     * @param integer : 需要校验的值
     * @param constraintValidatorContext
     * @return
     */
    @Override
    public boolean isValid(Integer integer, ConstraintValidatorContext constraintValidatorContext) {
        return set.contains(integer);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值