SpringBoot 参数校验国际化配置

2024/1/22 SpringBoot 框架

# 1、国际化目的

国际化又称为 i18n:internationalization,国际化配置的目的是使应用程序能够适应不同用户的语言和文化习惯,提供更好的用户体验。以下是一些进行国际化配置的原因:

  • 多语言支持:通过国际化配置,应用程序可以提供多语言支持,以满足不同语言用户的需求。这可以扩大应用程序的受众范围,并使其更具竞争力。
  • 提高用户体验:通过提供用户熟悉和舒适的语言环境,国际化配置可以改善用户体验。当用户可以用自己熟悉的语言和表达方式与应用程序进行交互时,他们会更容易理解和使用。
  • 遵循本地化约定:不同的语言和文化背景具有不同的约定和习惯。通过国际化配置,应用程序可以遵循这些本地化约定,如日期格式、数字格式、货币符号等,以提供更符合用户期望的界面。
  • 全球市场适应性:在全球化的今天,越来越多的应用程序需要适应不同国家和地区的市场。通过国际化配置,应用程序可以轻松地适应不同市场的需求,提供本地化的内容和功能。
  • 国际合规性和法律要求:某些国家和地区可能对语言和文化的使用有特定的法律要求。通过国际化配置,应用程序可以遵循这些法律要求,确保在相应的市场合规运营。

# 2、国际化配置案例

# 2.1、安装插件

先安装一个Resource Bundle Editor插件,方便后面进行国际化配置。

Resource Bundle Editor插件安装

# 2.2、创建国际化配置文件

  • 创建国际化配置文件最终效果如下图
  • 在resource的i18n目录下创建三个文件

可以看到我这里已经创建好了,按照效果图创建好就行先

# 2.3、修改国际化配置文件

按照如图修改配置文件信息,刚刚的插件就是在这里用的,可以按照自己的需要配置参数:email.is.not.valid

# 2.4、使用国际化配置数据

在DTO中使用国际化配置数据:

@Data
@Builder
public class StudentDTO implements Serializable {

    // 通过{数据名称}读取数据
    @Email(message = "{email.is.not.valid}")
    private String email;

}
1
2
3
4
5
6
7
8
9

# 3、中英文切换拦截器配置

# 3.1、创建自定义拦截器

SpringMVC默认是拦截request参数获取locale参数来实现的切换语言,这里我们可以改下,优先从header中获取,如果没有获取到再从request参数中获取。如果不需要从header上获取可以不配置,后面也不需要了,可以直接到测试环节。

/**
 * @ClassName CustomLocaleChangeInterceptor
 * @Description 自定义语言切换拦截器
 * @Date 2024/1/22 15:01
 */
@Slf4j
public class CustomLocaleChangeInterceptor extends LocaleChangeInterceptor {

    /**
     * 优先从header中获取,如果没有获取到再从request参数中获取。
     * @param request  request
     * @param response response
     * @param handler  handler
     * @return bool
     * @throws ServletException ServletException
     */
    @Override
    public boolean preHandle(HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler) throws ServletException {
        String newLocale = request.getHeader(getParamName());
        // 如果为空,则可以设置默认为中文
        // if(newLocale==null){
        //     newLocale = "zh_CN";
        // }

        if (newLocale!=null) {
            if (checkHttpMethods(request.getMethod())) {
                LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);
                if (localeResolver==null) {
                    throw new IllegalStateException("No LocaleResolver found: not in a DispatcherServlet request?");
                }
                try {
                    localeResolver.setLocale(request, response, parseLocaleValue(newLocale));
                } catch (IllegalArgumentException ex) {
                    if (isIgnoreInvalidLocale()) {
                        log.debug("Ignoring invalid locale value [" + newLocale + "]: " + ex.getMessage());
                    } else {
                        throw ex;
                    }
                }
            }
            return true;
        } 

        return super.preHandle(request, response, handler);
    }

    private boolean checkHttpMethods(String currentMethod) {
        String[] configuredMethods = getHttpMethods();
        if (ObjectUtils.isEmpty(configuredMethods)) {
            return true;
        }
        for (String configuredMethod : configuredMethods) {
            if (configuredMethod.equalsIgnoreCase(currentMethod)) {
                return true;
            }
        }
        return false;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

# 3.2、配置拦截器

将自定义拦截器配置到SpringMVC中

/**
 * @ClassName WebConfig
 * @Description 配置自定义语言切换拦截器
 * @Date 2024/1/22 15:05
 */
@Configuration
@RequiredArgsConstructor
public class WebConfig implements WebMvcConfigurer {

    /**
     * lang param name in header, default to 'locale'.
     */
    private static final String LANGUAGE_PARAM_NAME = LocaleChangeInterceptor.DEFAULT_PARAM_NAME;

    /**
     * message source.
     */
    private final ResourceBundleMessageSource resourceBundleMessageSource;

    /**
     * default locale.
     * @return locale resolver
     */
    @Bean
    public LocaleResolver localeResolver() {
        SessionLocaleResolver localeResolver = new SessionLocaleResolver();
        localeResolver.setDefaultLocale(Locale.SIMPLIFIED_CHINESE);
        return localeResolver;
    }

    /**
     * local validator factory bean.
     * @return LocalValidatorFactoryBean
     */
    @Bean
    public LocalValidatorFactoryBean localValidatorFactoryBean() {
        LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean();
        MessageInterpolatorFactory interpolatorFactory = new MessageInterpolatorFactory();
        factoryBean.setMessageInterpolator(interpolatorFactory.getObject());
        factoryBean.setValidationMessageSource(resourceBundleMessageSource);
        return factoryBean;
    }

    /**
     * locale change interceptor.
     * @return LocaleChangeInterceptor
     */
    @Bean
    public LocaleChangeInterceptor localeChangeInterceptor() {
        LocaleChangeInterceptor interceptor = new CustomLocaleChangeInterceptor();
        interceptor.setParamName(LANGUAGE_PARAM_NAME);
        return interceptor;
    }

    /**
     * register locale change interceptor.
     * @param registry registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(localeChangeInterceptor());
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

# 3.3、测试使用

  • 调用的接口
@ResponseResultApi
@PostMapping("/add")
public Boolean addStudent(@Valid @RequestBody StudentDTO student){
    StudentPO studentPO = new StudentPO();
    BeanUtils.copyProperties(student,studentPO);
    return studentService.save(studentPO);
}
1
2
3
4
5
6
7
  • 调用的请求