2014-12-04 86 views
2

我目前正在使用新的Camel REST DSL作爲基礎來開發基於REST的Java應用程序。 它主要的工作只是我通過一個REST客戶端調用URL時發現(而不是說一個瀏覽器)的JSON的反應是「亂碼」,並與我承擔什麼是錯誤的編碼駱駝休息DSL響應編碼


MyRouteBuilder來通過的.java

@Component 
public class MyRouteBuilder extends RouteBuilder{ 
    @Autowired 
    LocalEnvironmentBean environmentBean; 

    @Override 
    public void configure() throws Exception { 
     restConfiguration().component("jetty").host("0.0.0.0").port(80) 
      .bindingMode(RestBindingMode.auto); 

     rest("/testApp") 
      .get("/data").route() 
       .to("bean:daoService?method=getData") 
       .setProperty("viewClass", constant(CustomeJsonViews.class)) 
       .marshal("customDataFormat").endRest() 
      .get("/allData").route() 
       .to("bean:daoService?method=getDatas") 
       .setProperty("viewClass", constant(CustomeJsonViews.class)) 
       .marshal("customDataFormat").endRest(); 
    } 
} 

CustomeDataFormat.java

public class CustomDataFormat implements DataFormat{ 
    private ObjectMapper jacksonMapper; 
    public CustomDataFormat(){ 
     jacksonMapper = new ObjectMapper(); 
    } 
    @Override 
    public void marshal(Exchange exchange, Object obj, OutputStream stream) throws Exception { 
     Class view = (Class) exchange.getProperty("viewClass"); 
     if (view != null) 
     { 
      ObjectWriter w = jacksonMapper.writerWithView(view); 
      w.writeValue(stream, obj); 
     } 
     else 
      stream.write(jacksonMapper.writeValueAsBytes(obj)); 

    } 

    @Override 
    public Object unmarshal(Exchange exchange, InputStream stream) throws Exception { 
     return null; 
    } 
} 

一個完整的工作版本可以在這裏找到: https://github.com/zwhitten/camel-rest-test

當去到URL,{主機}在Chrome/testApp /數據,例如響應來自通過爲:

{ 
data: "Sherlock", 
value: "Holmes", 
count: 10 
} 

但是使用郵差瀏覽器插件的客戶端返回:

"W3siZGF0YSI6ImRhdGE6OjAiLCJ2YWx1ZSI6InZhbHVlOjowIiwiY291bnQiOjB9LHsiZGF0YSI6ImRhdGE6OjEiLCJ2YWx1ZSI6InZhbHVlOjoxIiwiY291bnQiOjF9LHsiZGF0YSI6ImRhdGE6OjIiLCJ2YWx1ZSI6InZhbHVlOjoyIiwiY291bnQiOjJ9LHsiZGF0YSI6ImRhdGE6OjMiLCJ2YWx1ZSI6InZhbHVlOjozIiwiY291bnQiOjN9LHsiZGF0YSI6ImRhdGE6OjQiLCJ2YWx1ZSI6InZhbHVlOjo0IiwiY291bnQiOjR9LHsiZGF0YSI6ImRhdGE6OjUiLCJ2YWx1ZSI6InZhbHVlOjo1IiwiY291bnQiOjV9LHsiZGF0YSI6ImRhdGE6OjYiLCJ2YWx1ZSI6InZhbHVlOjo2IiwiY291bnQiOjZ9LHsiZGF0YSI6ImRhdGE6OjciLCJ2YWx1ZSI6InZhbHVlOjo3IiwiY291bnQiOjd9LHsiZGF0YSI6ImRhdGE6OjgiLCJ2YWx1ZSI6InZhbHVlOjo4IiwiY291bnQiOjh9LHsiZGF0YSI6ImRhdGE6OjkiLCJ2YWx1ZSI6InZhbHVlOjo5IiwiY291bnQiOjl9XQ==" 

該問題似乎與REST綁定模式是「自動」並使用自定義編組器。 如果我將綁定模式設置爲「json」,那麼瀏覽器和客戶端響應都會出現亂碼。 如果我將綁定模式設置爲「json」並繞過自定義編組器,則一切正常。 有沒有辦法將路由配置爲使用自定義編組器並正確編碼響應而不考慮客戶端?

回答

7

我認爲解決方案是使用默認綁定選項(關閉),因爲您使用的是自定義marshallers。

2

你有兩種方法來實現它:

  1. 關閉RestBindingMode,因爲否則RestBindingMarshalOnCompletionRestBindingProcessor將被註冊和手動(UN)元帥。
  2. 註冊您自己的DataFormat並自動在RestBinding中使用它。您可以通過jsonDataFormat配置REST配置來設置自定義數據格式。

    Map<String, DataFormatDefinition> dataFormats = getContext().getDataFormats(); 
    if (dataFormats == null) { 
        dataFormats = new HashMap<>(); 
    } 
    dataFormats.put("yourFormat", new DataFormatDefinition(new CustomDataFormat())); 
    
    restConfiguration()....jsonDataFormat("yourFormat") 
    
0

您也可以創建自己的DATAFORMAT像這樣:在你的restconfiguration

它看起來STHG類似(請參閱JSON定製)

builder.restConfiguration().component("jetty") 
         .host(host(propertiesResolver)) 
         .port(port(propertiesResolver)) 
         .bindingMode(RestBindingMode.json) 
         .jsonDataFormat("json-custom") 
       ; 

您必須創建一個文件「json-custom」

  • 這是文件的名稱,該文件應包含實現您自己的編組和解組方式的類名稱...
  • 它必須位於您的jar中:META-INF \ services \ org \ apache \駱駝\ DATAFORMAT

因此該文件的內容應該是:

class=packageofmyclass.MyOwnDataformatter 
0

你收到的響應是JSON,但它已被編碼爲base64。以從您的文章的字符串,我可以把它作爲解碼:

[{ 「數據」: 「數據:: 0」, 「值」: 「值:: 0」, 「伯爵」:0}, { 「數據」: 「數據:: 1」, 「值」: 「值:: 1」, 「計數」:1},{ 「數據」: 「數據:: 2」, 「值」:「值:: 2" , 「計數」:2},{ 「數據」: 「數據:: 3」, 「值」: 「值:: 3」, 「計數」:3},{ 「數據」:「數據:: 4 」, 「值」: 「值:: 4」, 「計數」:4},{ 「數據」: 「數據:: 5」, 「值」: 「值:: 5」, 「計數」:5}, { 「數據」: 「數據:: 6」, 「值」: 「值:: 6」, 「計數」:6},{ 「數據」: 「數據:: 7」, 「值」:「值:: 7" , 「計數」:7},{ 「數據」: 「數據:: 8」, 「值」: 「值:: 8」, 「計數」:8},{ 「數據」:「數據:: 9 」, 「值」: 「值:: 9」, 「計數」:9}]

以上的答案停止響應主體被編碼爲base64。從Apache的駱駝上bindingMode的文檔是虛幻的,爲什麼當有明確編組結合它的行爲的方式。刪除顯式編組將返回一個JSON正文,但您也可能注意到它包含正文中的任何類名。該文件表明,bindingMode則多爲類的運輸和你specifiy一個類型(Pojo.class)和可選outType您的請求/響應的(Pojo.class)。有關更多詳細信息,請參閱http://camel.apache.org/rest-dsl.html(綁定到POJO使用部分)。

Base64是跨網絡傳輸JSON,以確保其獲得完全一樣的服務器發送的,根據一些帖子我讀過的最安全的方式。然後客戶有責任解碼響應。上述

的答案做解決問題。然而,我並不完全相信在服務路線中混合數據格式是件好事,理想情況下應該處於更高層次的抽象。這將允許在一個地方更改數據格式,而不必在每條生成JSON的路徑上更改它。儘管如此,我必須承認,我從來沒有見過一種服務在其生命週期中改變了數據格式,所以這真的是一個不起眼的點。