前端视角 Java Web 入门手册 5.3:真实世界 Web 开发——RESTful API 与 Spring MVC

RESTful API 设计指南 - 阮一峰的网络日志

RESTful API 最佳实践 - 阮一峰的网络日志

RESTful API 设计规范

REST(Representational State Transfer)是一种软件架构风格,用于设计可扩展的网络应用程序。RESTful API 根据 REST 原则构建,旨在利用现有的网络协议(特别是 HTTP)来创建高效、可扩展和易于维护的接口。RESTful API 包含一些关键设计规范和最佳实践:

1. 资源导向

所有的实体(如用户、订单、产品)都被视为资源,每个资源通过唯一的 URI(统一资源标识符)进行标识

plain 复制代码
https://api.example.com/users
https://api.example.com/orders/{id}
https://api.example.com/products/{id}

在RESTful架构中,每个网址代表一种资源(resource),所以网址中不能有动词。一般来说,数据库中的表都是同种记录的"集合"(collection),所以 API 中的名词也应该使用复数。

2. 使用标准的 HTTP 方法

  • GET:检索资源。例如,GET /users 获取用户列表,GET /users/{id} 获取特定用户。
  • POST:创建新资源。例如,POST /users 创建新用户。
  • PUT:更新资源的全部内容。例如,PUT /users/{id} 更新特定用户的所有信息。
  • PATCH:部分更新资源。例如,PATCH /users/{id} 部分更新用户信息。
  • DELETE:删除资源。例如,DELETE /users/{id} 删除特定用户。

3. 版本控制

通过 URI 版本号或其他方式管理 API 的版本,确保向后兼容。例如:

  • /v1/users
  • /api/v2/orders

4. 分页、过滤和排序

对于返回大量数据的 API,提供分页、过滤和排序功能,以提高性能和用户体验。例如:

ini 复制代码
GET /users?page=2&size=20&sort=name,asc
GET /products?category=electronics&price_lt=500

5. 返回结果

针对不同操作,服务器向用户返回的结果应该符合以下规范。

plain 复制代码
GET /collection:返回资源对象的列表(数组)
GET /collection/resource:返回单个资源对象
POST /collection:返回新生成的资源对象
PUT /collection/resource:返回完整的资源对象
PATCH /collection/resource:返回完整的资源对象
DELETE /collection/resource:返回一个空文档

Spring MVC

Spring MVC 是 Spring 框架中的一个模块,专门用于构建 Web 应用程序,借助 Spring MVC,开发者可以方便地创建 RESTful 风格的 Web 服务

控制器

在 RESTful 服务中,控制器负责处理 HTTP 请求,并返回资源表示。Spring MVC 提供了多个注解来简化这一过程

  • @RestController:表示控制器中的所有方法默认返回 JSON 或 XML 数据,而不是视图
  • @RequestMapping:将特定的 HTTP 请求路径和方法与控制器的方法关联起来,实现资源的操作。为了简化常用的HTTP方法映射,Spring MVC提供了一系列快捷注解,如 @GetMapping、@PostMapping 等
java 复制代码
@RestController
@RequestMapping("/api/users")
public class UserController {

    // 继承类级别的基础路径 /api/users
    @GetMapping
    public List<User> getAllUsers() {
        // 获取所有用户
    }

    @GetMapping("/{id}")
    public User getUserById(@PathVariable Long id) {
        // 根据 ID 获取用户
    }

    @PostMapping
    public User createUser(@RequestBody User user) {
        // 创建新用户
    }

    @PutMapping("/{id}")
    public User updateUser(@PathVariable Long id, @RequestBody User user) {
        // 更新用户信息
    }

    @DeleteMapping("/{id}")
    public void deleteUser(@PathVariable Long id) {
        // 删除用户
    }
}

请求与响应

  • @RequestBody:将HTTP请求体中的JSON或XML数据绑定到方法参数中。
  • @PathVariable:从URL路径中提取变量。
  • @RequestParam:从查询参数(query)中提取变量。
  • @ResponseStatus:用于为方法或异常类设置HTTP响应状态码
java 复制代码
@PutMapping("/users/{id}")
@ResponseStatus(HttpStatus.CREATED)
public User updateUser(@PathVariable Long id, @RequestBody User user) {
    // 方法实现
}

简单 demo

java 复制代码
@RestController
@RequestMapping("/api/users")
public class UserController {

    private final Map<Long, User> userRepository = new ConcurrentHashMap<>();

    @GetMapping
    public Collection<User> getAllUsers() {
        return userRepository.values();
    }

    @GetMapping("/{id}")
    public ResponseEntity<User> getUserById(@PathVariable Long id) {
        User user = userRepository.get(id);
        if (user != null) {
            return ResponseEntity.ok(user);
        } else {
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
        }
    }

    @PostMapping
    public ResponseEntity<User> createUser(@RequestBody User user) {
        user.setId(System.currentTimeMillis());
        userRepository.put(user.getId(), user);
        return ResponseEntity.status(HttpStatus.CREATED).body(user);
    }

    @PutMapping("/{id}")
    public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody User user) {
        if (userRepository.containsKey(id)) {
            user.setId(id);
            userRepository.put(id, user);
            return ResponseEntity.ok(user);
        } else {
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
        }
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
        if (userRepository.containsKey(id)) {
            userRepository.remove(id);
            return ResponseEntity.noContent().build();
        } else {
            return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
        }
    }
}
相关推荐
pianmian11 小时前
类(JavaBean类)和对象
java
我叫小白菜1 小时前
【Java_EE】单例模式、阻塞队列、线程池、定时器
java·开发语言
Albert Edison2 小时前
【最新版】IntelliJ IDEA 2025 创建 SpringBoot 项目
java·spring boot·intellij-idea
超级小忍2 小时前
JVM 中的垃圾回收算法及垃圾回收器详解
java·jvm
weixin_446122462 小时前
JAVA内存区域划分
java·开发语言·redis
Piper蛋窝3 小时前
深入 Go 语言垃圾回收:从原理到内建类型 Slice、Map 的陷阱以及为何需要 strings.Builder
后端·go
勤奋的小王同学~3 小时前
(javaEE初阶)计算机是如何组成的:CPU基本工作流程 CPU介绍 CPU执行指令的流程 寄存器 程序 进程 进程控制块 线程 线程的执行
java·java-ee
TT哇3 小时前
JavaEE==网站开发
java·redis·java-ee
2401_826097623 小时前
JavaEE-Linux环境部署
java·linux·java-ee
缘来是庄3 小时前
设计模式之访问者模式
java·设计模式·访问者模式