spring 在多线程环境中引导 LocaleChangeInterceptor 的行为

Behaviour of spring boot LocaleChangeInterceptor in a multithreaded environment

我正在使用以下 class 来管理我的 spring 启动应用程序中的本地化。

@Configuration
public class MessageConfig implements WebMvcConfigurer {

    private Logger logger = LoggerFactory.getLogger(MessageConfig.class);
    /**
     * Message source for localization.
     * @return message source.
     */
    @Bean
    public MessageSource messageSource() {
        if (logger.isDebugEnabled()) {
            logger.debug("Creating a ResourceBundleMessageSource.");
        }
        ResourceBundleMessageSource source = new ResourceBundleMessageSource();
        source.setBasename("messages");
        source.setUseCodeAsDefaultMessage(true);
        return source;
    }

    /**
     * Utility for localization.
     * @return locale resolver.
     */
    @Bean
    public LocaleResolver localeResolver() {
        if (logger.isDebugEnabled()) {
            logger.debug("Creating a locale resolver.");
        }
        SessionLocaleResolver slr = new SessionLocaleResolver();
        slr.setDefaultLocale(Locale.US);
        return slr;
    }

    /**
     * Utility for localization.
     * @return locale change interpreter.
     */
    @Bean
    public LocaleChangeInterceptor localeChangeInterceptor() {
        if (logger.isDebugEnabled()) {
            logger.debug("Creating a locale change interceptor.");
        }
        LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
        lci.setParamName("lang");
        return lci;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        if (logger.isDebugEnabled()) {
            logger.debug("Adding locale change interceptor to registry.");
        }
        registry.addInterceptor(localeChangeInterceptor());
    }

}

我的应用程序根据发送到 API 的 lang URL 参数决定要使用的语言环境。

当我发送localhost:8080/api时,它以默认语言发送内容,即英语。 如果我发送 localhost:8080/api?lang=si,它会发送僧伽罗语内容。

但是,如果我在没有指定语言的情况下向 localhost:8080/api 发送请求,我会收到之前调用中使用的僧伽罗语内容,而不是默认语言环境。 我在服务层使用 LocaleContextHolder 来决定输出的内容。 我的理解是对 API 的每个单独调用都将由一个新线程处理。那么,为什么在这个 API 调用中默认语言环境已更改为 'si',即使我没有指定语言?

SessionLocaleResolver 从用户会话中检索语言环境。我的猜测是,一旦设置了语言环境,它就会使用之前设置的值。来自 docs:

LocaleResolver implementation that uses a locale attribute in the user's session in case of a custom setting, with a fallback to the specified default locale or the request's accept-header locale.

至于为什么没有变化,可能是因为在没有lang参数的情况下请求/api时没有触发LocaleChangeInterceptor

LocaleChangeInterceptor changes the language based on the fact if the request parameter is present or not. If this parameter is present it will get the Locale and use the LocaleResolver.setLocale 方法为当前用户更改语言。

所有需要Locale翻译消息的代码都使用LocaleResolver.resolveLocale方法获取。

现在,当您使用 SessionLocaleResolver 时,它将存储在用户 HttpSession 中。因此,在更改后,当前 http 会话将保持不变 NOT 其他会话。如果您删除浏览器中的会话 cookie,它将再次成为默认语言。

您可以通过打开一个新的不同浏览器(与复制会话状态的浏览器不同)或浏览器的隐身 window 来测试它并检查您的站点。它仍将使用默认语言,而不是更改后的语言。