您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關怎么在Java中使用@Validated注解進行參數驗證,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
// 要驗證的實體類 @Data public class User implements Serializable { @NotBlank(message = "id不能為空!",groups = Update.class) protected String id = ""; @NotBlank(message = "商戶id不能為空!") protected String tenantId; @NotBlank(message = "名稱不能為空!") protected String name = ""; } // controller // 在要驗證的參數上添加@Validated注解即可 @PostMapping("add") public boolean addUser(@Validated @RequestBody User user) { ProdAllotStandard info = allotStandardService.getProdAllotStandardWithDetailById(id); return info; } // 修改則需要比添加的基礎上多驗證一個id,可以通過group的方式進行區分 // 實體類上不設置groups,默認會是Default,所以修改的時候,我們需要指定Update和Default這兩個組 // group是可以自定義的,我默認定義了Add,Update,Delete,Search這四個組 @PostMapping("update") public boolean updateUser(@Validated({Update.class, Default.class}) @RequestBody User user) { ProdAllotStandard info = allotStandardService.getProdAllotStandardWithDetailById(id); return info; } // 當然該注解也支持service上實現,同樣的使用方法,在service的實現類的參數上加上對應注解即可,如: public boolean addUser(@Validated User user) { } // 通過不同group的搭配,我們就可以靈活的在實體類上配置不同場景的驗證了 // group為一個接口,用以下方式創建 public interface Add { }
下面看一下具體的實現,驗證框架的核心實現采用的是hibernate-validator,我采用的是5.4.3.Final版本。
controller和service的實現方式不同,下面分別介紹下。
不管哪種實現,我們都需要先定義一個異常和一個異常攔截器,當參數校驗出現問題時,我們就拋出對應異常。
// 為了簡短,省略了部分代碼 public class ParamsException extends RuntimeException{ private String code; public BusinessException() { } public ParamsException(String code,String message) { super(message); this.code = code; } public ParamsException(String message) { super(message); } } // 定義異常處理類 @ControllerAdvice public class ExceptionAdvice { private static Logger L = LoggerFactory.getLogger(ExceptionAdvice.class); // 對所有的ParamsException統一進行攔截處理,如果捕獲到該異常,則封裝成MessageBody返回給前端 @ExceptionHandler(value = ParamsException.class) @ResponseStatus(HttpStatus.OK) @ResponseBody public MessageBody handleParamsException(HttpServletRequest request, BusinessException e){ L.error(e.getMessage(),e); return getErrorMessageBody(e.getData(),e.getMessage(),e.getMessage(), StringUtils.isEmpty(e.getCode())?ResponseCode.BUSINESS_ERROR:e.getCode()); } private MessageBody getErrorMessageBody(Object data,String message,String errorInfo,String code){ MessageBody body = new MessageBody(); body.setCode(code); body.setData(data); body.setErrorCode(Integer.parseInt(code)); body.setErrorInfo(errorInfo); body.setMessage(message); body.setSuccess(false); return body; } }
controller的驗證的實現:
主要是通過實現spring mvc給我們留下的接口進行實現的,該方案沒有用到反射和代理。
1. 實現spring提供的SmartValidator接口
public class ParamsValidator implements SmartValidator { private javax.validation.Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); @Override public boolean supports(Class<?> clazz) { return true; } // 注解上沒有有group的驗證邏輯 @Override public void validate(Object target, Errors errors) { validate(target,errors,null); } // 注解上帶有group的驗證邏輯 // 第一個參數為我們要驗證的參數,第二個不用管,第三個為注解上設置個groups @Override public void validate(Object target, Errors errors, Object... validationHints) { // 這里面為驗證實現,可以根據自己的需要進行完善與修改 if (target == null) { throw new ParamsException("參數不能為空!"); } else { if(target instanceof String) { if(StringUtils.isEmpty(target)) { throw new ParamsException("參數不能為空!"); } }else if(target instanceof Collection) { for(Object o:(Collection)target){ validate(o,validationHints); } }else { validate(target,validationHints); } } } private void validate(Object target,Object ... objs) { Set<ConstraintViolation<Object>> violations; // 沒有groups的驗證 if(objs==null || objs.length==0) { violations = validator.validate(target); } else { // 基于groups的驗證 Set<Class<?>> groups = new LinkedHashSet<Class<?>>(); for (Object hint : objs) { if (hint instanceof Class) { groups.add((Class<?>) hint); } } violations = validator.validate(target, ClassUtils.toClassArray(groups)); } // 若為空,則驗證通過 if(violations==null||violations.isEmpty()) { return; } // 驗證不通過則拋出ParamsException異常。 for(ConstraintViolation item:violations) { throw new ParamsException(item.getMessage()); } } }
2. 配置并設置Validator驗證器
@Configuration public class WebMvcConfigurer extends WebMvcConfigurerAdapter{ // 我們在這里重寫spring的一個方法,返回我們自定義的驗證器 @Override public Validator getValidator() { return createValidator(); } @Bean public ParamsValidator createValidator(){ return new ParamsValidator(); } }
非常簡單,通過上面配置,就可以在controller上使用注解了。
spring mvc對這個注解的處理主要是在RequestResponseBodyMethodProcessor這個類中的resolveArgument方法實現的,該類主要處理方法的參數和返回值。
spring mvc調用的一段代碼。
protected void validateIfApplicable(WebDataBinder binder, MethodParameter parameter) { Annotation[] annotations = parameter.getParameterAnnotations(); for (Annotation ann : annotations) { Validated validatedAnn = AnnotationUtils.getAnnotation(ann, Validated.class); if (validatedAnn != null || ann.annotationType().getSimpleName().startsWith("Valid")) { Object hints = (validatedAnn != null ? validatedAnn.value() : AnnotationUtils.getValue(ann)); Object[] validationHints = (hints instanceof Object[] ? (Object[]) hints : new Object[] {hints}); binder.validate(validationHints); break; } } }
service的驗證的實現:
該方案主要通過aop進行攔截處理的。如下配置:
@Component @Aspect public class ParamsValidateAdvice { // 這里重用上面定義的那個validator private ParamsValidator validator = new ParamsValidator(); /** * 攔截參數上加了@Validated的注解的方法 * 排除掉controller,因為controller有自己的參數校驗實現 不需要aop */ @Pointcut("execution(* com.choice..*(..,@org.springframework.validation.annotation.Validated (*), ..)) && " + "!execution(* com.choice..api..*(..)) && " + "!execution(* com.choice..controller..*(..)) ") public void pointCut(){} @Before("pointCut()") public void doBefore(JoinPoint joinPoint){ Object[] params=joinPoint.getArgs(); MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); Parameter[] parameters = method.getParameters(); // 驗證參數上的注解 for(int i=0;i<parameters.length;i++) { Parameter p = parameters[i]; // 獲取參數上的注解 Validated validated = p.getAnnotation(Validated.class); if(validated==null) { continue; } // 如果設置了group if(validated.value()!=null && validated.value().length>0) { validator.validate(params[i],null,validated.value()); } else { validator.validate(params[i],null); } } } }
Java的特點有哪些 1.Java語言作為靜態面向對象編程語言的代表,實現了面向對象理論,允許程序員以優雅的思維方式進行復雜的編程。 2.Java具有簡單性、面向對象、分布式、安全性、平臺獨立與可移植性、動態性等特點。 3.使用Java可以編寫桌面應用程序、Web應用程序、分布式系統和嵌入式系統應用程序等。
以上就是怎么在Java中使用@Validated注解進行參數驗證,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。