2014-12-04 9 views
2

В настоящее время я работаю над Java-приложением, основанным на REST, с использованием нового Camel REST DSL в качестве основы. Это в основном работает за исключением того, что я заметил при вызове URL-адресов с помощью клиента REST (вместо сказать, браузер) ответ JSON «разбитым» и приходит через с тем, что я предполагаю, что это неправильная кодировкаКодировка ответа DSL Camel Rest


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 {хост}/TestApp/данные, в Chrome, например, ответ приходит через как:

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

Однако с помощью плагина Почтальон браузера, как клиент возвращает:

"W3siZGF0YSI6ImRhdGE6OjAiLCJ2YWx1ZSI6InZhbHVlOjowIiwiY291bnQiOjB9LHsiZGF0YSI6ImRhdGE6OjEiLCJ2YWx1ZSI6InZhbHVlOjoxIiwiY291bnQiOjF9LHsiZGF0YSI6ImRhdGE6OjIiLCJ2YWx1ZSI6InZhbHVlOjoyIiwiY291bnQiOjJ9LHsiZGF0YSI6ImRhdGE6OjMiLCJ2YWx1ZSI6InZhbHVlOjozIiwiY291bnQiOjN9LHsiZGF0YSI6ImRhdGE6OjQiLCJ2YWx1ZSI6InZhbHVlOjo0IiwiY291bnQiOjR9LHsiZGF0YSI6ImRhdGE6OjUiLCJ2YWx1ZSI6InZhbHVlOjo1IiwiY291bnQiOjV9LHsiZGF0YSI6ImRhdGE6OjYiLCJ2YWx1ZSI6InZhbHVlOjo2IiwiY291bnQiOjZ9LHsiZGF0YSI6ImRhdGE6OjciLCJ2YWx1ZSI6InZhbHVlOjo3IiwiY291bnQiOjd9LHsiZGF0YSI6ImRhdGE6OjgiLCJ2YWx1ZSI6InZhbHVlOjo4IiwiY291bnQiOjh9LHsiZGF0YSI6ImRhdGE6OjkiLCJ2YWx1ZSI6InZhbHVlOjo5IiwiY291bnQiOjl9XQ==" 

Проблема заключается в том, что режим привязки REST является «авто» и использует пользовательский маршаллер. Если я установил режим привязки на «json», то оба ответа браузера и клиента будут искажены. Если я установил режим привязки на «json» и обход пользовательских маршаллеров, все будет работать правильно. Есть ли способ настроить маршрут для использования настраиваемого маршаллера и правильно кодировать ответы независимо от клиента?

ответ

7

Я думаю, что решение заключается в использовании опции привязки по умолчанию (off), поскольку вы используете пользовательские маршаллеры.

2

У вас есть два пути для достижения этой цели:

  1. Выключите RestBindingMode, поскольку в противном случае RestBindingMarshalOnCompletion в RestBindingProcessor будет зарегистрирован и вручную (ООН) маршалом.
  2. Зарегистрируйте свой собственный DataFormat и автоматически используйте его в RestBinding. Вы настраиваете конфигурацию REST с помощью jsonDataFormat, чтобы установить формат пользовательских данных.

    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"

  • это имя файла, и этот файл должен содержать имя класса, которое реализует ваш собственный способ маршалирования и отмены ...
  • должно быть расположено в вашей банке: META-INF \ services \ org \ apache \ верблюд \ DataFormat

поэтому содержимое файла должно быть:

class=packageofmyclass.MyOwnDataformatter 
0

ответ вы получали это JSON, но он был закодирован в base64. Взяв строку со своего поста, я смог ее расшифровать как:

[{"data": "data :: 0", "value": "value :: 0", "count": 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 "," value ":" value :: 9 "," count ": 9}]

Ответы выше останавливают тело ответа, закодированное на base64. Документация от Apache Camel по адресу bindingMode иллюзорна относительно того, почему она ведет себя таким образом, когда она сочетается с явным сортировкой. Удаление явного сортировки вернет тело JSON, но вы также можете заметить, что оно содержит имена всех классов в теле. Документация предполагает, что bindingMode больше предназначен для транспортировки классов и что вы указываете тип (Pojo.class) и необязательно outType (Pojo.class) ваших запросов/ответов. См. http://camel.apache.org/rest-dsl.html (раздел «Связывание с использованием POJO») для получения более подробной информации.

Base64 - самый безопасный способ передачи JSON по сетям, чтобы обеспечить его получение точно так же, как сервер отправил его, согласно некоторым сообщениям, которые я прочитал. Затем клиент должен затем декодировать ответ.

Ответы, приведенные выше, решают проблему. Тем не менее, я не совсем уверен, что смешивание формата данных в маршрутах обслуживания является таким, как хорошее, и в идеале должно быть на более высоком уровне абстракции. Это позволило бы изменить формат данных в одном месте, вместо того, чтобы изменять его на каждом маршруте, который создает JSON. Хотя, я должен признать, я никогда не видел службы, которая имеет формат данных изменений в своей жизни, так что это действительно немой пункт.

Смежные вопросы