Java:SpringBoot整合spring-boot-starter-validation实现自定义入参数据校验

本文通过简单的代码,实现validation自定义数据校验器

项目结构

$ tree -I target -I test
.
├── pom.xml
└── src
    └── main
        ├── java
        │   └── com
        │       └── example
        │           └── demo
        │               ├── DemoApplication.java
        │               ├── common
        │               │   ├── GlobalExceptionHandler.java
        │               │   └── JsonResult.java
        │               ├── controller
        │               │   └── UserController.java
        │               ├── dto
        │               │   └── UserDTO.java
        │               ├── validation
        │               │   └── StatusValidation.java
        │               └── validator
        │                   └── StatusValidator.java
        └── resources
            └── application.properties

validation依赖

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

完整pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>spring-boot-validation-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>2.3.7.RELEASE</spring-boot.version>
    </properties>

    <dependencies>

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

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

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

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>

    </dependencies>
</project>

自定义注解

package com.example.demo.validation;

import com.example.demo.validator.StatusValidator;

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;

@Target({
    
    ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = StatusValidator.class)
public @interface StatusValidation {
    
    
    String[] statusType() default {
    
    };

    String message() default "状态值错误";

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

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

}

自定义校验器

package com.example.demo.validator;

import com.example.demo.validation.StatusValidation;
import lombok.extern.slf4j.Slf4j;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.Arrays;
import java.util.List;

@Slf4j
public class StatusValidator implements ConstraintValidator<StatusValidation, Integer> {
    
    
    private List<String> statusType;

    @Override
    public void initialize(StatusValidation constraintAnnotation) {
    
    
        this.statusType = Arrays.asList(constraintAnnotation.statusType());
        ConstraintValidator.super.initialize(constraintAnnotation);
    }

    @Override
    public boolean isValid(Integer value, ConstraintValidatorContext context) {
    
    
        if (value != null) {
    
    
            if (!this.statusType.contains(String.valueOf(value))) {
    
    
                return false;
            }
        }
        return true;
    }
}

使用注解

package com.example.demo.dto;


import com.example.demo.validation.StatusValidation;
import lombok.Data;
import org.hibernate.validator.constraints.Length;

import javax.validation.constraints.NotNull;


@Data
public class UserDTO {
    
    

    private Long userId;

    @NotNull
    @Length(min = 2, max = 10)
    private String userName;

    @NotNull
    @Length(min = 6, max = 20)
    private String account;

    @NotNull
    @Length(min = 6, max = 20)
    private String password;

    @StatusValidation(statusType = {
    
    "1", "2"})
    private Integer status;
}

校验数据

package com.example.demo.controller;


import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.example.demo.common.JsonResult;
import com.example.demo.dto.UserDTO;

@RestController
public class UserController {
    
    
    @PostMapping("/save")
    public JsonResult saveUser(
            @RequestBody @Validated UserDTO userDTO) {
    
    
        // 校验通过,才会执行业务逻辑处理
        System.out.println(userDTO);

        return JsonResult.success(userDTO);
    }
}

捕获全局异常

package com.example.demo.common;

import org.springframework.http.HttpStatus;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolationException;
import java.util.Arrays;

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

    /**
     * 参数校验失败
     *
     * @param ex
     * @return
     */
    @ExceptionHandler({
    
    MethodArgumentNotValidException.class})
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public JsonResult handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
    
    
        FieldError fieldError = ex.getBindingResult()
                .getFieldErrors()
                .get(0);

        String msg = fieldError.getField() + fieldError.getDefaultMessage();

        return JsonResult.error("参数错误:" + msg);
    }

    /**
     * 参数校验失败
     *
     * @param ex
     * @return
     */
    @ExceptionHandler({
    
    ConstraintViolationException.class})
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public JsonResult handleConstraintViolationException(ConstraintViolationException ex) {
    
    
        return JsonResult.error("参数校验失败" + ex.getMessage());
    }
}

统一的数据返回

package com.example.demo.common;


/**
 * 统一的数据返回
 */
public class JsonResult {
    
    
    private Integer code;
    private String msg;
    private Object data;

    public JsonResult(Integer code, String msg, Object data) {
    
    
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    public static JsonResult success(Object data){
    
    
        return new JsonResult(0, "success", data);
    }

    public static JsonResult error(String errorMessage) {
    
    
        return new JsonResult(-1, errorMessage, null);
    }

    public Integer getCode() {
    
    
        return code;
    }

    public void setCode(Integer code) {
    
    
        this.code = code;
    }

    public String getMsg() {
    
    
        return msg;
    }

    public void setMsg(String msg) {
    
    
        this.msg = msg;
    }

    public Object getData() {
    
    
        return data;
    }

    public void setData(Object data) {
    
    
        this.data = data;
    }
}


测试用例及其结果如下

# 参数错误:account不能为null
POST {
    
    {
    
    baseUrl}}/save
content-type: application/json

{
    
    
  "name": "Tom"
}

###

# 参数错误:password不能为null

POST {
    
    {
    
    baseUrl}}/save
content-type: application/json

{
    
    
  "userName": "Tom"
}

###
# 参数错误:password长度需要在6和20之间
POST {
    
    {
    
    baseUrl}}/save
content-type: application/json

{
    
    
  "userName": "Tom",
  "password": "11"
}

###
# 参数错误:account不能为null
POST {
    
    {
    
    baseUrl}}/save
content-type: application/json

{
    
    
  "userName": "Tom",
  "password": "1133344"
}

###
# success
POST {
    
    {
    
    baseUrl}}/save
content-type: application/json

{
    
    
  "userName": "Tom",
  "password": "1133344",
  "account": "account"
}

###
# 参数错误:status状态值错误
POST {
    
    {
    
    baseUrl}}/save
content-type: application/json

{
    
    
  "userName": "Tom",
  "password": "1133344",
  "account": "account",
  "status": 0
}

###

###
# success
POST {
    
    {
    
    baseUrl}}/save
content-type: application/json

{
    
    
  "userName": "Tom",
  "password": "1133344",
  "account": "account",
  "status": 1
}

猜你喜欢

转载自blog.csdn.net/mouday/article/details/131274477