Как установить заголовок http в ответ Json

У меня есть служба CXF RESTful, которая возвращает формат XML и Json. Мне нужно добавить собственный заголовок http в службу RESTful. Вот пример фрагмента кода.


    @GET
    @Path("/test")
    @Produces("application/xml")
    public Response test(
            @QueryParam("p") String var
    {
        TestRequest req = new TestRequest();
        req.setVar(var);
        TestResponse res = p.getData(req);
        return Response.ok(res).header("Result", res.getResult()).build();
    }

В приведенном выше коде показан ответ XML, который устанавливает настраиваемый заголовок HTTP «Результат». Я вижу новый заголовок http в заголовке ответа. Все идет нормально.

Теперь вот версия Json, которая внутренне вызывает метод testService() для получения результата, а затем использует API Google Gson для отправки результата обратно. Это работало хорошо, пока я не решил вернуть новый заголовок. Вот фрагмент кода.


    @GET
    @Path("/test/jsonp")
    public String testJSONP(
            @QueryParam("p") String var,
            @QueryParam("cb") String callBack
    {
        Response resp = test(var);
        XStream xs = new XStream(new JsonHierarchicalStreamDriver());
        xs.setMode(XStream.NO_REFERENCES);
        xs.alias("TestResponse", TestResponse.class);
        StringBuilder sb = new StringBuilder();
        sb.append(callBack);
        sb.append("(");
        GsonBuilder gb = new GsonBuilder();
        gb.registerTypeAdapter(XMLGregorianCalendar.class, new XMLGregorianCalenderSerializer());
        gb.setPrettyPrinting();
        Gson gson = gb.create();
        sb.append(gson.toJson(resp));
        sb.append(")");
        return sb.toString();
    }

Я не вижу заголовок http в ответе Json.

Любая обратная связь будет высоко оценена.

-Спасибо

ОБНОВИТЬ

Я добавил следующий код в метод Json для тестирования.


    @GET
    @Path("/test/jsonp")
    public String testJSONP(
            @QueryParam("p") String var,
            @QueryParam("cb") String callBack
    {
        Response resp = test(var);
        XStream xs = new XStream(new JsonHierarchicalStreamDriver());
        xs.setMode(XStream.NO_REFERENCES);
        xs.alias("TestResponse", TestResponse.class);
        StringBuilder sb = new StringBuilder();
        sb.append(callBack);
        sb.append("(");
        GsonBuilder gb = new GsonBuilder();
        gb.registerTypeAdapter(XMLGregorianCalendar.class, new XMLGregorianCalenderSerializer());
        gb.setPrettyPrinting();
        Gson gson = gb.create();
        sb.append(gson.toJson(resp));
        sb.append(")");
        return Response.ok(sb.toString(), MediaType.APPLICATION_JSON).header("Result", "50").build();
    }

Это правильно устанавливает значение заголовка, но проблема в том, что формат ответа Json, похоже, изменился. Поскольку это существующая служба, мне не разрешено это делать. Вот существующий формат ответа


null({
  "status": "Completed",
  "totalResult": "252",
  "bin": [
    {
      "type": "source",
      "value": "documentation",
      "ndocs": "243"
    },
    {
      "type": "source",
      "value": "wikihelp",
      "ndocs": "6"
    },    
  "entries": {
    "item": [
      {
        "url": "http://test.com/test.htm",
        "title": "\u003cspan class\u003d\"vivbold qt0\"\u003eXREF\u003c/span\u003e",
        "snippet": "     Test data.",
        "source": "documentation",
        "type": "html",
        "shortDescription": "Starts the TEST command.",
        "category": [
          "User"
        ],
        "publishDate": "2012-02-05T12:00:00-0500",
        "lastUpdateDate": "2012-03-14T12:00:00-0400",
        "topicId": "GUID-7DD70C3C-B8AD-40F1-8A69-5D1EECEAB013"
      }
    ]
  }
})

Вот ответ после добавления этого изменения


null({
  "status": 200,
  "entity": {
    "status": "Completed",
    "totalResult": "252",
    "bin": [
      {
        "type": "source",
        "value": "documentation",
        "ndocs": "243"
      },
      {
        "type": "source",
        "value": "wikihelp",
        "ndocs": "6"
      }
    ],
    "entries": {
      "item": [
        {
          "url": "http://test.com/test.htm",
          "title": "\u003cspan class\u003d\"vivbold qt0\"\u003eXREF\u003c/span\u003e",
          "snippet": " Test data.",
          "source": "documentation",
          "type": "html",
          "shortDescription": "Starts the TEST command.",
          "category": [
            "User"
          ],
          "publishDate": "2012-02-05T12:00:00-0800",
          "lastUpdateDate": "2012-03-14T12:00:00-0700",
          "topicId": "GUID-7DD70C3C-B8AD-40F1-8A69-5D1EECEAB013"
        }
      ]
    }
  },
  "metadata": {
    "Result": {

    }
  }
})

person Shamik    schedule 17.06.2012    source источник


Ответы (1)


Вам нужно изменить сигнатуру вашего метода, чтобы вернуть экземпляр Response class вместо String, а затем создал ответ вручную.

На вики-странице CXF:

@Path("/example")
public ExampleResource {
    @GET
    public Response getSomething() {
        return Response.ok(/* some entity */).header("CustomHeader", "CustomValue").build();
    }
}

Обновлять

Вы также можете внедрить HttpServletResponse в свой обработчик, используя аннотацию @Context следующим образом:

@Path("/example")
public class Welcome {

    @GET
    public String getSomething(
            @QueryParam("p1") String param1, 
            @QueryParam("p2") String param2, 
            @Context HttpServletResponse response) {

        response.addHeader("CustomHeader", "CustomValue");

        return "my awesome response";
    }
}

Обратите внимание, что в версиях до 2.1 существует CXF-1498 ошибка, из-за которой HttpServletResponse не вводится, поэтому вам нужна более новая версия CXF.

person npe    schedule 17.06.2012
comment
@npe..Спасибо за ваш ответ.... Я попробовал это, используя следующий код в методе Jsonp.... return Response.ok(sb.toString(), MediaType.APPLICATION_JSON).header(Результат, 200) .строить(); Это устанавливает заголовок без изменения подписи, но по какой-то причине это меняет формат ответа. Поскольку это существующая служба, мне не разрешено это делать. - person Shamik; 18.06.2012
comment
Я обновил ответ другим решением, пожалуйста, проверьте его. - person npe; 18.06.2012
comment
@npe ... большое спасибо, я не знал, что объекты HTTPResponse могут передаваться как контекст. Это сработало отлично. - person Shamik; 18.06.2012
comment
+1 Параметр HttpServletResponse, похоже, не работает с CXF версии 2.7. Он выдает 2 значения IllegalAnnotationExceptions. Однако он работает как поле. Этот ответ все еще актуален? - person Gray; 21.02.2013
comment
Это — особенно определение метода updateCustomer — утверждает, что пример все еще действителен. Может это баг 2.7? - person npe; 22.02.2013