程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 使用mule生成WSDL中文亂碼問題解決方法

使用mule生成WSDL中文亂碼問題解決方法

編輯:關於JAVA

在發布Web服務 的時候,WSDL 作為服務的描述,裡面有一個標簽可以寫入中文,是用來作為注解來寫入描述性信息的,這個標簽就是。OECP平台中使用開源ESB總線mule 來做webService 發布使用.發布時就遇到了中文 描述亂碼 問題,經過一天多的時間來翻閱mule和cxf的源代碼,問題最終被解決。這裡記錄一下解決的過程和方法。

mule 內使用的spring-cxf來將一個Java方法轉換為webService 。cxf有一個annotation是生成wsdl 中的 標簽用的,這個annotation就是@WSDLDocumentation 。但是這個標簽使用後,生成的WSDL 文件,中文 卻顯示成了亂碼 。

經過測試發現,單純使用Spring-cxf時,@WSDLDocumentation 不會產生亂碼 。這就說明問題出在mule 上。只能翻一下mule 的源代碼來查找原因了。由於找不到與當前使用的jar包版本相同的源代碼,只能使用升級版的源碼,調試的時候發現升級的改動比較大,刪掉的以前的一些方法和代碼修改也蠻多,錯行缺行導致調試可讀性極差,讓我一直看了一天多。比較安慰的是最終還是找到了問題原因並解決了。下面就具體說一下原理。

我們知道發布WebService 以後,使用url+?wsdl的方式訪問,將會獲取到服務描述文件wsdl 文件.mule 中發布服務後,使用這種方式訪問服務器將會啟動一個線程,線程調用鏈如下圖:

標記①下面,是http請求引起的mule 事件級聯鏈條,是mule 內部的架構機制,這個不是我們現在要所關注的.重點在第②行,紅色標記出的OutputStream就是用來承載wsdl 文件流的對象,實際上它是一個ByteArrayOutputStream。在圖上⑥的位置執行完後,這個Stream將被寫入完成。前面的每一個步驟中文字符 的編碼都是正確的,即便是寫入到Stream中,字符的byte編碼也沒有問題。但是,此時我們發現查看這個Stream的內容時,卻看到了亂碼 。這是為什麼呢?為什麼Stream中存儲的byte沒錯,但是卻能看到亂碼呢?

經常調試程序的朋友們知道,當我們查看一個對象的內容時,對象查看器,將調用對象的toString方法。經檢查發現ByteArrayOutputStream的toString方法果然被重寫:

Java 代碼

  1. public synchronized String toString() {
  2. return new String(buf, 0 , count);
  3. }

ByteArrayOutputStream使用buffer中所有的byte創建並返回了一個String對象。這裡注意,創建String的時候並沒有指定編碼格式。那麼它用的是什麼編碼格式?我們去String中看看,String使用了StringCoding來轉化byte為char數組,而其中選用的編碼格式是從Charset.defaultCharset()得來的。從JDK的API中我們能找到了這個方法,上面是這麼說的:

在我們的服務器運行環境中得到的默認編碼 格式為GBK。於是亂碼形成的原因找到了:由於Spring-cxf生成服務的wsdl 時用的是UTF-8編碼,而被mule 錯誤的使用了服務器運行環境默認編碼GBK,所以UTF-8下的正常顯示中文 最終被顯示為亂碼 了。

mule 中的類CxfInboundMessageProcessor第201行:

msg = out.toString();

這就是亂碼 產生的根源,在將字節流轉為字符串的時候,沒有指定編碼格式,而默認使用了GBK,就是wsdl 文件亂碼 的原因。

解決這個問題又兩種方案:

1. 改變jvm的默認字符編碼。

2. 修改CxfInboundMessageProcessor類的源代碼。

第一種方案通過修改服務器的啟動參數,追加一段“-Dfile.encoding=UTF-8”,就可以改變服務器的Java運行環境。此時啟動服務器時我們會發現,雖然我們的WSDL中文不再出現亂碼了,但是服務器控制台顯示的中文 卻全都成了亂碼 。我猜是服務器的日志輸出依賴於操作系統的默認字符集吧。暫且不說這個日志亂碼 問題,即使不存在這個問題我認為這種方案也是不太合適的。wsdl 是否出現亂碼依賴於運行服務器的默認字符集,對於OECP平台來說是不可控的。OECP平台使用什麼樣的字符編碼應該依賴於應用自己的配置。

於是決定修改mule 的源代碼,比較幸運的是CxfInboundMessageProcessor這個類,在升級的過程中沒有改動,不然就要反編譯來獲取源碼了。

將201行的msg = out.toString();修改為如下代碼:

Java 代碼

  1. String enc = event.getMuleContext().getConfiguration().getDefaultEncoding();
  2. msg = out.toString(enc);

從mule 的配置中得到配置的編碼格式,並在將Stream轉換為String的時候指定使用此編碼格式.至此問題解決了.

我們可以在使用mule發布服務時,使用WSDLDocumentation 標簽來為服務添加描述了.wsdl 作為WebService 的描述,如果沒有注釋性的文字,wsdl 描述可讀性實在不是很好. WSDLDocumentation 標簽就是作為這種描述存在的,如果你想在WSDL 中加入中文 的描述這個標簽應該是唯一的選擇.如果你使用的也是mule ,也遇到了中文 的亂碼 問題,希望可上面的內容可以幫助你。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved