基于Spring Validation自定义校验注解
admin
2024-02-11 02:58:13

常用的原生校验注解有:

@NotNull 所有对象判空
@NotBlank 字符串判空
@NotEmpty 集合判空

自定义校验注解实现方式:

引入依赖

如果spring-boot版本小于2.3.x,spring-boot-starter-web会自动传入hibernate-validator依赖。如果spring-boot版本大于2.3.x,则需要手动引入依赖:

org.hibernatehibernate-validator6.0.1.Final

定义校验注解

自定义一个校验注解,针对字符串参数校验,校验逻辑是字符串必须是"xzh"。

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE_USE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;import javax.validation.Constraint;
import javax.validation.Payload;/*** @author 向振华* @date 2022/11/23 16:52*/
@Documented
@Constraint(validatedBy = {EqualsXzhValidator.class})
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
public @interface EqualsXzh {String message() default "必须是xzh";Class[] groups() default { };Class[] payload() default { };
}

实现校验逻辑

校验逻辑是字符串必须是"xzh"。

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;/*** @author 向振华* @date 2022/11/23 16:56*/
public class EqualsXzhValidator implements ConstraintValidator {public EqualsXzhValidator() {}@Overridepublic boolean isValid(String value, ConstraintValidatorContext context) {// 自定义校验规则,字段的value必须是"xzh",否则抛异常return "xzh".equals(value);}
}

全局异常捕获处理

参数校验会默认抛出MethodArgumentNotValidException异常,通常使用全局异常捕获拦截,然后返回提示信息出去 。

import com.xzh.exception.BusinessException;
import com.xzh.web.ApiResponse;
import lombok.extern.slf4j.Slf4j;
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.RestControllerAdvice;import javax.servlet.http.HttpServletRequest;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.StringJoiner;/*** 全局异常捕获处理** @author 向振华* @date 2022/11/23 16:52*/
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {/*** 异常处理程序** @param request* @param exception* @return*/@ExceptionHandler(value = Exception.class)public Object handler(HttpServletRequest request, Exception exception) {String errorLog = this.errorLog(request, exception);log.error("全局异常捕获日志 ---> {}", errorLog);String message;if (exception instanceof MethodArgumentNotValidException) {MethodArgumentNotValidException e = (MethodArgumentNotValidException) exception;BindingResult bindingResult = e.getBindingResult();StringJoiner sj = new StringJoiner(",");for (FieldError fieldError : bindingResult.getFieldErrors()) {String longField = fieldError.getField();String shortField = longField.substring(longField.lastIndexOf(".") + 1);String defaultMessage = fieldError.getDefaultMessage();sj.add(shortField + defaultMessage);}message = sj.toString();} else if (exception instanceof BusinessException) {BusinessException e = (BusinessException) exception;message = e.getMessage();} else {message = "系统异常,请稍后重试";}return ApiResponse.fail(message);}private String errorLog(HttpServletRequest request, Exception exception) {StringWriter sw = new StringWriter();sw.append(String.format("[接口] %s\n", request.getRequestURL()));exception.printStackTrace(new PrintWriter(sw));return sw.toString();}
}

参数校验工具

 参数校验也可以使用工具类进行校验,校验不通过抛出业务异常(也会被全局异常捕获拦截)

import com.xzh.exception.BusinessException;import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.Set;
import java.util.StringJoiner;/*** 参数校验工具** @author 向振华* @date 2022/11/23 16:52*/
public class ValidatedUtils {private static final Validator VALIDATOR;static {VALIDATOR = Validation.buildDefaultValidatorFactory().getValidator();}private ValidatedUtils() {}public static void verify(Object object, Class... groups) {Set> constraintViolations = VALIDATOR.validate(object, groups);if (!constraintViolations.isEmpty()) {StringJoiner sj = new StringJoiner(",");for (ConstraintViolation constraint : constraintViolations) {sj.add(constraint.getPropertyPath().toString() + constraint.getMessage());}throw new BusinessException(sj.toString());}}
} 

使用

在参数上面加上@EqualsXzh注解即可

@EqualsXzh
private String name;

如果是嵌套校验还需要加上@Valid

@Data
public class OrderDTO {@EqualsXzhprivate String name;@Validprivate AccountDTO account;@Validprivate List orderItemList;
}

在对象前加@Validated注解

@PostMapping("/test")
public ApiResponse test(@RequestBody @Validated OrderDTO dto) {// TODOreturn ApiResponse.success();
}

校验不通过会出现提示:name必须是xzh

其中BusinessException是自定义的业务异常,ApiResponse是自定义的通用返回格式。

补充

以前的校验注解文章

Spring Boot 全局异常处理 与 Hibernate Validator校验框架整合_抓手的博客-CSDN博客

Spring校验框架的使用 @Validated_抓手的博客-CSDN博客

 

相关内容

热门资讯

赤水性价比粮食酒推荐:2025... 赤水性价比粮食酒推荐:2025年酱香酒选购全攻略 一、开篇背景与市场痛点 2025年的赤水河流域酒类...
非白酒板块11月19日跌0.3... 证券之星消息,11月19日非白酒板块较上一交易日下跌0.33%,*ST椰岛领跌。当日上证指数报收于3...
以运河文化赋能产业发展|古贝春... 11月17日至19日,以“新质开新局,聚力创未来”为主题的2025年第六届中国白酒黄淮核心产区高质量...
深夜小酌的灵魂搭档:油炝脆骨,... 油炝脆骨是一道充满锅气与烟火气息的家常菜,以其爽脆的口感和浓郁的香辣风味深受许多人喜爱。这道菜的制作...
初中毕业新征程:为什么西点烘焙... 站在初中毕业的人生路口,许多女孩都在思考:哪条路能通往一个既美好又独立的未来?如果有一条道路,能将女...