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

该文章通过示例展示了如何在SpringBoot项目中创建并使用自定义的数据校验器。首先,定义了一个自定义注解`StatusValidation`,然后创建了对应的校验器`StatusValidator`。接着,这个自定义校验器被应用到`UserDTO`类的`status`字段上,以限制状态值只能为特定的字符串。当校验失败时,全局异常处理器`GlobalExceptionHandler`捕获异常并返回相应的错误信息。最后,文章提供了测试用例来验证校验功能的正确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文通过简单的代码,实现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
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值