欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot集成I18n國際化文件在jar包外生效問題

 更新時間:2024年04月03日 10:58:20   作者:鋒璠  
這篇文章主要介紹了SpringBoot集成I18n國際化文件在jar包外生效問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

i18n無法讀取jar包外國際化文件的根本原因

首先我們看一下i18n是如何綁定資源文件路徑的.

綁定資源文件路徑的方法是通過下面方法綁定的。

ResourceBundle.getBundle()

我們查看源碼:

最終發(fā)現(xiàn)i18n是通過類加載器加載國際化文件的。

然而類加載器是不能加載jar包外的資源文件的,所以我們要改變加載資源文件的方式,我們可以通過file加載jar包外的資源文件。

改變文件讀取方式

我們讀取源碼發(fā)現(xiàn),i18n通過將資源文件讀取為stream流存儲在ResourceBundle對象中,同時i18n存在緩存,將產(chǎn)生的stream對象存儲在緩存中。

首先重寫下面方法,修改i18n的讀取方式。

這樣我們就可以讀取到j(luò)ar包外面的資源文件了。

    private class I18nMessageSourceControl extends ResourceBundle.Control {

        @Override
        @Nullable
        public ResourceBundle newBundle(String baseName, Locale locale, String format, ClassLoader loader, boolean reload)
                throws IllegalAccessException, InstantiationException, IOException {
            // Special handling of default encoding
            if (format.equals("java.properties")) {
                String bundleName = toBundleName(baseName, locale);
                final String resourceName = toResourceName(bundleName, "properties");
                InputStream inputStream;
                try {
                    inputStream = AccessController.doPrivileged((PrivilegedExceptionAction<InputStream>) () -> getBufferedInputStream(resourceName));
                } catch (PrivilegedActionException ex) {
                    throw (IOException) ex.getException();
                }
                if (inputStream != null) {
                    String encoding = getDefaultEncoding();
                    if (encoding != null) {
                        try (InputStreamReader bundleReader = new InputStreamReader(inputStream, encoding)) {
                            return loadBundle(bundleReader);
                        }
                    } else {
                        try (InputStream bundleStream = inputStream) {
                            return loadBundle(bundleStream);
                        }
                    }
                } else {
                    return null;
                }
            } else {
                // Delegate handling of "java.class" format to standard Control
                return super.newBundle(baseName, locale, format, loader, reload);
            }
        }

    }
    /**
     *  拼接url 并返回輸入流
     */
    public InputStream getBufferedInputStream(String resourceName) throws FileNotFoundException {
        String fileUrl = System.getProperty("user.dir")+ "/"+ resourceName;
        System.out.println(fileUrl+"..*");
        File file = new File(fileUrl);
        if (file.exists()) {
            return new FileInputStream(file);
        }
        return  null;
    }

尋找切入點

我們不難發(fā)現(xiàn),ResourceBundle.getBundle()這個方法就是為了獲取一個ResourceBundle對象,所以我們可以重寫doGetBundle方法從而獲取ResourceBundle對象。

public class I18nConfig extends ResourceBundleMessageSource {
    private final static Logger logger = LoggerFactory.getLogger(I18nConfig.class);
    @Nullable
    private volatile I18nMessageSourceControl control = new I18nMessageSourceControl();
    /**
     * Obtain the resource bundle for the given basename and Locale.
     *
     * @param basename the basename to look for
     * @param locale   the Locale to look for
     * @return the corresponding ResourceBundle
     * @throws MissingResourceException if no matching bundle could be found
     * @see java.util.ResourceBundle#getBundle(String, Locale, ClassLoader)
     * @see #getBundleClassLoader()
     */
    public ResourceBundle doGetBundle(String basename, Locale locale) throws MissingResourceException {
        ClassLoader classLoader = getBundleClassLoader();
        Assert.state(classLoader != null, "No bundle ClassLoader set");

        I18nMessageSourceControl control = this.control;
        if (control != null) {
            try {
                return ResourceBundle.getBundle(basename, locale, classLoader, control);
            } catch (UnsupportedOperationException ex) {
                // Probably in a Jigsaw environment on JDK 9+
                this.control = null;
                String encoding = getDefaultEncoding();
                if (encoding != null && logger.isInfoEnabled()) {
                    logger.info("ResourceBundleMessageSource is configured to read resources with encoding '" +
                            encoding + "' but ResourceBundle.Control not supported in current system environment: " +
                            ex.getMessage() + " - falling back to plain ResourceBundle.getBundle retrieval with the " +
                            "platform default encoding. Consider setting the 'defaultEncoding' property to 'null' " +
                            "for participating in the platform default and therefore avoiding this log message.");
                }
            }
        }

        // Fallback: plain getBundle lookup without Control handle
        return ResourceBundle.getBundle(basename, locale, classLoader);
    }

    @Scheduled(fixedRate = 180000)
    public  void clearI18nCache() {
        ResourceBundle.clearCache(Objects.requireNonNull(getBundleClassLoader()));
    }
}

最后的clearI18nCache方法

因為i18n存在緩存想要外部資源文件修改后生效,清除緩存,我們讀取源碼不難發(fā)現(xiàn)i18n為我們提供了清理緩存的方法。

我們可以定時清理緩存,也可以通過接口調(diào)取手動清理緩存,根據(jù)自己需求來定。

總結(jié)

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

相關(guān)文章

  • Java動態(tài)線程池插件dynamic-tp集成zookeeper

    Java動態(tài)線程池插件dynamic-tp集成zookeeper

    ZooKeeper是一個分布式的,開放源碼的分布式應(yīng)用程序協(xié)調(diào)服務(wù),是Google的Chubby一個開源的實現(xiàn),是Hadoop和Hbase的重要組件。它是一個為分布式應(yīng)用提供一致性的軟件,提供的功能包括:配置維護、域名服務(wù)、分布式同步、組服務(wù)等
    2023-03-03
  • 老生常談Scanner的基本用法

    老生常談Scanner的基本用法

    下面小編就為大家?guī)硪黄仙U凷canner的基本用法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-07-07
  • springBoot?啟動指定配置文件環(huán)境多種方案(最新推薦)

    springBoot?啟動指定配置文件環(huán)境多種方案(最新推薦)

    springBoot?啟動指定配置文件環(huán)境理論上是有多種方案的,一般都是結(jié)合我們的實際業(yè)務(wù)選擇不同的方案,比如,有pom.xml文件指定、maven命令行指定、配置文件指定、啟動jar包時指定等方案,今天我們一一分享一下,需要的朋友可以參考下
    2023-09-09
  • JAVA讀取文件流,設(shè)置瀏覽器下載或直接預(yù)覽操作

    JAVA讀取文件流,設(shè)置瀏覽器下載或直接預(yù)覽操作

    這篇文章主要介紹了JAVA讀取文件流,設(shè)置瀏覽器下載或直接預(yù)覽操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10
  • Java常見面試題之多線程和高并發(fā)詳解

    Java常見面試題之多線程和高并發(fā)詳解

    這篇文章主要給大家介紹了關(guān)于Java面試題之多線程和高并發(fā)的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學(xué)習(xí)或者使用java具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • MyBatis動態(tài)SQL標簽的用法詳解

    MyBatis動態(tài)SQL標簽的用法詳解

    這篇文章主要介紹了MyBatis動態(tài)SQL標簽的用法詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • mybatis-plus查詢方式,部分字段沒有值

    mybatis-plus查詢方式,部分字段沒有值

    這篇文章主要介紹了mybatis-plus查詢方式,部分字段沒有值問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • 解決ApplicationContext獲取不到Bean的問題

    解決ApplicationContext獲取不到Bean的問題

    這篇文章主要介紹了解決ApplicationContext獲取不到Bean的問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-06-06
  • Java中ReUtil正則表達式工具庫的使用

    Java中ReUtil正則表達式工具庫的使用

    ReUtil是Hutool庫中的正則表達式工具類,提供了多種常用正則表達式操作方法,下面就來介紹一下ReUtil的使用,具有一定的參考價值,感興趣的可以了解一下
    2025-02-02
  • MyBatis查詢時屬性名和字段名不一致問題的解決方法

    MyBatis查詢時屬性名和字段名不一致問題的解決方法

    這篇文章主要給大家介紹了關(guān)于MyBatis查詢時屬性名和字段名不一致問題的解決方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01

最新評論