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

SpringBoot集成I18n國(guó)際化文件在jar包外生效問(wèn)題

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

i18n無(wú)法讀取jar包外國(guó)際化文件的根本原因

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

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

ResourceBundle.getBundle()

我們查看源碼:

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

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

改變文件讀取方式

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

首先重寫(xiě)下面方法,修改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;
    }

尋找切入點(diǎn)

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

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方法

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

我們可以定時(shí)清理緩存,也可以通過(guò)接口調(diào)取手動(dòng)清理緩存,根據(jù)自己需求來(lái)定。

總結(jié)

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

相關(guān)文章

  • 深入淺出分析Java抽象類和接口【功能,定義,用法,區(qū)別】

    深入淺出分析Java抽象類和接口【功能,定義,用法,區(qū)別】

    這篇文章主要介紹了Java抽象類和接口,結(jié)合實(shí)例形式深入淺出的分析了java抽象類與接口的功能功能,定義,用法及區(qū)別,需要的朋友可以參考下
    2017-08-08
  • 詳解簡(jiǎn)單基于spring的redis配置(單機(jī)和集群模式)

    詳解簡(jiǎn)單基于spring的redis配置(單機(jī)和集群模式)

    這篇文章主要介紹了詳解簡(jiǎn)單基于spring的redis配置(單機(jī)和集群模式),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-02-02
  • 基于Quartz定時(shí)調(diào)度任務(wù)(詳解)

    基于Quartz定時(shí)調(diào)度任務(wù)(詳解)

    下面小編就為大家?guī)?lái)一篇基于Quartz定時(shí)調(diào)度任務(wù)(詳解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-11-11
  • SpringBoot @SpringBootTest加速單元測(cè)試的小訣竅

    SpringBoot @SpringBootTest加速單元測(cè)試的小訣竅

    這篇文章主要介紹了SpringBoot @SpringBootTest加速單元測(cè)試的小訣竅,具有很好的參考價(jià)值,對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Activiti7通過(guò)代碼動(dòng)態(tài)生成工作流實(shí)現(xiàn)詳解

    Activiti7通過(guò)代碼動(dòng)態(tài)生成工作流實(shí)現(xiàn)詳解

    這篇文章主要為大家介紹了Activiti7通過(guò)代碼動(dòng)態(tài)生成工作流實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • 詳解java關(guān)于對(duì)象的比較

    詳解java關(guān)于對(duì)象的比較

    這篇文章主要為大家介紹了java關(guān)于對(duì)象的比較,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-01-01
  • Spring基于注解配置AOP詳解

    Spring基于注解配置AOP詳解

    這篇文章主要介紹了Spring基于注解配置AOP詳解,Spring 的 AOP 功能是基于 AspectJ 實(shí)現(xiàn)的,支持使用注解聲明式定義 AOP 切面,Spring 基于注解配置 AOP 需要啟用 AspectJ 自動(dòng)代理功能,需要的朋友可以參考下
    2023-09-09
  • Java 向上轉(zhuǎn)型和向下轉(zhuǎn)型的詳解

    Java 向上轉(zhuǎn)型和向下轉(zhuǎn)型的詳解

    這篇文章主要介紹了 Java 向上轉(zhuǎn)型和向下轉(zhuǎn)型的詳解的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • Java類成員訪問(wèn)權(quán)限控制知識(shí)總結(jié)

    Java類成員訪問(wèn)權(quán)限控制知識(shí)總結(jié)

    這篇文章主要介紹了Java類成員訪問(wèn)權(quán)限控制知識(shí)總結(jié),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-04-04
  • 用java WebSocket做一個(gè)聊天室

    用java WebSocket做一個(gè)聊天室

    這篇文章主要為大家詳細(xì)介紹了用java WebSocket做一個(gè)聊天室,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-10-10

最新評(píng)論

富裕县| 保德县| 孝义市| 清徐县| 简阳市| 泗阳县| 重庆市| 南通市| 凭祥市| 鄂托克前旗| 甘孜| 西昌市| 桐乡市| 容城县| 昌邑市| 潢川县| 左贡县| 舟山市| 冕宁县| 荥经县| 剑河县| 靖边县| 民丰县| 肃南| 当涂县| 新田县| 黔江区| 泰州市| 龙江县| 榕江县| 周宁县| 嵩明县| 漳平市| 教育| 邵阳县| 濮阳市| 九台市| 宁远县| 霍林郭勒市| 安岳县| 乌鲁木齐县|