通過自定義spring invalidator註解校驗資料合法性
阿新 • • 發佈:2018-12-10
在專案中經常會對使用者輸入的資料,或者外部匯入到系統的資料做合法性檢查。在spring boot框架的微服務中可以使用invalidator註解對資料做合法性,安全性校驗。下面給一個樣例說明如何自定義註解實現校驗邏輯。
一、定義校驗屬性字串長度的註解
package com.elon.springbootdemo.manager.invalidator; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import javax.validation.Constraint; import javax.validation.Payload; /** * 屬性欄位長度校驗註解定義。 * * @author elon * @version 2018年9月19日 */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = FieldLengthInvalidatorImpl.class) @Documented public @interface FieldLengthInvalidator { // 欄位支援的最大長度(字元數) int maxLength() default 50; // 校驗失敗後返回的錯誤資訊 String message() default ""; // 分組 Class<?>[] groups() default {}; // 負載 Class<? extends Payload>[] payload() default {}; }
在定義註解時可宣告變數用於輔助校驗。上面的註解中定義了maxLength變數用於指定最大長度限制。變數可以設定預設值,使用註解時不傳引數,變數就使用預設值。
二、實現校驗邏輯,校驗失敗後返回錯誤提示
package com.elon.springbootdemo.manager.invalidator; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; /** * 欄位長度校驗實現類。 * * @author elon * @version 2018年9月19日 */ public class FieldLengthInvalidatorImpl implements ConstraintValidator<FieldLengthInvalidator, String> { private int maxLength = 0; @Override public void initialize(FieldLengthInvalidator invalidator) { maxLength = invalidator.maxLength(); } @Override public boolean isValid(String fieldValue, ConstraintValidatorContext context) { if (fieldValue.length() > maxLength) { context.disableDefaultConstraintViolation(); context.buildConstraintViolationWithTemplate("物件屬性長度超過限制。").addConstraintViolation(); // 校驗失敗返回false。返回true上游收集不到錯誤資訊。 return false; } return true; } }
三、在模型欄位屬性上增加校驗的註解
public class User
{
private int userId = -1;
@FieldLengthInvalidator(maxLength=10)
private String name = "";
}
四、提供統一的校驗方法
package com.elon.springbootdemo.manager; import java.util.ArrayList; import java.util.List; import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; /** * 有效性校驗管理類。對外提供統一的校驗呼叫介面。 * @author elon * @version 2018年9月19日 */ public class InvalidatorMgr { private InvalidatorMgr() { } /** * 獲取單例物件。 * * @return 單例物件 */ public static InvalidatorMgr instance() { return InvalidatorMgrBuilder.instance; } /** * 校驗模型所有屬性的有效性。 * * @param model 待校驗模型 * @return 錯誤資訊列表 */ public <T> List<String> validate(T model) { ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory(); Validator validator = validatorFactory.getValidator(); Set<ConstraintViolation<T>> resultSet = validator.validate(model); List<String> messageList = new ArrayList<>(); resultSet.forEach((r)->messageList.add(r.getMessage())); return messageList; } /** * 單例構建器。 * @author elon * @version 2018年9月19日 */ private static class InvalidatorMgrBuilder{ private static InvalidatorMgr instance = new InvalidatorMgr(); } }
五、業務層呼叫校驗方法
User user = new User();
user.setName("ahskahskhqlwjqlwqlwhqlhwlqjwlqhwlhqwhqlwjjqlwl");
List<String> messageList = InvalidatorMgr.instance().validate(user);
System.out.println(messageList);
invalidator註解主要用於實現長度,範圍,非法字元等通用的規則校驗。不適合用於做業務邏輯的校驗,特定的業務校驗寫在業務層。