RESTful之Content negotiation

Content negotiation

Content negotiation

Content negotiation means allowing different representations of a resource in the

same URI so that clients can make a choice on what suits them best.

"HTTP has provisions for several mechanisms for "content negotiation" - the

process of selecting the best representation for a given response when there are

multiple representations available."

– RFC 2616, Fielding et al.

There are different patterns for content negotiation.

These are as follows:

? Using HTTP headers

? Using URL patterns

Content negotiation using HTTP headers

When the client sends requests to create or update a resource, there is some form

of payload that should be transferred from the client to the endpoint. Also, when

a response is generated, a payload can be sent back to the client. These payloads

are handled by HTTP request and response entities, which are sent as part of the

HTTP messages body.

Entities are sent via a request, usually for HTTP
POST and
PUT methods, or they

are returned in a response for the HTTP methods. The Content-Type HTTP header

is used to indicate the MIME type of the entity being sent by the server. Common

examples of content types are "text/plain",
"application/xml",
"text/html",

"application/json",
"image/gif", and
"image/jpeg".

A client can make a request to the server and specify what media types it can

handle and what is its order of preference as part of the
"Accept" HTTP header.

The client can also specify in what language it wants the response as part of the

"Accept-Language"
header to be. If no Accept
header is present in the request,

the server can send the representation it chooses.

The JAX-RS specification provides standard annotations to support content

negotiation. These are javax.ws.rs.Produces
and javax.ws.rs.Consumes

annotations. The following snippet shows an example of the
@Produces

annotation in a resource method:

@GET
@Path("orders")
@Produces(MediaType.APPLICATION_JSON)
public List<Coffee> getCoffeeList(){
return CoffeeService.getCoffeeList();
}

The getCoffeeList()
method returns a list of coffees and is annotated with

@Produces(MediaType.APPLICATION_JSON). The
@Produces
annotation is used

to specify which MIME types the resource can send back to the client and match

it up to the client‘s Accept
header.

This
method will produce a response as shown:

X-Powered-By: Servlet/3.1 JSP/2.3 (GlassFish Server Open Source
Edition 4.0 Java/Oracle Corporation/1.7)
Server: GlassFish Server Open Source Edition 4.0
Content-Type: application/json
Date: Thu, 31 Jul 2014 15:25:17 GMT
Content-Length: 268
{
"coffees": [
{
"Id": 10,
"Name": "Cappuchino",
"Price": 3.82,
"Type": "Iced",
"Size": "Medium"
},
{
"Id": 11,
"Name": "Americano",
"Price": 3.42,
"Type": "Brewed",
"Size": "Large"
}
]
}

In a resource, if no methods are able to produce the MIME type requested
by a client

request, the JAX-RS runtime sends back an HTTP 406 Not Acceptable
error.

The following snippet shows a resource method annotated with the

@Consumes
annotation:

@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response addCoffee(Coffee coffee) {
// Implementation here
}

The @Consumes
annotation specifies which media types the resource can consume.

When a client makes a request, JAX-RS finds all the methods that will match the path,

and it will then invoke the method based on the content type sent by the client.

If a resource is unable to consume the MIME type of a client request, the JAX-RS

runtime sends back an HTTP 415 ("Unsupported Media Type")
error.

Multiple MIME types can be specified in the
@Produces
or @Consumes
annotation

as @Produces(MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML).

Along with the support for static content negotiation, JAX-RS also contains runtime

content negotiation support using the javax.ws.rs.core.Variant
class and the

javax.ws.rs.core.Request
objects. A Variant
object in a JAX-RS specification

is a combination of media types, content-language, and content encoding as well

as ETags, last-modified headers, and other preconditions. The
Variant object

defines the resource representation that is supported by the server. The
Variant.

VariantListBuilder class is used to build a list of representation variants.

The following code snippet shows how to create a list of resource representation

variants:

List<Variant> variants = Variant.mediatypes("application/xml",
"application/json").build();

The code snippet calls the build method of the
VariantListBuilder
class.

The Request.selectVariant
method takes a list of Variant
objects and chooses

the one based on the client‘s Accept
header, as shown in the following snippet:

@GET
public Response getCoffee(@Context Request r) {
List<Variant> vs = ...;
Variant v = r.selectVariant(vs);
if (v == null) {
return Response.notAcceptable(vs).build();
} else {
Coffee coffee = ..//select the representation based on v
return Response.ok(coffee, v);
}
}

Content negotiation based on URL patterns

Another approach for content negotiation adopted by some APIs is to send the

resource representation based on the extension of a resource in the URL. For

example, a client can ask for details using http://foo.api.com/v2/library/

books.xml or
http://foo.api.com/v2/library/books.json. The server has

different methods, which can handle the two URIs. However, both of these are

representations of the same resource.

	@Path("/v1/books/")
	public class BookResource {

	@Path("{resourceID}.xml")
	@GET
	public Response getBookInXML(@PathParam("resourceID") String
	resourceID) {
	//Return Response with entity in XML
	}
	@Path("{resourceID}.json")
	@GET
	public Response getBookInJSON(@PathParam("resourceID") String
	resourceID) {
	//Return Response with entity in JSON
	}
	}

As you can see in the preceding snippet, there are two methods defined:

getBookInXML()
and getBookInJSON(), and the response is returned based

on the path of the URL.

It is a good practice to use the HTTP content negotiation
Accept

header. Using headers for content negotiation provides a clear

separation of IT concerns from business. The other advantage with

using the Accept
header for content negotiation is that there is

only one resource method for all the different representations.

读书笔记:RESTful Java Patterns and Best Practices

时间: 2024-11-06 20:24:26

RESTful之Content negotiation的相关文章

WebApi2官网学习记录---Content Negotiation

Content Negotiation的意思是:当有多种Content-Type可供选择时,选择最合适的一种进行序列化并返回给client. 主要依据请求中的Accept.Accept-Charset.Accept-Encoding.Accept-Language这些属性决定的,但也会查看其它属性 如,如果请求中包含“ X-Requested-With”(ajax请求),在没哟其它Accept时,则使用JSON. Content Negotiation的工作原理 首先,pipeline从Http

Asp.Net Web API 2第十四课——Content Negotiation(内容协商)

前言 阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.html 本文描述ASP.NET Web API如何实现内容协商. HTTP规范(RFC 2616)将内容协商定义为“在有多个表现可用时,为一个给定的响应选择最佳表现的过程”.在HTTP中内容协商的主要机制是以下请求报头: Accept:响应可接收的媒体类型,如“application/json”.“application/xml”,

使用Spring MVC编写RESTful Controller

1.Spring对REST的支持 Spring3(这里讨论Spring3.2+)对Spring MVC的一些增强功能为REST提供了良好的支持.Spring对开发REST资源提供以下支持: 操作方式:控制器可以处理所有的HTTP方法,包含4个主要的REST方法:GET.PUT.DELETE以及POST.Spring的表单绑定JSP标签库的<form:form>标签以及新的HiddenHttpMethodFilter,使得通过HTML表单提交的PUT和DELETE请求成为可能 资源标识:新的@P

?Jersey 开发RESTFUL服务器

?Jersey 开发RESTFUL服务器 RESTful 一种软件架构风格,设计风格而不是标准,只是提供了一组设计原则和约束条件.它主要用于客户端和服务器交互类的软件.基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制. REST(英文:Representational State Transfer,简称REST)描述了一个架构样式的网络系统,比如 web 应用程序.REST相比于SOAP(Simple Object Access protocol,简单对象访问协议)以及XML-R

学习RESTFul架构

一.RESTFul介绍 1.一种软件架构风格,设计风格而不是标准,只是提供了一组设计原则和约束条件.它主要用于客户端和服务器交互类的软件.基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制. REST(英文:Representational State Transfer,简称REST)描述了一个架构样式的网络系统,比如 web 应用程序.它首次出现在 2000 年 Roy Fielding 的博士论文中,他是 HTTP 规范的主要编写者之一.在目前主流的三种Web服务交互方案中,R

《RESTful Web APIs中文版》

<RESTful Web APIs中文版> 基本信息 原书名:RESTful Web APIs 原出版社: O'Reilly Media 作者: Leonard Richardson    Mike Amundsen 译者: 赵震一 李哲 出版社:电子工业出版社 ISBN:9787121231155 上架时间:2014-6-11 出版日期:2014 年6月 开本:16开 页码:382 版次:1-1 所属分类:计算机 > 计算机网络 > Web Server > WebServ

SpringMVC之Restful

Spring MVC本身对Restful支持非常好.它的@RequestMapping.@RequestParam.@PathVariable.@ResponseBody注解很好的支持了REST. 1. @RequestMapping @RequestMapping 方法注解指定一个请求的URI映射地址. 类似于struts的action-mapping,同时可以指定POST或者GET请求类型. @RequestMapping("/owners/{ownerId}", method=R

Restful API 的设计规范

Restful API 的设计规范 1. URI URI规范 资源集合 vs 单个资源 避免层级过深的URI 对Composite资源的访问 2. Request HTTP方法 安全性和幂等性 复杂查询 Bookmarker Format Content Negotiation 6. Response 分页response 7. 错误处理 8. 服务型资源 9. 异步任务 10. API的演进 版本 URI失效 11. 安全 参考文档 本文总结了 RESTful API 设计相关的一些原则,只覆

RESTful API规范

RESTful 规范指南: 1. HTTP 协议 API 与用户的通信协议, 总是使用 HTTPS 协议 2. 域名: # 子域名方式:(解决跨域的问题) www.baidu.com api.baidu.com # 存在跨域的风险         # ========================================= # URL 方式: www.baidu.com www.baidu.com/api/ 3. 版本: URL  如: https://api.baidu.com/v1