☰
Springboot 常用注解(苍穹外卖)
2026/10/31 1:36:26 网站建设 项目流程

1、@RestController

@RestController = @Controller + @ResponseBody

它是接口的 “业务入口”:

  • 你写的SetmealController、AddressBookController都用它标记
  • 里面的方法用@GetMapping/@PostMapping标记,直接接收前端请求、执行业务逻辑、返回数据
  • 就像餐厅里的服务员,直接对接顾客,处理点餐、结账这些业务请求
@RestController @RequestMapping("/admin/setmeal") public class SetmealController { // 套餐分页查询接口,直接给前端返回数据 @GetMapping("/page") public Result<PageResult> page(...) { return Result.success(pageResult); } }

2.@RestControllerAdvice

它是所有接口的 “全局管家”:(作全局异常处理器)

  • 不写业务接口,只做 “增强处理”,比如全局异常捕获、统一响应格式、全局数据处理
  • 它的方法永远不会被前端直接调用,只有当业务接口出问题 / 需要增强时,才会被触发
  • 就像餐厅里的后勤主管,服务员出问题了(比如顾客投诉、订单报错),主管统一出来处理,不用每个服务员自己解决
@RestControllerAdvice public class GlobalExceptionHandler { // 全局捕获所有业务异常,统一返回错误信息 @ExceptionHandler(BaseException.class) public Result handleException(BaseException ex) { log.error("异常:{}", ex.getMessage()); return Result.error(ex.getMessage()); } }

3、@ExceptionHandler

@ExceptionHandler = 抓异常的 “钩子”

哪个方法加了它,哪个方法就负责 “接住” 抛出来的异常!

必须配合@RestControllerAdvice一起用!

@RestControllerAdvice // 全局管家 public class GlobalExceptionHandler { @ExceptionHandler // 抓异常钩子 public Result handler(BaseException e) { // 处理异常 } }

括号里写的是什么异常,它就抓什么异常

例子 1:只抓自定义业务异常

@ExceptionHandler(BaseException.class)

只抓:(所有继承BaseException的异常)

优先匹配最精确、最子类的异常,找不到才去匹配父类。

例子 2:抓所有异常(包括空指针、数据库错)

@ExceptionHandler(Exception.class)

例子3:括号里啥都不写 → 默认捕获「方法参数声明的那个异常类型」

@ExceptionHandler public Result exceptionHandler(BaseException ex){ }

方法参数写的是BaseException ex

那它就只抓:BaseException 本身,所有继承 BaseException 的子类自定义异常

4、@RequestMapping

@RequestMapping:一般写在类上,统一给整个控制器加接口前缀

@RestController @RequestMapping("/admin/employee") public class EmployeeController { }

作用:

  1. 给当前类所有接口统一加路径前缀
  2. 后面每个方法的地址,都会拼接在它后面

比如:

  • 方法@PostMapping("/login")
  • 最终完整路径:/admin/employee/login

5、@PostMapping

写在方法上

@PostMapping("/login") public Result login(){...}

等价于简写:

@RequestMapping(value = "/login", method = RequestMethod.POST)

作用:

  • 限定这个接口只能用 POST 请求
  • 适合:登录、新增、修改、删除(要传请求体数据)

6、@GetMapping

作用:

  • 只能GET 请求
  • 适合:查询、分页、获取数据
  • 参数一般拼在 URL 地址栏,不能传 JSON 请求体

还有其他的Mapping直接总结:

注解请求方式业务用法
@GetMappingGET查询、获取详情、分页列表
@PostMappingPOST登录、新增、提交表单
@PutMappingPUT整体修改、全量更新
@DeleteMappingDELETE删除数据
@PatchMappingPATCH局部更新、部分字段修改

7、@Slf4j

@Slf4j是Lombok 提供的注解,加在类上,自动帮你生成日志对象,不用自己手动写。

写上@Slf4j之后,你在类里可以直接用:

log.info("员工登录:{}", dto); log.error("异常信息:{}", e.getMessage());

不用自己手动声明 Logger 对象。

不加 @Slf4j 你要自己手写

如果不用这个注解,你得每一个类都手动写一行:

private static final Logger log = LoggerFactory.getLogger(EmployeeController.class);

很麻烦、重复代码多。

加了 @Slf4j,这行代码 Lombok 自动帮你生成了。

日志常用四个级别(从低到高)

log.debug("调试信息"); // 开发调试用 log.info("普通业务日志"); // 正常业务记录 log.warn("警告信息"); // 不崩溃但有风险 log.error("错误异常"); // 报错、异常

8、@Configuration

@Configuration标记这个类是【配置类】Spring 会把它当成配置文件来用,代替传统 xml 配置。

一、核心作用

  1. 被@Configuration修饰的类,本身也会被 Spring 当成 Bean 纳入容器管理

  2. 类里面配合@Bean注解,手动创建对象、交给 Spring 容器,供后续@Autowired注入使用

二、最经典用法搭配

@Configuration public class MyConfig { // @Bean:把方法返回的对象,交给Spring容器 @Bean public RestTemplate restTemplate() { return new RestTemplate(); } }

之后在任意 Controller/Service 直接注入:

@Autowired private RestTemplate restTemplate;

注意:

自己写的类用@Service/@Component托管;第三方框架类(RedisTemplate、RestTemplate、Mybatis 插件等)没法加注解,就用@Configuration + @Bean手动注册。

解释:

第一种:自己写的类 → 直接加注解托管

你自己写的类:

  • EmployeeService

  • DishService

  • 各种工具类、自定义类

你能改源代码,所以直接在类上加:

  • @Service

  • @Component

  • @RestController

举例:

@Service public class EmployeeServiceImpl implements EmployeeService { // 这是你自己写的类,想加注解随便加 }

加完注解 → Spring 启动自动把这个类创建对象、放进容器后面直接:

@Autowired private EmployeeService employeeService;

第二种:第三方框架类 → 你改不了源码

比如:RedisTemplate,RestTemplate,Mybatis 分页插件,阿里云 OSS 工具类,JwtUtil 第三方类

这些类不是你写的,是框架自带的,你打不开源码、不能在类上面加 @Service / @Component。

用@Configuration + @Bean手动帮你 new 对象,然后放进 Spring 容器。


举个最直观例子

// 这是Spring框架自带的类,你不能编辑它源码 public class RestTemplate { // 里面代码都是框架写好的 }

你没法在上面加@Component。

那你就写配置类,手动创建并交给 Spring

@Configuration public class WebConfig { @Bean public RestTemplate restTemplate() { // 手动new出来 return new RestTemplate(); } }
  • @Configuration:告诉 Spring 这是配置类,@Bean:把方法返回的对象自动放入 Spring 容器

三、关键特性(重点)

1. 配置类里面@Bean方法互相调用,不会重复 new 对象

@Configuration是Full 全配置模式,底层用 CGLIB 动态代理,调用本类@Bean方法,直接从容器拿现成 Bean,不会新建。

9、@ConditionalOnMissingBean

只有当 Spring 容器里没有这个 Bean时,我才创建

作用:保证一个类在 Spring 容器里只有一个实例(Bean)。

它不是必须加的!它只用于一种场景:

你不确定别人会不会也创建这个 Bean!

示例:

@Configuration public class MyConfig { /** * @ConditionalOnMissingBean * 作用:当 Spring 容器中 没有 JdbcTemplate 这个 Bean 时 * 才创建这个 Bean */ @Bean @ConditionalOnMissingBean public JdbcTemplate jdbcTemplate() { return new JdbcTemplate(); } }

10、@Controller

标记这是一个控制器

用来接收前端请求

默认返回:页面(视图)比如返回login.html

@Controller // 标记这是控制器 public class UserController { @RequestMapping("/hello") // 访问地址:localhost:8080/hello public String hello() { return "index"; // 返回页面 index.html } }

11、@ResponseBody

不可以单独使用。它必须搭配控制器注解使用:@Controller。

@ResponseBody仅负责转换返回数据为 JSON / 字符串,本身不能把类交给 Spring 管理、也无法接收请求。

@Controller // 接收请求 public class UserController { // 加了 @ResponseBody → 返回 JSON,不返回页面 @GetMapping("/user") @ResponseBody public Result getUser() { return Result.success("查询成功"); } }

不加 @ResponseBody:

@Controller @GetMapping("/user") public Result getUser() { return Result.success(); }

Spring 会把返回值当成页面名字去查找

比如去找:Result.success.jsp→ 直接报 404 错误

12、@Mapper

@Mapper 是 MyBatis 提供的注解,专门标记一个接口为 Mapper 接口。

@Mapper public interface UserMapper { User selectById(Integer id); }

自动做 :

不用写实现类,自动生成一个代理对象(impl),把这个对象交给 Spring 管理,可以 @Autowired 注入

自动生成的实现类(impl),会自动帮你做:连接数据库,执行 SQL,封装结果集,关闭连接,处理异常

13、@MapperScan

和@Mapper功能一模一样,都是告诉 MyBatis:这是 Mapper 接口,帮我生成代理对象!

@MapperScan直接在启动类上加一行,扫描整个包,所有接口自动生效!

@SpringBootApplication @MapperScan("com.sky.mapper") // 扫描这个包下所有Mapper public class SkyApplication { public static void main(String[] args) { SpringApplication.run(SkyApplication.class, args); } }

14、@Component

@Component是 Spring 通用组件注解作用:把当前类交给 Spring 容器管理,自动创建对象,放入容器,后续可以用 @Autowired 注入

平时用的这几个,底层全部继承 @Component:

  1. @RestController👉 控制器层
  2. @Controller👉 控制器层
  3. @Service👉 业务层
  4. @Repository👉 持久层 / Mapper

15、@ConfigurationProperties

@ConfigurationProperties(prefix = "sky.jwt")

= 自动把 application.yml 里的配置,读到 Java 类里!**

配置文件里一定有这段

application.yml

sky: jwt: admin-secret-key: the-key admin-ttl: 7200000

它会自动匹配前缀sky.jwt把下面的配置自动赋值到 Java 类的字段里!

比如这个类:

@Component @ConfigurationProperties(prefix = "sky.jwt") public class JwtProperties { private String adminSecretKey; private Long adminTtl; // get set }

效果:

sky.jwt.admin-secret-key→ 自动赋值给adminSecretKey

sky.jwt.admin-ttl→ 自动赋值给adminTtl

16、Swagger常用注解

1. @Api

作用:给整个控制器打标签,接口文档里显示模块名称

@Api(tags = "员工管理接口") @RestController @RequestMapping("/admin/employee") public class EmployeeController { }

2. @ApiOperation

作用:给单个接口加功能描述

@PostMapping("/login") @ApiOperation("员工登录") public Result<EmployeeLoginVO> login(@RequestBody EmployeeLoginDTO dto){ }

3. @ApiModel

作用:给实体类起说明名称

@ApiModel("员工登录DTO") public class EmployeeLoginDTO { }

4. @ApiModelProperty

作用:给类的字段加说明、是否必填、示例值

@ApiModelProperty(value = "用户名",required = true,example = "admin") private String username; @ApiModelProperty(value = "密码",required = true,example = "123456") private String password;

17、@Target

@Target 用在自定义注解上,(一般和@Retention搭配使用)

作用:规定这个注解能贴在哪

常用值(必须记住这 4 个)

@Target({ ElementType.TYPE, // 类、接口、枚举 ElementType.METHOD, // 方法 ElementType.FIELD, // 字段(成员变量) ElementType.PARAMETER // 方法参数 })

示例:

@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface AutoFill { OperationType value(); }

18、@Retention

作用:控制注解能保留到哪个阶段(生命周期)

三种级别(从短到长):

RetentionPolicy.SOURCE // 1. 只在源码阶段,编译后直接丢弃 RetentionPolicy.CLASS // 2. 保留到class字节码,运行时丢失(默认) RetentionPolicy.RUNTIME // 3. 一直保留,运行时可以通过反射读取

1.SOURCE源码级别

  • 只在.java源码里有效

  • 编译成 class 就没了

  • 用途:IDE 校验、Lombok 这类编译期生成代码

2.CLASS字节码级别(默认不写就是它)

  • 留在 class 文件里

  • 程序运行时拿不到

  • 一般普通标记注解用的少

3.RUNTIME运行时级别(开发最常用)

  • 源码 → class →运行时还在

  • 可以通过反射获取注解信息

  • Spring、MyBatis、自定义切面、@AutoFill 全都必须用这个

使用场景:

例子 1:自动填充注解 @AutoFill

// 限制:只能写在方法上 @Target(ElementType.METHOD) // 限制:运行时还能被反射/AOP读取 @Retention(RetentionPolicy.RUNTIME) public @interface AutoFill { }

例子 2:权限注解、日志注解、拦截注解 全是这样

@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface LogRecord { }

19、@Pointcut

@Pointcut = 切点(切面的 “瞄准器”)作用:告诉 AOP 要对哪些方法进行增强!

@Pointcut 最常用的 2 种写法(两种可用&&连接)

1)按包 / 类 / 方法拦截(execution)

// 拦截 mapper 包下所有类的所有方法 @Pointcut("execution(* com.sky.mapper.*.*(..))") public void pt(){}

2)按注解拦截(@annotation)

// 拦截所有加了 @AutoFill 注解的方法 @Pointcut("@annotation(com.sky.annotation.AutoFill)") public void autoFillPointCut(){}

20、@Aspect

@Aspect = 告诉 Spring:这个类是【切面类】,里面装 AOP 增强逻辑

import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; /** * @Aspect 【关键】标记这个类是 AOP 切面类 * @Component 必须交给 Spring 管理,否则 AOP 不生效 * @Slf4j 日志输出 */ @Aspect // ✅ 核心注解:标记这是【切面】 @Component // ✅ 必须加:交给 Spring 容器管理 @Slf4j public class MyAspect { // 1. 定义切点:要拦截哪些方法 @Pointcut("execution(* com.sky.service.*.*(..))") public void pt(){} // 2. 前置通知:方法执行前运行 @Before("pt()") public void before(){ log.info("【切面】方法执行前..."); } // 3. 后置通知:方法执行后运行 @After("pt()") public void after(){ log.info("【切面】方法执行后..."); } }

21、@Before,@After,@AfterReturning,@AfterThrowing,@Around

注解作用执行时机
@Before前置通知目标方法执行之前运行
@After后置通知目标方法执行之后(无论是否异常都执行)
@AfterReturning返回通知目标方法正常执行完后运行
@AfterThrowing异常通知目标方法抛出异常后运行
@Around环绕通知方法执行前后都可以增强(最强大)

1)@Before—— 方法执行前

最常用:权限校验、日志记录、自动填充

@Before("execution(* com.sky.service.*.*(..))") public void before(JoinPoint joinPoint) { System.out.println("方法执行前 ~~~"); }

2)@After—— 方法执行后(无论是否异常都走)

相当于finally

@After("execution(* com.sky.service.*.*(..))") public void after() { System.out.println("方法一定执行后 ~~~"); }

3)@AfterReturning—— 方法正常返回后

只有不抛异常才会走

@AfterReturning("execution(* com.sky.service.*.*(..))") public void afterReturning() { System.out.println("方法正常执行完毕!"); }

4)@AfterThrowing—— 方法抛异常时

只有抛异常才会走

@AfterThrowing("execution(* com.sky.service.*.*(..))") public void afterThrowing() { System.out.println("方法出错了!出现异常!"); }

5)@Around—— 环绕通知(最强大)

可以控制方法是否执行、获取返回值、计算耗时

@Around("execution(* com.sky.service.*.*(..))") public Object around(ProceedingJoinPoint pjp) throws Throwable { System.out.println("方法执行前"); // 执行目标方法(必须写!) Object result = pjp.proceed(); System.out.println("方法执行后"); return result; // 返回方法结果 }

三、执行顺序

正常执行:

@Around 前 @Before 目标方法 @AfterReturning @After @Around 后

抛异常时:

@Around 前 @Before 目标方法(报错) @AfterThrowing @After

22、@RequestParam

@RequestParam 用来接收「地址栏拼接的普通参数」也就是接收:?name=xxx&age=18这种Query 参数

一、核心用法

1. 基本写法

// 浏览器地址:/user/get?name=张三 @GetMapping("/user/get") public Result getUser(@RequestParam String name){ // name 就拿到 "张三" }

2. 参数名不一致时

前端传:?username=张三后端变量叫name,就要指定映射:

@RequestParam("username") String name

3. 设置是否必传

// 默认 required = true 必传,不传400报错 @RequestParam(value = "username", required = false) String name

4. 设置默认值

不传参数时给默认值:

@RequestParam(defaultValue = "1") Integer page
  • 不加 @RequestParam前端参数名 和 后端形参名一致也能自动接收;

  • 加 @RequestParam可以起别名、设必传、设默认值,更灵活规范。

示例:

前端传1,2,3逗号拼接字符串,后端 3 种接收方式

前端传参形式:

?ids=1,2,3

方式一:用 @RequestParam 接字符串自己分割

@GetMapping("/list") public Result getList(@RequestParam String ids){ // 分割成数组 String[] idArr = ids.split(","); // 再转 List<Long> List<Long> idList = Arrays.stream(idArr) .map(Long::valueOf) .collect(Collectors.toList()); }

(优先)方式二:直接接List<Long>(Spring 自动切分)

@GetMapping("/list") public Result getList(@RequestParam List<Long> ids){ // 直接就能用,ids 里面就是 [1,2,3] }

最简单、项目最常用原理:Spring 自动按逗号分割封装成集合


方式三:直接接 数组

@GetMapping("/list") public Result getList(@RequestParam Long[] ids){ // ids = [1,2,3] }

23、@PathVariable

作用:获取 URL 路径占位符{变量}里的参数(路径参数)

请求格式:/user/10接口定义

@GetMapping("/user/{id}") public Result getUser(@PathVariable Integer id){ // id=10 }

特点:参数拼在请求路径中,无?,REST 风格

常用简写:参数名和占位符同名可省略括号,@PathVariable Integer id

24、@SpringBootApplication

@SpringBootApplication是组合注解,它内部包含了:

1.@SpringBootConfiguration

标记这是一个配置类

相当于@Configuration

2.@EnableAutoConfiguration

SpringBoot 最核心:自动配置

自动加载 Redis、Mysql、MyBatis、OSS 等配置

自动创建DataSource、RedisTemplate等 Bean

3.@ComponentScan

自动扫描组件

扫描:@Controller、@Service、@Mapper、@Component、@Aspect

告诉 Spring 去哪里扫描这些 Bean

把它们变成 Bean 交给 Spring 管理


@SpringBootApplication 会自动扫描:

启动类 所在的包 以及 所有子包

例如:启动类包:com.sky

会自动扫描:

com.sky.controller

com.sky.service

com.sky.mapper

等所有子包

示例:

@SpringBootApplication @EnableTransactionManagement //开启注解方式的事务管理 @Slf4j @EnableCaching//开启缓存注解功能 @EnableScheduling//开启任务调度 public class SkyApplication { public static void main(String[] args) { SpringApplication.run(SkyApplication.class, args); log.info("server started"); } }

25、@Transactional

声明事务!让方法里的数据库操作:要么全部成功,要么全部失败回滚。

@Service public class UserService { @Transactional // 加这里! public void add() { // 两步数据库操作 userMapper.insert(); logMapper.insert(); // 如果这里报错 → 两步操作全部回滚! } }

默认:运行时异常(RuntimeException)才回滚编译期异常不回滚

想让所有异常都回滚:

@Transactional(rollbackFor = Exception.class)

不能单独用

因为 @Transactional 必须满足 2 个条件才生效:

  1. 这个类必须交给 Spring 管理(变成 Bean)→ 需要:@Service/@Component

  2. Spring 必须开启事务功能→ 需要:@EnableTransactionManagement(SpringBoot 自动开)

26、@EnableTransactionManagement

必须开这个开关,@Transactional才会生效

@SpringBootApplication @EnableTransactionManagement // 开启事务 public class ReggieApplication { public static void main(String[] args) { Spring.run(...); } }

27、@EnableCaching

开启 Spring 缓存功能的总开关

必须先开这个开关,缓存注解@Cacheable,@CacheEvict,@CachePut才会生效

@SpringBootApplication @EnableCaching // 开启缓存 public class ReggieApplication { public static void main(String[] args) { SpringApplication.run(ReggieApplication.class, args); } }

28、@Cacheable

1.@Cacheable —— 查询用

作用:先查缓存,缓存没有才执行方法,查完自动存缓存

@Cacheable(cacheNames = "dishCache", key = "#categoryId")

2.@CachePut —— 修改 / 新增用

作用:一定执行方法,把最新结果更新到缓存

@CachePut(cacheNames = "dishCache", key = "#dish.id")

3.@CacheEvict —— 删除 / 清空用

作用:删除缓存

//删除某一对应key的缓存 @CacheEvict(cacheNames = "dishCache", key = "#dish.id")
// 清空整个缓存 @CacheEvict(cacheNames = "dishCache", allEntries = true)

29、@EnableScheduling

开启 Spring 的【定时任务】功能,让@Scheduled注解生效。

@SpringBootApplication @EnableScheduling // 开启定时任务 public class ReggieApplication { public static void main(String[] args) { SpringApplication.run(ReggieApplication.class, args); } }

30、@Scheduled

示例:

@Scheduled(cron = "0 0 2 * * ?") public void test3() { System.out.println("每天凌晨2点执行 → " + new Date()); }

@Scheduled 有 3 种核心用法(全部掌握)

1. fixedRate —— 固定频率执行

每隔多久执行一次,不管方法执行多久

@Scheduled(fixedRate = 5000) // 单位:毫秒

意思:每 5 秒执行一次


2. fixedDelay —— 固定延迟执行

方法执行完后,再等多久执行

@Scheduled(fixedDelay = 5000)

意思:执行完 → 等 5 秒 → 再执行


3. cron —— 最强大、最常用(指定时间)

像闹钟一样,指定:秒 分 时 日 月 周

@Scheduled(cron = "0 0 2 * * ?") // 每天凌晨2点执行

一、cron 表达式固定格式

一共 6 个部分,用空格分开:

秒 分 时 日 月 周

顺序绝对不能乱


二、每个位置的取值范围

位置

名称

取值

允许符号

1

秒

0-59

, - * /

2

分

0-59

, - * /

3

时

0-23

, - * /

4

日

1-31

, - * / ? L W

5

月

1-12

, - * /

6

周

1-7(1 = 周日,7 = 周六)

, - * / ? L #


三、5 个核心符号

1.*:每一秒 / 每一分 / 每一小时

代表 “所有”例:

* * * * * ?

意思:每秒都执行


2.?:不指定(日和周不能同时有值,必须一个用?)

日和周互斥!

指定了日 → 周必须用?

指定了周 → 日必须用?

例:

0 0 0 * * ?

每天 0 点执行(日用了 *,周用?)


3./:每隔多久执行一次

格式:开始时间/间隔

包括开始的0

例:

每 5 秒执行一次

0/5 * * * * ?

每 5 分钟执行一次

0 0/5 * * * ?

每 2 小时执行一次

0 0 0/2 * * ?

4.-:范围

例:

10-20 * * * * ?

每分钟的 10 秒~20 秒,每秒都执行


5.,:枚举(多个值)

例:

10,20,30 * * * * ?

每分钟的 10、20、30 秒执行


四、注意用例

每周一 9 点

0 0 9 ? * 2

周:1 = 周日,2 = 周一,3 = 周二…7 = 周六

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询