springboot下手動驗證對象util封裝
問題背景
在http的請求中,我們常用在接口方法入?yún)⒅?,加入@Validated 或者 @Valid注解,來驗證入?yún)ο蟮膶傩?,如下?br>
@ApiOperation(value="新增", notes="新增")
@PostMapping("/save")
public RestResponse<Boolean> save(@RequestBody @Validated SaveRequest request){
boolean isOk = xxxervice.save(request);
return RestResponse.ok(isOk);
}
但是在我們的業(yè)務(wù)中,不可避免需要在其他非入?yún)⒌拇a中進行其他的轉(zhuǎn)換類,比如 PO類 進行對象驗證,避免大段代碼的 if 非空校驗,最好支持給予注解的可以對象全量檢驗和指定屬性校驗和忽略屬性校驗,所以,就需要分裝出可以在任何代碼地方進行手動驗證的工具類,來提高代碼的簡潔性和驗證抽象性化的通用性
下面看代碼
springboot項目引入maven依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
基礎(chǔ)工具準備
package com.example.demo.util.constant;
/**
* 描述:http響應(yīng)code </br>
* 作者:IT學習道場 </br>
* 時間:2022-10-19 14:20
*/
public enum HttpCode {
/** 10系統(tǒng)異常 */
SYS_EXCEPTION("10"),
/** 200請求成功 */
OK("200"),
/** 207頻繁操作 */
MULTI_STATUS("207"),
/** 400請求參數(shù)出錯 */
BAD_REQUEST("400"),
/** 401沒有登錄 */
UNAUTHORIZED("401"),
/** 4012沒有登錄-沒token匹配-登錄超時*/
UNAUTHORIZED2("4012"),
/** 4013 用戶被限制登錄*/
UNAUTHORIZED3("4013"),
/** 4014沒有登錄-沒token匹配-異地登錄*/
UNAUTHORIZED4("4014"),
/** 402登錄失敗 */
LOGIN_FAIL("402"),
/** 403沒有權(quán)限 */
FORBIDDEN("403"),
/** 404找不到頁面 */
NOT_FOUND("404"),
/** 405請求方法不能被用于請求相應(yīng)的資源 */
METHOD_NOT_ALLOWED("405"),
/** 406內(nèi)容特性不滿足 */
NOT_ACCEPTABLE("406"),
/** 408請求超時 */
REQUEST_TIMEOUT("408"),
/** 409發(fā)生沖突 */
CONFLICT("409"),
/** 410已被刪除 */
GONE("410"),
/** 411沒有定義長度 */
LENGTH_REQUIRED("411"),
/** 412條件不滿足 */
PRECONDITION_FAILED("412"),
/** 413數(shù)據(jù)太大 */
ENTITY_TOO_LARGE("413"),
/** 415不是服務(wù)器中所支持的格式 */
UNSUPPORTED_MEDIA_TYPE("415"),
/** 421連接數(shù)過多 */
TOO_MANY_CONNECTIONS("421"),
/** 423已被鎖定 */
LOCKED("423"),
/** 451法律不允許 */
UNAVAILABLE_LEGAL("451"),
/** 500服務(wù)器出錯 */
SERVER_ERROR("500"),
/** 503服務(wù)器升級中,暫時不可用 */
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;
/**
* 描述: 基礎(chǔ)異常 </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;
/**
* 描述: 業(yè)務(wù)異常 </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 大區(qū)間str
* @param substring 小區(qū)間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 大區(qū)間str
* @param substring 小區(qū)間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 大區(qū)間str
* @param substring 小區(qū)間str
* @param message 異常消息
*/
public static void doesNotContain(@Nullable String textToSearch, String substring, String message) {
doesNotContain(textToSearch, substring, defaultCode, message);
}
/**
* textToSearch字符串是否包含 substring ,期望不包含
* @param textToSearch 大區(qū)間str
* @param substring 小區(qū)間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 判斷對象數(shù)組
* @param message 異常消息
*/
public static void notEmpty(@Nullable Object[] array, String message) {
notEmpty(array, defaultCode, message);
}
/**
* 期望值不為空
* @param array 判斷對象數(shù)組
* @param message 異常消息
*/
public static void notEmpty(@Nullable Object[] array, String code, String message) {
if (ObjectUtils.isEmpty(array)) {
throw new BusinessException(code, message);
}
}
/**
* 期望值不為空
* @param array 判斷對象數(shù)組
* @param message 異常消息
* @param logInfo 輸出日志對象
*/
public static void notEmpty(@Nullable Object[] array, String message, Object logInfo) {
notEmpty(array, defaultCode, message, logInfo);
}
/**
* 期望值不為空
* @param array 判斷對象數(shù)組
* @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);
}
}
}
/**
* 檢查入?yún)⑹欠駷閚ull
* @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");
}
}
完事,自己動手,封裝抽象,提高生產(chǎn)力!
作者:IT學習道場
歡迎關(guān)注微信公眾號 : IT學習道場