最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot實現(xiàn)國際化的教程

 更新時間:2025年03月22日 08:59:20   作者:對酒當歌丶人生幾何  
這篇文章主要介紹了SpringBoot實現(xiàn)國際化的教程,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

前言

SpringBoot提供了國際化功能,其原理是將配置的各個語言資源文件信息,以Map的形式進行緩存。

當前端請求給定某個語言標識時(一般是放到請求頭中),拿去指定的語言標識去獲取響應的響應信息。

Springboot項目啟動時,由MessageSourceAutoConfiguration類進行消息資源自動配置。

該類存在 @Conditional 條件注解,也就是說必須滿足某個條件是才會進行自動裝載配置。

  • ResourceBundleCondition類用于判斷是否滿足自動注入條件。
  • getMatchOutcome用于返回一個 ConditionOutcome 對象,用于后續(xù)判斷是否滿足自動注入條件。該方法會自動讀取spring.messages.basename配置的資源文件地址信息,通過getResources方法獲取默認的文件資源。如果該資源不存在,則不滿足自動注入條件。
  • getResources明確標注了只能從classpath*下拿去資源文件,文件類型為properties。
/**
         * 判斷是否滿足自動注入條件
         * @param context the condition context
         * @param metadata the annotation metadata
         * @return
         */
        @Override
        public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
            String basename = context.getEnvironment().getProperty("spring.messages.basename", "messages");
            ConditionOutcome outcome = cache.get(basename);
            if (outcome == null) {
                outcome = getMatchOutcomeForBasename(context, basename);
                cache.put(basename, outcome);
            }
            return outcome;
        }

        private ConditionOutcome getMatchOutcomeForBasename(ConditionContext context, String basename) {
            ConditionMessage.Builder message = ConditionMessage.forCondition("ResourceBundle");
            for (String name : StringUtils.commaDelimitedListToStringArray(StringUtils.trimAllWhitespace(basename))) {
                for (Resource resource : getResources(context.getClassLoader(),name)) {
                    if (resource.exists()) {
                        return ConditionOutcome.match(message.found("bundle").items(resource));
                    }
                }
            }
            return ConditionOutcome.noMatch(message.didNotFind("bundle with basename " + basename).atAll());
        }

        //讀取消息資源文件,從classpath下尋找格式為properties類型的資源文件
        private Resource[] getResources(ClassLoader classLoader, String name) {
            String target = name.replace('.', '/');
            try {
                return new PathMatchingResourcePatternResolver(classLoader)
                        .getResources("classpath*:" + target + ".properties");
            }
            catch (Exception ex) {
                return NO_RESOURCES;
            }
        }

MessageSourceProperties類則用于配置消息源的配置屬性。在ResourceBundleCondition返回條件成立的情況下,會通過注解Bean進行注入。讀取前綴帶有spring.messages的配置信息。

  @Bean
    @ConfigurationProperties(prefix = "spring.messages")
    public MessageSourceProperties messageSourceProperties() {
        return new MessageSourceProperties();
    }

MessageSourceProperties類可配置的屬性并不多,具體屬性含義用途如下:

#配置國際化資源文件路徑,基礎包名名稱地址
spring.messages.basename=il8n/messages
#編碼格式,默認使用UTF-8
spring.messages.encoding=UTF-8
#是否總是應用MessageFormat規(guī)則解析信息,即使是解析不帶參數(shù)的消息
spring.messages.always-use-message-format=false
# 是否使用消息代碼作為默認消息,而不是拋出NoSuchMessageException.建議在開發(fā)測試時開啟,避免不必要的拋錯而影響正常業(yè)務流程
spring.messages.use-code-as-default-message=true

MessageSourceProperties完成讀取配置之后,將會自動注入MessageSource,而默認注入的MessageSource的實現(xiàn)類ResourceBundleMessageSource。ResourceBundleMessageSourceSpringBoot實現(xiàn)國際化的核心。其采用的是及時加載文件的形式。

即:只有當某種特定的語言要求被返回時,才會去讀取資源文件,將消息內(nèi)容緩存起來并通過響應碼進行返回具體消息。ResourceBundleMessageSource的源碼并不復雜,這里就不展開講解。

 @Bean
    public MessageSource messageSource(MessageSourceProperties properties) {
        //消息資源綁定類,用于緩存資源消息
        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
        if (StringUtils.hasText(properties.getBasename())) {
            //設置資源消息默認包名
            messageSource.setBasenames(StringUtils.commaDelimitedListToStringArray(StringUtils.trimAllWhitespace(properties.getBasename())));
        }
        if (properties.getEncoding() != null) {
            //設置編碼格式
            messageSource.setDefaultEncoding(properties.getEncoding().name());
        }
        messageSource.setFallbackToSystemLocale(properties.isFallbackToSystemLocale());
        Duration cacheDuration = properties.getCacheDuration();
        if (cacheDuration != null) {
            //設置消息資源過期時間
            messageSource.setCacheMillis(cacheDuration.toMillis());
        }
        //是否總是應用MessageFormat規(guī)則解析信息,即使是解析不帶參數(shù)的消息
        messageSource.setAlwaysUseMessageFormat(properties.isAlwaysUseMessageFormat());
        //是否使用消息代碼作為默認消息,而不是拋出NoSuchMessageException.建議在開發(fā)測試時開啟,避免不必要的拋錯而影響正常業(yè)務流程
        messageSource.setUseCodeAsDefaultMessage(properties.isUseCodeAsDefaultMessage());
        return messageSource;
    }

一、配置消息資源文件

消息資源文件用于存儲不同國家語言響應的消息,我們通過源碼知道該文件必須是properties類型(在你不去更改源碼的時候),因此我們需要在resources資源文件下存放消息文件。

這里我存放三個文件,message基礎資源文件(內(nèi)容可以為空),messages_en_US.properties英文文件,messages_zh_CN.properties中文文件。

messages_zh_CN.propertiesmessages_en_US.properties內(nèi)容如下:

二、配置消息源

這里采用的是以application.properties形式進行配置,您也可以采用yaml文件形式進行配置:

#配置國際化資源文件路徑
spring.messages.basename=il8n/messages
#編碼格式,默認使用UTF-8
spring.messages.encoding=UTF-8
#是否總是應用MessageFormat規(guī)則解析信息,即使是解析不帶參數(shù)的消息
spring.messages.always-use-message-format=false
# 是否使用消息代碼作為默認消息,而不是拋出NoSuchMessageException.建議在開發(fā)測試時開啟,避免不必要的拋錯而影響正常業(yè)務流程
spring.messages.use-code-as-default-message=true

三、配置消息攔截器

攔截器用于從請求頭中獲取語言標識,以便于后續(xù)根據(jù)語言標識響應不同的響應信息。

package com.il8n.config;

import lombok.Getter;
import lombok.Setter;
import org.jetbrains.annotations.NotNull;
import org.springframework.util.ObjectUtils;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.support.RequestContextUtils;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @Author: Greyfus
 * @Create: 2024-01-12 13:06
 * @Version: 1.0.0
 * @Description:國際化攔截器
 */
@Setter
@Getter
public class IL8nLangInterceptor extends LocaleChangeInterceptor {

    private String langHeader;

    @Override
    public boolean preHandle(HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler) throws ServletException {
        String locale = request.getHeader(getLangHeader());
        if (locale != null) {
            if (iL8nCheckHttpMethod(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(locale));
                } catch (IllegalArgumentException ex) {
                    if (isIgnoreInvalidLocale()) {
                        if (logger.isDebugEnabled()) {
                            logger.debug("Ignoring invalid locale value [" + locale + "]: " + ex.getMessage());
                        }
                    } else {
                        throw ex;
                    }
                }
            }
        }
        // Proceed in any case.
        return true;
    }

    public boolean iL8nCheckHttpMethod(String currentMethod) {
        String[] configuredMethods = getHttpMethods();
        if (ObjectUtils.isEmpty(configuredMethods)) {
            return true;
        }
        for (String configuredMethod : configuredMethods) {
            if (configuredMethod.equalsIgnoreCase(currentMethod)) {
                return true;
            }
        }
        return false;
    }

}

注入消息攔截器,并設置默認語言為中文

package com.il8n.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;

import java.util.Locale;

/**
 * @Author: Greyfus
 * @Create: 2024-01-12 00:22
 * @Version: 1.0.0
 * @Description:語言國際化配置
 */
@Configuration
public class IL8nLangConfig implements WebMvcConfigurer {

    private static final String LANG_HEADER = "lang";
    
    @Bean
    public LocaleResolver localeResolver() {
        SessionLocaleResolver sessionLocaleResolver = new SessionLocaleResolver();
        sessionLocaleResolver.setDefaultLocale(Locale.SIMPLIFIED_CHINESE);
        return sessionLocaleResolver;
    }

    @Bean
    public LocaleChangeInterceptor localeChangeInterceptor() {
        IL8nLangInterceptor lci = new IL8nLangInterceptor();
        //設置請求的語言變量
        lci.setLangHeader(LANG_HEADER);
        return lci;
    }

    /**
     * 注冊攔截器
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(localeChangeInterceptor());
    }

}

四、編寫消息工具類

消息工具類用于通過指定的消息碼獲取對應的響應消息

package com.il8n.config;

import lombok.Getter;
import org.jetbrains.annotations.NotNull;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * @Author: Greyfus
 * @Create: 2024-01-12 00:36
 * @Version: 1.0.0
 * @Description: 工具
 */
@Component
public class SpringUtils implements ApplicationContextAware {
    @Getter
    private static ApplicationContext applicationContext;

    public SpringUtils() {
    }

    public void setApplicationContext(@NotNull ApplicationContext applicationContext) {
        SpringUtils.applicationContext = applicationContext;
    }

    public static <T> T getBean(String name) {
        return (T) applicationContext.getBean(name);
    }

    public static <T> T getBean(Class<T> clazz) {
        return applicationContext.getBean(clazz);
    }

    public static <T> T getBean(String name, Class<T> clazz) {
        return applicationContext.getBean(name, clazz);
    }

    public static <T> Map<String, T> getBeansOfType(Class<T> type) {
        return applicationContext.getBeansOfType(type);
    }

    public static String[] getBeanNamesForType(Class<?> type) {
        return applicationContext.getBeanNamesForType(type);
    }

    public static String getProperty(String key) {
        return applicationContext.getEnvironment().getProperty(key);
    }

    public static String[] getActiveProfiles() {
        return applicationContext.getEnvironment().getActiveProfiles();
    }

}
package com.il8n.config;

import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;

/**
 * @Author: Greyfus
 * @Create: 2024-01-12 00:29
 * @Version: 1.0.0
 * @Description: IL8N語言轉(zhuǎn)換工具
 */
public class IL8nMessageUtils {


    private static final MessageSource messageSource;

    static {
        messageSource = SpringUtils.getBean(MessageSource.class);
    }

    /**
     * 獲取國際化語言值
     *
     * @param messageCode
     * @param args
     * @return
     */
    public static String message(String messageCode, Object... args) {
        return messageSource.getMessage(messageCode, args, LocaleContextHolder.getLocale());
    }
}

五、測試國際化

編碼一個Controller用于模擬測試效果,代碼如下:

package com.il8n.controller;

import com.il8n.config.IL8nMessageUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Author: DI.YIN
 * @Date: 2025/1/6 9:37
 * @Version:
 * @Description:
 **/
@RestController
@RequestMapping("/mock")
public class IL8nTestController {

    @RequestMapping(value = "/login")
    public ResponseEntity<String> login(@RequestParam(value = "userName") String userName, @RequestParam(value = "password") String password) {
        if (!"admin".equals(userName) || !"admin".equals(password)) {
            return new ResponseEntity<>(IL8nMessageUtils.message("LoginFailure", (Object) null), HttpStatus.OK);
        }
        return new ResponseEntity<>(IL8nMessageUtils.message("loginSuccess", userName), HttpStatus.OK);
    }
}

消息攔截器會嘗試從請求頭中獲取屬性為lang的值,將其作為語言標識,因此我們在使用PostMan模擬時,需要在請求頭中增加lang屬性。

模擬結(jié)果如下:

中文語言標識:

英文語言標識:

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Window中安裝構(gòu)建神器Jenkins詳解

    Window中安裝構(gòu)建神器Jenkins詳解

    Jenkins是一款開源 CI&CD 軟件,用于自動化各種任務,包括構(gòu)建、測試和部署軟件。支持各種運行方式,可通過系統(tǒng)包、Docker 或者通過一個獨立的 Java 程序。是解放人工集成部署的自動化構(gòu)建神器
    2021-07-07
  • SpringBoot集成MongoDB的實現(xiàn)

    SpringBoot集成MongoDB的實現(xiàn)

    本文主要介紹了SpringBoot集成MongoDB的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2025-01-01
  • Java中保證線程順序執(zhí)行的操作代碼

    Java中保證線程順序執(zhí)行的操作代碼

    本文給大家分享一篇教程關(guān)于java線程順序執(zhí)行問題,如何保證線程的順序執(zhí)行呢?今天通過實例代碼給大家詳細講解下,感興趣的朋友跟隨小編一起看看吧
    2021-05-05
  • springboot獲取根目錄下lib目錄下文件位置

    springboot獲取根目錄下lib目錄下文件位置

    在 Spring Boot 項目中,如果你有一個 lib 目錄,并且需要訪問這個目錄下的文件,你可以通過幾種不同的方式來獲取該文件的位置,下面小編就來和大家詳細講講
    2024-12-12
  • 詳解Java讀取本地文件并顯示在JSP文件中

    詳解Java讀取本地文件并顯示在JSP文件中

    這篇文章主要介紹了詳解Java讀取本地文件并顯示在JSP文件中的相關(guān)資料,這里提供實例幫助大家實現(xiàn)這樣的功能,希望能幫助到大家,需要的朋友可以參考下
    2017-08-08
  • SpringBoot整合RabbitMQ, 實現(xiàn)生產(chǎn)者與消費者的功能

    SpringBoot整合RabbitMQ, 實現(xiàn)生產(chǎn)者與消費者的功能

    這篇文章主要介紹了SpringBoot整合RabbitMQ, 實現(xiàn)生產(chǎn)者與消費者的功能,幫助大家更好得理解和學習使用SpringBoot框架,感興趣的朋友可以了解下
    2021-03-03
  • Spring Boot使用yml格式進行配置的方法

    Spring Boot使用yml格式進行配置的方法

    很多springboot項目使用的是yml格式,主要目的是方便對讀懂其他人的項目,下面小編通過本文給大家分享Spring Boot使用yml格式進行配置的方法,需要的朋友參考下吧
    2018-04-04
  • Java 1.8使用數(shù)組實現(xiàn)循環(huán)隊列

    Java 1.8使用數(shù)組實現(xiàn)循環(huán)隊列

    這篇文章主要為大家詳細介紹了Java 1.8使用數(shù)組實現(xiàn)循環(huán)隊列,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-10-10
  • Android開發(fā)Kotlin實現(xiàn)圓弧計步器示例詳解

    Android開發(fā)Kotlin實現(xiàn)圓弧計步器示例詳解

    這篇文章主要為大家介紹了Android開發(fā)Kotlin繪制圓弧計步器示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06
  • Java圖形化編程中的鍵盤事件設計簡介

    Java圖形化編程中的鍵盤事件設計簡介

    這篇文章主要介紹了Java圖形化編程中的鍵盤事件設計,是Java的GUI編程當中的基礎部分,需要的朋友可以參考下
    2015-10-10

最新評論

稷山县| 铁岭县| 梅州市| 景泰县| 太湖县| 全南县| 霍山县| 香港| 青龙| 安塞县| 宜阳县| 庆云县| 宣化县| 治县。| 衢州市| 广宁县| 呼图壁县| 织金县| 敦化市| 卢氏县| 普陀区| 五华县| 涪陵区| 出国| 太和县| 钟山县| 阜城县| 宿迁市| 潜山县| 洞口县| 麻江县| 高密市| 界首市| 车致| 犍为县| 崇明县| 新竹市| 永新县| 东光县| 雅江县| 象山县|