Bootstrap

JSR303 统一校验实现

1.简介

JSR 303 是 Java Specification Request 303 的简称,它定义了一套 Java Bean Validation API,用于对 Java 应用中的 Bean(通常是指 POJOs,即 Plain Old Java Objects)进行声明式校验。JSR 303 为 Java 开发者提供了一套标准的校验注解,使得开发者可以非常方便地在 Bean 属性上声明校验规则,而不需要编写大量的校验代码。

JSR 303 的主要特点和组件包括:

  1. 校验注解:JSR 303 定义了一系列的校验注解,如 @NotNull@Size@Min@Max@Pattern 等,这些注解可以直接应用于 Java Bean 的属性上,以声明校验规则。

  2. 约束Violation:当校验失败时,JSR 303 会生成一系列的 ConstraintViolation 对象,每个对象包含有关违反约束的详细信息,如属性路径、违规值、错误消息等。

  3. 校验器(Validator):JSR 303 提供了一个 Validator 接口,用于执行实际的校验操作。开发者可以通过 Validator 对象对 Bean 进行校验,并获取校验结果。

  4. 校验组(Validation Groups):JSR 303 支持校验组的概念,允许开发者将校验规则分组,以便在不同的场景下应用不同的校验规则。

  5. 自定义约束:除了使用标准的校验注解外,JSR 303 还允许开发者定义自己的校验注解和约束。

2实战

2.1 引入依赖

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

2.2 创建exception类

2.2.1 CommonError通用异常处理类

package com.etc.shop.exception;

public enum CommonError {
    UNKOWN_ERROR("执行过程异常,请重试。"),
    PARAMS_ERROR("非法参数"),
    OBJECT_NULL("对象为空"),
    QUERY_NULL("查询结果为空"),
    REQUEST_NULL("请求参数为空");


    private String errMessage;

    public String getErrMessage(){
        return errMessage;
    }

    CommonError(String errMessage) {
        this.errMessage = errMessage;
    }
}

2.2.2 该系统的异常类ShopSystem

package com.etc.shop.exception;

public class ShopSystemException extends RuntimeException{

    private String errMessage;

    public ShopSystemException(){
        super();
    }

    public ShopSystemException(String errMessage){
        super(errMessage);
        this.errMessage = errMessage;
    }

    public String getErrMessage(){
        return errMessage;
    }

    public static void cast(CommonError commonError){
        throw new ShopSystemException(commonError.getErrMessage());
    }

    public static void cast(String errMessage){
        throw new ShopSystemException(errMessage);
    }

}

2.2.3  响应请求的错误类

package com.etc.shop.exception;

import java.io.Serializable;

public class RestErrorResponse implements Serializable {

    private String errMessage;

    public RestErrorResponse(String errMessage){
        this.errMessage = errMessage;
    }

    public String getErrMessage(){
        return errMessage;
    }

    public void setErrMessage(String errMessage){
        this.errMessage = errMessage;
    }
}

2.2.4 GlobalException全局异常处理类

package com.etc.shop.exception;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {

    @ResponseBody
    @ExceptionHandler(ShopSystemException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public RestErrorResponse customException(ShopSystemException e){

        log.error("系统异常:{}",e.getErrMessage(),e);
        String errMessage = e.getErrMessage();
        RestErrorResponse restErrorResponse = new RestErrorResponse(errMessage);
        return restErrorResponse;
    }

    @ResponseBody
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public RestErrorResponse exception(Exception e){
        log.error("系统异常:{}",e.getMessage(),e);

        RestErrorResponse restErrorResponse = new RestErrorResponse(CommonError.UNKOWN_ERROR.getErrMessage());
        return restErrorResponse;
    }
}

2.2.5 设置异常分组类

public class ValidationGroups {
    public interface Insert{};

    public interface Update{};

    public interface Delete{};

}

2.3 对实体添加异常处理注解示例,以及分组示例

@Data
public class OrderDTO {

    @NotEmpty(message = "订单上的商品不能为空")
    private List<OrderItem> orderItems;

    @NotEmpty(message = "订单上的总金额不能为空")
    private BigDecimal totalAmount;

    @NotEmpty(message = "接收人的姓名不能为空",groups = {ValidationGroups.Insert.class})
    @NotEmpty(message = "更改后的接收人的姓名不能为空",groups = {ValidationGroups.Update.class})
    private String receiverName;

    @NotEmpty(message = "接收地址不能为空",groups = {ValidationGroups.Insert.class})
    @NotEmpty(message = "更改后的接收地址不能为空",groups = {ValidationGroups.Update.class})
    private String receiverAddress;

    @NotEmpty(message = "接收人的手机号不能为空",groups = {ValidationGroups.Insert.class})
    @NotEmpty(message = "更改后的接收人的手机号不能为空",groups = {ValidationGroups.Update.class})
    private String receiverPhone;

}

2.4 在controller中对请求的接口添加@Validated注解,可以设置groups分组

;