第 6 章:云原生应用程序
本章系统梳理了 REST API 的成熟度模型、Spring MVC 实现 REST 服务的最佳实践、内容协商、二进制数据处理、超媒体(HATEOAS)、API 版本管理与自动化文档生成等关键技术,帮助开发者构建高质量、可演进的云原生服务接口。
伦纳德·理查森的 REST 成熟度模型
REST 的核心在于充分利用 HTTP 协议的动词(GET、PUT、POST、DELETE)和语义(如状态码、头部),描述业务状态变化。伦纳德·理查森提出了 REST 成熟度模型,用于衡量 API 的 RESTful 程度:
- 0 级:POX(Plain Old XML)
仅使用 HTTP 作为传输协议,通常只用 POST,未充分利用 HTTP 语义。典型如 SOAP、XML-RPC。 - 1 级:资源
使用多个 URI 区分资源,但未用好 HTTP 动词。 - 2 级:HTTP 动词
利用 HTTP 动词和状态码,提升 API 语义和一致性。大多数 Spring MVC/JAX-RS API 达到此级别。 - 3 级:超媒体(HATEOAS)
API 通过超媒体自描述,客户端无需预知服务内容即可导航和操作。
本章将以 Spring MVC 为例,介绍如何从 2 级起步,逐步实现更高阶的 REST API。
Spring MVC 实现 REST API
Spring MVC 通过 @RestController
和注解驱动的路由,简化了 REST 服务开发。以 Customer 实体为例,典型 REST 控制器结构如下(伪代码):
@RestController
@RequestMapping("/v1/customers")
public class CustomerRestController {
@Autowired
private CustomerRepository customerRepository;
@GetMapping
public ResponseEntity<Collection<Customer>> getCollection() { ... }
@GetMapping("/{id}")
public ResponseEntity<Customer> get(@PathVariable Long id) { ... }
@PostMapping
public ResponseEntity<Customer> post(@RequestBody Customer c) { ... }
@PutMapping("/{id}")
public ResponseEntity<Customer> put(@PathVariable Long id, @RequestBody Customer c) { ... }
@DeleteMapping("/{id}")
public ResponseEntity<?> delete(@PathVariable Long id) { ... }
}
- 通过
@RequestMapping
、@GetMapping
、@PostMapping
等注解映射 HTTP 动词和路径。 - 支持
@RequestBody
、@PathVariable
、@RequestParam
等参数绑定。 - 推荐返回
ResponseEntity
,便于自定义状态码和响应头。
内容协商与二进制数据处理
Spring MVC 支持内容协商,自动根据请求头 Accept
选择合适的 HttpMessageConverter
,实现 JSON、XML、Protobuf 等多格式响应。对于二进制数据(如图片、文件),可通过 Resource
类型和 MultipartFile
实现上传与下载。
@GetMapping("/customers/{id}/photo")
public ResponseEntity<Resource> readPhoto(@PathVariable Long id) { ... }
@PostMapping("/customers/{id}/photo")
public Callable<ResponseEntity<?>> uploadPhoto(@PathVariable Long id, @RequestParam MultipartFile file) { ... }
- 推荐异步处理大文件上传,避免阻塞 Servlet 线程池。
- 支持多种
Resource
实现(如FileSystemResource
、GridFsResource
)。
Google Protocol Buffers 与高效内容协商
为提升跨语言兼容性和性能,可通过 Google Protocol Buffers 实现高效二进制协议。Spring MVC 支持自定义 HttpMessageConverter
,自动处理 application/x-protobuf
类型。
- 使用
.proto
文件定义消息结构,生成多语言客户端代码。 - 通过内容协商,客户端可选择 JSON、XML 或 Protobuf 格式。
集中式错误处理
REST API 需统一错误响应格式。Spring MVC 支持 @ControllerAdvice
+ @ExceptionHandler
实现全局异常处理,推荐结合 Spring HATEOAS 的 VndError
格式:
@ControllerAdvice(annotations = RestController.class)
public class CustomerControllerAdvice {
@ExceptionHandler(CustomerNotFoundException.class)
public ResponseEntity<VndErrors> notFoundException(CustomerNotFoundException e) { ... }
}
- 统一返回 HTTP 状态码、错误码、详细信息,便于客户端自动处理。
超媒体(HATEOAS)与 HAL
HATEOAS(Hypermedia as the Engine of Application State)是 REST 的高级特性,API 通过超媒体链接自描述,客户端可动态导航。Spring HATEOAS 提供 Resource<T>
、Resources<T>
、Link
等类型,支持 HAL(Hypertext Application Language)协议。
@RestController
@RequestMapping(value = "/v2", produces = "application/hal+json")
public class CustomerHypermediaRestController {
@Autowired
private CustomerResourceAssembler customerResourceAssembler;
@GetMapping("/customers")
public ResponseEntity<Resources<Resource<Customer>>> getCollection() { ... }
}
- 通过
ResourceAssembler
自动为实体添加超媒体链接。 - HAL 浏览器等工具可自动发现和导航 API。
API 版本管理与演进
API 难免演进,需兼顾向后兼容和创新。常见版本管理方式:
- URL 路径中携带版本号(如
/api/v1/hi
) - 自定义请求头(如
X-API-Version
) - Accept 头中指定媒体类型(如
application/vnd.bootifuldemo-v1+json
)
Spring MVC 支持多种方式灵活路由和内容协商,推荐结合语义化版本控制,避免破坏性变更。
自动化 API 文档生成
高质量 API 需配套自动化文档。Spring REST Docs 结合测试生成 AsciiDoctor 文档片段,确保文档与实现同步。典型流程:
- 在测试中通过 MockMvc 触发 API 调用,捕获请求与响应。
- 生成 AsciiDoctor 片段,集成到主文档。
- 构建时自动生成 HTML/PDF 文档,并可集成到 Spring Boot 静态资源目录。
REST 客户端与自动化测试
开发与测试阶段推荐使用多种 REST 客户端工具:
- 浏览器插件(如 Poster、Postman、Advanced REST Client)
- 命令行工具(如 curl、httpie)
- Spring 的 RestTemplate、WebClient、Traverson 等编程客户端
Spring 的 RestTemplate 支持内容协商、拦截器、泛型响应等高级特性,便于自动化测试和集成。
总结
本章系统梳理了 REST API 的设计与实现,从成熟度模型、内容协商、二进制处理、超媒体、错误处理、版本管理到自动化文档与客户端集成,全面覆盖了云原生服务接口的核心技术要素。通过合理设计和自动化实践,开发者可持续提升 API 的可维护性、可演进性和开发效率。