暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

SpringBoot国际化和Validation融合

原创 我为啥没洁癖 2023-12-12
949

场景

在应用交互时,可能需要根据客户端得语言来返回不同的语言数据。前端通过参数、请求头等往后端传入locale相关得参数,后端获取参数,根据不同得locale来获取不同得语言得文本信息返回给前端。

此时一般有两种常见会用到文本的国际化:

  • 代码里响应,手动获取

    使用MessageSource的getMessage方法即可,也就是spring容器中的getMessage()

  • 校验参数框架校验message

    注解校验多个参数使自动响应提示语,此时使用校验框架的占位符实现

Spring+Validate融合

Validation为主

以校验框架Validation的默认国际化文件ValidationMessages为来源,让Spring的MessageSource去读取ValidationMessages以达到融合的目的。具体参考下面的默认Validation处理方式。

Spring为主

不使用校验框架Validation的默认文件,使用任意自定义路径的国际化文件。让Validation去读取MessageSource中的文件。具体参考Spring自定义处理。

前置

设置IDEA

将项目编码配置成UTF-8,避免中文乱码

image.png

Boundle插件

安装Boundle插件可以将一个包下的配置文件的一个字段进行同步编辑

image.png

image.png

Validation依赖

引入支持hibernate得validation功能进行参数校验。

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
复制

默认Validation

默认路径

spring的配置文件默认路径是resource目录下的message,可以通过spring.message配置进行指定。

Validate的默认配置文件路径是resource目录下的ValidationMessages,正常情况下可以通过自定义Validator对象来自定义文件路径,但是可能会出现读取不到占位符值得问题,可以优先使用默认值。

ValidationMessages

在Validate使用默认文件时,创建ValidationMessages得boundle。

image.png

配置spring.message

让spring得message读取路径读取ValidationMessages

spring: messages: basename: ValidationMessages encoding: utf-8
复制

获取国际化文本

Spring工具类

工具类API一般是在抛出异常,手动根据配置的code来响应不同语言的信息。通过ApplicationContext调取messageSource即可通过请求上线文得locale来获取不同语言版本得信息。getMessage中code就bundle文件中的配置文件的key,key对应不同语言的value,args就占位符传参,底层通过messageFormat来填充数据。

@Component public class SpringUtil implements ApplicationContextAware { private static ApplicationContext applicationContext; @Override public void setApplicationContext(@NotNull ApplicationContext applicationContext) throws BeansException { if (SpringUtil.applicationContext == null) { SpringUtil.applicationContext = applicationContext; } } //获取applicationContext public static ApplicationContext getApplicationContext() { return applicationContext; } public static String getMessage(String code, Object... args) { return applicationContext.getMessage(code, args, LocaleContextHolder.getLocale()); } }
复制

Locale获取

默认情况下spring注册的messageSource对象为ResourceBundleMessageSource,会读取spring.message配置。

请求中Locale的获取是通过LocaleResolver进行处理,默认是AcceptHeaderLocaleResolver,通过WebMvcAutoConfiguration注入,从Accept-Language请求头中获取locale信息。

此时前端可以在不同语言环境时传入不同的请求头Accept-Language即可达到切换语言的效果

Accept-Language: en-Us Accept-Language: zh-CN
复制

validation文本

在校验请求体参数合法性时我们会通过注解形式来指定特定的校验非法的message返回值,这个返回值需要Validation的国际化支持,{dictName}就是一个占位符语句,代表配置文件中的dictName值进行国际化。

@NotNull(message = "{dictName}{notNull}") @Length(max = 128,message = "{dictName}{lengthMax}") private String dictName;
复制

Spring自定义

自定义ValidationMessages需要替换Validator的用户配置信息路径。

配置Validator

路径从ValidationMessages改为i18n/messages

import org.hibernate.validator.HibernateValidator; import org.springframework.context.MessageSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; import javax.validation.Validator; import java.util.Properties; @Configuration public class ValidateConfig { @Bean public Validator validator(MessageSource messageSource){ LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean(); // 国际化 factoryBean.setValidationMessageSource(messageSource); // 设置使用 HibernateValidator 校验器 factoryBean.setProviderClass(HibernateValidator.class); Properties properties = new Properties(); // 设置 快速异常返回 properties.setProperty("hibernate.validator.fail_fast", "true"); factoryBean.setValidationProperties(properties); // 加载配置 factoryBean.afterPropertiesSet(); return factoryBean.getValidator(); } }
复制

Spring配置

image.png

spring: messages: basename: i18n/messages encoding: utf-8
复制

自定义Locale获取

使用自定义的I18nLocaleResolver替换默认的AcceptHeaderLocaleResolver,重写resolveLocale方法就可以自定义Locale的解析逻辑。

自定义后使用content-language传Locale信息,使用_划分语言个地区。

content-language: en_US content-language: zh_CN
复制
import cn.hutool.core.util.StrUtil; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.LocaleResolver; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.Locale; @Configuration public class I18nConfig { @Bean public LocaleResolver localeResolver() { return new I18nLocaleResolver(); } /** * 获取请求头国际化信息 */ static class I18nLocaleResolver implements LocaleResolver { @Override public Locale resolveLocale(HttpServletRequest httpServletRequest) { String language = httpServletRequest.getHeader("content-language"); Locale locale = Locale.getDefault(); if (StrUtil.isNotBlank(language)) { String[] split = language.split("_"); locale = new Locale(split[0], split[1]); } return locale; } @Override public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) { } } }
复制

捕捉自定义校验异常

自定义的这种校验异常会抛出MethodArgumentNotValidException异常,异常msg如下:

org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in xxx.xxx(xxx): [Field error in object 'xxx' on field 'xxx': rejected value [null]; codes [NotBlank.xxx.xxx,NotBlank.xxx,NotBlank.java.lang.String,NotBlank]; arguments
复制

image.png

image.png

这样响应就代表自定义校验生效了,需要将异常信息转成正常的提示信息。在全局异常处理器中处理MethodArgumentNotValidException异常:

@ExceptionHandler(MethodArgumentNotValidException.class) public Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { log.error(e.getMessage(), e); // 提取异常消息提示明文 String message = e.getBindingResult().getFieldError().getDefaultMessage(); return new ResponseUtil<>().setErrorMsg(message); }
复制

image.png

image.png

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论

目录
  • 场景
  • Spring+Validate融合
    • Validation为主
    • Spring为主
  • 前置
    • 设置IDEA
    • Boundle插件
    • Validation依赖
  • 默认Validation
    • 默认路径
    • ValidationMessages
  • 获取国际化文本
    • Spring工具类
    • Locale获取
    • validation文本
  • Spring自定义
    • 配置Validator
    • Spring配置
    • 自定义Locale获取
    • 捕捉自定义校验异常