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

解決Spring國(guó)際化文案占位符失效問(wèn)題的方法

 更新時(shí)間:2018年04月10日 14:28:01   作者:打破突破  
本篇文章主要介紹了解決Spring國(guó)際化文案占位符失效問(wèn)題的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

寫在前面:接下來(lái)很長(zhǎng)一段時(shí)間的文章主要會(huì)記錄一些項(xiàng)目中實(shí)際遇到的問(wèn)題及對(duì)應(yīng)的解決方案,在相應(yīng)代碼分析時(shí)會(huì)直指問(wèn)題所在,不會(huì)將無(wú)關(guān)的流程代碼貼出,感興趣的讀者可以自行跟蹤。同時(shí)希望大家能夠?qū)⑿牡皿w會(huì)在評(píng)論區(qū)分享出來(lái),讓大家共同進(jìn)步!

環(huán)境或版本:Spring 3.2.3

現(xiàn)象:利用Spring自帶的MessageSource來(lái)處理國(guó)際化文案,us狀態(tài)下的文案有部分占位符未被替換,cn狀態(tài)下的正常。文案如下:

tms.pallet.order.box.qty=The total palletized boxes quantity {0} doesn't match with the received boxes quantity {1},Please double check!
tms.pallet.order.box.qty=打板總箱數(shù)件{0},與訂單收貨總箱數(shù){1}不一致。請(qǐng)檢查!

直覺(jué):是不是英文文案太長(zhǎng)了,Spring處理時(shí)對(duì)長(zhǎng)度做了限制,仔細(xì)想了想Spring應(yīng)該不會(huì)設(shè)計(jì)的這么坑。

排查:斷點(diǎn)跟蹤Spring源碼(入口:MessageSource的getMessage方法),最后發(fā)現(xiàn)了MessageFormat中這樣的一段處理方法:

 // Indices for segments
  private static final int SEG_RAW   = 0;
  private static final int SEG_INDEX  = 1;
  private static final int SEG_TYPE   = 2;
  private static final int SEG_MODIFIER = 3; // modifier or subformat

/**
   * Sets the pattern used by this message format.
   * The method parses the pattern and creates a list of subformats
   * for the format elements contained in it.
   * Patterns and their interpretation are specified in the
   * <a href="#patterns" rel="external nofollow" >class description</a>.
   *
   * @param pattern the pattern for this message format
   * @exception IllegalArgumentException if the pattern is invalid
   */
  @SuppressWarnings("fallthrough") // fallthrough in switch is expected, suppress it
  public void applyPattern(String pattern) {
      StringBuilder[] segments = new StringBuilder[4];
      // Allocate only segments[SEG_RAW] here. The rest are
      // allocated on demand.
      segments[SEG_RAW] = new StringBuilder();

      int part = SEG_RAW;
      int formatNumber = 0;
      boolean inQuote = false;
      int braceStack = 0;
      maxOffset = -1;
      for (int i = 0; i < pattern.length(); ++i) {
        char ch = pattern.charAt(i);
        if (part == SEG_RAW) {
          if (ch == '\'') {
            if (i + 1 < pattern.length()
              && pattern.charAt(i+1) == '\'') {
              segments[part].append(ch); // handle doubles
              ++i;
            } else {
              inQuote = !inQuote;
            }
          } else if (ch == '{' && !inQuote) {
            part = SEG_INDEX;
            if (segments[SEG_INDEX] == null) {
              segments[SEG_INDEX] = new StringBuilder();
            }
          } else {
            segments[part].append(ch);
          }
        } else {
          if (inQuote) {       // just copy quotes in parts
            segments[part].append(ch);
            if (ch == '\'') {
              inQuote = false;
            }
          } else {
            switch (ch) {
            case ',':
              if (part < SEG_MODIFIER) {
                if (segments[++part] == null) {
                  segments[part] = new StringBuilder();
                }
              } else {
                segments[part].append(ch);
              }
              break;
            case '{':
              ++braceStack;
              segments[part].append(ch);
              break;
            case '}':
              if (braceStack == 0) {
                part = SEG_RAW;
                makeFormat(i, formatNumber, segments);
                formatNumber++;
                // throw away other segments
                segments[SEG_INDEX] = null;
                segments[SEG_TYPE] = null;
                segments[SEG_MODIFIER] = null;
              } else {
                --braceStack;
                segments[part].append(ch);
              }
              break;
            case ' ':
              // Skip any leading space chars for SEG_TYPE.
              if (part != SEG_TYPE || segments[SEG_TYPE].length() > 0) {
                segments[part].append(ch);
              }
              break;
            case '\'':
              inQuote = true;
              // fall through, so we keep quotes in other parts
            default:
              segments[part].append(ch);
              break;
            }
          }
        }
      }
      if (braceStack == 0 && part != 0) {
        maxOffset = -1;
        throw new IllegalArgumentException("Unmatched braces in the pattern.");
      }
      this.pattern = segments[0].toString();
  }

上面的這段代碼寫的有點(diǎn)讓人費(fèi)解,略微奇特,我們主要看第一個(gè)邏輯分支:對(duì)每一個(gè)待處理的國(guó)際化文案模板串中的字符進(jìn)行遍歷,當(dāng)字符為"'"時(shí),判斷后一個(gè)字符是否也為“'”,如果是則將“‘”拼接到已處理的StringBuilder中,不是則將inQuote至為True,如果該字符不會(huì)‘{'且inQuote為false則將part重新置為0,并且segments[SEG_INDEX]=null的話重新創(chuàng)建StringBuilder對(duì)象,否則繼續(xù)拼接。

原因分析:

  1. 結(jié)合我們配置的英文文案(其中一共有兩個(gè)占位符,在這這兩占位符之前有一個(gè)單引號(hào)),根據(jù)上面Spring的處理源碼看,實(shí)際處理會(huì)是:對(duì)該字符串進(jìn)行逐個(gè)字符處理,逐個(gè)拼接到已處理的StringBuilder中,當(dāng)處理到‘{'時(shí),此處part將被置為1,同時(shí)segments第1個(gè)存儲(chǔ)位上會(huì)引用StringBuilder類型的對(duì)象,程序繼續(xù)處理下面的待處理的字符,繼續(xù)拼接(請(qǐng)自行看part!= SEG_RAW的邏輯分支),直到處理到‘}'時(shí),part被重新賦值為0,sefgments的其他位被清空,于是繼續(xù)處理下面的字符串繼續(xù)拼接,處理到單引號(hào)時(shí),inQuote被置為True,接下來(lái)就一路拼接了,不再對(duì)后面的“{“做占位符處理。
  2. 中文文案中兩個(gè)占位符之間并沒(méi)有出現(xiàn)單引號(hào),因此解決了問(wèn)題現(xiàn)象中的第二點(diǎn),中文文案顯示正常。

解決方案:

從源碼看只有一種解決方式,{}之間的單引號(hào)需要成對(duì)出現(xiàn),我們的處理方式是將文案修改為了:

tms.pallet.order.box.qty=The total palletized boxes quantity {0} doesn''t match with the received boxes quantity {1},Please double check!

直接修改文案其實(shí)并不是一種很好的解決方法,最好是能夠重寫Spring調(diào)用applyPattern方法前的某一方法來(lái)將單引號(hào)替換為雙引號(hào)。無(wú)奈spring 3.2.3版本中對(duì)應(yīng)國(guó)際化的處理方法一路private,不給你重寫的機(jī)會(huì)。

查閱相關(guān)資料得知,在Spring4.3.2版本中可以通過(guò)重寫ResourceBundleMessageSource類中的getStringOrNull方法來(lái)實(shí)現(xiàn)。

長(zhǎng)遠(yuǎn)方案:升級(jí)項(xiàng)目中的Spring版本,同時(shí)使用更多的新版特性。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • springboot+thymeleaf整合阿里云OOS對(duì)象存儲(chǔ)圖片的實(shí)現(xiàn)

    springboot+thymeleaf整合阿里云OOS對(duì)象存儲(chǔ)圖片的實(shí)現(xiàn)

    本文主要介紹了springboot+thymeleaf整合阿里云OOS對(duì)象存儲(chǔ)圖片的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • 本地安裝MinIO分布式對(duì)象存儲(chǔ)服務(wù)器的詳細(xì)步驟

    本地安裝MinIO分布式對(duì)象存儲(chǔ)服務(wù)器的詳細(xì)步驟

    本地安裝MinIO非常簡(jiǎn)單,MinIO提供了獨(dú)立的二進(jìn)制文件,無(wú)需額外的依賴,本文介紹如何在本地安裝MinIO分布式對(duì)象存儲(chǔ)服務(wù)器,感興趣的朋友一起看看吧
    2024-01-01
  • Java數(shù)據(jù)結(jié)構(gòu)之圖的領(lǐng)接矩陣詳解

    Java數(shù)據(jù)結(jié)構(gòu)之圖的領(lǐng)接矩陣詳解

    圖的領(lǐng)接矩陣存儲(chǔ)方式是用兩個(gè)數(shù)組來(lái)表示圖。一個(gè)一位數(shù)組存儲(chǔ)圖中頂點(diǎn)信息,一個(gè)二維數(shù)組存儲(chǔ)圖中的邊或弧的信息。本文將為大家重點(diǎn)介紹一下數(shù)據(jù)結(jié)構(gòu)中的圖的鄰接矩陣,快來(lái)跟隨小編一起學(xué)習(xí)吧
    2021-11-11
  • 詳解如何在Spring中為@Value注解設(shè)置默認(rèn)值

    詳解如何在Spring中為@Value注解設(shè)置默認(rèn)值

    在Spring開(kāi)發(fā)中,我們經(jīng)常會(huì)遇到需要從配置文件中讀取屬性的情況,@Value注解是Spring提供的一種便捷方式,能夠讓我們輕松地將配置文件中的屬性注入到Spring Bean中,
    2024-10-10
  • IDEA生成servlet程序的實(shí)現(xiàn)步驟

    IDEA生成servlet程序的實(shí)現(xiàn)步驟

    這篇文章主要介紹了IDEA生成servlet程序的實(shí)現(xiàn)步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • btrace定位生產(chǎn)故障的方法示例

    btrace定位生產(chǎn)故障的方法示例

    這篇文章主要介紹了btrace定位生產(chǎn)故障的方法示例,文中通過(guò)示例代碼介紹的很詳細(xì),相信對(duì)大家具有一定的參考價(jià)值,需要的朋友們下面來(lái)一起看看吧。
    2017-02-02
  • JAVA冒泡排序和二分查找的實(shí)現(xiàn)

    JAVA冒泡排序和二分查找的實(shí)現(xiàn)

    本文詳細(xì)介紹了JAVA冒泡排序和二分查找的實(shí)現(xiàn),雖然這兩種算法比較簡(jiǎn)單,但是確實(shí)我們必須需要掌握的。下面來(lái)看看。
    2016-07-07
  • java進(jìn)行數(shù)據(jù)的比較的實(shí)例方法

    java進(jìn)行數(shù)據(jù)的比較的實(shí)例方法

    在本篇文章里小編給大家整理的是一篇關(guān)于java進(jìn)行數(shù)據(jù)的比較的實(shí)例方法,有需要的朋友們可以學(xué)習(xí)下。
    2021-04-04
  • 反射機(jī)制:getDeclaredField和getField的區(qū)別說(shuō)明

    反射機(jī)制:getDeclaredField和getField的區(qū)別說(shuō)明

    這篇文章主要介紹了反射機(jī)制:getDeclaredField和getField的區(qū)別說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • logback-spring.xml配置詳解

    logback-spring.xml配置詳解

    這篇文章主要介紹了logback-spring.xml詳解,本文介紹了logback-spring.xml相關(guān)的知識(shí)與概念,結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-07-07

最新評(píng)論