2014-12-04 283 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的路径上更改它。尽管如此,我必须承认,我从来没有见过一种服务在其生命周期中改变了数据格式,所以这真的是一个不起眼的点。