使用POJO Order. java.
@XmlRootElement public class Order { private String id; private String description; public Order() { } @XmlElement public String getId() { return id; } @XmlElement public String getDescription() { return description; } // Other setters and methods }
Webservice被定义为
@Path("/orders") public class OrdeRSService { // Return the list of orders for applications with json or xml formats @Path("/oneOrder") @GET @Produces({MediaType.APPLICATION_JSON}) public Order getOrder_json() { System.out.println("inside getOrder_json"); Order o1 = OrderDao.instance.getOrderFromId("1"); System.out.println("about to return one order"); return o1; } @Path("/writeAndIncrementOrder") @GET @Produces({MediaType.APPLICATION_JSON}) @Consumes({MediaType.APPLICATION_JSON}) public Order writeAndIncrementOrder(Order input) { System.out.println("inside writeAndIncrementOrder"); Order o1 = new Order(); o1.setId(input.getId()+1000); o1.setDescription(input.getDescription()+"10000"); System.out.println("about to return one order"); return o1; }
我可以编写客户端代码来调用不接受任何东西但返回对象的Web服务.客户端代码如下
import java.net.URI; import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.Invocation.Builder; import javax.ws.rs.client.WebTarget; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriBuilder; import org.glassfish.jersey.client.ClientConfig; public class Test { public static void main(String[] args) { WebTarget target2 = client.target(getBaseURI()).path("rest").path("orders"); String o2 = target2.path("oneOrder").request().accept(MediaType.APPLICATION_JSON).get(String.class); System.out.println(o2); } private static URI getBaseURI() { return UriBuilder.fromUri("http://localhost:8090/FirstRESTProject").build(); }
但我不明白如何调用接受的其他服务以及返回对象.
我在互联网上尝试了不同的解决方案但没有什么对我有用一些解决方案只适用于发送对象,一些只适用于接受.但是没有人在一个电话中做这两个工作.
编辑
如下面的建议回答我注册了JacksonJaxbJsonProvider.class但是自动转换为Order对象并没有发生.
String o2 = target2.path("oneOrder").request().accept(MediaType.APPLICATION_JSON).get(String.class); client.register(JacksonJaxbJsonProvider.class); Order o4 = target2.path("oneOrder").request().accept(MediaType.APPLICATION_JSON).get(Order.class);
在上面的程序中,我成功获取字符串为{“id”:“1”,“description”:“这是第一个命令”}但是获取直接对象抛出错误
MessageBodyReader未找到媒体类型= application / json,type = class shopping.cart.om.Order,genericType = class shopping.cart.om.Order.
解决方法
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本质上只是一个String.但是,如果您想将其解组成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>
大多数实现将为此模块提供一个包装器,例如泽西的泽西媒体杰克逊或Resteasy的resteasy-jackson提供商.但是他们仍然在使用基础的jackson-jaxrs-json-provider.
话虽如此,一旦你在类路径上有这个模块,应该自动注册,所以MessageBodyReader将可用.如果不是,您可以向客户端明确注册,如client.register(JacksonJaxbJsonProvider.class).一旦你配置了杰克逊支持,那么你可以简单地做一些事情
MyPojo myPojo = client.target(..).path(...).request().accept(..).get(MyPojo.class);
对于发布/发送数据,您可以再次查看不同的Invocation.Builder方法.例如
Invocation.Builder builder = target.request();
> Response post(实体<?>实体) – 我们的请求可能看起来像
Response response = builder.post(Entity.json(myPojo));
你会注意到Entity
.所有的post方法接受一个实体,这就是请求如何知道实体的类型应该是什么,客户端将调用相应的MessageBodyWriter以及设置相应的头
>< T> T post(Entity<?> entity,Class< T> responseType) – 还有一个重载,我们可以指定要解组的类型,而不是返回一个Response.我们可以做
MyPojo myPojo = builder.post(Entity.json(myPojo),MyPojo.class)
请注意,使用Response,我们将其readEntity(类pojoType)方法称为从实体体的响应中读取.这个优点是,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);