目录
一、Validation及国际化配置
1、添加依赖
2、校验失败提示消息国际化配置
3、application.properties
4、国际化资源文件
二、代码演示
1、全局异常处理
2、MessageUtils工具类
3、响应VO
2、测试Controller和请求DTO
3、多语言属性文件
4、测试用例
(1)简单对象UserReqDTO测试
(2)包含List集合对象的ChargeRuleReqDTO测试
一、Validation及国际化配置
1、添加依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
2、校验失败提示消息国际化配置
@Configuration public class ValidationConfig { @Bean public LocalValidatorFactoryBean defaultValidator(MessageSource messageSource) { LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean(); factoryBean.setValidationMessageSource(messageSource); return factoryBean; } }
3、application.properties
#国际化配置,basename可以用全限定类名,如下,也可以是i18n/message spring.messages.basename=i18n.messages spring.messages.encoding=UTF-8
4、国际化资源文件
注意:我们basename的配置为:spring.messages.basename=i18n.messages
因此在类路径下新建i18n的文件夹即可,而不是i18n/messages文件夹,文件夹内必须有一个文件名称为message.properties的属性文件,不然会有问题。多语言以messages_语言_国家.properties命名。
二、代码演示
1、全局异常处理
public class GlobalExceptionHandler { @ResponseBody @ExceptionHandler(MethodArgumentNotValidException.class) public ApiRespVO<?> handleException(MethodArgumentNotValidException e) { FieldError fieldError = e.getBindingResult().getFieldError(); // 校验注解名称 String code = fieldError.getCode(); // 校验字段名称 String field = fieldError.getField(); // 检验失败默认消息 String defaultMessage = fieldError.getDefaultMessage(); List<Object> args = Arrays.stream(Optional.ofNullable(fieldError.getArguments()).orElse(new Object[] {})) .filter(argument -> !(argument instanceof DefaultMessageSourceResolvable)) .map(Object::toString) .collect(Collectors.toList()); args.add(0, field); // 默认根据注解名称取,如果没有则取默认消息 String errorMsg = MessageUtils.getMessage(code, args.toArray(), LocaleContextHolder.getLocale(), StringUtils.EMPTY); if (StringUtils.isNotBlank(errorMsg)) { return ApiRespVO.failure(ErrorCode.INVALID_PARAM, errorMsg); } return ApiRespVO.failure(ErrorCode.INVALID_PARAM, defaultMessage); } }
备注:关于LocalContextHolder,每次web请求到来时,Spring中的RequestContextFilter
会将Locale实例注入到LocalContextHolder。
2、MessageUtils工具类
public class MessageUtils { private static MessageSource messageSource = WebApplicationContextHolder.getBean(MessageSource.class); public static String getMessage(String code, Object[] args, Locale locale, String defaultValue) { return messageSource.getMessage(code, args, defaultValue, locale); } public static String getMessage(String code, Object[] args, Locale locale) { return messageSource.getMessage(code, args, locale); } }
3、响应VO
public class ApiRespVO<T> { private static final String SUCCESS = "00000"; private static final String FAILURE = "99999"; private String code; private String message; private T data; public static <T> ApiRespVO<T> success() { return success(null); } public static <T> ApiRespVO<T> success(T data) { ApiRespVO<T> apiRespDTO = new ApiRespVO<>(); apiRespDTO.setCode(SUCCESS); apiRespDTO.setData(ObjectUtils.defaultIfNull(data, (T) new Object())); return apiRespDTO; } public static <T> ApiRespVO<T> failure(String code) { return failure(code, new Object[] {}); } public static <T> ApiRespVO<T> failure(String code, Object[] args) { String errorMsg = MessageUtils.getMessage(code, args, LocaleContextHolder.getLocale()); return failure(FAILURE, errorMsg); } public static <T> ApiRespVO<T> failure(String code, String message) { ApiRespVO<T> apiRespDTO = new ApiRespVO<>(); apiRespDTO.setCode(code); apiRespDTO.setMessage(message); return apiRespDTO; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public T getData() { return data; } public void setData(T data) { this.data = data; } @Override public String toString() { return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); } }
2、测试Controller和请求DTO
@RestController public class ValidationController { @Autowired private MessageSource messageSource; @RequestMapping("/validate") public ApiRespVO<?> hanldeRequest(@Validated @RequestBody UserReqDTO userDTO) { return ApiRespVO.success(); } @RequestMapping("/validate-list") public ApiRespVO<?> validateListParam(@Validated @RequestBody ChargeRuleReqDTO request) { return ApiRespVO.success(); } }
public class UserReqDTO { @NotNull private String username; @NotBlank @Length(min = 5,max = 8) private String password; @Size(max = 1) private String gender; @Positive private int age; @NotBlank @Pattern(regexp = "^\\d{11}$", message = "{Pattern.UserReqDTO.phone}") private String phone; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } }
public class ChargeRuleReqDTO { @NotBlank private String appId; @Valid private List<ChannelChargeInfo> chargeInfo; private static class ChannelChargeInfo { @NotBlank private String channelCode; @NotNull private BigDecimal channelCharge; public String getChannelCode() { return channelCode; } public void setChannelCode(String channelCode) { this.channelCode = channelCode; } public BigDecimal getChannelCharge() { return channelCharge; } public void setChannelCharge(BigDecimal channelCharge) { this.channelCharge = channelCharge; } } public String getAppId() { return appId; } public void setAppId(String appId) { this.appId = appId; } public List<ChannelChargeInfo> getChargeInfo() { return chargeInfo; } public void setChargeInfo(List<ChannelChargeInfo> chargeInfo) { this.chargeInfo = chargeInfo; } }
备注:如果请求参数DTO中实例变量为List集合对象,则要加上@Valid注解
,否则校验不会生效。
3、多语言属性文件
messages.properties
NotNull= NotBlank= Length= Positive= Pattern.UserReqDTO.phone=
messages_en_US.properties
NotNull=[{0}] cannot be null NotBlank=[{0}] cannot be blank Length=[{0}] minimum length is {2},maximum length is {1} Positive=[{0}] must be greater than 0 Pattern.UserReqDTO.phone=phone number format is invalid and must be digit. maximum length is 11
NotNull=[{0}]不能为空 NotBlank=[{0}]不能为空 Length=[{0}]最小长度为{2},最大长度为{1} Positive=[{0}]必须大于 Pattern.UserReqDTO.phone=手机号格式不正确,必须为全数字,长度为11位
4、测试用例
(1)简单对象UserReqDTO测试
语言为中文: