CrabNote螃蟹笔记

Spring&SpringMVC&SpringBoot常用注解总结

可以毫不夸张地说,这篇文章介绍的 Spring/SpringBoot 常用注解基本已经涵盖你工作中遇到的大部分常用的场景。对于每一个注解本文都提供了具体用法,掌握这些内容后,使用 Spring Boo

可以毫不夸张地说,这篇文章介绍的 Spring/SpringBoot 常用注解基本已经涵盖你工作中遇到的大部分常用的场景。对于每一个注解本文都提供了具体用法,掌握这些内容后,使用 Spring Boot 来开发项目基本没啥大问题了! 为什么要写这篇文章? 最近看到网上有一篇关于 Spring Boot 常用注解的文章被广泛转载,但文章内容存在一些误导性,可能对没有太多实际使用经验的开发者不太友好。于是我花了几天时间总结了这篇文章,希望能够帮助大家更好地理解和使用 Spring 注解。 因为个人能力和精力有限,如果有任何错误或遗漏,欢迎指正!非常感激! Spring Boot 基础注解 是 Spring Boot 应用的核心注解,通常用于标注主启动类。 示例: 我们可以把 看作是下面三个注解的组合: :启用 Spring Boot 的自动配置机制。 :扫描 、 、 、 等注解的类。 :允许注册额外的 Spring Bean 或导入其他配置类。 源码如下: Spring Bean 依赖注入(Dependency Injection, DI) 用于自动注入依赖项(即其他 Spring Bean)。它可以标注在构造器、字段、Setter 方法或配置方法上,Spring 容器会自动查找匹配类型的 Bean 并将其注入。 当存在多个相同类型的 Bean 时, 默认按类型注入可能产生歧义。此时,可以与 结合使用,通过指定 Bean 的名称来精确选择需要注入的实例。 同样是为了解决同一类型存在多个 Bean 实例的注入问题。在 Bean 定义时(例如使用 或类注解)添加 注解,表示该 Bean 是 首选 的注入对象。当进行 注入时,如果没有使用 指定名称,Spring 将优先选择带有 的 Bean。 是 JSR 250 规范定义的注解,也用于依赖注入。它默认按 名称 (by Name) 查找 Bean 进行注入,而 默认按 类型 (by Type) 。如果未指定 属性,它会尝试根据字段名或方法名查找,如果找不到,则回退到按类型查找(类似 )。 只能标注在字段 和 Setter 方法上,不支持构造器注入。 Bean 作用域 定义 Spring Bean 的作用域,即 Bean 实例的生命周期和可见范围。常用的作用域包括: singleton : IoC 容器中只有唯一的 bean 实例。Spring 中的 bean 默认都是单例的,是对单例设计模式的应用。 prototype : 每次获取都会创建一个新的 bean 实例。也就是说,连续 两次,得到的是不同的 Bean 实例。 request (仅 Web 应用可用): 每一次 HTTP 请求都会产生一个新的 bean(请求 bean),该 bean 仅在当前 HTTP request 内有效。 session (仅 Web 应用可用) : 每一次来自新 session 的 HTTP 请求都会产生一个新的 bean(会话 bean),该 bean 仅在当前 HTTP session 内有效。 application/global session (仅 Web 应用可用):每个 Web 应用在启动时创建一个 Bean(应用 Bean),该 bean 仅在当前应用启动时间内有效。 websocket (仅 Web 应用可用):每一次 WebSocket 会话产生一个新的 bean。 Bean 注册 Spring 容器需要知道哪些类需要被管理为 Bean。除了使用 方法显式声明(通常在 类中),更常见的方式是使用 Stereotype(构造型) 注解标记类,并配合组件扫描(Component Scanning)机制,让 Spring 自动发现并注册这些类作为 Bean。这些 Bean 后续可以通过 等方式注入到其他组件中。 下面是常见的一些注册 Bean 的注解: :通用的注解,可标注任意类为 组件。如果一个 Bean 不知道属于哪个层,可以使用 注解标注。 : 对应持久层即 Dao 层,主要用于数据库相关操作。 : 对应服务层,主要涉及一些复杂的逻辑,需要用到 Dao 层。 : 对应 Spring MVC 控制层,主要用于接受用户请求并调用 Service 层返回数据给前端页面。 :一个组合注解,等效于 + 。它专门用于构建 RESTful Web 服务的控制器。标注了 的类,其所有处理器方法(handler methods)的返回值都会被自动序列化(通常为 JSON)并写入 HTTP 响应体,而不是被解析为视图名称。 vs : :主要用于传统的 Spring MVC 应用,方法返回值通常是逻辑视图名,需要视图解析器配合渲染页面。如果需要返回数据(如 JSON),则需要在方法上额外添加 注解。 :专为构建返回数据的 RESTful API 设计。类上使用此注解后,所有方法的返回值都会默认被视为响应体内容(相当于每个方法都隐式添加了 ),通常用于返回 JSON 或 XML 数据。在现代前后端分离的应用中, 是更常用的选择。 关于 和 的对比,请看这篇文章:@RestController vs @Controller。 配置 声明配置类 主要用于声明一个类是 Spring 的配置类。虽然也可以用 注解替代,但 能够更明确地表达该类的用途(定义 Bean),语义更清晰,也便于 Spring 进行特定的处理(例如,通过 CGLIB 代理确保 方法的单例行为)。 读取配置信息 在应用程序开发中,我们经常需要管理一些配置信息,例如数据库连接细节、第三方服务(如阿里云 OSS、短信服务、微信认证)的密钥或地址等。通常,这些信息会 集中存放在配置文件 (如 或 )中,方便管理和修改。 Spring 提供了多种便捷的方式来读取这些配置信息。假设我们有如下 文件: 下面介绍几种常用的读取配置的方式: 1、 注入配置文件(如 或 )中的单个属性值。它还支持 Spring 表达式语言 (SpEL),可以实现更复杂的注入逻辑。 2、 可以读取配置信息并与 Bean 绑定,用的更多一些。 你可以像使用普通的 Spring Bean 一样,将其注入到类中使用。 加载指定的配置文件 注解允许加载自定义的配置文件。适用于需要将部分配置信息独立存储的场景。 注意 :当使用 时,确保外部文件路径正确,且文件在类路径(classpath)中。 更多内容请查看我的这篇文章:10 分钟搞定 SpringBoot 如何优雅读取配置文件? 。 MVC HTTP 请求 5 种常见的请求类型: GET :请求从服务器获取特定资源。举个例子: (获取所有学生) POST :在服务器上创建一个新的资源。举个例子: (创建学生) PUT :更新服务器上的资源(客户端提供更新后的整个资源)。举个例子: (更新编号为 12 的学生) DELETE :从服务器删除特定的资源。举个例子: (删除编号为 12 的学生) PATCH :更新服务器上的资源(客户端提供更改的属性,可以看做作是部分更新),使用的比较少,这里就不举例子了。 GET 请求 等价于 。 POST 请求 等价于 。 通常与 配合,用于接收 JSON 数据并映射为 Java 对象。 PUT 请求 等价于 。 DELETE 请求 等价于 PATCH 请求 一般实际项目中,我们都是 PUT 不够用了之后才用 PATCH 请求去更新数据。 参数绑定 在处理 HTTP 请求时,Spring MVC 提供了多种注解用于绑定请求参数到方法参数中。以下是常见的参数绑定方式: 从 URL 路径中提取参数 用于从 URL 路径中提取参数。例如: 若请求 URL 为 ,则 。 绑定查询参数 用于绑定查询参数。例如: 若请求 URL 为 ,则 , 。 绑定请求体中的 JSON 数据 用于读取 Request 请求(可能是 POST,PUT,DELETE,GET 请求)的 body 部分并且 Content Type 为 application/json 格式的数据,接收到数据之后会自动将数据绑定到 Java 对象上去。系统会使用 或者自定义的 将请求的 body 中的 json 字符串转换为 java 对象。 我用一个简单的例子来给演示一下基本使用! 我们有一个注册的接口: 对象: 我们发送 post 请求到这个接口,并且 body 携带 JSON 数据: 这样我们的后端就可以直接把 json 格式的数据映射到我们的 类上。 注意 : 一个方法只能有一个 参数,但可以有多个 和 。 如果需要接收多个复杂对象,建议合并成一个单一对象。 数据校验 数据校验是保障系统稳定性和安全性的关键环节。即使在用户界面(前端)已经实施了数据校验, 后端服务仍必须对接收到的数据进行再次校验 。这是因为前端校验可以被轻易绕过(例如,通过开发者工具修改请求或使用 Postman、curl 等 HTTP 工具直接调用 API),恶意或错误的数据可能直接发送到后端。因此,后端校验是防止非法数据、维护数据一致性、确保业务逻辑正确执行的最后一道,也是最重要的一道防线。 Bean Validation 是一套定义 JavaBean 参数校验标准的规范 (JSR 303, 349, 380),它提供了一系列注解,可以直接用于 JavaBean 的属性上,从而实现便捷的参数校验。 JSR 303 (Bean Validation 1.0): 奠定了基础,引入了核心校验注解(如 、 、 、 等),定义了如何通过注解的方式对 JavaBean 的属性进行校验,并支持嵌套对象校验和自定义校验器。 JSR 349 (Bean Validation 1.1): 在 1.0 基础上进行扩展,例如引入了对方法参数和返回值校验的支持、增强了对分组校验(Group Validation)的处理。 JSR 380 (Bean Validation 2.0): 拥抱 Java 8 的新特性,并进行了一些改进,例如支持 包中的日期和时间类型、引入了一些新的校验注解(如 , 等)。 Bean Validation 本身只是一套 规范(接口和注解) ,我们需要一个实现了这套规范的 具体框架 来执行校验逻辑。目前, Hibernate Validator 是 Bean Validation 规范最权威、使用最广泛的参考实现。 Hibernate Validator 4.x 实现了 Bean Validation 1.0 (JSR 303)。 Hibernate Validator 5.x 实现了 Bean Validation 1.1 (JSR 349)。 Hibernate Validator 6.x 及更高版本实现了 Bean Validation 2.0 (JSR 380)。 在 Spring Boot 项目中使用 Bean Validation 非常方便,这得益于 Spring Boot 的自动配置能力。关于依赖引入,需要注意: 在较早版本的 Spring Boot(通常指 2.3.x 之前)中, 依赖默认包含了 hibernate validator。因此,只要引入了 Web Starter,就无需额外添加校验相关的依赖。 从 Spring Boot 2.3.x 版本开始,为了更精细化的依赖管理,校验相关的依赖被移出了 spring boot starter web。如果你的项目使用了这些或更新的版本,并且需要 Bean Validation 功能,那么你需要显式地添加 依赖: 非 SpringBoot 项目需要自行引入相关依赖包,这里不多做讲解,具体可以查看我的这篇文章:如何在 Spring/Spring Boot 中做参数校验?你需要了解的都在这里!。 👉 需要注意的是:所有的注解,推荐使用 JSR 注解,即 ,而不是 一些常用的字段验证的注解 Bean Validation 规范及其实现(如 Hibernate Validator)提供了丰富的注解,用于声明式地定义校验规则。以下是一些常用的注解及其说明: : 检查被注解的元素(任意类型)不能为 。 : 检查被注解的元素(如 、 、 、 )不能为 且其大小/长度不能为 0。注意:对于字符串, 允许包含空白字符的字符串,如 。 : 检查被注解的 (如 )不能为 ,并且去除首尾空格后的长度必须大于 0。(即,不能为空白字符串)。 : 检查被注解的元素必须为 。 / : 检查被注解的 或 类型元素必须为 / 。 / : 检查被注解的数字类型(或其字符串表示)的值必须大于等于 / 小于等于指定的 。适用于整数类型( 、 、 、 、 等)。 / : 功能类似 / ,但适用于包含小数的数字类型( 、 、 、 、 、 、 及其包装类)。 必须是数字的字符串表示。 : 检查被注解的元素(如 、 、 、 )的大小/长度必须在指定的 和 范围之内(包含边界)。 : 检查被注解的数字类型(或其字符串表示)的值,其整数部分的位数必须 ≤ ,小数部分的位数必须 ≤ 。 : 检查被注解的 (如 )是否匹配指定的正则表达式 ( )。 可以指定匹配模式(如不区分大小写)。 : 检查被注解的 (如 )是否符合 Email 格式(内置了一个相对宽松的正则表达式)。 / : 检查被注解的日期或时间类型( 、 、JSR 310 包下的类型)是否在当前时间之前 / 之后。 / : 类似 / ,但允许等于当前时间。 …… 验证请求体(RequestBody) 当 Controller 方法使用 注解来接收请求体并将其绑定到一个对象时,可以在该参数前添加 注解来触发对该对象的校验。如果验证失败,它将抛出 。 验证请求参数(Path Variables 和 Request Parameters) 对于直接映射到方法参数的简单类型数据(如路径变量 或请求参数 ),校验方式略有不同: 1. 在 Controller 类上添加 注解 :这个注解是 Spring 提供的(非 JSR 标准),它使得 Spring 能够处理方法级别的参数校验注解。 这是必需步骤。 2. 将校验注解直接放在方法参数上 :将 , , , 等校验注解直接应用于对应的 或 参数。 一定一定不要忘记在类上加上 注解了,这个参数可以告诉 Spring 去校验方法参数。 全局异常处理 介绍一下我们 Spring 项目必备的全局处理 Controller 层异常。 相关注解: 1. :注解定义全局异常处理类 2. :注解声明异常处理方法 如何使用呢?拿我们在第 5 节参数校验这块来举例子。如果方法参数不对的话就会抛出 ,我们来处理这个异常。 更多关于 Spring Boot 异常处理的内容,请看我的这两篇文章: 1. SpringBoot 处理异常的几种常见姿势 2. 使用枚举简单封装一个优雅的 Spring Boot 全局异常处理! 事务 在要开启事务的方法上使用 注解即可! 我们知道 Exception 分为运行时异常 RuntimeException 和非运行时异常。在 注解中如果不配置 属性,那么事务只会在遇到 的时候才会回滚,加上 ,可以让事务在遇到非运行时异常时也回滚。 注解一般可以作用在 或者 上。 作用于类 :当把 注解放在类上时,表示所有该类的 public 方法都配置相同的事务属性信息。 作用于方法 :当类配置了 ,方法也配置了 ,方法的事务会覆盖类的事务配置信息。 更多关于 Spring 事务的内容请查看我的这篇文章:可能是最漂亮的 Spring 事务管理详解 。 JPA Spring Data JPA 提供了一系列注解和功能,帮助开发者轻松实现 ORM(对象关系映射)。 创建表 用于声明一个类为 JPA 实体类,与数据库中的表映射。 指定实体对应的表名。 主键生成策略 声明字段为主键。 指定主键的生成策略。 JPA 提供了 4 种主键生成策略: :通过数据库表生成主键。 :通过数据库序列生成主键(适用于 Oracle 等数据库)。 :主键自增长(适用于 MySQL 等数据库)。 :由 JPA 自动选择合适的生成策略(默认策略)。 通过 声明自定义主键生成策略: 等价于: JPA 提供的主键生成策略有如下几种: 字段映射 用于指定实体字段与数据库列的映射关系。 :指定数据库列名。 :指定是否允许为 。 :设置字段的长度(仅适用于 类型)。 :指定字段的数据库类型和默认值。 忽略字段 用于声明不需要持久化的字段。 其他不被持久化的字段方式: :静态字段不会被持久化。 :最终字段不会被持久化。 :使用 Java 的 关键字声明的字段不会被序列化或持久化。 大字段存储 用于声明大字段(如 或 )。 枚举类型映射 用于将枚举类型映射为数据库字段。 :存储枚举的序号(默认)。 :存储枚举的名称(推荐)。 数据库中存储的值为 或 。 审计功能 通过 JPA 的审计功能,可以在实体中自动记录创建时间、更新时间、创建人和更新人等信息。 审计基类: 配置审计功能: 简单介绍一下上面涉及到的一些注解: 1. : 表示该字段为创建时间字段,在这个实体被 insert 的时候,会设置值 2. :表示该字段为创建人,在这个实体被 insert 的时候,会设置值 、 同理。 3. :开启 JPA 审计功能。 修改和删除操作 注解用于标识修改或删除操作,必须与 一起使用。 关联关系 JPA 提供了 4 种关联关系的注解: :一对一关系。 :一对多关系。 :多对一关系。 :多对多关系。 JSON 数据处理 在 Web 开发中,经常需要处理 Java 对象与 JSON 格式之间的转换。Spring 通常集成 Jackson 库来完成此任务,以下是一些常用的 Jackson 注解,可以帮助我们定制化 JSON 的序列化(Java 对象转 JSON)和反序列化(JSON 转 Java 对象)过程。 过滤 JSON 字段 有时我们不希望 Java 对象的某些字段被包含在最终生成的 JSON 中,或者在将 JSON 转换为 Java 对象时不处理某些 JSON 属性。 作用在类上用于过滤掉特定字段不返回或者不解析。 作用于字段或 方法级别,用于指定在序列化或反序列化时忽略该特定属性。 更适用于在类定义时明确排除多个字段,或继承场景下的字段排除; 则更直接地用于标记单个具体字段。 格式化 JSON 数据 用于指定属性在序列化和反序列化时的格式。常用于日期时间类型的格式化。 比如: 扁平化 JSON 对象 注解作用于字段上,用于在序列化时将其嵌套对象的属性“提升”到当前对象的层级,反序列化时执行相反操作。这可以使 JSON 结构更扁平。 假设有 类,包含 和 两个嵌套对象。 未扁平化之前的 JSON 结构: 使用 扁平对象: 扁平化后的 JSON 结构: 测试 一般作用于测试类上, 用于声明生效的 Spring 配置文件。 是 JUnit 框架(通常是 JUnit 5 Jupiter)提供的注解,用于标记一个方法为测试方法。虽然不是 Spring 自身的注解,但它是执行单元测试和集成测试的基础。 被声明的测试方法的数据会回滚,避免污染测试数据。 是 Spring Security Test 模块提供的注解,用于在测试期间模拟一个已认证的用户。可以方便地指定用户名、密码、角色(authorities)等信息,从而测试受安全保护的端点或方法。 注解分类总结 (表格) 写在最后 如果内容对你有帮助的话,欢迎顺手给 JavaGuide 点一个免费的 Star 支持一下:GitHub | Gitee。 JavaGuide 已持续维护近七年,累计 6100+ 次提交,来自 620+ 位贡献者共同完善。你的 Star、反馈和 PR,都是这个项目继续更新的动力。 如果你正在准备后端/AI 应用开发面试,也可以了解一下我的知识星球,里面包括后端和 AI 实战项目、简历优化、一对一提问和高频考点资料,已经持续维护六年。