Java的JSR303参数校验

95 阅读2分钟

安装依赖

image.png

常用注解

image.png

基本使用

dto 中使用注解

import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size;

@Data
public class AddCourseDto {
    @NotEmpty(message = "课程名称不能为空")
    private String name;

    @NotEmpty(message = "适用人群不能为空")
    @Size(message = "适用人群内容过少", min = 10)
    private String users;

    @NotEmpty(message = "课程分类不能为空")
    private String mt;

    @NotEmpty(message = "课程分类不能为空")
    private String st;

    @NotEmpty(message = "课程等级不能为空")
    private String grade;

    @NotEmpty(message = "收费规则不能为空")
    private String charge;
    ...
}

创建全局异常处理类 GlobalExceptionHandler 与异常返回类 R

image.png

  • @ControllerAdvice注解在Java中实现全局异常处理
  • @ResponseBody注解用于指示Spring将方法返回的对象转换为HTTP响应正文
  • @ControllerAdvice@ResponseBody 结合一起使用
  • @RestControllerAdvice@ControllerAdvice@ResponseBody 结合,使用了它就不需要再使用 @ResponseBody
  • @ExceptionHandler(MethodArgumentNotValidException.class) 表示该方法用于处理 MethodArgumentNotValidException 类型的异常。当系统抛出该类型的异常时,该方法将会被调用,并且可以对异常进行处理
package com.xuecheng.base.exception;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import java.util.ArrayList;
import java.util.List;

@Slf4j
@ControllerAdvice
//@RestControllerAdvice
public class GlobalExceptionHandler {
    ...

    @ResponseBody
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public RestErrorResponse methodArgumentNotValidException(MethodArgumentNotValidException e) {

        BindingResult bindingResult = e.getBindingResult();
        // 获取错误的文本字段 为一个数组
        List<String> errors = new ArrayList<>();
        bindingResult.getFieldErrors().stream().forEach(item -> {
            errors.add(item.getDefaultMessage());
        });

        // 将List的信息拼接
        String errMessage = StringUtils.join(errors, ",");

        // 使@Slf4j的log输出异常
        log.error("系统异常{}", e.getMessage(), errMessage);

        // 返回异常信息
        return R.error(1, errMessage);
    }
}

错误返回类 R

package com.xuecheng.base.model;

import lombok.Data;

import java.io.Serializable;

@Data
public class R<T> implements Serializable {
    private Integer code;
    private T data;
    private String msg;


    public R() {
    }

    public R(Integer code, T data, String msg) {
        this.code = code;
        this.data = data;
        this.msg = msg;
    }

    public R(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public static <T> R<T> ok(T data) {
        return new R(0, data, "success");
    }

    public static <T> R<T> success(String msg, T data) {
        return new R(0, data, msg);
    }

    public static <T> R<T> error(Integer code, String msg) {
        return new R(code, msg);
    }
}

controller 中校验参数

  • 使用 @Validated 注解开启校验
@PostMapping("/course")
public CourseBaseInfoDto createCourseBase(@RequestBody @Validated AddCourseDto addCourseDto) {
    ...
}

参数错误结果如下

image.png

分组

当我们有多个接口需要同一个 dto 时,且 dto 的校验信息是不一样的,这时候就需要分组功能了,如下

创建一个分组的类

package com.xuecheng.base.exception;

public class ValidationGroups {
    public interface Inster {
    }


    public interface Update {
    }
}

dto 中使用

@Data
public class AddCourseDto {
    @NotEmpty(message = "新增课程名称不能为空", groups = {ValidationGroups.Inster.class})
    @NotEmpty(message = "修改课程名称不能为空", groups = {ValidationGroups.Update.class})
    private String name;

    ...
}

controller 中使用

@PostMapping("/course")
public CourseBaseInfoDto createCourseBase(@RequestBody 
@Validated(ValidationGroups.Update.class) AddCourseDto addCourseDto) {
    ...
}

测试结果

image.png