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

常用的原生校验注解有:

@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博客

 

相关内容

热门资讯

对话地方 发展新篇 | “半岛... 7月29日上午,“半岛1号”正式启航。7月29日,山东省烟台市蓬莱区蓬长客港海风习习,山东“好客山东...
蒸馒头,奶奶教我30年老方法,... 馒头是一种很普通的食物,但却是很多朋友离不开的一种食物,南方人还好,东北人才是真的喜欢吃馒头,东北人...
西苑科普 | 头晕走不稳,竟是... 作者:中国中医科学院西苑医院脑病科 主任医师 刘红梅 审核:中国中医科学院西苑医院脑病科 主任医师 ...
口感软糯绵密、香甜不腻!这道紫... 紫薯蒸熟捣泥后包裹着金黄软糯的香蕉,再均匀裹上一层雪白的椰蓉,造型小巧可爱。一口下去,椰香、薯香与香...
关晓彤“晒碗”,火了 最近彩椒火了。 先是关晓彤晒了妈妈做的“夏日低卡彩椒碗”,以彩椒作为容器,填入鸡胸肉碎、土豆胡萝卜泥...
邹义荣:放大景区文化价值,带动... 广州市景协旅游发展中心主任邹义荣表示,2025年“羊城八景”的评选,既延续了历届“羊城八景”的文化脉...
甘肃6天5晚自由行超全指南,甘... 宝子们,是不是和曾经的我一样,心里一直怀揣着对甘肃甘南的向往,那片神秘而又美丽的土地,有广袤无垠的草...
安徽旅游4天3夜要花多少?黄山... 自从孩子上了小学,我们一家三口就很少有机会一起出远门旅游了。这次,趁着孩子暑假,我们决定去黄山走一走...
从古城西安到盛京沈阳——K20... 8月3日,由中国铁路沈阳局集团有限公司沈阳客运段客运五队担当K2046/5次列车满载旅客一路向北,从...
刚从西北回来八月的甘肃简直封神... 今年夏天,我跟着朋友一起报名了青甘8天7晚的户外线路,全程草原徒步+戈壁露营体验,真正挑战自我。而这...
4日起,太阳岛风景区花卉园临时... 记者从太阳岛风景区资产经营有限公司了解到,为整体优化太阳岛风景区的空间资源配置,提升景区业态及未来可...
新版“羊城八景”以景点组合形式... 广州这座城,天生就是个大戏台。 千年城脉是永不改换的曲牌,粤剧四功是历久弥新的程式。这座城的妙处,在...
共赏梨园风采 豫晋文旅有约——... 跟着戏剧游中原,共赏梨园好风采。8月2日晚,“豫晋相约 山河同游”河南文旅(山西)宣传推广活动走进龙...
2025甘肃口碑好的导游,六天... 宝子们,2025 年的旅游热潮已经来袭!在众多旅游目的地中,甘肃甘南犹如一颗闪耀的明珠,散发着独特的...
陕西5日游旅游攻略,西安五日游... 西安拥有众多闻名遐迩的旅游景点,每一处都承载着丰富的历史信息和独特的文化价值。兵马俑,被誉为“世界第...
关于严禁伪造、冒用证件套取景区... 公 告 尊敬的游客朋友们: 为贯彻落实各级政府惠民政策,切实保障特定群体合法权益,安顺旅游集团旗下各...
突破100万!第二十三届哈尔滨... 自2025年7月5日开幕,截至8月3日21:30,第二十三届哈尔滨国际啤酒节共运营30天,累计接待游...
北京中大中医医院到北京西站行程... 从北京中大中医医院到北京西站,有以下几种行程路线可供选择: 地铁线路: 步行至地铁花园桥站,乘坐地铁...
丹东凤凰山女子目睹丈夫坠亡详情... 近日,辽宁丹东凤城市凤凰山景区有游客坠崖身亡一事引发广泛关注。8月4日,丹东市文旅局工作人员向南都N...
甘肃旅游六天正规当地导游微信,... 家人们,谁不想去甘肃来一场深度游呢?甘肃这片土地,有着广袤无垠的沙漠、五彩斑斓的丹霞、庄严肃穆的石窟...