当前位置: 首页 > 知识库问答 >
问题:

在所有JSON生成endpoint上使用@produces(“application/JSON”)是一种好的做法吗?

岑驰
2023-03-14

我们开始对前端代码使用的内部RESTendpoint使用Jersey/JAX-RS。必须返回结果的endpoint总是发送JSON对象。

出于调试目的,我们使用firefox restclient扩展。直到最近,我只需输入URL并单击send,就会得到显示为JSON的内容。

但是当我今天早上这样做的时候,FF扩展返回并告诉我必须将响应类型更改为二进制(BLOB)。这样做会导致显示编码字符串而不是JSON。

问题:真的那么简单吗?还是有很好的技术理由不这么做?

共有1个答案

陆正德
2023-03-14

为了内容协商和HTTP协议的正确性,您应该始终声明@produces@consumes注释(无论是在类级别还是方法级别)。如果没有这些注释,结果将依赖于客户机请求和服务器的默认行为(在不同的实现中可能有所不同),这将导致不可预测和不明确的结果。

有了这些注释,我们就可以宣传我们可以生产和消费的媒体类型。在Retrieve(GET)请求上,客户端应该发送Accept标头,其中包含它们期望返回的资源的媒体类型。在创建请求(PUT、POST)时,客户端应该发送content-type标头,告诉服务器它们发送的数据是哪种媒体类型。如果这些头与服务器广告要处理的内容不匹配,那么客户机将返回错误响应,告诉他们问题所在;对于Retrieve请求和不匹配的Accept标头,响应将是406不可接受。对于创建请求和不匹配的content-type标头,响应将是415不支持的媒体类型。

这就是内容协商的工作原理。为了确保我们的服务器按照客户机期望的行为,我们应该声明我们可以在服务器上处理什么。注释就是这样做的。

正如您所提到的,当您停止@produces时,客户机告诉您需要更改响应类型。这是因为结果是content-type响应头被设置为application/octet-stream,这就是本文答案的结论。客户端使用content-type标头来确定如何处理响应。

最后一个示例用于检索请求。如果我们在创建endpoint上不使用@consumes,就会出现许多不同的问题。例如,我们有一个希望接受JSON的endpoint,所以我们创建一个POJO来映射JSON。

@POST
public Response create(Customer customer) {}

要做到这一点,取决于客户机在对application/json的请求中设置content-type标头。但是如果没有@consumes注释,我们基本上是在宣传这个endpoint能够接受任何媒体类型,这太荒谬了。@consumes注释的作用就像一个警卫,说“如果不发送正确类型的数据,就不能通过”。但是由于我们没有保护,所有数据都可以通过,结果是不可预测的,因为根据客户机将Content-Type设置为什么,我们不知道MessageBodyReader1将如何处理从实体主体到Customer的转换。如果没有选择正确的MessageBodyReader(将JSON转换为POPJOs的那个),那么很可能会导致异常,客户机将返回一个500内部服务器错误,这不像得到一个415不受支持的媒体类型那么具体。

1。参见泽西岛文件第8章和第9章。它将解释如何分别使用MessageBodyReaderMessageBodyWriter将实体主体转换为Java对象(反之亦然)。

 类似资料:
  • 问题内容: 我们开始将Jersey / JAX-RS用于内部REST端点,这些端点被我们的前端代码使用。必须返回结果的端点始终发送JSON对象。 出于调试目的,我们使用了firefox restclient扩展。直到最近,我才输入URL并单击send,然后返回显示为JSON的内容。 但是,当我今天早上这样做时,FF扩展名又回来了,并告诉我必须将响应类型更改为二进制(BLOB)。这样做会导致显示编码

  • 问题内容: 使用JQuery或任何其他类似框架从自定义URL / Web服务中加载HTML内容非常容易。到目前为止,我已经使用了很多次这种方法,并且发现性能令人满意。 但是所有书籍,所有专家都试图让我使用JSON而不是生成的HTML。它比HTML优越得多吗? 它快很多吗? 它在服务器上的负载是否要小得多? 另一方面,我有一些使用生成的HTML的原因。 它是简单的标记,通常与JSON一样紧凑或实际上

  • 我有一个枚举: 在枚举成员之间使用方法检查“层次结构”有什么问题吗?我的意思是-当有人将来可能会意外更改顺序时,使用它排除冗长是否有任何缺点。 还是这样做更好:

  • 我有一个IntentService,它使用TimerTask每隔45秒在OnHandleContent中调用webservice。 我的问题是:我正在调用应用程序启动IntentService,而在OnHandleIntent中,由于TimerTask,任务不断重复。。这样做是一种好做法还是有任何缺点?我应该在我的活动中使用报警管理器每次调用intent service,还是继续使用timer任务

  • 问题内容: 如果使用Sun的专有Java类,则编译器将显示警告。我认为使用这些类通常不是一个好主意。我在某处阅读过。但是,除了警告之外,还有其他根本原因不建议您使用它们? 问题答案: 因为它们是内部API,所以它们可能会以未记录或不受支持的方式进行更改,并且已绑定到特定的JRE / JDK(在您的情况下为Sun),从而限制了程序的可移植性。 尽量避免使用此类API,请始终偏爱公开记录和指定的类。

  • 在Android上,有两种可能的方式通过广播接收器收听系统事件: 静态地,通过清单 由于一些项目包含大量活动、服务和“管理器”类,因此使用一个BroadcastReceiver通知应用程序上的所有侦听器所发生的事情,而不是使用多个BroadcastReceiver(以及它们的代码处理),可能会很有用。 这种广播接收器的一个示例是侦听连接更改的接收器: 目的是在应用程序处于活动状态时(通过服务和/或