接口参数校验工具类ValidationParamUtils,让参数校验从“繁琐、重复”变得“省事、简单”!
文章目录
- 前言
- 一、为什么不采用已有参数校验技术?
- 二、ValidationParamUtils让参数校验变得简单
- (1)BusinessException支持国际化
- (2)ValidationParamUtils参数校验
前言
在使用JAVA语言开发软件时,会面临前后端数据交互、多方系统接口数据传输等问题。数据的交互是个永远都绕不开的话题,那么有数据,就会涉及到数据的校验问题。不知你是否因为数据合法性判断而头大?重复的写if判断,然后抛出异常信息,这种繁琐且重复的事情,是否让人感觉到无聊枯燥?为了避免重复编写这种繁琐枯燥的数据校验代码,我们打算写一个参数校验工具类ValidationParamUtils,让参数校验从“繁琐、重复”变得“省事、简单”!
一、为什么不采用已有参数校验技术?
我们知道市面上有很多成熟的参数校验技术,大家可能最常见的就是 javax.validation,这种基于注解的校验方式,是十分受到大家的青睐,并且其提供了丰富的参数校验注解,可以满足大多数接口参数校验场景。
但是它存在以下几点弊端需要我们处理:
- 数据的校验如果是在serice(业务)层、持久层、工具包时,应该如何进行参数校验?
- 校验抛出异常为ConstraintViolationException,还需要我们定义全局异常进行捕获,转换为统一异常格式。
- 后端若要支持国际化,那么这种基于注解的参数校验,完全无法满足后端国际化的业务场景。
对于以上的几点弊端,第一点和第二点是可以从技术上快速解决的,而第三点则可能需要我们修改其源码,才能达到支持国际化的要求。而ValidationParamUtils则可以完美解决以上这些问题。它并不是只试用于接口参数校验,它适用于任何业务情况下的数据校验,并且可以根据结合自身需要新增数据校验方法。
二、ValidationParamUtils让参数校验变得简单
ValidationParamUtils其实是Apache Commons ValidationUtils的一种改良,Apache Commons的ValidationUtils提供了很好的参数校验方法,但是其弊端在于无法让用户自定义异常以及不支持国际化操作。
(1)BusinessException支持国际化
BusinessException作为我们后端的统一异常格式,其内嵌了IL8nMessageUtils(国际化语音工具类),从而可以根据错误码找到对应的不同国家的错误信息,通过 String.format进行参数替换,实现异常信息国际化。如果您还不熟悉后端如何实现国际化操作,您可以参考文章SpringBoot实现国际化。BusinessException的源码如下:
/*** @Author: Greyfus* @Create: 2023-08-07 22:46* @Version: 1.0.0* @Description:系统业务异常*/
import com.hl.by.common.il8n.IL8nMessageUtils;
import lombok.Getter;@Getter
public class BusinessException extends RuntimeException {/*** 错误码*/private final String errorCode;/*** 错误描述*/private final String errorMsg;/*** 国际化消息处理* @param errorCode* @param errorMsg* @param args* @return* @Author: Greyfus* @Create: 2023-08-07 22:46*/private static String handlerIl8nString(String errorCode, String errorMsg, Object... args) {try {//获取国际化信息String il8nErrorMsg = IL8nMessageUtils.message(errorCode, (Object) null);if (!il8nErrorMsg.equals(errorCode)) {//如果返回的信息不是消息码,则表示找到国际化信息,替换原来的errorMsgerrorMsg = il8nErrorMsg;}} catch (Throwable ignored) {}//如果携带了参数,则进行参数替换errorMsg = (args == null || args.length == 0) ? errorMsg : String.format(errorMsg, args);return errorMsg;}/*** 支持多参数替换,采用String.format* @param errorCode* @param errorMsg* @param args*/public BusinessException(String errorCode, String errorMsg, Object... args) {super(handlerIl8nString(errorCode, errorMsg, args));this.errorCode = errorCode;this.errorMsg = handlerIl8nString(errorCode, errorMsg, args);}
}
(2)ValidationParamUtils参数校验
ValidationParamUtils目前提供了参数范围校验、notNull对象不为空、空集合、空数组、空字符串、状态校验validState、布尔boolean校验等。
具体使用如下:
public static void main(String[] args) {ValidationParamUtils.isTrue(1 > 2, "0001", "条件%S不大于%s", 1, 2);Integer number = null;ValidationParamUtils.notNull(number, "0002", "number不能为空");Integer[] array = new Integer[]{};ValidationParamUtils.notEmpty(array, "0003", "数组array不能为空");Collection collection = new ArrayList();ValidationParamUtils.notEmpty(collection, "0004", "集合collection不能为空");Collection list = new ArrayList();list.add("A");ValidationParamUtils.isEmpty(list, "0005", "集合List不是空集合");ValidationParamUtils.notBlank(" ", "0006", "字符串不能为空");ValidationParamUtils.validState(1 > 2, "0007", "条件%S不大于%s", 1, 2);ValidationParamUtils.inclusiveBetween(1, 2, 3, "0008", "值%S不在%S到%S之间", 3, 1, 2);//闭区间[0,1]ValidationParamUtils.exclusiveBetween(1, 2, 2, "0009", "值%S不在%S到%S之间", 3, 1, 2);//开区间(0,1)}
ValidationParamUtils的源码如下,校验规则可根据自身业务进行扩展修改:
import com.hl.by.common.exception.BusinessException;
import java.util.ArrayList;
import java.util.Collection;/*** @Author: Greyfus* @Date: 2025/8/12 10:08* @Version: 1.0.0* @Description: 参数验证工具类**/
public class ValidationParamUtils {public ValidationParamUtils() {}/*** 验证参数是否为真,为假则抛出异常* @param expression* @param errorCode* @param errorMsg*/public static void isTrue(boolean expression, String errorCode, String errorMsg) {if (!expression) {throw new BusinessException(errorCode, errorMsg);}}/*** 验证参数是否为真,为假则抛出异常* @param expression* @param errorCode* @param errorMsg* @param values*/public static void isTrue(boolean expression, String errorCode, String errorMsg, Object... values) {if (!expression) {throw new BusinessException(errorCode, errorMsg, values);}}/*** 验证参数是否为真,为假则抛出异常* @param expression* @param errorCode* @param message* @param value*/public static void isTrue(boolean expression, String errorCode, String message, long value) {if (!expression) {throw new BusinessException(errorCode, message, value);}}/*** 验证参数是否为真,为假则抛出异常* @param expression* @param errorCode* @param message* @param value*/public static void isTrue(boolean expression, String errorCode, String message, double value) {if (!expression) {throw new BusinessException(errorCode, message, value);}}/*** 验证参数是否为真,为假则抛出异常* @param object* @param errorCode* @param message* @param <T>*/public static <T> void notNull(T object, String errorCode, String message) {if (object == null) {throw new BusinessException(errorCode, message);}}/*** 验证参数是否为真,为假则抛出异常* @param object* @param errorCode* @param message* @param values* @param <T>*/public static <T> void notNull(T object, String errorCode, String message, Object... values) {if (object == null) {throw new BusinessException(errorCode, message, values);}}/*** 验证数组参数是否为空,为假则抛出异常* @param array* @param errorCode* @param message* @param <T>* @return*/public static <T> T[] notEmpty(T[] array, String errorCode, String message) {if (array == null || array.length == 0) {throw new BusinessException(errorCode, message);}return array;}/*** 验证数组参数是否为空,为假则抛出异常* @param array* @param errorCode* @param message* @param values* @param <T>* @return*/public static <T> T[] notEmpty(T[] array, String errorCode, String message, Object... values) {if (array == null || array.length == 0) {throw new BusinessException(errorCode, message, values);}return array;}/*** 验证集合参数是否为空,为假则抛出异常* @param collection* @param errorCode* @param message*/public static void notEmpty(Collection collection, String errorCode, String message) {if (collection == null || collection.isEmpty()) {throw new BusinessException(errorCode, message);}}/*** 验证集合参数是否为空,为假则抛出异常* @param collection* @param errorCode* @param message* @param values*/public static void notEmpty(Collection collection, String errorCode, String message, Object... values) {if (collection == null || collection.isEmpty()) {throw new BusinessException(errorCode, message, values);}}/*** 验证集合参数是否不为空,为假则抛出异常* @param collection* @param errorCode* @param message* @param values*/public static void isEmpty(Collection collection, String errorCode, String message, Object... values) {if (collection != null && !collection.isEmpty()) {throw new BusinessException(errorCode, message, values);}}/*** 验证集合参数是否不为空,为假则抛出异常* @param collection* @param errorCode* @param message*/public static void isEmpty(Collection collection, String errorCode, String message) {if (collection != null && !collection.isEmpty()) {throw new BusinessException(errorCode, message);}}/*** 验证参数是否为空,为假则抛出异常* @param str* @param errorCode* @param message* @param <T>* @return*/public static <T extends CharSequence> void notBlank(T str, String errorCode, String message) {if (str == null || str.length() == 0 || str.toString().trim().isEmpty()) {throw new BusinessException(errorCode, message);}}/*** 验证参数是否为空,为假则抛出异常* @param str* @param errorCode* @param message* @param values* @param <T>* @return*/public static <T extends CharSequence> void notBlank(T str, String errorCode, String message, Object... values) {if (str == null || str.length() == 0 || str.toString().trim().isEmpty()) {throw new BusinessException(errorCode, message, values);}}/*** 验证参数规则是否为真,为假则抛出异常* @param expression* @param errorCode* @param errorMsg*/public static void validState(boolean expression, String errorCode, String errorMsg) {if (!expression) {throw new BusinessException(errorCode, errorMsg);}}/*** 验证参数规则是否为真,为假则抛出异常* @param expression* @param errorCode* @param errorMsg* @param values*/public static void validState(boolean expression, String errorCode, String errorMsg, Object... values) {if (!expression) {throw new BusinessException(errorCode, errorMsg, values);}}/*** 验证参数是否在范围内,不在范围内则抛出异常!!!!闭区间[0, 1]* @param start* @param end* @param value* @param errorCode* @param message* @param <T>*/public static <T> void inclusiveBetween(T start, T end, Comparable<T> value, String errorCode, String message) {if (value.compareTo(start) < 0 || value.compareTo(end) > 0) {throw new BusinessException(errorCode, message);}}/*** 验证参数是否在范围内,不在范围内则抛出异常!!!!闭区间[0, 1]* @param start* @param end* @param value* @param errorCode* @param message* @param values* @param <T>*/public static <T> void inclusiveBetween(T start, T end, Comparable<T> value, String errorCode, String message, Object... values) {if (value.compareTo(start) < 0 || value.compareTo(end) > 0) {throw new BusinessException(errorCode, message, values);}}/*** 验证参数是否在范围内,不在范围内则抛出异常开区间(0, 1)* @param start* @param end* @param value* @param errorCode* @param message* @param <T>*/public static <T> void exclusiveBetween(T start, T end, Comparable<T> value, String errorCode, String message) {if (value.compareTo(start) <= 0 || value.compareTo(end) >= 0) {throw new BusinessException(errorCode, message);}}/*** 验证参数是否在范围内(),不在范围内则抛出异常!!!!!开区间(0, 1)* @param start* @param end* @param value* @param errorCode* @param message* @param values* @param <T>*/public static <T> void exclusiveBetween(T start, T end, Comparable<T> value, String errorCode, String message, Object... values) {if (value.compareTo(start) <= 0 || value.compareTo(end) >= 0) {throw new BusinessException(errorCode, message, values);}}public static void main(String[] args) {ValidationParamUtils.isTrue(1 > 2, "0001", "条件%S不大于%s", 1, 2);Integer number = null;ValidationParamUtils.notNull(number, "0002", "number不能为空");Integer[] array = new Integer[]{};ValidationParamUtils.notEmpty(array, "0003", "数组array不能为空");Collection collection = new ArrayList();ValidationParamUtils.notEmpty(collection, "0004", "集合collection不能为空");Collection list = new ArrayList();list.add("A");ValidationParamUtils.isEmpty(list, "0005", "集合List不是空集合");ValidationParamUtils.notBlank(" ", "0006", "字符串不能为空");ValidationParamUtils.validState(1 > 2, "0007", "条件%S不大于%s", 1, 2);ValidationParamUtils.inclusiveBetween(1, 2, 3, "0008", "值%S不在%S到%S之间", 3, 1, 2);//闭区间[0,1]ValidationParamUtils.exclusiveBetween(1, 2, 2, "0009", "值%S不在%S到%S之间", 3, 1, 2);//开区间(0,1)}
}