内容协商(Content Negotiation)指的是客户端与服务端在进行数据交换的时候,通过某种机制来协商数据如何展示的机制。一般在HTTP协议中,内容协商机制主要是通过请求头中的Accept参数字段来实现设置的。也就是说客户端在发送请求的时候可以指定需要处理的数据格式,然后再服务端这边会根据其需要的数据结构来生成相应的数据进行反馈。
而在SpringBoot中要想实现接口内容协商的功能,我们就可以使用Accept请求头来实现,下面我们就来看看在SpringBoot中如何实现接口内容协商功能。
添加依赖
首先需要确保在项目中添加了相关的数据处理依赖,如下所示包含了Jackson(用于 JSON 处理)和Jackson-dataformat-xml(用于 XML 处理)。
<!-- 在 pom.xml 中添加 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
配置内容协商
接下就是需要添加对于请求头的过滤信息,可以通过
ContentNegotiationConfigurer 来配置内容协商的处理,如下所示。
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer
.defaultContentType(MediaType.APPLICATION_JSON) // 默认返回 JSON
.favorParameter(true) // 启用 URL 参数支持
.parameterName("mediaType") // URL 参数名称
.ignoreAcceptHeader(false) // 不忽略 Accept 头
.useRegisteredExtensionsOnly(false) // 允许文件扩展名
.mediaType("json", MediaType.APPLICATION_JSON)
.mediaType("xml", MediaType.APPLICATION_XML);
}
}
创建控制器
我们可以创建一个Controller用来测试内容协商的效果。
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api")
public class MyController {
@GetMapping(value = "/greeting", produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE})
public Greeting greeting() {
return new Greeting("Hello, World!");
}
public static class Greeting {
private String message;
public Greeting(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
}
测试
我们可以通过如下的两种方式来测试内容协商的效果。如下所示。
使用Accept 头
curl -H "Accept: application/json" http://localhost:8080/api/greeting
curl -H "Accept: application/xml" http://localhost:8080/api/greeting
使用用 URL 参数
curl http://localhost:8080/api/greeting?mediaType=json
curl http://localhost:8080/api/greeting?mediaType=xml
上面我们分别通过请求头参数和请求参数来测试了内容协商的功能,也看出了内容协商的重要性。
总结
在实际开发过程中,有些API可能既可以被网页调用,也要被移动端调用,而在不同的客户端调用的时候可能会涉及到不同数据可是的响应,通过内容协商机制就可以很完美的解决这个问题。上面的示例只是一个简单的示例,在实际的开发工作中我们还需要结合具体的操作来处理请求头中的信息,来提供更加完美的API接口。