springboot下手动验证对象util封装
问题背景
在http的请求中,我们常用在接口方法入参中,加入@Validated 或者 @Valid注解,来验证入参对象的属性,如下:
@ApiOperation(value="新增", notes="新增")
@PostMapping("/save")
public RestResponse<Boolean> save(@RequestBody @Validated SaveRequest request){
boolean isOk = xxxervice.save(request);
return RestResponse.ok(isOk);
}
但是在我们的业务中,不可避免需要在其他非入参的代码中进行其他的转换类,比如 PO类 进行对象验证,避免大段代码的 if 非空校验,最好支持给予注解的可以对象全量检验和指定属性校验和忽略属性校验,所以,就需要分装出可以在任何代码地方进行手动验证的工具类,来提高代码的简洁性和验证抽象性化的通用性
下面看代码
springboot项目引入maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
基础工具准备
package com.example.demo.util.constant;
/**
* 描述:http响应code </br>
* 作者:IT学习道场 </br>
* 时间:2022-10-19 14:20
*/
public enum HttpCode {
/** 10系统异常 */
SYS_EXCEPTION("10"),
/** 200请求成功 */
OK("200"),
/** 207频繁操作 */
MULTI_STATUS("207"),
/** 400请求参数出错 */
BAD_REQUEST("400"),
/** 401没有登录 */
UNAUTHORIZED("401"),
/** 4012没有登录-没token匹配-登录超时*/
UNAUTHORIZED2("4012"),
/** 4013 用户被限制登录*/
UNAUTHORIZED3("4013"),
/** 4014没有登录-没token匹配-异地登录*/
UNAUTHORIZED4("4014"),
/** 402登录失败 */
LOGIN_FAIL("402"),
/** 403没有权限 */
FORBIDDEN("403"),
/** 404找不到页面 */
NOT_FOUND("404"),
/** 405请求方法不能被用于请求相应的资源 */
METHOD_NOT_ALLOWED("405"),
/** 406内容特性不满足 */
NOT_ACCEPTABLE("406"),
/** 408请求超时 */
REQUEST_TIMEOUT("408"),
/** 409发生冲突 */
CONFLICT("409"),
/** 410已被删除 */
GONE("410"),
/** 411没有定义长度 */
LENGTH_REQUIRED("411"),
/** 412条件不满足 */
PRECONDITION_FAILED("412"),
/** 413数据太大 */
ENTITY_TOO_LARGE("413"),
/** 415不是服务器中所支持的格式 */
UNSUPPORTED_MEDIA_TYPE("415"),
/** 421连接数过多 */
TOO_MANY_CONNECTIONS("421"),
/** 423已被锁定 */
LOCKED("423"),
/** 451法律不允许 */
UNAVAILABLE_LEGAL("451"),
/** 500服务器出错 */
SERVER_ERROR("500"),
/** 503服务器升级中,暂时不可用 */
SERVICE_UNAVAILABLE("503"),
/** 501获取资源所需要的策略并没有被满足 */
NOT_EXTENDED("510");
public final String code;
private HttpCode(String code) {
this.code = code;
}
/**
* Return the integer value of this status code.
*/
public String code() {
return this.code;
}
@Override
public String toString() {
return this.code.toString();
}
}
自定义异常类
package com.example.demo.exception;
import java.io.PrintWriter;
import java.io.StringWriter;
/**
* 描述: 基础异常 </br>
* 时间: 2022-02-07 16:18 </br>
* 作者:IT学习道场
*/
public abstract class BaseException extends RuntimeException {
private String code;
private String message;
public BaseException() {
}
public BaseException(String code, String message) {
super(message);
this.code = code;
this.message = message;
}
public BaseException(String msg, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(msg, cause, enableSuppression, writableStackTrace);
}
public BaseException(String message, Throwable cause) {
super(message, cause);
}
public BaseException(String message) {
super(message);
}
public BaseException(Throwable cause) {
super(cause);
}
public static String getStackTrace(Throwable throwable) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw, true);
throwable.printStackTrace(pw);
return sw.getBuffer().toString();
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
@Override
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
@Override
public String toString() {
return "BaseException{" +
"code=" + code +
", msg='" + message + '\'' +
'}';
}
}
package com.example.demo.exception;
import com.example.demo.util.constant.HttpCode;
/**
* 描述: 业务异常 </br>
* 时间: 2022-02-07 16:18 </br>
* 作者:IT学习道场
*/
public class BusinessException extends BaseException {
private String code = HttpCode.SERVER_ERROR.code;
private String message;
public BusinessException() {
}
public BusinessException(String code, String message) {
super(code, message);
this.code = code;
this.message = message;
}
public BusinessException(Throwable ex) {
super(ex);
}
public BusinessException(String message) {
this(HttpCode.SERVER_ERROR.code, message);
}
public BusinessException(String msg, Throwable ex) {
super(msg, ex);
}
@Override
public String getCode() {
return code;
}
@Override
public void setCode(String code) {
this.code = code;
}
@Override
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
自定义断言类
package com.example.demo.util;
import com.example.demo.exception.BusinessException;
import com.example.demo.util.constant.HttpCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import java.util.Collection;
import java.util.Map;
/**
* 描述: 老王专用断言 </br>
* 时间: 2021-02-25 9:28 </br>
* 作者:IT学习道场
*/
@Slf4j
public class AssertUtil extends Assert {
private static final String defaultCode = HttpCode.NOT_ACCEPTABLE.code;
/**
* 期望值是等于,不满足期望,则抛异常
* @param o1 值1
* @param o2 值2
* @param message 异常消息
*/
public static void isEquals(Object o1, Object o2 , String message) {
isEquals(o1, o2 ,defaultCode, message);
}
/**
* 期望值是等于,不满足期望,则抛异常
* @param o1 值1
* @param o2 值2
* @param message 异常消息
*/
public static void isEquals(Object o1, Object o2 ,String code, String message) {
if (!o1.toString().equals(o2.toString())) {
throw new BusinessException(code, message);
}
}
/**
* 期望值是不等于,不满足期望,则抛异常
* @param o1 值1
* @param o2 值2
* @param message 异常消息
*/
public static void isNotEquals(Object o1, Object o2 ,String message) {
isNotEquals(o1, o2 , defaultCode, message);
}
/**
* 期望值是不等于,不满足期望,则抛异常
* @param o1 值1
* @param o2 值2
* @param message 异常消息
*/
public static void isNotEquals(Object o1, Object o2 ,String code, String message) {
if (o1.toString().equals(o2.toString())) {
throw new BusinessException(code, message);
}
}
/**
* 期望值等于true,不满足期望值即expression = false,则抛异常
* @param expression 表达式boolean值
* @param message 异常消息
* @param logInfo 异常日志打印对象
*/
public static void isTrue(boolean expression, String message, Object logInfo) {
isTrue(expression, defaultCode, message, logInfo);
}
/**
* 期望值等于true,不满足期望值即expression = false,则抛异常
* @param expression 表达式boolean值
* @param message 异常消息
* @param logInfo 异常日志打印对象
*/
public static void isTrue(boolean expression, String code, String message, Object logInfo) {
if (!expression) {
if (!ObjectUtils.isEmpty(logInfo)){
log.error(logInfo.toString());
}
throw new BusinessException(code, message);
}
}
/**
* 期望值等于true,不满足期望值即expression = false,则抛异常
* @param expression 表达式boolean值
* @param message 异常消息
*/
public static void isTrue(boolean expression, String message) {
isTrue(expression, defaultCode, message);
}
/**
* 期望值等于true,不满足期望值即expression = false,则抛异常
* @param expression 表达式boolean值
* @param message 异常消息
*/
public static void isTrue(boolean expression, String code, String message) {
if (!expression) {
throw new BusinessException(code, message);
}
}
/**
* 期望值等于true,不满足期望值即expression = false,则抛异常
* @param expression 表达式boolean值
* @param message 异常消息
*/
public static void isNotTrue(boolean expression, String message) {
isNotTrue(expression, defaultCode, message);
}
/**
* 期望值等于true,不满足期望值即expression = false,则抛异常
* @param expression 表达式boolean值
* @param message 异常消息
*/
public static void isNotTrue(boolean expression, String code, String message) {
if (expression) {
throw new BusinessException(code, message);
}
}
/**
* 期望值等于true,不满足期望值即expression = false,则抛异常
* @param expression 表达式boolean值
* @param message 异常消息
* @param logInfo 异常日志打印对象
*/
public static void isNotTrue(boolean expression, String message, Object logInfo) {
isNotTrue( expression, defaultCode, message, logInfo);
}
/**
* 期望值等于true,不满足期望值即expression = false,则抛异常
* @param expression 表达式boolean值
* @param message 异常消息
* @param logInfo 异常日志打印对象
*/
public static void isNotTrue(boolean expression, String code, String message, Object logInfo) {
if (expression) {
if (!ObjectUtils.isEmpty(logInfo)){
log.error(logInfo.toString());
}
throw new BusinessException(code, message);
}
}
/**
* 期望值object = null,若object != null,则抛异常
* @param object 判断对象
* @param message 异常消息
* @param logInfo 异常日志
*/
public static void isNull(@Nullable Object object, String message, Object logInfo) {
isNull( object, defaultCode, message, logInfo);
}
/**
* 期望值object = null,若object != null,则抛异常
* @param object 判断对象
* @param message 异常消息
* @param logInfo 异常日志
*/
public static void isNull(@Nullable Object object, String code, String message, Object logInfo) {
if (object != null) {
if (!ObjectUtils.isEmpty(logInfo)){
log.error(logInfo.toString());
}
throw new BusinessException(code, message);
}
}
/**
* 期望值object = null,若object != null,则抛异常
* @param object 判断对象
* @param message 异常消息
*/
public static void isNull(@Nullable Object object, String message) {
isNull(object, defaultCode, message);
}
/**
* 期望值object = null,若object != null,则抛异常
* @param object 判断对象
* @param message 异常消息
*/
public static void isNull(@Nullable Object object, String code, String message) {
if (object != null) {
throw new BusinessException(code, message);
}
}
/**
* 期望值object != null,若object == null,则抛异常
* @param object 判断对象
* @param message 异常消息
* @param logInfo 异常日志
*/
public static void notNull(@Nullable Object object, String message, Object logInfo) {
notNull(object, defaultCode, message, logInfo);
}
/**
* 期望值object != null,若object == null,则抛异常
* @param object 判断对象
* @param message 异常消息
* @param logInfo 异常日志
*/
public static void notNull(@Nullable Object object, String code, String message, Object logInfo) {
if (object == null) {
if (!ObjectUtils.isEmpty(logInfo)){
log.error(logInfo.toString());
}
throw new BusinessException(code, message);
}
}
/**
* 期望值object != null,若object == null,则抛异常
* @param object 判断对象
* @param message 异常消息
*/
public static void notNull(@Nullable Object object, String message) {
notNull(object, defaultCode, message);
}
/**
* 期望值object != null,若object == null,则抛异常
* @param object 判断对象
* @param message 异常消息
*/
public static void notNull(@Nullable Object object, String code, String message) {
if (ObjectUtils.isEmpty(object)) {
throw new BusinessException(code, message);
}
}
/**
* textToSearch字符串是否包含 substring ,期望不包含
* @param textToSearch 大区间str
* @param substring 小区间str
* @param message 异常消息
* @param logInfo 打印日志对象
*/
public static void doesNotContain(@Nullable String textToSearch, String substring, String message, Object logInfo) {
doesNotContain(textToSearch, substring, defaultCode, message, logInfo);
}
/**
* textToSearch字符串是否包含 substring ,期望不包含
* @param textToSearch 大区间str
* @param substring 小区间str
* @param message 异常消息
* @param logInfo 打印日志对象
*/
public static void doesNotContain(@Nullable String textToSearch, String substring, String code, String message, Object logInfo) {
if (StringUtils.hasLength(textToSearch) && StringUtils.hasLength(substring) && textToSearch.contains(substring)) {
if (!ObjectUtils.isEmpty(logInfo)){
log.error(logInfo.toString());
}
throw new BusinessException(code, message);
}
}
/**
* textToSearch字符串是否包含 substring ,期望不包含
* @param textToSearch 大区间str
* @param substring 小区间str
* @param message 异常消息
*/
public static void doesNotContain(@Nullable String textToSearch, String substring, String message) {
doesNotContain(textToSearch, substring, defaultCode, message);
}
/**
* textToSearch字符串是否包含 substring ,期望不包含
* @param textToSearch 大区间str
* @param substring 小区间str
* @param message 异常消息
*/
public static void doesNotContain(@Nullable String textToSearch, String substring, String code, String message) {
if (StringUtils.hasLength(textToSearch) && StringUtils.hasLength(substring) && textToSearch.contains(substring)) {
throw new BusinessException(code, message);
}
}
/**
* 期望值不为空
* @param array 判断对象数组
* @param message 异常消息
*/
public static void notEmpty(@Nullable Object[] array, String message) {
notEmpty(array, defaultCode, message);
}
/**
* 期望值不为空
* @param array 判断对象数组
* @param message 异常消息
*/
public static void notEmpty(@Nullable Object[] array, String code, String message) {
if (ObjectUtils.isEmpty(array)) {
throw new BusinessException(code, message);
}
}
/**
* 期望值不为空
* @param array 判断对象数组
* @param message 异常消息
* @param logInfo 输出日志对象
*/
public static void notEmpty(@Nullable Object[] array, String message, Object logInfo) {
notEmpty(array, defaultCode, message, logInfo);
}
/**
* 期望值不为空
* @param array 判断对象数组
* @param message 异常消息
* @param logInfo 输出日志对象
*/
public static void notEmpty(@Nullable Object[] array, String code, String message, Object logInfo) {
if (ObjectUtils.isEmpty(array)) {
if (!ObjectUtils.isEmpty(logInfo)){
log.error(logInfo.toString());
}
throw new BusinessException(code, message);
}
}
/**
* 期望值不为空
* @param collection 判断集合
* @param message 异常消息提醒
* @param logInfo 打印异常日志对象
*/
public static void notEmpty(@Nullable Collection<?> collection, String message, Object logInfo) {
notEmpty(collection, defaultCode, message, logInfo);
}
/**
* 期望值不为空
* @param collection 判断集合
* @param message 异常消息提醒
* @param logInfo 打印异常日志对象
*/
public static void notEmpty(@Nullable Collection<?> collection, String code, String message, Object logInfo) {
if (CollectionUtils.isEmpty(collection)) {
if (!ObjectUtils.isEmpty(logInfo)){
log.error(logInfo.toString());
}
throw new BusinessException(code, message);
}
}
/**
* 期望值不为空
* @param collection 判断集合
* @param message 异常消息提醒
*/
public static void notEmpty(@Nullable Collection<?> collection, String message) {
notEmpty(collection, defaultCode, message);
}
/**
* 期望值不为空
* @param collection 判断集合
* @param message 异常消息提醒
*/
public static void notEmpty(@Nullable Collection<?> collection, String code, String message) {
if (CollectionUtils.isEmpty(collection)) {
throw new BusinessException(code, message);
}
}
/**
* 期望值不为空
* @param map 判断map
* @param message 异常消息提醒
* @param logInfo 打印异常日志对象
*/
public static void notEmpty(@Nullable Map<?, ?> map, String message, Object logInfo) {
notEmpty(map, defaultCode, message, logInfo);
}
/**
* 期望值不为空
* @param map 判断map
* @param message 异常消息提醒
* @param logInfo 打印异常日志对象
*/
public static void notEmpty(@Nullable Map<?, ?> map, String code, String message, Object logInfo) {
if (CollectionUtils.isEmpty(map)) {
if (!ObjectUtils.isEmpty(logInfo)){
log.error(logInfo.toString());
}
throw new BusinessException(code, message);
}
}
/**
* 期望值不为空
* @param map 异常消息提醒
* @param message 异常消息提醒
*/
public static void notEmpty(@Nullable Map<?, ?> map, String message) {
notEmpty(map, defaultCode, message);
}
/**
* 期望值不为空
* @param map 异常消息提醒
* @param message 异常消息提醒
*/
public static void notEmpty(@Nullable Map<?, ?> map, String code, String message) {
if (CollectionUtils.isEmpty(map)) {
throw new BusinessException(code, message);
}
}
}
正餐开始,验证工具类
package com.example.demo.validation;
import com.example.demo.util.AssertUtil;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.groups.Default;
import java.util.*;
/**
* 描述: bean 校验类 </br>
* 时间: 2022-11-02 17::35 </br>
* 作者:IT学习道场
*/
public class ValidUtil {
private static javax.validation.Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
/**
* 验证指定对象
*
* @param obj 需要被验证对象
* @return
*/
public static <T> void validEntity(T obj) {
if(!ObjectUtils.isEmpty(obj)){
Set<ConstraintViolation<T>> set = validator.validate(obj, Default.class);
if (!CollectionUtils.isEmpty(set)) {
List<String> errorList = new ArrayList<>();
for (ConstraintViolation<T> cv : set) {
errorList.add(cv.getMessage());
}
String errorMsg = String.join("\n", errorList);
AssertUtil.isTrue(false, errorMsg);
}
}
}
/**
* 验证指定对象的指定属性
* @param obj 需要被验证对象
* @param propertyName 需要验证的属性名称
* @return
*/
public static <T> void validProperty(T obj, String... propertyName) {
if(!ObjectUtils.isEmpty(obj)){
List<String> errorList = new ArrayList<>();
for (String pName : propertyName) {
Set<ConstraintViolation<T>> set = validator.validateProperty(obj, pName, Default.class);
if (!CollectionUtils.isEmpty(set)) {
for (ConstraintViolation<T> cv : set) {
errorList.add(cv.getMessage());
}
}
}
String errorMsg = String.join("\n", errorList);
AssertUtil.isTrue(false, errorMsg);
}
}
/**
* 验证指定对象
* @param obj 要被验证对象
* @param exceptPropertyName 排除属性(不希望验证的属性)
* @return
*/
public static <T> void validEntity(T obj, String... exceptPropertyName) {
if(!ObjectUtils.isEmpty(obj)){
Set<ConstraintViolation<T>> set = validator.validate(obj, Default.class);
if (!CollectionUtils.isEmpty(set)) {
List<String> errorList = new ArrayList<>();
for (ConstraintViolation<T> cv : set) {
String field = cv.getPropertyPath().toString();
if (!isExcept(field, exceptPropertyName)) {
errorList.add(cv.getMessage());
}
}
String errorMsg = String.join("\n", errorList);
AssertUtil.isTrue(false, errorMsg);
}
}
}
/**
* 检查入参是否为null
* @param obj 验证对象
* @param <T>
* @return true - 空,false - 不为空
*/
private static <T> boolean checkObjNull(T obj) {
if (ObjectUtils.isEmpty(obj)){
return true;
}
return false;
}
/**
*
* 判断字段是否属于例外字段列表
*
* @param field
* @param exceptFieldName
* @return true:属于例外字段 false:不是例外字段
* @exception
* @since 1.0.0
*/
private static boolean isExcept(String field, String... exceptFieldName) {
for (String ef : exceptFieldName) {
if (!ObjectUtils.isEmpty(ef) && ef.equalsIgnoreCase(field)) {
return true;
}
}
return false;
}
}
测试代码类
package com.example.demo.dto;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* 描述:todo </br>
* 作者:IT学习道场 </br>
* 时间:2022-10-31 11:36
*/
@Data
public class BBB {
@NotBlank(message = "BBB用户名不能为空")
private String userName;
@NotNull(message = "userAge不能为空")
private Long userAge;
}
测试类
package com.example.demo.test;
import com.example.demo.dto.BBB;
import com.example.demo.validation.ValidUtil;
/**
* 描述:验证实验类测试 </br>
* 作者:IT学习道场 </br>
* 时间:2022-11-02 16:32
*/
public class ValidTest {
public static void main(String[] args) {
BBB bbb = new BBB();
//类全部属性验证
ValidUtil.validEntity(bbb);
//指定属性验证,只验证对象的用户名
// ValidUtil.validProperty(bbb, "userName");
//忽略属性验证,验证对象,忽略用户名属性,其他属性都验证
// ValidUtil.validEntity(bbb, "userName");
}
}
完事,自己动手,封装抽象,提高生产力!
作者:IT学习道场
欢迎关注微信公众号 : IT学习道场