JSR303的使用

文章目录

一、相关概念说明

概念 说明
JSR JSR是Java Specification Requests的缩写,意思是Java规范提案。是指向JCP(Java Community Process)提出新增一个标准化技术规范的正式请求。任何人都可以提交JSR,以向Java平台增添新的API和服务。JSR已成为Java界的一个重要标准。
JSR-303 JSR-303 是JAVA EE 6 中的一项子规范,叫做Bean Validation
Hibernate Validatorx Hibernate Validator是Bean Validation的参考实现 。Hibernate Validator提供了JSR 303规范中所有内置constraint的实现,除此之外还有一些附加的constraint。

二、JSR303 的使用

2.1 相关注解说明

JSR303的使用
Hibernate中填充一部分:
JSR303的使用

2.2 JSR303 使用步骤

  1. Bean添加校验注解javax.validation.constraints相关注解,并定义自己的message提示
  2. 开启校验功能@Valid,效果:校验错误以后会有默认的响应
  3. 给校验的参数bean后紧跟一个BindingResult,就可以获取到校验的结果

实体BrandEntity

	@NotBlank(message = "品牌名必须提交")
	private String name;

接口:

    @RequestMapping("/update")
    public R update(@Valid @RequestBody BrandEntity brand, BindingResult result) {
        if (result.hasErrors()) {
            Map<String, Object> map = new HashMap<>();
            result.getFieldErrors().forEach(error -> {
                map.put(error.getField(), error.getDefaultMessage());
            });
            return R.error(400, "提交数据不合法").put("data", map);
        }
        brandService.updateById(brand);
        return R.ok();
    }

此时请求返回:
JSR303的使用

2.3 统一异常处理

对于项目中出现的异常,我们通常采用ControllerAdvice的方式进行统一处理,简化代码:

  1. 编写异常处理类,使用@ControllerAdvice
  2. 使用@ExceptionHandler标注方法可以处理的异常
@Slf4j
@RestControllerAdvice(basePackages = "com.hucheng.mall.product.controller")
public class ProductExceptionControllerAdvice {

    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public R handleValidException(MethodArgumentNotValidException e){
        log.error("数据校验出现问题{},异常类型:{}",e.getMessage(),e.getClass());
        BindingResult result = e.getBindingResult();
        Map<String,String> errorMap = new HashMap<>();
        result.getFieldErrors().forEach((fieldError)->{
            errorMap.put(fieldError.getField(),fieldError.getDefaultMessage());
        });
        return R.error(BizCodeEnume.VAILD_EXCEPTION.getCode(),BizCodeEnume.VAILD_EXCEPTION.getMsg()).put("data",errorMap);
    }

    @ExceptionHandler(value = Throwable.class)
    public R handleException(Throwable throwable){

        log.error("错误:",throwable);
        return R.error(BizCodeEnume.UNKNOW_EXCEPTION.getCode(),BizCodeEnume.UNKNOW_EXCEPTION.getMsg());
    }
}

2.4 分组校验

适用于多场景的复杂校验:

  1. 给校验注解标注什么情况需要进行校验,例:@NotBlank(message = "品牌名必须提交",groups = {AddGroup.class,UpdateGroup.class})
  2. @Validated({AddGroup.class})
  3. 默认没有指定分组的校验注解@NotBlank,在分组校验情况@Validated({AddGroup.class})下不生效,只会在@Validated生效;

实体:

package com.hucheng.mall.product.entity;

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;

import java.io.Serializable;
import java.util.Date;

import com.hucheng.common.valid.AddGroup;
import com.hucheng.common.valid.UpdateGroup;
import com.hucheng.common.valid.UpdateStatusGroup;
import lombok.Data;
import org.hibernate.validator.constraints.URL;

import javax.validation.constraints.*;

@Data
@TableName("pms_brand")
public class BrandEntity implements Serializable {
	private static final long serialVersionUID = 1L;

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

	@NotBlank(message = "品牌名必须提交", groups = {AddGroup.class, UpdateGroup.class})
	private String name;

	@NotBlank(groups = {AddGroup.class})
	@URL(message = "logo必须是一个合法的url地址", groups = {AddGroup.class, UpdateGroup.class})
	private String logo;

	private String descript;

	@NotNull(groups = {AddGroup.class, UpdateStatusGroup.class})
	private Integer showStatus;

	@NotEmpty(groups = {AddGroup.class})
	@Pattern(regexp = "^[a-zA-Z]$", message = "检索首字母必须是一个字母", groups = {AddGroup.class, UpdateGroup.class})
	private String firstLetter;

	@NotNull(groups = {AddGroup.class})
	@Min(value = 0, message = "排序必须大于等于0", groups = {AddGroup.class, UpdateGroup.class})
	private Integer sort;

}

接口:

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

        return R.ok();
    }

    /**
     * 修改
     */
    @RequestMapping("/update")
    public R update(@Validated({UpdateGroup.class}) @RequestBody BrandEntity brand) {
        brandService.updateById(brand);
        return R.ok();
    }

2.5 自定义校验

  1. 编写一个自定义的校验注解
  2. 编写一个自定义的校验器ConstraintValidator
  3. 关联自定义的校验器和自定义的校验注解

需求:我们需要将一个字段值控制在0、1

① 自定义校验注解

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

    String message() default "{com.hucheng.common.valid.ListValue.message}";

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

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

    int[] values() default {};
}

② 自定义校验器

public class ListValueConstraintValidator implements ConstraintValidator<ListValue,Integer> {

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

    /**
     * 判断是否校验成功
     */
    @Override
    public boolean isValid(Integer value, ConstraintValidatorContext context) {
        return set.contains(value);
    }
}

③ 创建校验信息提示配置文件

resource文件下创建:ValidationMessages.properties

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

④ 自定义注解的使用

	/**
	 * 显示状态[0-不显示;1-显示]
	 */
	@NotNull(groups = {AddGroup.class, UpdateStatusGroup.class})
	@ListValue(values = {0, 1}, groups = {AddGroup.class, UpdateStatusGroup.class})
	private Integer showStatus;
上一篇:business logic on Power App with Modern driven


下一篇:IfcMappedItem——Mapped shape with multiple items