首页 文章

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

提问于
浏览
0

我正在尝试使用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 类已经使用正确的Jackson注释( JsonProperty 等)进行了注释 .

有任何想法吗?

3 回答

  • 2

    你正在使用Jersey 1.x,所以看看the user guide for JSON/POJO support

    First thing: 我们需要确保你有 jersey-json 模块

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

    该模块将具有所需的 MessageBodyReaderMessageBodyWriter ,它将从JSON读取和写入POJO

    Second thing: 我们需要确保启用POJO映射支持功能 . 与服务器/应用程序和客户端

    带有web.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);
        }
    }
    

    见其他Deployment Options

    客户端配置

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

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

    对于接受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);
    }
    

    Here are other pieces of code I used for my test

    @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
    
  • 0

    你可以使用Jackson的ObjectMapper:

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

    只要Fizz被正确注释,这应该可以满足您的需求 .

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

  • 1

    如果你包括(假设你使用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);
    }
    

相关问题