validator百度博客一大堆,本文是摘取的部份內容結合在項目中使用的經驗.前端
<dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>1.1.0.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>5.2.0.Final</version> </dependency>
@Data public class InformationBasicInfoAO { /** * 主鍵id */ private Long id; /** * 文章標題 */ @NotBlank(message = "文章標題不能爲空") private String title; /** * 發佈日期 */ @NotNull(message = "發佈時間不能爲空") private Date releaseDate; /** * 文章來源 */ @NotBlank(message = "文章來源不能爲空") private String source;
message的內容是返回給前端的提醒信息,能夠不填java
1.通用的校驗工具spring
@Slf4j public class ValidatorUtil { //也能夠使用spring注入的方式 private static Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); /** * 使用指定分組 * * @param object 被校驗的bean * @param groups 分組 * @return */ public static <T> Map<String, StringBuilder> validate(T object, Class<?>... groups) { Map<String, StringBuilder> errorMap = new HashMap<>(16); if (groups == null) { groups = new Class[]{Default.class}; } Set<ConstraintViolation<T>> set = validator.validate(object, groups); if (CollectionUtils.isEmpty(set)) { return null; } String property; for (ConstraintViolation<T> c : set) { // 這裏循環獲取錯誤信息,能夠自定義格式 property = c.getPropertyPath().toString(); if (errorMap.get(property) != null) { errorMap.get(property).append(",").append(c.getMessage()); } else { StringBuilder sb = new StringBuilder(); sb.append(c.getMessage()); errorMap.put(property, sb); } } return errorMap; } }
2.使用工具校驗api
這種方式直接拋去異常,全局異常處理app
Map<String, StringBuilder> errorMap = ValidatorUtil.validate(object); if (!CollectionUtils.isEmpty(errorMap)) { log.info("------參數校驗失敗:{}", errorMap); throw new ApplicationException(new ExceptionContext("參數校驗失敗"), "000005", errorMap.toString()); }
也能夠在controller中返回.框架
Map<String, StringBuilder> errorMap = ValidatorUtils.validate(accountAO); if (!CollectionUtils.isEmpty(errorMap)) { simpleData.setData(errorMap); result.setContent(simpleData); return result; }
也能夠在controller的形參上使用註解@Valid,這種方式不須要util類,能夠直接使用,直接拋出異常,須要加配置項,具體能夠百度,我的不喜歡這種方式,不夠靈活.maven
@PostMapping(value = "/order") public PojoResult<String> purchase(@RequestBody @Valid OrderAO orderAO, HttpServletRequest request) throws IOException, ServletException { PojoResult<String> pojoResult = new PojoResult<>(); }
框架自帶的註解只能解決一些常規的校驗,一些複雜邏輯的校驗,能夠使用自定義校驗器,這是本人很喜歡的功能,重複的複雜的校驗邏輯能夠使用註解很優雅的代替,讓代碼的耦合性下降,也更簡潔.
自定義校驗的基本思路是--自定義註解+自定義校驗器ide
自定義註解工具
//這裏能夠加上原生的註解,直接使用非空等功能 @Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) //這裏須要引入校驗器 @Constraint(validatedBy = CheckTagsValidator.class) @Documented public @interface CheckTags { String message() default ""; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
自定義校驗器post
//接口的兩個泛型,分別是自定義註解和註解校驗的參數類型 public class CheckTagsValidator implements ConstraintValidator<CheckTags, List<String>> { @Override public void initialize(CheckTags constraintAnnotation) { } //方法體內能夠寫本身須要校驗的邏輯,返回值爲false則校驗不經過 @Override public boolean isValid(List<String> value, ConstraintValidatorContext context) { boolean isValid = false; //限定最多3個tag,最少能夠0個,tag不超過4個漢字 if (CollectionUtils.isEmpty(value)) { return true; } String filter = value.stream().filter(tag -> tag.length() > 4).findAny().orElse(null); if (StringUtils.isBlank(filter) && value.size() < 4) { isValid = true; } if (!isValid) { context.disableDefaultConstraintViolation(); context.buildConstraintViolationWithTemplate("標籤輸入錯誤").addConstraintViolation(); } return isValid; } }
結合ValidatorUtil使用
Validator自己是支持用@Valid註解自動校驗的,也可能夠配置校驗返回策略,以下
@Configuration public class ValidatorConfiguration { @Bean public Validator validator(){ ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class ) .configure() .addProperty( "hibernate.validator.fail_fast", "true" ) .buildValidatorFactory(); Validator validator = validatorFactory.getValidator(); return validator; } }
我的並不推薦這種方式,參數不對時會直接拋出異常,而後@ControllerAdvice全局異常處理,返回結果
有兩個弊端,一是try/catch相對而言性能較低,二是返回異常結果不夠清晰;
推薦使用ValidatorUtil結合AOP,直接返回結果,代碼以下
@Slf4j @Aspect @Component public class ValidatorAspect { private static final String METHOD_POST = "POST"; @Around("execution(* com.test.government.affair.controller..*(..))") public Object handlerControllerMethod(ProceedingJoinPoint point) throws Throwable { long s = System.currentTimeMillis(); // 從獲取RequestAttributes中獲取HttpServletRequest的信息 RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); HttpServletRequest request = (HttpServletRequest) requestAttributes .resolveReference(RequestAttributes.REFERENCE_REQUEST); BucSSOUser user = SimpleUserUtil.getBucSSOUser(request); Object[] args = point.getArgs(); //校驗post請求參數 log.info("Controller: 請求 URI( {} )| user( {} )| args:( {} )| ", request.getRequestURI(), user.getEmpId(), args); if (METHOD_POST.equals(request.getMethod())) { for (int i = 0; i < args.length; i++) { Object arg = args[i]; Map<String, StringBuilder> errorMap = ValidatorUtil.validate(arg); if (!CollectionUtils.isEmpty(errorMap)) { log.info("參數校驗失敗 errorMap:{}", errorMap); return ServiceResult.error("000005", errorMap.toString()); } } } Object proceed = point.proceed(); log.info("Controller: 響應 result:( {} )| 請求耗時:( {} )", proceed, System.currentTimeMillis() - s); return proceed; } }
統一參數校驗,同時打印log 做者:從入門到脫髮 連接:https://www.jianshu.com/p/b3876bf9396c 來源:簡書 著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。