使用 Jackson 将 POJO 作为实体传递的 Jersey/JAX-RS 客户端



我正在尝试使用Jersey/JAX-RS实现RESTful Web服务客户端:

public class MyClient implements Closeable {
    private Client client;
    private FizzResource fizzResource;
    // Several other resources omitted for brevity.
    // Ctor, getters and setters, etc.
    @Override
    public void close() throws Exception {
        client.destroy();
        client.getExecutorService().shutdown();
    }
}
public class FizzResource {
    private Client client;
    public Fizz saveFizz(Fizz fizz) {
        WebResource webResource = client.resource("whatever");
        ClientResponse response = webResource.accept(???).post(???);
        if(response.getStatus() != 200) {
            // do something...
        } else {
            // do something else...
        }
    }
}
我的

问题是我不想使用JSON;相反,我想直接使用我的实体(例如 Fizz)。我想使用 Jackson 自动在 JSON 和我的实体之间进行序列化(而无需在每个方法中显式进行转换),但我看不到这如何可能/可行。理想情况下,我的saveFizz方法可能如下所示:

public Fizz saveFizz(Fizz fizz) {
    WebResource webResource = client.resource("whatever");
    ClientResponse response = webResource.accept("application/json").post(fizz);
    if(response.getStatus() != 200) {
        throw new RuntimeException("Errors are bad, mkay?");
    }
    Fizz fizz = response.extractSomehow();
    return fizz;
}

假设我的Fizz类已经用正确的杰克逊注释(JsonProperty等)进行了注释。

有什么想法吗?

您使用的是 Jersey 1.x,因此请查看 JSON/POJO 支持的用户指南

第一件事:我们需要确保您拥有jersey-json模块

<dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-json</artifactId>
    <version>${jersey-version}</version>
</dependency>

此模块将具有所需的MessageBodyReaderMessageBodyWriter,这些和将 POJO 读取和写入 JSON

第二件事:我们需要确保启用 POJO 映射支持功能。服务器/应用程序和客户端

带网络的服务器.xml

<init-param>
    <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
    <param-value>true</param-value>
</init-param>

服务器编程

public class MyApplication extends PackagesResourceConfig {
    public MyApplication() {
        getFeatures()..put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
    }
}

查看其他部署选项

客户端配置

ClientConfig clientConfig = new DefaultClientConfig();
clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, 
                               Boolean.TRUE);
Client client = Client.create(clientConfig);

第三件事:我们只需要确保我们的资源方法被正确注释,并且我们正确地调用客户端(以允许发现正确的编写器/读取器)。

对于接受 JSON 的方法,它应该用 @Consumed("application/json") 注释,

如果该方法也在 JSON 中产生响应,它也应该用 @Produces("application/json") 注释。因此,这取决于方法的语义,要包含哪些注释,它可以是一个或两个。

对于客户端来说,只要我们必须正确配置,提取 Java 对象,就只需调用具有 Java 类型的getXxx即可。

public void testGetFizz() {
    // Directly extact
    Fizz fizz = r.path("fizz").accept("application/json").get(Fizz.class);
    System.out.println(fizz);
    // Extract from ClientResponse
    ClientResponse response = r.path("fizz").
                     accept("application/json").get(ClientResponse.class);
    Fizz fizz1 = response.getEntity(Fizz.class);
    System.out.println(fizz1);
}

以下是我用于测试的其他代码片段

@Path("/fizz")
public class FizzResource {
    @POST
    @Consumes("application/json")
    public Response postFizz(Fizz fizz) {
        System.out.println("==== Created Fizz ===");
        System.out.println(fizz);
        System.out.println("=====================");
        return Response.created(null).build();
    }
    @GET
    @Produces("application/json")
    public Response getFizz() {
        Fizz fizz = new Fizz(1, "fizz");
        return Response.ok(fizz).build();
    }
}

服务器配置

ResourceConfig resourceConfig = new PackagesResourceConfig("test.json.pojo");
resourceConfig.getFeatures().put(
                       JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);

客户端配置

ClientConfig clientConfig = new DefaultClientConfig();
clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, 
                               Boolean.TRUE);
Client client = Client.create(clientConfig);
r = client.resource(Main.BASE_URI);
// r = WebResource
你可以

使用Jackson的ObjectMapper:

final ObjectMapper mapper = new ObjectMapper();
mapper.readValue(response.getEntity(String.class), Fizz.class);

只要正确注释了 Fizz,它应该可以满足您的需求。

还有其他选项,通常涉及实现自定义提供程序。

如果你包括(假设你使用 maven)

 <dependency>
      <groupId>org.glassfish.jersey.media</groupId>
      <artifactId>jersey-media-moxy</artifactId>
      <version>${jersey.version}</version>
  </dependency>

然后,您将无需设置任何内容即可自动转换。您可以编写如下函数:

@POST
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
public Activity createActivity(@Valid Activity activity) {
    return activityDAO.createActivity(vuser,activity);
}

最新更新