Springboot 使用 JSR 303 对 Controller 控制层校验及 Service 服务层 AOP 校验,使用消息资源文件对消息国际化

导入 JSR 303 的包、hibernate valid 的包

<dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>6.0.5.Final</version> </dependency> <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>2.0.0.Final</version> </dependency>

springboot 配置

resources/application.yml 消息资源文件国际化处理配置

spring: messages: basename: base,todo # 资源文件 base.properties 和 todo.properties,多个用逗号隔开 encoding: UTF-8 # 必须指定解析编码,否则中文乱码

在 springboot 启动类里面配置

@SpringBootApplication public class Application extends WebMvcConfigurerAdapter { @Value("${spring.messages.basename}") private String basename; public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Bean @Primary public MessageSource messageSource() { ResourceBundleMessageSource resourceBundleMessageSource = new ResourceBundleMessageSource(); resourceBundleMessageSource.setUseCodeAsDefaultMessage(false); resourceBundleMessageSource.setDefaultEncoding("UTF-8"); // 重复定义 resourceBundleMessageSource.setBasenames(basename.split(",")); return resourceBundleMessageSource; } @Bean @Primary public LocalValidatorFactoryBean validator() { LocalValidatorFactoryBean validatorFactoryBean = new LocalValidatorFactoryBean(); validatorFactoryBean.setProviderClass(HibernateValidator.class); validatorFactoryBean.setValidationMessageSource(messageSource()); return validatorFactoryBean; } @Override public Validator getValidator() { return validator(); } /** * 方法级别的单个参数验证开启 */ @Bean public MethodValidationPostProcessor methodValidationPostProcessor() { return new MethodValidationPostProcessor(); } }

我们对于校验参数通过不了抛出的异常进行处理,是通过统一异常捕捉。

@ControllerAdvice @Component public class BindValidExceptionHandler { @ResponseStatus(value = HttpStatus.OK) @ExceptionHandler(ConstraintViolationException.class) public @ResponseBody Msg handleConstraintViolationException(ConstraintViolationException e) { String messageTemplate = e.getConstraintViolations().iterator().next().getMessageTemplate(); return Msg.error(messageTemplate); } @ResponseStatus(value = HttpStatus.OK) @ExceptionHandler(BindException.class) public @ResponseBody Msg handleBindException(BindException e) { BindingResult bindingResult = e.getBindingResult(); String className = bindingResult.getTarget().getClass().getName(); FieldError next = bindingResult.getFieldErrors().iterator().next(); String fieldName = next.getField(); String defaultMessage = next.getDefaultMessage(); if (Pattern.compile("IllegalArgumentException: No enum").matcher(defaultMessage).find()) { Matcher matcher = Pattern.compile("for value '(.*?)'").matcher(defaultMessage); if (matcher.find()) { defaultMessage = "找不到枚举类型【" + matcher.group(1) + "】"; } } return Msg.error(defaultMessage); } @ResponseStatus(value = HttpStatus.OK) @ExceptionHandler(ValidError.class) public @ResponseBody Msg handleValidError(ValidError e) { return Msg.error(e.getMessage()); } }

resources/base.propertie

creatorId=创建者 id 不能为小于 {value}。 modifierId=修改者 id 不能为小于 {value}。

resources/todo.properties

todo.privateId.min=私有 id 不能为小于 {value}。

在 bean 字段上使用注解,其中 group 中的 C 和 S 接口是指 Controller 和 Service 的叫法简称,里面分别有 Insert 接口、Update 接口等等,都是自定义约定的东西。

/** * 私有 id,是代表项目任务/非项目任务/风险/问题/评审待办问题等多张表的外键 */ @Min(value = 1, message = "{todo.privateId.min}", groups = {C.Insert.class, C.Update.class, S.Insert.class, S.Update.class}) private long privateId; /** * 创建者id */ @Min(value = 1, message = "{creatorId}", groups = {S.Insert.class}) private long creatorId; Controller 控制层验证 @Validated @RestController @RequestMapping("todo") public class TodoController { @Autowired private TodoService todoService; @GetMapping("getVo") public Msg getVo( @Min(value = 1, message = "待办 id 不能小于 1。") @RequestParam(required = false, defaultValue = "0") long id ) { return this.todoService.getVo(id); } @PostMapping("add") public Msg add(@Validated({C.Insert.class}) Todo todo) { return this.todoService.add(todo); } }

@Validated({C.Insert.class}) 声明启用 bean 注解上的验证组,其他验证组不会进行验证,这样可以区别开来进行单独验证。

而像没有实体,只有一个基础数据类型的,可以进行验证,但是需要满足三个条件:

在启动类配置方法级别验证启用类

在 Controller 类上注解 @Validated

在方法参数里使用验证注解如 @Min,@NotNull 等等

自行验证。

Service 服务层 AOP 验证 ValidUtil 工具类

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyyydg.html