第 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 实现(如 FileSystemResourceGridFsResource)。

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 文档片段,确保文档与实现同步。典型流程:

  1. 在测试中通过 MockMvc 触发 API 调用,捕获请求与响应。
  2. 生成 AsciiDoctor 片段,集成到主文档。
  3. 构建时自动生成 HTML/PDF 文档,并可集成到 Spring Boot 静态资源目录。

REST 客户端与自动化测试

开发与测试阶段推荐使用多种 REST 客户端工具:

  • 浏览器插件(如 Poster、Postman、Advanced REST Client)
  • 命令行工具(如 curl、httpie)
  • Spring 的 RestTemplate、WebClient、Traverson 等编程客户端

Spring 的 RestTemplate 支持内容协商、拦截器、泛型响应等高级特性,便于自动化测试和集成。

总结

本章系统梳理了 REST API 的设计与实现,从成熟度模型、内容协商、二进制处理、超媒体、错误处理、版本管理到自动化文档与客户端集成,全面覆盖了云原生服务接口的核心技术要素。通过合理设计和自动化实践,开发者可持续提升 API 的可维护性、可演进性和开发效率。

文章导航

独立页面

这是书籍中的独立页面。

书籍首页

评论区