RESTful 编程风格实践

一、什么是 RESTful

RESTful (Representational State Transfer,表述性状态转移)是一种 Web 服务接口的设计风格,它定义了一组约束和规范,使得 Web 服务接口更加简洁、易懂、可扩展且易于维护。 在 REST 架构中,“表述性” 指的是通过 URI(Uniform Resource Identifier)加上 HTTP 方法来唯一定位和操作某个资源;“状态转移” 指的是客户端通过不同的请求方式(GET/POST/PUT/DELETE 等)来改变服务器端的资源状态。

RESTful 对一个 Web 服务接口的规范,主要体现在以下几个方面:

  1. URL 设计

    • 资源(Resource)的 URI 应该名词化,且能体现资源层级关系。例如:

      • 查询单个用户:GET /user/{id}

      • 查询所有用户:GET /user

      • 新增用户:POST /user

      • 更新用户:PUT /user/{id}PUT /user(视具体实现而定)

      • 删除用户:DELETE /user/{id}

  2. HTTP 方法(Method)

    • 查询资源: GET

    • 创建(新增)资源: POST

    • 更新(修改)资源: PUTPATCH

    • 删除资源: DELETE

  3. 数据格式

    • 请求与响应的数据格式通常使用 JSON 或 XML。

    • 通过 HTTP 头 Content-TypeAccept 来声明请求体与响应体的格式,例如:

      Content-Type: application/json
      Accept: application/json
  4. HTTP 状态码

    • 通过恰当的 HTTP 状态码来表达操作结果,如:

      • 200 OK:请求成功,通常用于 GET、PUT、DELETE 操作。

      • 201 Created:资源创建成功(POST 操作)。

      • 204 No Content:操作成功但无返回内容(DELETE 或 PUT 操作可用)。

      • 400 Bad Request:客户端请求错误,例如参数校验失败。

      • 404 Not Found:资源不存在。

      • 415 Unsupported Media Type:请求的 Content-Type 不被支持。

      • 500 Internal Server Error:服务器内部错误。

总之,RESTful 风格的核心 在于:通过 “统一资源标识符(URI)+ 合理的 HTTP 方法” 来定位和操作资源,从而使接口语义更加直观、一致且易于扩展。


二、RESTful 与传统接口的对比

传统接口(基于方法名)RESTful 接口(基于资源)
GET /getUserById?id=1GET /user/1
GET /getAllUserGET /user
POST /addUserPOST /user
POST /modifyUserPUT /user (或 PUT /user/{id})
GET /deleteUserById?id=1DELETE /user/1

  1. URI 的表达方式

    • 传统接口中,URI 通常带有动词(getUserById、addUser、modifyUser、deleteUserById),并且使用查询参数传递 ID。

    • RESTful 接口中,URI 仅使用名词(user)并通过路径层级(/user/{id})区分单个资源或集合资源,操作类型由 HTTP 方法来区分。

  2. 操作语义更清晰

    • RESTful 将“查询”、“新增”、“修改”、“删除”操作分别映射到 GETPOSTPUT/PATCHDELETE,符合 HTTP 标准,语义一目了然。

    • 传统方式则将这些操作都用 GETPOST 实现,混淆了方法与操作的对应关系,不利于理解与维护。

  3. 可扩展性与可维护性

    • 当资源越来越多时,RESTful 通过统一的资源路径进行管理,接口层次清晰。

    • 传统接口随着业务增多往往会出现“getXXXById”、“getXXXList” 等大量方法,接口命名繁琐且易产生歧义。


三、Spring MVC 中的 RESTful 实现示例

下面通过 Spring MVC 的示例代码,演示如何在 Controller 中实现典型的 CRUD(增删改查)操作。假设项目包结构如下:

com.sangui.springmvc
├── controller
│   └── UserController.java
├── pojo
│   └── User.java
└── resources
  └── templates
      ├── index.html
      └── ok.html

说明

  1. 示例中视图层使用 Thymeleaf(即 .html 中带 th: 前缀),也可根据实际项目改为 JSP 或其他模板引擎。

  2. 需要在项目中引入 Spring MVC 和 Jackson 依赖,并在 Spring 配置中启用注解驱动:

    <mvc:annotation-driven />
  3. User 类示例(位于 com.sangui.springmvc.pojo.User):

    public class User {
       private String username;
       private String password;
       // getter、setter、toString 等省略
    }

3.1 根据 ID 查询 (GET /user/{id})

页面:index.html


<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
   <meta charset="UTF-8">
   <title>首页title>
head>
<body>
   <h1>RESTful 示例h1>
   
   <a th:href="@{/user/1}">查看用户 ID=1 的信息a>
body>
html>

Controller:UserController.java

package com.sangui.springmvc.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class UserController {

   /**
    * 根据 ID 查询用户信息
    * 访问示例:GET /user/1
    */
   @RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
   public ModelAndView getOne(@PathVariable("id") String id) {
       ModelAndView modelAndView = new ModelAndView();
       // 这里可以从数据库或服务层获取 User 对象,此处仅模拟示例
       modelAndView.addObject("msg", "查询到用户 ID = " + id + ",正在展示其详细信息……");
       modelAndView.setViewName("ok");
       return modelAndView;
  }
}

视图:ok.html


<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
   <meta charset="UTF-8">
   <title>操作成功title>
head>
<body>
   <h1>操作结果h1>
   <div th:text="${msg}">div>
body>
html>

效果说明

  1. 启动服务器后,访问 http://localhost:8080/springmvc/ 可以看到首页链接 “查看用户 ID=1 的信息”。

  2. 点击后会向后端发送 GET /user/1 请求,控制台会打印 “查询到用户 ID = 1,正在展示其详细信息……”,并返回 ok.html 页面。


3.2 查询所有用户 (GET /user)

当需要获取所有用户列表时,按照 RESTful 规范,发送 GET 请求到 /user 即可。示例如下:

Controller 中新增方法:

/**
* 查询所有用户
* 访问示例:GET /user
*/
@RequestMapping(value = "/user", method = RequestMethod.GET)
public ModelAndView getAll() {
   ModelAndView modelAndView = new ModelAndView();
   // 这里可以从数据库或服务层获取 User 列表,此处仅模拟示例
   modelAndView.addObject("msg", "查询所有用户列表,展示所有用户信息……");
   modelAndView.setViewName("ok");
   return modelAndView;
}

页面示例:


<a th:href="@{/user}">查看所有用户列表a>

效果说明

  1. 点击“查看所有用户列表”后,浏览器会发送 GET /user 请求。

  2. 后端处理后返回 ok.html,页面中会显示 “查询所有用户列表,展示所有用户信息……”。


3.3 新增用户 (POST /user)

按照 RESTful 规范,创建资源(新增用户)应使用 POST 方法,且请求体中携带用户的 JSON 或 x-www-form-urlencoded 表单数据。

示例:新增用户(使用 x-www-form-urlencoded)

  • Postman 配置

    • 方法:POST

    • URL:http://localhost:8080/springmvc/user

    • 选中 Body → x-www-form-urlencoded

      username=zhangsan
      password=11111
  • Controller 方法

    /**
    * 新增用户
    * 访问示例:POST /user
    * 如果不需要 JSON,只需要直接通过表单提交 username 和 password,可省略 @RequestBody
    */
    @RequestMapping(value = "/user", method = RequestMethod.POST)
    public ModelAndView addOne(User user) {
       ModelAndView modelAndView = new ModelAndView();
       // 控制台打印 user 对象的数据
       System.out.println("新增用户: " + user + ",添加成功。");
       modelAndView.addObject("msg", "新增用户: " + user + ",添加成功。");
       modelAndView.setViewName("ok");
       return modelAndView;
    }
    • 解释:此处直接将 User user 作为参数,Spring MVC 会自动将 x-www-form-urlencoded 表单中的 usernamepassword 绑定到 User 对象上,无需使用 @RequestBody

效果说明

  1. 在 Postman 里发送上述请求后,服务端控制台会打印:

    新增用户: User{username='zhangsan', password='11111'},添加成功。
  2. 前端会返回 ok.html,页面中显示 “新增用户: User{username='zhangsan', password='11111'},添加成功。”


3.4 修改用户 (PUT /user)

修改资源时,RESTful 规范建议使用 PUT 方法,并通过请求体提交 JSON 数据或者 x-www-form-urlencoded 表单数据。但在 Spring MVC 中,如果直接使用 @RequestBody 并发送 application/json,必须确保项目已配置 Jackson,才能实现 JSON 自动反序列化。

3.4.1 使用 JSON 和 @RequestBody

  1. 添加 Jackson 依赖(以 Maven 为例)


    <dependency>
       <groupId>com.fasterxml.jackson.coregroupId>
       <artifactId>jackson-databindartifactId>
       <version>2.15.2version>
    dependency>

    如果项目是 Spring Boot,只需引入 spring-boot-starter-web,它会自动包含 Jackson。

  2. Controller 方法

    /**
    * 修改用户信息
    * 访问示例:PUT /user
    * 请求头:Content-Type: application/json
    * 请求体示例(raw、JSON):
    * {
    *     "username": "zhangsan",
    *     "password": "222"
    * }
    */
    @RequestMapping(value = "/user", method = RequestMethod.PUT)
    public ModelAndView updateOne(@RequestBody User user) {
       ModelAndView modelAndView = new ModelAndView();
       System.out.println("更新用户: " + user + ",修改成功。");
       modelAndView.addObject("msg", "更新用户: " + user + ",修改成功。");
       modelAndView.setViewName("ok");
       return modelAndView;
    }
  3. Postman 配置

    • 方法:PUT

    • URL:http://localhost:8080/springmvc/user

    • 选中 Body → raw → JSON,并填写:

      {
       "username": "zhangsan",
       "password": "222"
      }
    • 请求头会自动带上:

      Content-Type: application/json

注意事项

  • 如果出现 415 Unsupported Media Type 错误,通常是因为 Spring MVC 没有找到 MappingJackson2HttpMessageConverter 来解析 application/json,需要检查:

    1. 是否已经引入 Jackson 相关依赖(jackson-databind 等)。

    2. 是否启用了 (或在 Spring Boot 项目中无需额外配置)。

  • 如果无需 JSON,也可以改用 x-www-form-urlencoded,但在 PUT 请求中,Servlet 容器默认不会把 form 数据解析到 request.getParameter(),需要借助 HiddenHttpMethodFilter 或自定义过滤器,故更推荐使用 JSON + @RequestBody


3.5 删除用户 (DELETE /user/{id})

按 RESTful 规范,删除资源要使用 DELETE 方法,URI 中带上资源唯一标识(如 {id})。

Controller 方法

/**
* 删除用户
* 访问示例:DELETE /user/1
*/
@RequestMapping(value = "/user/{id}", method = RequestMethod.DELETE)
public ModelAndView deleteOne(@PathVariable("id") String id) {
   ModelAndView modelAndView = new ModelAndView();
   System.out.println("删除用户: ID = " + id + ",删除成功。");
   modelAndView.addObject("msg", "删除用户: ID = " + id + ",删除成功。");
   modelAndView.setViewName("ok");
   return modelAndView;
}

Postman 配置

  • 方法:DELETE

  • URL:http://localhost:8080/springmvc/user/1

  • 无需在 Body 里添加任何参数,点击发送即可。

效果说明

  1. 控制台会打印:

    删除用户: ID = 1,删除成功。
  2. 前端页面返回 ok.html,显示 “删除用户: ID = 1,删除成功。”


四、小结

  1. RESTful 架构风格核心

    • 通过“统一资源标识符(URI)”+“HTTP 方法”来定位并操作资源。

    • 语义清晰、符合 HTTP 标准,可读性和可维护性更高。

  2. Spring MVC 实现要点

    • 引入 Jackson(或使用 Spring Boot 自带的 JSON 解析器),并启用注解驱动:

      <mvc:annotation-driven />
    • 使用 @PathVariable 从 URI 中获取路径参数。

    • 使用 @RequestBody 将 JSON 请求体反序列化为 Java 对象。

    • 对于表单形式的 POST,可直接让 Spring MVC 将 x-www-form-urlencoded 参数绑定到方法入参的 POJO 上;对于 PUT、DELETE 等非 POST 请求,如果不使用 JSON,则需要额外配置(如 HiddenHttpMethodFilter)。

  3. 接口设计建议

    • URI 统一使用小写,使用短横线(-)或驼峰分隔资源名称;避免大小写混杂。

    • 合理使用 HTTP 状态码表示请求结果。

    • 返回值可选用 JSON 对象,以便前后端分离或移动端调用。

  • 微信
  • 赶快加我聊天吧
  • QQ
  • 赶快加我聊天吧
  • weinxin
三桂

发表评论 取消回复 您未登录,登录后才能评论,前往登录