当前位置: 首页 > article >正文

【 <二> 丹方改良:Spring 时代的 JavaWeb】之 Spring Boot 中的 RESTful API 设计:从上手到骨折

 <前文回顾>

点击此处查看 合集 https://blog.csdn.net/foyodesigner/category_12907601.html?fromshare=blogcolumn&sharetype=blogcolumn&sharerId=12907601&sharerefer=PC&sharesource=FoyoDesigner&sharefrom=from_link

<今日更新>

一、开篇整活儿

咱今儿个唠唠 Spring Boot 里头咋整 RESTful API。这玩意儿吧,说难不难,说简单也不简单,整好了是 API,整不好就是 AP(挨批)。你要是刚入门,那可得悠着点儿,别一上来就整得自己“骨折”了。

二、Spring MVC 和 RESTful API 是啥关系?

Spring MVC 是 Spring 里头用来搞 Web 开发的框架,RESTful API 呢,就是一种设计风格,讲究用 HTTP 协议里头的 GET、POST、PUT、DELETE 这些方法来操作资源。Spring MVC 里头有个叫 @Controller 的注解,专门用来处理 HTTP 请求,跟 RESTful API 那是天造地设的一对儿。

1. Controller 是咋回事?

Controller 就是 Spring MVC 里头的一个组件,专门负责处理请求和返回响应。你可以把它想象成一个“接线员”,客户端的请求来了,它得接电话,然后根据请求的内容,决定该干啥。

Java Code

@RestController

@RequestMapping("/api")

public class MyController {

    @GetMapping("/hello")

    public String sayHello() {

        return "Hello, World!";

    }

}

这段代码里头,@RestController 是 @Controller 和 @ResponseBody 的结合体,意思就是这个类里头的方法返回的都是直接写给客户端的数据,不用再整啥视图解析了。@RequestMapping 是用来映射 URL 的,/api 就是根路径,/hello 就是子路径。

2. RESTful 风格的 URL 设计

RESTful 风格的 URL 讲究的是“资源”和“操作”。比如说,你要操作一个用户资源,那 URL 就得设计成 /users,然后根据不同的 HTTP 方法来做不同的操作:

  • GET /users:获取所有用户
  • GET /users/{id}:获取某个用户
  • POST /users:创建一个用户
  • PUT /users/{id}:更新某个用户
  • DELETE /users/{id}:删除某个用户

Java Code

@RestController

@RequestMapping("/users")

public class UserController {

    @GetMapping

    public List<User> getUsers() {

        // 返回所有用户

    }

    @GetMapping("/{id}")

    public User getUser(@PathVariable Long 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) {

        // 删除用户

    }

}

这段代码里头,@PathVariable 是用来从 URL 里头提取参数的,@RequestBody 是用来接收客户端传过来的 JSON 数据的。

三、Filter 是咋过滤 RESTful 请求的?

Filter 是 Java Web 开发里头的一个玩意儿,用来在请求到达 Controller 之前或者响应返回客户端之前,做一些预处理或者后处理。比如说,你可以用 Filter 来过滤掉一些不合法的请求,或者给请求加上一些额外的信息。

1. 实现一个简单的 Filter

Java Code

@Component

public class MyFilter implements Filter {

    @Override

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

            throws IOException, ServletException {

        HttpServletRequest httpRequest = (HttpServletRequest) request;

        String method = httpRequest.getMethod();

        if ("GET".equals(method)) {

            // 处理 GET 请求

        } else if ("POST".equals(method)) {

            // 处理 POST 请求

        }

        chain.doFilter(request, response);

    }

}

这段代码里头,doFilter 方法是 Filter 的核心方法,所有的请求都会经过这个方法。chain.doFilter 是让请求继续往下走,如果不调用这个方法,那请求就被拦截了。

2. Filter 的应用场景

Filter 可以用来干很多事儿,比如说:

  • 权限校验:看看用户有没有权限访问某个资源
  • 日志记录:记录每个请求的详细信息
  • 请求参数处理:对请求参数做一些预处理,比如说去掉空格啥的

Java Code

@Component

public class AuthFilter implements Filter {

    @Override

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

            throws IOException, ServletException {

        HttpServletRequest httpRequest = (HttpServletRequest) request;

        String token = httpRequest.getHeader("Authorization");

        if (token == null || !isValidToken(token)) {

            HttpServletResponse httpResponse = (HttpServletResponse) response;

            httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);

            return;

        }

        chain.doFilter(request, response);

    }

    private boolean isValidToken(String token) {

        // 校验 token 是否有效

        return true;

    }

}

这段代码里头,AuthFilter 是用来做权限校验的,如果请求里头没有带 Authorization 头,或者 token 无效,那就返回 401 状态码,表示未授权。

四、Spring Boot 里头的 RESTful API 设计小技巧

1. 使用 @ExceptionHandler 处理异常

RESTful API 里头,异常处理是个大事儿。Spring Boot 里头有个 @ExceptionHandler 注解,专门用来处理 Controller 里头的异常。

Java Code

@RestControllerAdvice

public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)

    public ResponseEntity<String> handleException(Exception e) {

        return new ResponseEntity<>("出错了:" + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);

    }

}

这段代码里头,@RestControllerAdvice 是用来定义一个全局的异常处理类,@ExceptionHandler 是用来处理特定类型的异常的。ResponseEntity 是用来返回 HTTP 响应的,里头可以带上状态码和响应体。

2. 使用 @Valid 做参数校验

RESTful API 里头,参数校验也是个大事儿。Spring Boot 里头有个 @Valid 注解,专门用来做参数校验。

Java Code

@PostMapping("/users")

public User createUser(@Valid @RequestBody User user) {

    // 创建用户

}

这段代码里头,@Valid 是用来校验 User 对象的,如果 User 对象里头的字段不符合要求,那就会抛出 MethodArgumentNotValidException 异常。

3. 使用 @ConfigurationProperties 做配置绑定

Spring Boot 里头有个 @ConfigurationProperties 注解,专门用来把配置文件里头的属性绑定到 Java 对象里头。

Java Code

@ConfigurationProperties(prefix = "myapp")

public class MyAppProperties {

    private String name;

    private String version;

    // getters and setters

}

这段代码里头,@ConfigurationProperties 是用来把 application.properties 里头以 myapp 开头的属性绑定到 MyAppProperties 对象里头的。

五、Spring Boot 里头的 RESTful API 设计坑点

1. 路径冲突

Spring Boot 里头,路径设计得不好,就容易出现冲突。比如说,你有两个方法,一个映射到 /users/{id},另一个映射到 /users/new,那 Spring Boot 就不知道该调用哪个方法了。

Java Code

@GetMapping("/users/{id}")

public User getUser(@PathVariable Long id) {

    // 返回某个用户

}

@GetMapping("/users/new")

public User newUser() {

    // 返回一个新用户

}

这段代码里头,/users/{id} 和 /users/new 就冲突了,因为 new 会被当成 id 来处理。

2. 跨域问题

RESTful API 里头,跨域是个常见问题。Spring Boot 里头可以用 @CrossOrigin 注解来解决跨域问题。

Java Code

@CrossOrigin(origins = "http://example.com")

@RestController

@RequestMapping("/api")

public class MyController {

    // ...

}

这段代码里头,@CrossOrigin 是用来允许 http://example.com 这个域名跨域访问的。

专有名词解释

  1. Spring MVC:Spring 框架中的一个模块,用于构建 Web 应用程序,基于 Model-View-Controller 设计模式。
  2. RESTful API:一种基于 HTTP 协议的 API 设计风格,强调资源的操作和状态转移。
  3. Controller:Spring MVC 中的一个组件,负责处理 HTTP 请求并返回响应。
  4. Filter:Java Web 开发中的一个组件,用于在请求到达 Controller 之前或响应返回客户端之前进行预处理或后处理。
  5. RestController:Spring MVC 中的一个注解,结合了 Controller 和 ResponseBody,用于返回直接写给客户端的数据。
  6. RequestMapping:Spring MVC 中的一个注解,用于映射 URL 路径到 Controller 方法。
  7. PathVariable:Spring MVC 中的一个注解,用于从 URL 路径中提取参数。
  8. RequestBody:Spring MVC 中的一个注解,用于接收客户端传过来的 JSON 数据。
  9. ExceptionHandler:Spring MVC 中的一个注解,用于处理 Controller 中的异常。
  10. Valid:Spring MVC 中的一个注解,用于做参数校验。
  11. ConfigurationProperties:Spring Boot 中的一个注解,用于将配置文件中的属性绑定到 Java 对象中。
  12. CrossOrigin:Spring Boot 中的一个注解,用于解决跨域问题。
  13. Async:Spring Boot 中的一个注解,用于让方法异步执行。

相关文章:

【 <二> 丹方改良:Spring 时代的 JavaWeb】之 Spring Boot 中的 RESTful API 设计:从上手到骨折

<前文回顾> 点击此处查看 合集 https://blog.csdn.net/foyodesigner/category_12907601.html?fromshareblogcolumn&sharetypeblogcolumn&sharerId12907601&sharereferPC&sharesourceFoyoDesigner&sharefromfrom_link <今日更新> 一、开篇整活…...

【深度学习与大模型基础】第8章-概率分布

一、概率质量函数 什么是概率质量函数&#xff1f; 概率质量函数是用来描述离散随机变量的概率分布的工具。它告诉我们&#xff0c;某个离散随机变量取某一个特定值的概率是多少。 举个例子&#xff1a;抛硬币 假设你有一个程序&#xff0c;模拟抛硬币的结果。硬币有两个可能…...

数据结构5(初):排序

目录 1、排序的概念以及常见的排序算法 1.1、排序的概念 1.2、常见的排序算法 2、常见排序算法的实现 2.1、插入排序 2.1.1、直接插入排序 2.1.2、希尔排序 2.2、选择排序 2.2.1、直接选择排序 2.2.2、堆排序 2.3、交换排序 2.3.1、冒泡排序 2.3.2、快速排序 2.3.…...

表达式括号匹配(stack)(信息学奥赛一本通-1353)

【题目描述】 假设一个表达式有英文字母&#xff08;小写&#xff09;、运算符&#xff08;&#xff0c;—&#xff0c;∗&#xff0c;/&#xff09;和左右小&#xff08;圆&#xff09;括号构成&#xff0c;以“ ”作为表达式的结束符。请编写一个程序检查表达式中的左右圆括号…...

RabbitMQ 详细原理解析

RabbitMQ 是一个基于 AMQP&#xff08;Advanced Message Queuing Protocol&#xff09; 协议的开源消息代理中间件&#xff0c;广泛用于分布式系统中的异步通信、服务解耦、流量削峰等场景。其核心设计围绕生产者、消费者、队列、交换机和虚拟主机等组件&#xff0c;结合 AMQP …...

2025-03-23 学习记录--C/C++-C语言 sprintf()实现将多个值按指定格式拼接成字符串

C语言 sprintf()实现将多个值按指定格式拼接成字符串 举个例子 &#x1f330;&#xff1a;将字符串 “m” 与数字 0、1、2 动态拼接成 “m0”、“m1”、“m2”&#xff1a;&#x1f447;&#x1f3fb; #include <stdio.h> // 包含标准输入输出库&#xff0c;用于使用输入…...

【小程序开发】完整项目结构长啥样?

Hello,欢迎来到AI技术库。AI写代码的时代,人人都可以成为程序员。欢迎继续【小程序开发】系列课。上节课中,我们学习了【手把手教你小程序开发】什么是大前端?,本节课,我们学习第二篇 小程序的完整项目结构。 本文适合阅读对象: 1. 非计算机专业AI爱好者;2. 小程序开发…...

JVM的组成及各部分的作用

JVM&#xff08;Java虚拟机&#xff09;是Java程序运行的核心环境&#xff0c;负责将Java字节码转换为机器码并执行。以下是JVM的主要组成部分及其作用&#xff1a; 1. 类加载器子系统&#xff08;Class Loader Subsystem&#xff09; 作用 加载&#xff1a;将 .class 文件加载…...

计算机网络精讲day2———计算机网络的性能指标(下)

性能指标5&#xff1a;时延带宽积 时延带宽积传播时延*带宽 这里要注意是传播时延不是发送时延 重点&#xff1a;管道法解析时延带宽积 我们以一个圆柱形管道来代表链路&#xff0c;管道的长度是链路的传播时延&#xff08;以时间作为单位单位表示链路长度&#xff09;&#x…...

Android LiveData 的 `setValue` 与 `postValue` 区别详解

Android LiveData 的 setValue 与 postValue 区别详解 一、核心区别 线程限制 • setValue:必须且仅能在主线程调用,否则会抛出 IllegalStateException。 • postValue:可在任意线程调用,内部通过 Handler 将任务切换到主线程执行 setValue。 数据更新机制 • setValue:同…...

【多线程】初始线程和Thread类

一. 线程 1. 线程的引入 虽然进程已经可以解决并发编程这种问题&#xff0c;但是进程在频繁进行创建和销毁的时候&#xff0c;系统开销非常大&#xff0c;如果一个服务器向你发送多个请求&#xff0c;针对每一个请求&#xff0c;都需要创建一个进程来应答&#xff0c;每个进程…...

WebLogic中间件常见漏洞

一、后台弱⼝令GetShell 1.环境搭建 cd vulhub-master/weblogic/weak_password docker-compose up -d 2.访问网站并登陆后台 /console/login/LoginForm.jsp 默认账号密码&#xff1a;weblogic/Oracle123 3.点击部署&#xff0c;点击安装&#xff…...

[笔记.AI]多头自注意力机制(Multi-Head Attention)

多头自注意力是深度学习领域&#xff0c;特别是自然语言处理&#xff08;NLP&#xff09;和Transformer模型中的关键概念。其发展源于对序列数据中复杂依赖关系的建模需求&#xff0c;特别是在Transformer架构的背景下。 举例 比喻-读长篇文章 用一个简单的比喻来理解“多头注…...

【基于ROS的A*算法实现路径规划】A* | ROS | 路径规划 | Python

### 记录一下使用Python实现ROS平台A*算法路径规划 ### 代码可自取 &#xff1a;Xz/little_projecthttps://gitee.com/Xz_zh/little_project.git 目录 一、思路分析 二、算法实现 三、路径规划实现 一、思路分析 要求使用A*算法实现路径规划&#xff0c;可以将该任务分为三…...

keda基于postgresql伸缩dify-api服务

1 概述 dify-api使用postgresql来存储数据&#xff0c;在dify控制台每新建一个聊天机器的聊天框&#xff0c;就会在conversations表里新插入一条记录&#xff0c;并且不断地更新字段updated_at&#xff0c;示例如下&#xff1a; dify# select * from conversations limit 1; …...

趣味极简品牌海报艺术贴纸设计圆润边缘无衬线粗体装饰字体 Chunko Bold - Sans Serif Font

Chunko Bold 是一种功能强大的显示字体&#xff0c;体现了大胆极简主义的原则 – 当代设计的主流趋势。这种自信的字体将粗犷的几何形状与现代的趣味性相结合&#xff0c;具有圆润的边缘和强烈的存在感&#xff0c;与当今的极简主义设计方法完美契合。无论是用于鲜明的构图还是…...

VoLTE(Voice over Long-Term Evolution)

VoLTE&#xff0c;即Voice over Long-Term Evolution&#xff0c;是一种基于4G LTE网络的高质量语音通话技术。与传统的2G和3G网络中的语音通话不同&#xff0c;VoLTE将语音信号转换为数据包&#xff0c;通过LTE网络进行传输&#xff0c;从而实现了更快的连接速度和更高的通话质…...

指针,数组 易混题解析(一)

目录 一.相关知识点 1.数组名是什么&#xff1f; 两个例外&#xff1a; 2.strlen 3.sizeof 4. * ( ) 与 [ ] 的互换 二.一维数组 三.字符数组 1. 字符 &#xff08;1&#xff09;sizeof &#xff08;2&#xff09;strlen 2.字符串 &#xff08;1&#xff09;si…...

Java 基础篇:数组

前言 数组&#xff08;Array&#xff09;是 Java 中最基本的数据结构之一&#xff0c;它用于存储相同类型的元素&#xff0c;并且在内存中是连续存储的。数组具有高效的索引访问特点&#xff0c;但长度固定&#xff0c;不能动态调整。 本文将介绍数组的基本概念、声明和初始化方…...

从汽车 BCM 方案看国产 MCU 芯片的突围与挑战

摘要 &#xff1a;汽车车身控制模块&#xff08;BCM&#xff09;作为汽车电子系统的核心控制单元&#xff0c;其性能高度依赖于微控制单元&#xff08;MCU&#xff09;芯片。随着汽车智能化与电动化的发展&#xff0c;国产 MCU 芯片在 BCM 领域的应用逐渐扩大。本文结合行业数据…...

深入理解 Spring 框架中的 IOC 容器

一、Spring 框架概述 Spring 框架是一个轻量级的 Java 开发框架&#xff0c;由 Rod Johnson 在 2003 年创建。它的诞生旨在简化企业级应用开发的复杂性。Spring 框架提供了诸如 IoC&#xff08;控制反转&#xff09;和 AOP&#xff08;面向切面编程&#xff09;等核心功能&…...

深入理解 Java 中 instanceof 操作符

目录 1. instanceof 的基本用法 1.1 语法 1.2 示例 2. instanceof 的用途 2.1 类型检查 2.2 类型转换 2.3 多态编程 3. instanceof 的注意事项 3.1 null 检查 3.2 接口检查 3.3 继承关系 3.4 性能问题 4. instanceof 代码示例 4.1 多态处理 4.2 接口检查 4.3 n…...

2025前端面试题记录

vue项目目录的执行顺序是怎么样的&#xff1f; 1、package.json   在执行npm run dev时&#xff0c;会在当前目录寻找package.json文件&#xff0c;此文件包含了项目的名称版本、项目依赖等相关信息。 2、webpack.config.js(会被vue-cli脚手架隐藏) 3、vue.config.js   对…...

复变函数摘记2

复变函数摘记2 3. 级数3.1 复数项级数3.2 复变幂级数3.3 泰勒级数3.4 洛朗级数 3. 级数 \quad 复数项级数的一般项 α n a n i b n \alpha_na_n\text{i}b_n αn​an​ibn​ 为复数&#xff0c;与高等数学中无穷级数的分析方式类似&#xff0c;也是通过和函数来研究级数的收敛…...

光纤的频率和带宽

光纤通信中的频率和带宽涉及光波的物理特性以及通信系统的设计&#xff0c;以下是详细解释&#xff1a; ‌1. 光纤的工作频率‌ 光纤通信利用光波作为载波&#xff0c;工作频率主要在‌近红外波段‌&#xff0c;具体频段和对应的波长如下&#xff1a; ‌C波段&#xff08;Conve…...

高频面试题(含笔试高频算法整理)基本总结回顾67

干货分享&#xff0c;感谢您的阅读&#xff01; &#xff08;暂存篇---后续会删除&#xff0c;完整版和持续更新见高频面试题基本总结回顾&#xff08;含笔试高频算法整理&#xff09;&#xff09; 备注&#xff1a;引用请标注出处&#xff0c;同时存在的问题请在相关博客留言…...

Kafka--常见问题

1.为什么要使用 Kafka&#xff0c;起到什么作用 Kafka是一个高吞吐量、分布式、基于发布订阅的消息系统&#xff0c;它主要用于处理实时数据流 Kafka 设计上支持高吞吐量的消息传输&#xff0c;每秒可以处理数百万条消息。它能够在处理大量并发请求时&#xff0c;保持低延迟和…...

优选算法的睿智之林:前缀和专题(一)

专栏&#xff1a;算法的魔法世界 个人主页&#xff1a;手握风云 目录 一、前缀和 二、例题讲解 2.1. 一维前缀和 2.2. 二维前缀和 2.3. 寻找数组的中心下标 2.4. 除自身以外数组的乘积 一、前缀和 前缀和算法是一种用于处理数组或序列数据的算法&#xff0c;其核心思想是…...

嵌入式八股文学习——STL相关内容学习

文章目录 map和set的区别与实现1. map和set的区别2. 为什么set的元素和map的key不可修改&#xff1f; map和set的实现1. map的实现原理map的操作&#xff1a;map的特点&#xff1a; 2. set的实现原理set的操作&#xff1a;set的特点&#xff1a; map和set的底层原理&#xff08…...

【清华大学】AIGC发展研究(3.0版)

目录 AIGC发展研究报告核心内容一、团队简介二、AI哲学三、国内外大模型四、生成式内容&#xff08;一&#xff09;文本生成&#xff08;二&#xff09;图像生成&#xff08;三&#xff09;音乐生成&#xff08;四&#xff09;视频生成 五、各行业应用六、未来展望 AIGC发展研究…...