6.2 构建 RESTful 应用接口
第6章 构建 RESTful 服务
6.1 RESTful 简介
6.2 构建 RESTful 应用接口
6.3 使用 Swagger 生成 Web API 文档
6.4 实战:实现 Web API 版本控制
6.2 构建 RESTful 应用接口
6.2.1 Spring Boot 对 RESTful 的支持
Spring Boot 提供的spring-boot-starter-web
组件完全支持开发 RESTful API,提供了与 REST 操作方式(GET、POST、PUT、DELETE)对应的注解:
- @GetMapping:处理 GET 请求,获取资源。
- @PostMapping:处理 POST 请求,新增资源。
- @PutMapping:处理 PUT 请求,更新资源。
- @DeleteMapping:处理 DELETE 请求,删除资源。
- @PatchMapping:处理 PATCH 请求,用于部分更新资源。
通过这些注解就可以在 Spring Boot 项目中轻松构建 RESTful 接口。其中比较常用的是 @GetMapping、@PostMapping、@PutMapping、@DeleteMapping 四个注解。
使用 Spring Boot 开发 RESTful 接口非常简单,通过 @RestController 定义控制器,然后使用 @GetMapping 和 @PostMapping 等注解定义地址映射,实现相应的资源操作方法即可。
示例:
RESTfulController.java
package com.example.restfulproject.controller;import com.example.restfulproject.model.User;
import org.springframework.web.bind.annotation.*;/*** RESTful 接口简单案例(增删改查)*/
@RestController
public class RESTfulController {@GetMapping(value = "/user/{id}")public String getUserById(@PathVariable String id) {return "getUserById:" + id;}@PostMapping(value = "/user")public String save(@RequestBody User user) {String name = user.getName();return "save successed";}@PutMapping(value = "/user")public String update(@RequestBody User user) {return "update successed";}@DeleteMapping(value = "/user/{id}")public String delete(@PathVariable String id) {return "delete id:" + id;}/*// 上面的注解是 @RequestMapping 注解的简化:@RequestMapping(value = "/user/{id}", method = RequestMethod.GET)public String getUserById(@PathVariable String id) {return "getUserById:" + id;}@RequestMapping(value = "/user", method = RequestMethod.POST)public String save(User user) {return "save successed";}@RequestMapping(value = "/user", method = RequestMethod.PUT)public String update(User user) {return "update successed";}@RequestMapping(value = "/user/{id}", method = RequestMethod.DELETE)public String delete(@PathVariable String id) {return "delete id:" + id;}
*/
}
6.2.2 Spring Boot 实现 RESTful API
1. 设计API
在 RESTful 架构中,每个网址代表一种资源,所以 URI 中建议不要包含动词,只包含名词即可,而且所用的名词往往与数据库的表名对应。
(1)接口定义
下表是用户管理模块的接口定义,实际项目的 RESTful API 文档要更详细,还会定义全部请求的数据结构体。
用户管理模块API说明
HTTP Method | 接口地址 | 接口说明 |
---|---|---|
POST | /user | 创建用户 |
GET | /user/id | 根据id获取用户信息 |
PUT | /user | 更新用户 |
DELETE | /user/id | 根据id删除对应的用户 |
上表中定义了用户管理模块的接口,根据 REST 的定义,我们将用户定义为一种资源,通过 POST、DELETE、PUT、GET 等 HTTP Method 实现对用户的增、删、改、查。
(2)状态码和提示信息定义
除了设计 URL 接口之外,还需要定义服务端向客户端返回的状态码和提示信息。详细状态码说明见下表。
用户管理模块状态码
说明:
状态码 | 状态说明 |
---|---|
200 | Ok,请求成功 |
201 | Created,新增成功 |
203 | Updated,修改成功 |
204 | Deleted,删除成功 |
除了定义用户管理相关的业务状态码之外,还需要定义通用的错误码,如 400 对应数据校验错误、401 对应数据无权限等。
用户管理模块错误码
说明:
错误码 | 错误说明 |
---|---|
400 | 数据验证错误 |
401 | 无权限 |
404 | 资源不存在 |
500 | 服务端错误 |
2. 实现用户管理接口
UserManagementController.java
package com.example.restfulproject.controller;import com.example.restfulproject.comm.utils.JSONResult;
import com.example.restfulproject.model.User;
import org.springframework.web.bind.annotation.*;/*** Spring Boot 实现 RESTful API*/
@RestController
@RequestMapping("/userManagement")
public class UserManagementController {/*** 用户新增*/@PostMapping(value = "/user")public JSONResult save(@RequestBody User user) {System.out.println("用户创建成功:" + user.getName());return JSONResult.ok(201, "用户创建成功");}/*** 用户修改*/@PutMapping(value = "/user")public JSONResult update(@RequestBody User user) {System.out.println("用户修改成功:" + user.getName());return JSONResult.ok(203, "用户修改成功");}/*** 用户删除*/@DeleteMapping(value = "/user/{userId}")public JSONResult delete(@PathVariable String userId) {System.out.println("用户删除成功:" + userId);return JSONResult.ok(204, "用户删除成功");}/*** 获取用户*/@GetMapping(value = "/user/{userId}")public JSONResult queryUserById(@PathVariable String userId) {User user = new User();user.setId(userId);user.setName("zhangsan");user.setAge(20);System.out.println("获取用户成功:" + userId);return JSONResult.ok(200, "获取用户成功", user);}}
JSONResult.java
package com.example.restfulproject.comm.utils;import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;import java.util.List;/*** 定义数据处理类** @Title:: JSONResult.java* @Package com.example.webproject.comm.utils* @Description: 自定义响应数据结构* 200: 表示成功* 500: 表示错误,错误信息在 msg 字段中* 501: bean 验证错误,无论多少个错误都以 map 形式返回* 502: 拦截器拦截到用户 token 出错* 555: 异常抛出信息* Copyright: Copyright (c) 2023** @create: 2023-02-05 17:35:54* @Modify: 2023-02-17 19:41:30* @version V1.1*/
public class JSONResult {// 定义 jackson 对象 (关于jackson的使用详解请参考:https://juejin.cn/post/6844904166809157639)private static final ObjectMapper MAPPER = new ObjectMapper();// 响应业务状态private Integer code;// 响应消息private String msg;// 响应中的数据private Object data;public Integer getCode() {return code;}public void setCode(Integer code) {this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public Object getData() {return data;}public void setData(Object data) {this.data = data;}public JSONResult() {}public JSONResult(Integer code, String msg, Object data) {this.code = code;this.msg = msg;this.data = data;}public JSONResult(Object data) {this.code = 200;this.msg = "OK";this.data = data;}// // 是否成功
// public Boolean isSuccess() {
// return this.code == 200;
// }// 构建返回的数据public static JSONResult build(Integer status, String msg, Object data) {return new JSONResult(status, msg, data);}// 200:成功,有返回值public static JSONResult ok(Object data) {return new JSONResult(data);}// 200:成功,没有返回值public static JSONResult ok() {return new JSONResult(null);}//200:成功,没有返回值public static JSONResult ok(Integer code, String msg) {return new JSONResult(code, msg, null);}// 200: 成功public static JSONResult ok(Integer code, String msg, Object data) {return new JSONResult(code, msg, data);}//500:错误,错误信息在 msg 字段中public static JSONResult errorMsg(String msg) {return new JSONResult(500, msg, null);}//501:bean 验证错误,无论多少个错误都以 map 形式返回public static JSONResult errorMap(Object data) {return new JSONResult(501, "error", data);}//502:拦截器拦截到用户 token 出错public static JSONResult errorTokenMsg(String msg) {return new JSONResult(502, msg, null);}//555:异常抛出信息public static JSONResult errorException(String msg) {return new JSONResult(555, msg, null);}/*** @Description: 将 json 结果集转化为 JSONResult 对象,需要转换的对象是一个类** @param jsonData* @param clazz* @return*/public static JSONResult formatToPojo(String jsonData, Class<?> clazz) {try {if (clazz == null) {return MAPPER.readValue(jsonData, JSONResult.class);}JsonNode jsonNode = MAPPER.readTree(jsonData);JsonNode data = jsonNode.get("data");Object obj = null;if (clazz != null) {if (data.isObject()) {obj = MAPPER.readValue(data.traverse(), clazz);} else if (data.isTextual()) {obj = MAPPER.readValue(data.asText(), clazz);}}return build(jsonNode.get("code").intValue(), jsonNode.get("msg").asText(), obj);} catch (Exception e) {return null;}}/*** @Description: 没有 object 对象的转化** @param json* @return*/public static JSONResult format(String json) {try {return MAPPER.readValue(json, JSONResult.class);} catch (JsonProcessingException e) {e.printStackTrace();}return null;}/*** @Description: Object 是集合转化,需要转换的对象是一个list** @param jsonData* @param clazz* @return*/public static JSONResult formatToList(String jsonData, Class<?> clazz) {try {JsonNode jsonNode = MAPPER.readTree(jsonData);JsonNode data = jsonNode.get("data");Object obj = null;if(data.isArray() && data.size() > 0) {obj = MAPPER.readValue(data.traverse(), MAPPER.getTypeFactory().constructCollectionType(List.class,clazz));}return build(jsonNode.get("code").intValue(), jsonNode.get("msg").asText(), obj);} catch (Exception e) {return null;}}}
3. 验证测试
(1)获取用户:http://localhost:8080/userManagement/user/2001
(2)用户新增:http://localhost:8080/userManagement/user
(3)用户修改:http://localhost:8080/userManagement/user
(4)用户删除:http://localhost:8080/userManagement/user/2001
来源:《Spring Boot 从入门到实战》学习笔记
相关文章:

6.2 构建 RESTful 应用接口
第6章 构建 RESTful 服务 6.1 RESTful 简介 6.2 构建 RESTful 应用接口 6.3 使用 Swagger 生成 Web API 文档 6.4 实战:实现 Web API 版本控制 6.2 构建 RESTful 应用接口 6.2.1 Spring Boot 对 RESTful 的支持 Spring Boot 提供的spring-boot-starter-web组件完全…...
20230218英语学习
How Italian Artist’s Mild Colors Dominate World of Design 温柔的“莫兰迪色”,如何引领设计时尚? The Morandi color scheme has become an across-the-board fashion that now prevails in the world of design.Soft and sophisticated Morandi c…...

Linux单一服务管理systemctl
基本上systemd这个启动服务机制只有systemctl命令来处理,所以全部的操作都需要使用systemctl systemctl管理单一服务 一般来说服务的启动有两个阶段,一个是开机是否启动,以及现在是否启动 systemctl【command】【unit】 command主要有&…...

【GStreamer 】 TX1中CPU和GPU解码显示海康相机RTSP流
大家好,我是虎哥,今天找了一套海康的相机,想后续测试一下DeepStream用网络相机RTSP流做输入看看后续目标识别和分类。但是还是想先实时看看视频,当然,可以选择VLC去查看,顺道我也用GStreamer 来测试了一下&…...
匿名内部类、Lambda表达式、方法引用对比分析
文章目录一、匿名内部类1. 语法格式2. 使用方法① 传统方式② 匿名内部类方式二、Lambda表达式1. 语法格式2. 使用方法① 匿名内部类方式② Lambda表达式方式三、方法引用1. 语法格式2. 使用方法① 类型的静态方法引用② 类型的构造方法引用③ 类型的实例方法引用④ 对象的实例…...

ESXi主机CVE-2021-21972漏洞复现安全处置建议
一、漏洞简介 vSphere 是 VMware 推出的虚拟化平台套件,包含 ESXi、vCenter Server 等一系列的软件。其中 vCenter Server 为 ESXi 的控制中心,可从单一控制点统一管理数据中心的所有 vSphere 主机和虚拟机。 vSphere Client(HTML5…...

研报精选230217
目录 【行业230217毕马威】奢侈品行业新气象【行业230217国信证券】医药生物行业2023年2月投资策略:持续关注疫后复苏和创新两大主线【行业230217国金证券】航空锻造:稳定格局筑专业化壁垒,顺势而为拓产业链深度【个股230217西南证券_招商轮船…...
c++11 标准模板(STL)(std::unordered_set)(一)
定义于头文件 <unordered_set> template< class Key, class Hash std::hash<Key>, class KeyEqual std::equal_to<Key>, class Allocator std::allocator<Key> > class unordered_set;(1)(C11 起)namespace pmr { templ…...

【C语言进阶】你听说过柔性数组吗?
👦个人主页:Weraphael ✍🏻作者简介:目前是C语言学习者 ✈️专栏:C语言航路 🐋 希望大家多多支持,咱一起进步!😁 如果文章对你有帮助的话 欢迎 评论💬 点赞&a…...

[LeetCode]1237. 找出给定方程的正整数解
题目链接:https://leetcode.cn/problems/find-positive-integer-solution-for-a-given-equation/description/ 题目描述: 样例1: 输入:function_id 1, z 5 输出:[[1,4],[2,3],[3,2],[4,1]] 解释:functi…...

【路径规划】基于A*算法和Dijkstra算法的路径规划(Python代码实现)
👨🎓个人主页:研学社的博客💥💥💞💞欢迎来到本博客❤️❤️💥💥🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密…...
蓝桥杯 stm32 PWM 设置占空比
本文代码使用 HAL 库。 文章目录 前言一、创建CubeMX 工程 ,占空比分析:二、相关函数:1. 获取 CNT函数2.设置CNT为 0 函数(计算器清零)3.开启TIM2_CH1的输入捕获中断函数4.TIM 回调函数三、设置上升沿,下降沿四、在lcd上显示 R40 占空比 详细代码五、设置占空比,输出 PW…...

React 合成事件理解
1 事件三个阶段 捕获、目标、处理 (具体百度,后面有空补全)2import React from "react";class Test extends React.Component {parentRef;childRef;constructor(props) {super(props);this.parentRef React.createRef();this.chil…...
202302|读书笔记——国图点滴
杂志剪影|看一本赚一本系列 anywhere 随心而行随心而动,极简相生复古文艺 热情洋溢 色彩斑斓 极致优雅 深邃魅力 新生绽放 灿若星空 异彩纷呈含苞待放 惊艳绽放 爱在云端 空中婚礼 暗夜浪漫 策马逐梦橘影相映 浆果红唇 梦幻无暇 永无止境浮光掠影 微酥清风低调奢华…...
Linux 操作系统原理 — NUMA 架构中的多线程调度开销与性能优化
目录 文章目录 目录前言NUMA 架构中的多线程性能开销1、跨 Node 的 Memory 访问开销2、跨 Core 的多线程 Cache 同步开销3、多线程上下文切换开销4、多线程模式切换开销5、中断处理的开销6、TLB 缓存失效的开销7、内存拷贝的开销NUMA 架构中的性能优化:使用多核编程代替多线程…...

OpenGL - 如何理解 VAO 与 VBO 之间的关系
系列文章目录 LearnOpenGL 笔记 - 入门 01 OpenGLLearnOpenGL 笔记 - 入门 02 创建窗口LearnOpenGL 笔记 - 入门 03 你好,窗口LearnOpenGL 笔记 - 入门 04 你好,三角形 文章目录系列文章目录1. 前言2. 渲染管线的入口 - 顶点着色器2.1 顶点着色器处理过…...
Linux中sed的使用
语法: sed [选项] [sed内置命令字符] [输入文件]选项: 参数说明-n取消默认色的输出常与sed内置命令p一起使用-i直接将修改结果写入文件,不用-i,sed修改的是内存数据-e多次编译,不需要管道符了-r支持正则扩展 sed的内…...

[软件工程导论(第六版)]第1章 软件工程学概述(复习笔记)
文章目录1.1 软件危机1.1.1 软件危机的介绍1.1.2 产生软件危机的原因1.1.3 消除软件危机的途径1.2 软件工程1.2.1 软件工程的介绍1.2.2 软件工程的基本原理1.2.3 软件工程方法学1.3 软件生命周期组成1.4 软件过程概念1.4.1 瀑布模型1.4.2 快速原型模型1.4.3 增量模型1.4.4 螺旋…...
ISP相关
Internet Service Provider,网络提供商/运营商,如电信、联通、移动等。 1. 与ISP互联的出口带宽 IDC或云提供商会与各运营商互联,互联的具体带宽数值一旦泄露,就会被恶意的攻击者利用。例如,若DDos攻击者知道了被攻击…...

vTESTstudio - VT System CAPL Functions - VT2004(续1)
成熟,就是某一个突如其来的时刻,把你的骄傲狠狠的踩到地上,任其开成花或者烂成泥。vtsStartStimulation - 启动激励输出功能:自动激励输出注意:在启动激励输出之前,一定要设置好输出模式Target:目标通道变量空间名称,例…...

SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建
制造业采购供应链管理是企业运营的核心环节,供应链协同管理在供应链上下游企业之间建立紧密的合作关系,通过信息共享、资源整合、业务协同等方式,实现供应链的全面管理和优化,提高供应链的效率和透明度,降低供应链的成…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...

嵌入式学习笔记DAY33(网络编程——TCP)
一、网络架构 C/S (client/server 客户端/服务器):由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序,负责提供用户界面和交互逻辑 ,接收用户输入,向服务器发送请求,并展示服务…...

基于PHP的连锁酒店管理系统
有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发,数据库mysql,前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...

【LeetCode】算法详解#6 ---除自身以外数组的乘积
1.题目介绍 给定一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O…...