Spring Boot 请求参数校验

141 阅读2分钟

#代码有问题

注解: @Validated,@Valid

Dependencies

implementation 'org.springframework.boot:spring-boot-starter-validation:2.7.3'

请求对象

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.List;

/**
 * @author yonglin.wang@wyze.cn
 */
@Getter
@Setter
@ToString
public class VerificationRequest {
    @NotBlank(message = "User name must not be null")
    private String userName;

    @NotNull(message = "Age must not be null")
    private Integer age;

    /**
     * 如果需要对嵌套的内容进行验证需要添加注解 {@code @Valid} 
     */
    @Valid
    private List<Teacher> teacherList;

    @Getter
    @Setter
    @ToString
    public static class Teacher {
        @Size(min = 1, max = 2, message = "Course list size must be between 1 and 2")
        @NotNull(message = "Course list must not be null")
        private List<String> courseList;
    }
}

Controller

import com.wyl.demo.config.response.ResponseResult;
import com.wyl.demo.verification.request.VerificationRequest;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author yonglin.wang@wyze.cn
 */
@RequestMapping("/verification")
@RestController
public class VerificationController {

    /**
     * 全局异常处理器处理参数校验错误的结果
     *
     * @param request 请求对象
     * @return 响应结果
     */
    @GetMapping("global")
    public ResponseResult<String> get(@Validated final VerificationRequest request) {
        return ResponseResult.success();
    }

    /**
     * 手动处理参数校验错误的结果,当参数包含时{@code org.springframework.validation.BindingResult},
     * 异常处理器捕获不到对应的异常(正常应该说是没有抛出异常),所以如果想要异常处理器处理参数错误,
     * 就不要在入参中添加{@code org.springframework.validation.BindingResult}
     *
     * @param request       请求对象
     * @param bindingResult BindingResult
     * @return 响应结果
     */
    @GetMapping("manual")
    public ResponseResult<String> get(@Validated final VerificationRequest request, final BindingResult bindingResult) {
        return bindingResult.hasErrors() ? ResponseResult.failed() : ResponseResult.success();
    }

    /**
     * 全局异常处理器处理参数校验错误的结果
     *
     * @param request 请求对象
     * @return 响应结果
     */
    @PostMapping("global")
    public ResponseResult<String> post(@Validated @RequestBody final VerificationRequest request) {
        return ResponseResult.success();
    }

    /**
     * 手动处理参数校验错误的结果,当参数包含时{@code org.springframework.validation.BindingResult},
     * 异常处理器捕获不到对应的异常(正常应该说是没有抛出异常),所以如果想要异常处理器处理参数错误,
     * 就不要在入参中添加{@code org.springframework.validation.BindingResult}
     *
     * @param request       请求对象
     * @param bindingResult BindingResult
     * @return 响应结果
     */
    @PostMapping("manual")
    public ResponseResult<String> post(@Validated @RequestBody final VerificationRequest request, final BindingResult bindingResult) {
        return bindingResult.hasErrors() ? ResponseResult.failed() : ResponseResult.success();
    }
}

全局异常拦截处理器

import com.wyl.demo.config.response.ResponseResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * @author yonglin.wang@wyze.cn
 */
@Slf4j
@RestControllerAdvice
public class ControllerAdvice {

    /**
     * 处理GET请求参数验证抛出的异常
     *
     * @param ex BindException 实例
     * @return 错误响应结果
     */
    @ExceptionHandler(BindException.class)
    public ResponseEntity<ResponseResult<Object>> bindExceptionException(final BindException ex) {
        // 没有全部输出
        String errorMessage = null;
        if (ex.getFieldError() != null) {
            errorMessage = ex.getFieldError().getDefaultMessage();
        }
        log.error("MethodArgumentNotValidException", ex);
        return new ResponseEntity<>(ResponseResult.failed(errorMessage), HttpStatus.BAD_REQUEST);
    }

    /**
     * 处理POST请求参数验证抛出的异常
     *
     * @param ex MethodArgumentNotValidException 实例
     * @return 错误响应结果
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ResponseResult<Object>> methodArgumentNotValidException(final MethodArgumentNotValidException ex) {
        // 没有全部输出
        String errorMessage = null;
        if (ex.getFieldError() != null) {
            errorMessage = ex.getFieldError().getDefaultMessage();
        }
        log.error("MethodArgumentNotValidException", ex);
        return new ResponseEntity<>(ResponseResult.failed(errorMessage), HttpStatus.BAD_REQUEST);
    }
}