46

I am working on building a REST api. My question is, when using Jersey, what are the differences between my services building and returning a Response object or returning the the bean or collection. I am only concerned with successful calls, I am throwing appropriate exceptions for errors and exceptional situations.

Here is a example:

@Produces(MediaType.APPLICATION_JSON)
public Response search(FooBean foo){
    List<FooBean> results = bar.search(foo);
    return Response.ok(results).build();
}

vs.

@Produces(MediaType.APPLICATION_JSON)
public List<FooBean> search(FooBean foo){
    List<FooBean> results = bar.search(foo);
    return results;
}

I've seen both examples used, and I'd prefer the second scenario, just to make it easier to recognize the service method. I've examined the responses to both of these methods and they appear to be identical.

Thoughts?

4

3 回答 3

41

JAX-RS 规范中解释了这些差异:

3.3.3 返回类型

资源方法可以返回 void、Response、GenericEntity 或其他 Java 类型,这些返回类型映射到响应实体主体,如下所示:

void
产生一个带有 204 状态代码的空实体主体。

响应
生成从响应的实体属性映射的实体主体,其状态代码由响应的状态属性指定。空返回值导致 204 状态代码。如果未设置 Response 的状态属性:非空实体属性使用 200 状态码,如果实体属性为空,则使用 204 状态码。

GenericEntity
生成从 GenericEntity 的 Entity 属性映射的实体主体。如果返回值不为空,则使用 200 状态代码,空返回值将导致 204 状态代码。

其他
生成从返回实例的类映射的实体主体。如果返回值不为空,则使用 200 状态代码,空返回值将导致 204 状态代码。

需要为响应提供额外元数据的方法应该返回一个 Response 实例, ResponseBuilder 类提供了一种使用构建器模式创建 Response 实例的便捷方法。

'常规' bean 的映射方式几乎与原来的方式相同Response,除了 aResponse允许您设置其他元数据(响应标头、专用状态、专用内容类型等)。至于使用哪一个,这完全取决于你自己决定——Response给你更多的灵活性,但普通的 bean 更“自我记录”。

于 2013-05-03T05:18:16.120 回答
8

如果您想始终返回 response 200 - OK,捕获和操作在您的方法返回结果之前或之后可能发生的所有异常,使用拦截或WebApplicationException. 因此,这两种方法都会产生相同的响应。

唯一的区别是在特定的场景下,比如返回空对象,或者创建对象,比如这个例子:

@POST
@Consumes("application/json")
public Response post(String content) {
    URI createdUri = ...
    Object createdContent = create(content);
    return Response.created(createdUri).entity(createdContent).build();
}

在这种情况下,返回将是201 - CREATED(使用 URI 访问创建的对象)

所以,下面的方法:

@POST
@Consumes("application/json")
public Object post(String content) {
    URI createdUri = ...
    Object createdContent = create(content);
    return createdContent;
}

...将返回响应200 - OK

如果您不关心您的客户将收到哪种响应状态,您可以毫无问题地使用任何声明。

资料来源:泽西岛

于 2013-05-02T21:56:18.817 回答
4

我个人的看法是,如果响应包含 DTO(bean/bean 集合),那么 rest 服务总是必须返回 DTO,而不是 Response 对象。

动机:早晚都会要求您通过提供rest客户端api来使客户更容易使用rest服务。通常,您必须为其提取休息接口,并使用您的休息服务实现它们。这些休息接口由您的休息客户端的客户端使用。

从客户端的角度来看,处理 DTO 和普通响应之间存在巨大差异。如果使用 Response ,您的客户端将被强制:

  1. 明确检查响应代码以处理成功的响应
  2. 通过明确检查代码来处理错误
  3. 自己将您的响应正文转换为 DTO。

这意味着处理 Response 与在方法中返回错误代码非常相似,这被认为是一种非常糟糕的做法。为了在一个地方处理错误,使用了异常(我不是在谈论处理错误的 FP 方式,这是最好的)。

那么你可以做什么:

  1. 如果请求处理成功,则将您的其余服务数据转换为 DTO/Bean 并返回。
  2. 如果验证失败或出现问题,请在您的休息服务中抛出异常。也许默认的异常映射器对您不利,因此,您必须实现自己的异常映射器。

所以如果要提前考虑,你应该返回DTO。

一个用例,当应返回纯响应时 - 例如,当您导出文件时。似乎 JAX RS 不允许返回 InputStream 对象。不确定,必须检查。

@Perception 指出了另一个用例,但它更像是一个例外,而不是规则:

需要为响应提供附加元数据的方法应该返回一个 Response 实例,ResponseBuilder 类提供了一种使用构建器模式创建 Response 实例的便捷方法。

注意:这是 JAX RS 的一般问题,不依赖于确切的实现,如 Resteasy 或 Jersey

于 2017-05-29T08:00:43.640 回答