Ответ 1
Если вам потребуется немного времени, чтобы понять WebTarget
API, а также различные типы, возвращаемые из вызовов WebTarget
, вы должны лучше понять, как совершать звонки. Это может быть немного запутанным, так как почти весь пример использует метод цепочки, поскольку это очень удобный способ, но при этом вы пропускаете все фактические классы, участвующие в создании и отправке запроса. Пусть немного сломается
WebTarget target = client.target(getBaseURI()).path("rest").path("orders");
WebTarget.path()
просто возвращает WebTarget
. Ничего интересного нет.
target.path("oneOrder").request().accept(MediaType.APPLICATION_JSON).get(String.class)
-
WebTarget.request()
возвращаетInvocation.Builder
-
Invocation.Builder.accept(..)
возвращаетInvocation.Builder
-
Invocation.Builder.get()
вызывает свой суперклассSyncInvoker.get()
, который делает фактический запрос и возвращает тип, на основе аргумента мы предоставитьget(Class returnType)
То, что вы делаете с get(String.class)
, означает, что поток ответа следует десериализовать в ответ типа Sting. Это не проблема, поскольку JSON по своей сути является просто строкой. Но если вы хотите развязать его с POJO, вам нужно иметь MessageBodyReader
, который знает, как развязать JSON с вашим типом POJO. Джексон предоставляет MessageBodyReader
в нем jackson-jaxrs-json-provider
зависимость
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.4.0</version>
</dependency>
В большинстве реализаций будет использоваться оболочка для этого модуля, например jersey-media-json-jackson
для Джерси или resteasy-jackson-provider
для Resteasy. Но они все еще используют базовый jackson-jaxrs-json-provider
.
При этом, если у вас есть этот модуль в пути к классам, он должен быть автоматически зарегистрирован, поэтому будет доступен MessageBodyReader
. Если нет, вы можете зарегистрировать его явно с клиентом, например client.register(JacksonJaxbJsonProvider.class)
. После того, как вы настроили поддержку Jackson, вы можете просто сделать что-то вроде
MyPojo myPojo = client.target(..).path(...).request().accept(..).get(MyPojo.class);
Что касается отправки/отправки данных, вы можете снова просмотреть различные методы Invocation.Builder
. Например,
Invocation.Builder builder = target.request();
Если мы хотим опубликовать, просмотрите различные методы post
. Мы можем использовать
-
Response post(Entity<?> entity)
- Наш запрос может выглядеть примерно какResponse response = builder.post(Entity.json(myPojo));
Вы заметите
Entity
. Все методыpost
принимаютEntity
, и именно так запрос будет знать, каким типом должен быть объект сущности, и клиент будет вызывать approriateMessageBodyWriter
, а также установить соответствующий заголовок -
<T> T post(Entity<?> entity, Class<T> responseType)
- Там есть другая перегрузка, где мы можем указать тип, который нужно развязать, вместо возвратаResponse
. Мы могли бы сделатьMyPojo myPojo = builder.post(Entity.json(myPojo), MyPojo.class)
Обратите внимание, что с помощью Response
мы вызываем его метод readEntity(Class pojoType)
для чтения из тела Response
, тела объекта. Преимущество этого заключается в том, что объект Response
поставляется с большим количеством полезной информации, которую мы можем использовать, например, заголовками и т.д. Лично я всегда получаю Response
Response response = builder.get();
MyPojo pojo = response.readEntity(MyPojo.class);
Как в стороне, для вашего конкретного кода, который вы показываете, вы, скорее всего, хотите сделать его методом @POST
. Помните @GET
в основном для получения данных, PUT
для обновления и post
для создания. Это хорошее эмпирическое правило, которое следует придерживаться при первом запуске. Таким образом, вы можете изменить метод на
@Path("orders")
public class OrdersResource {
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes({MediaType.APPLICATION_JSON})
public Response createOrder(@Context UriInfo uriInfo, Order input) {
Order order = orderService.createOrder(input);
URI uri = uriInfo.getAbsolutePathBuilder().path(order.getId()).build();
return Response.create(uri).entity(order).build();
}
}
Затем вы можете сделать
WebTarget target = client.target(BASE).path("orders");
Response response = target.request().accept(...).post(Entity.json(order));
Order order = response.readEntity(Order.class);