Jersey Client 2.19 不会在错误状态代码上抛出异常

Jersey Client 2.19 doesn't throw exceptions on bad status code

我正在构建一个 Rest Client 使用 jersey-client 2.19:

public ReleaseEntity createRelease(ReleaseEntity newRelease, int workspaceId) {

    Releases wrapper = new Releases();
    wrapper.setData(Arrays.asList(newRelease));

    WebTarget target = client.target(urlPrefix)
            .path(AgmUrls.getReleasesUrl(workspaceId));

    wrapper = target
            .request()
            .accept(MediaType.APPLICATION_JSON)
            .post(Entity.entity(wrapper, MediaType.APPLICATION_JSON))
            .readEntity(Releases.class);

    return wrapper.getData().get(0); 
} 

客户端在constructor

初始化
this.client = ClientBuilder.newClient();

问题是,如果响应不佳,post 调用不会抛出异常,explicitruntime 都不会。

我应该手动执行此操作,还是我遗漏了什么?

框架不应抛出异常。用户应该按照他们认为合适的方式处理响应。这对任何客户都是一样的。 Response 对象将包含处理响应所需的所有上下文,但您认为合适。

所以你应该做的是先获得Response

Response response = target
         .request()
         .accept(MediaType.APPLICATION_JSON)
         .post(Entity.entity(wrapper, MediaType.APPLICATION_JSON));

然后你可以查看状态

int status = response.getStatus();

然后处理状态

if (status == 200) {
    wrapper = response.readEntity(Releases.class);
    ...
} else { 
    handleOtherStatus();   
}

如果您没有先得到 Response,那么您不知道实际问题是什么,因为 readEntity(...) 会失败(因为它不是您期望的正文),并且抛出一个不同的异常。如果你想告诉用户实际问题是什么,使用 Response 至少你有一些上下文。

这个问题已经过时了,但最好防止其他人重蹈覆辙...

而不是

result = target
            .request()
            .accept(MediaType.APPLICATION_JSON)
            .post(Entity.entity(input, MediaType.APPLICATION_JSON))
            .readEntity(Releases.class);

post(entity) return 一个 Response 在上面调用 readEntity,最好使用重载的 post(entity, responseType) 会抛出 WebApplicationException错误状态代码。

// throws runtime exception derived from WebApplicationException
// on error-statuscodes
result = target
            .request()
            .accept(MediaType.APPLICATION_JSON)
            .post(Entity.entity(input, MediaType.APPLICATION_JSON), Releases.class);

JAX-RS 中的每个 http 方法都有这样的重载方法来读取响应或表示对象。强烈建议读取表示对象以在任何情况下消耗潜在的响应主体。

// consumes response as string and guarantees to close the http call.
// A no-arg delete(); would be a potential leak!
target.request().delete(String.class); 

不幸的是,当必须读取响应头时,仍然需要读取 Response 而不是表示对象。