一波带走,SpringBoot 中的各种参数校验方案汇总

1、前言

在控制器类的方法里自己写校验逻辑代码当然也可以,只是代码比较丑陋,有点“low”。业界有更好的处理方法,分别阐述如下。

2、PathVariable校验


一波带走,SpringBoot 中的各种参数校验方案汇总

用法是:路径变量:正则表达式。当请求URI不满足正则表达式时,客户端将收到404错误码。不方便的地方是,不能通过捕获异常的方式,向前端返回统一的、自定义格式的响应参数。

3、方法参数校验

@GetMapping("/validate1")
@ResponseBody
public String validate1(
        @Size(min = 1,max = 10,message = "姓名长度必须为1到10")@RequestParam("name") String name,
        @Min(value = 10,message = "年龄最小为10")@Max(value = 100,message = "年龄最大为100") @RequestParam("age") Integer age) {
    return "validate1";
}

如果前端传递的参数不满足规则,则抛出异常。注解Size、Min、Max来自validation-api.jar,更多注解参见相关标准小节。

4、表单对象/VO对象校验

当参数是VO时,可以在VO类的属性上添加校验注解。

一波带走,SpringBoot 中的各种参数校验方案汇总

其中,Future注解要求必须是相对当前时间来讲“未来的”某个时间。

一波带走,SpringBoot 中的各种参数校验方案汇总

5、自定义校验规则

5.1 自定义注解校验

需要自定义一个注解类和一个校验类。

一波带走,SpringBoot 中的各种参数校验方案汇总


一波带走,SpringBoot 中的各种参数校验方案汇总

使用我们自定义的注解:

一波带走,SpringBoot 中的各种参数校验方案汇总

5.2 分组校验

一波带走,SpringBoot 中的各种参数校验方案汇总

  /**
     * 使用Defaul分组进行验证
     * @param resume
     * @return
     */
    @PostMapping("/validate5")
    public String addUser(@Validated(value = Resume.Default.class) @RequestBody Resume resume) {
        return "validate5";
    }

    /**
     * 使用Default、Update分组进行验证
     * @param resume
     * @return
     */
    @PutMapping("/validate6")
    public String updateUser(@Validated(value = {Resume.Update.class, Resume.Default.class}) @RequestBody Resume resume) {
        return "validate6";
    }

建立了两个分组,名称分别为Default、Update。POST方法提交时使用Defaut分组的校验规则,PUT方法提交时同时使用两个分组规则。

6、异常拦截器

通过设置全局异常处理器,统一向前端返回校验失败信息。

import com.scj.springbootdemo.WebResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.ObjectError;
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 javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.Set;

/**
 * 全局异常处理器
 */
@ControllerAdvice
public class GlobalExceptionHandler {

    private Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    /**
     * 用来处理bean validation异常
     * @param ex
     * @return
     */
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseBody
    public  WebResult resolveConstraintViolationException(ConstraintViolationException ex){
        WebResult errorWebResult = new WebResult(WebResult.FAILED);
        Set> constraintViolations = ex.getConstraintViolations();
        if(!CollectionUtils.isEmpty(constraintViolations)){
            StringBuilder msgBuilder = new StringBuilder();
            for(ConstraintViolation constraintViolation :constraintViolations){
                msgBuilder.append(constraintViolation.getMessage()).append(",");
            }
            String errorMessage = msgBuilder.toString();
            if(errorMessage.length()>1){
                errorMessage = errorMessage.substring(0,errorMessage.length()-1);
            }
            errorWebResult.setInfo(errorMessage);
            return errorWebResult;
        }
        errorWebResult.setInfo(ex.getMessage());
        return errorWebResult;
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public WebResult resolveMethodArgumentNotValidException(MethodArgumentNotValidException ex){
        WebResult errorWebResult = new WebResult(WebResult.FAILED);
        List  objectErrors = ex.getBindingResult().getAllErrors();
        if(!CollectionUtils.isEmpty(objectErrors)) {
            StringBuilder msgBuilder = new StringBuilder();
            for (ObjectError objectError : objectErrors) {
                msgBuilder.append(objectError.getDefaultMessage()).append(",");
            }
            String errorMessage = msgBuilder.toString();
            if (errorMessage.length() > 1) {
                errorMessage = errorMessage.substring(0, errorMessage.length() - 1);
            }
            errorWebResult.setInfo(errorMessage);
            return errorWebResult;
        }
        errorWebResult.setInfo(ex.getMessage());
        return errorWebResult;
    }
}

7、相关标准

JSR 303 是Bean验证的规范 ,Hibernate Validator 是该规范的参考实现,它除了实现规范要求的注解外,还额外实现了一些注解。
validation-api-1.1.0.jar 包括如下约束注解:

一波带走,SpringBoot 中的各种参数校验方案汇总

hibernate-validator-5.3.6.jar 包括如下约束注解:

一波带走,SpringBoot 中的各种参数校验方案汇总

8、同时校验2个或更多个字段/参数

常见的场景之一是,查询某信息时要输入开始时间和结束时间。显然,结束时间要 开始时间。可以在查询VO类上使用自定义注解,下面的例子来自这里。划重点:@ValidAddress使用在类上。


一波带走,SpringBoot 中的各种参数校验方案汇总


一波带走,SpringBoot 中的各种参数校验方案汇总


一波带走,SpringBoot 中的各种参数校验方案汇总


一波带走,SpringBoot 中的各种参数校验方案汇总

展开阅读全文

页面更新:2024-04-03

标签:参数   注解   全局   处理器   异常   对象   规则   两个   时间   方案   方法

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号

Top