RESTful 编程风格实践
RESTful (Representational State Transfer,表述性状态转移)是一种 Web 服务接口的设计风格,它定义了一组约束和规范,使得 Web 服务接口更加简洁、易懂、可扩展且易于维护。 在 REST 架构中,“表述性” 指的是通过 URI(Uniform Resource Identifier)加上 HTTP 方法来唯一定位和操作某个资源;“状态转移” 指的是客户端通过不同的请求方式(GET/POST/PUT/DELETE 等)来改变服务器端的资源状态。
RESTful 对一个 Web 服务接口的规范,主要体现在以下几个方面:
URL 设计
资源(Resource)的 URI 应该名词化,且能体现资源层级关系。例如:
查询单个用户:
GET /user/{id}
查询所有用户:
GET /user
新增用户:
POST /user
更新用户:
PUT /user/{id}
或PUT /user
(视具体实现而定)删除用户:
DELETE /user/{id}
HTTP 方法(Method)
查询资源:
GET
创建(新增)资源:
POST
更新(修改)资源:
PUT
或PATCH
删除资源:
DELETE
数据格式
请求与响应的数据格式通常使用 JSON 或 XML。
通过 HTTP 头
Content-Type
与Accept
来声明请求体与响应体的格式,例如:Content-Type: application/json
Accept: application/json
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=1 | GET /user/1 |
GET /getAllUser | GET /user |
POST /addUser | POST /user |
POST /modifyUser | PUT /user (或 PUT /user/{id}) |
GET /deleteUserById?id=1 | DELETE /user/1 |
URI 的表达方式
传统接口中,URI 通常带有动词(getUserById、addUser、modifyUser、deleteUserById),并且使用查询参数传递 ID。
RESTful 接口中,URI 仅使用名词(user)并通过路径层级(
/user/{id}
)区分单个资源或集合资源,操作类型由 HTTP 方法来区分。
操作语义更清晰
RESTful 将“查询”、“新增”、“修改”、“删除”操作分别映射到
GET
、POST
、PUT
/PATCH
、DELETE
,符合 HTTP 标准,语义一目了然。传统方式则将这些操作都用
GET
或POST
实现,混淆了方法与操作的对应关系,不利于理解与维护。
可扩展性与可维护性
当资源越来越多时,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
说明
示例中视图层使用 Thymeleaf(即
.html
中带th:
前缀),也可根据实际项目改为 JSP 或其他模板引擎。需要在项目中引入 Spring MVC 和 Jackson 依赖,并在 Spring 配置中启用注解驱动:
<mvc:annotation-driven />
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;
public class UserController {
/**
* 根据 ID 查询用户信息
* 访问示例:GET /user/1
*/
value = "/user/{id}", method = RequestMethod.GET) (
public ModelAndView getOne( ("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>
效果说明
启动服务器后,访问
http://localhost:8080/springmvc/
可以看到首页链接 “查看用户 ID=1 的信息”。点击后会向后端发送
GET /user/1
请求,控制台会打印“查询到用户 ID = 1,正在展示其详细信息……”
,并返回ok.html
页面。
3.2 查询所有用户 (GET /user)
当需要获取所有用户列表时,按照 RESTful 规范,发送 GET
请求到 /user
即可。示例如下:
Controller 中新增方法:
/**
* 查询所有用户
* 访问示例:GET /user
*/
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>
效果说明
点击“查看所有用户列表”后,浏览器会发送
GET /user
请求。后端处理后返回
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
*/
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
表单中的username
、password
绑定到User
对象上,无需使用@RequestBody
。
效果说明
在 Postman 里发送上述请求后,服务端控制台会打印:
新增用户: User{username='zhangsan', password='11111'},添加成功。
前端会返回
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
添加 Jackson 依赖(以 Maven 为例)
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-databindartifactId>
<version>2.15.2version>
dependency>如果项目是 Spring Boot,只需引入
spring-boot-starter-web
,它会自动包含 Jackson。Controller 方法
/**
* 修改用户信息
* 访问示例:PUT /user
* 请求头:Content-Type: application/json
* 请求体示例(raw、JSON):
* {
* "username": "zhangsan",
* "password": "222"
* }
*/
value = "/user", method = RequestMethod.PUT) (
public ModelAndView updateOne( User user) {
ModelAndView modelAndView = new ModelAndView();
System.out.println("更新用户: " + user + ",修改成功。");
modelAndView.addObject("msg", "更新用户: " + user + ",修改成功。");
modelAndView.setViewName("ok");
return modelAndView;
}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
,需要检查:
是否已经引入 Jackson 相关依赖(
jackson-databind
等)。是否启用了
(或在 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
*/
value = "/user/{id}", method = RequestMethod.DELETE) (
public ModelAndView deleteOne( ("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 里添加任何参数,点击发送即可。
效果说明
控制台会打印:
删除用户: ID = 1,删除成功。
前端页面返回
ok.html
,显示 “删除用户: ID = 1,删除成功。”
四、小结
RESTful 架构风格核心:
通过“统一资源标识符(URI)”+“HTTP 方法”来定位并操作资源。
语义清晰、符合 HTTP 标准,可读性和可维护性更高。
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
)。
接口设计建议:
URI 统一使用小写,使用短横线(
-
)或驼峰分隔资源名称;避免大小写混杂。合理使用 HTTP 状态码表示请求结果。
- 微信
- 赶快加我聊天吧
- 赶快加我聊天吧