查缺补漏
springboot有哪些功能、异步任务、定时任务还有没有其他的
Spring Boot 本质上是用来简化 Spring 项目开发、配置、部署和集成的。常用功能还有很多。
核心功能
-
自动配置
Spring Boot 会根据你引入的依赖自动配置组件,比如引入spring-boot-starter-web后自动配置 Spring MVC、Tomcat、JSON 转换等。 -
Starter 依赖管理
用starter简化依赖引入,例如:spring-boot-starter-web spring-boot-starter-data-jpa spring-boot-starter-security spring-boot-starter-data-redis -
内嵌 Web 容器
默认内嵌 Tomcat,也可以换 Jetty、Undertow,不需要单独部署到外部 Tomcat。 -
配置管理
支持application.yml、application.properties、环境变量、命令行参数等。 -
多环境配置
例如:application-dev.yml application-test.yml application-prod.yml
任务相关功能
- 异步任务
用于把耗时任务放到子线程执行,比如发送邮件、导出文件、日志处理等。
@EnableAsync
@SpringBootApplication
public class App {
}
@Service
public class AsyncService {
@Async
public void sendEmail() {
System.out.println("异步发送邮件");
}
}
常用注解:
@EnableAsync
@Async
- 定时任务
用于定时执行任务,比如每天凌晨清理数据、每隔 5 分钟同步订单。
@EnableScheduling
@SpringBootApplication
public class App {
}
@Component
public class ScheduleTask {
@Scheduled(cron = "0 0 2 * * ?")
public void cleanData() {
System.out.println("每天凌晨 2 点执行");
}
}
常用注解:
@EnableScheduling
@Scheduled
常见写法:
@Scheduled(fixedRate = 5000) // 每 5 秒执行一次
@Scheduled(fixedDelay = 5000) // 上次执行完 5 秒后再执行
@Scheduled(cron = "0 0 2 * * ?") // cron 表达式
还有这些常用功能
- Web 开发
用于开发 REST API、传统 MVC 接口。
常用注解:
@RestController
@RequestMapping
@GetMapping
@PostMapping
@RequestBody
@PathVariable
@RequestParam
- 数据库访问
支持 MyBatis、MyBatis-Plus、JPA、JdbcTemplate 等。
常见技术:
Spring JDBC
Spring Data JPA
MyBatis
MyBatis-Plus
Druid / HikariCP
- 事务管理
用于保证数据库操作的一致性。
@Transactional
public void createOrder() {
// 扣库存
// 创建订单
// 扣余额
}
常用注解:
@Transactional
- 缓存
可以集成 Redis、Caffeine、Ehcache 等。
@Cacheable
@CachePut
@CacheEvict
例如:
@Cacheable(value = "user", key = "#id")
public User getUser(Long id) {
return userMapper.selectById(id);
}
- Redis 集成
常用于缓存、分布式锁、验证码、登录 token、排行榜等。
@Autowired
private RedisTemplate<String, Object> redisTemplate;
- 消息队列
可以集成 RabbitMQ、Kafka、RocketMQ 等。
常用于:
异步解耦
削峰填谷
订单通知
日志收集
延迟任务
- Spring Security 安全认证
用于登录认证、权限控制、JWT、OAuth2 等。
常见功能:
登录认证
接口鉴权
角色权限
密码加密
JWT Token
OAuth2
- 参数校验
用于校验前端传入的数据。
public class UserDTO {
@NotBlank
private String username;
@Min(18)
private Integer age;
}
Controller 中使用:
@PostMapping("/user")
public void addUser(@Valid @RequestBody UserDTO dto) {
}
常用注解:
@NotNull
@NotBlank
@NotEmpty
@Min
@Max
@Email
@Pattern
@Valid
- 全局异常处理
统一处理异常,避免每个接口都写 try-catch。
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public String handle(Exception e) {
return "系统异常";
}
}
常用注解:
@RestControllerAdvice
@ExceptionHandler
- 日志功能
默认集成 Logback,可以配合 SLF4J 使用。
private static final Logger log = LoggerFactory.getLogger(UserService.class);
log.info("查询用户:{}", id);
- 文件上传下载
常用于头像上传、Excel 导入导出、附件下载等。
@PostMapping("/upload")
public String upload(MultipartFile file) {
return file.getOriginalFilename();
}
- 邮件发送
可以集成 spring-boot-starter-mail。
常用于:
验证码
注册通知
告警邮件
订单通知
- Actuator 监控
用于查看服务健康状态、内存、线程、接口等运行信息。
常见端点:
/actuator/health
/actuator/info
/actuator/metrics
- AOP 切面编程
常用于日志、权限校验、接口耗时统计、统一参数处理等。
@Aspect
@Component
public class LogAspect {
}
常用注解:
@Aspect
@Before
@After
@Around
- 事件机制
适合做业务解耦,比如用户注册成功后发送短信、邮件、优惠券。
@EventListener
public void handle(UserRegisterEvent event) {
// 处理注册事件
}
- WebSocket
用于实时通信。
常见场景:
在线聊天
实时通知
消息推送
大屏数据刷新
- 测试支持
Spring Boot 提供完整测试支持。
@SpringBootTest
class UserServiceTest {
}
常用:
@SpringBootTest
@MockBean
@WebMvcTest
- 开发热部署
通过 spring-boot-devtools 实现开发阶段自动重启。
常见功能分类总结
| 类型 | 功能 |
|---|---|
| 基础能力 | 自动配置、Starter、内嵌 Tomcat、配置文件 |
| Web 开发 | REST API、MVC、JSON、文件上传 |
| 数据库 | MyBatis、JPA、事务、连接池 |
| 任务 | 异步任务、定时任务 |
| 缓存 | Redis、Caffeine、Spring Cache |
| 安全 | Spring Security、JWT、OAuth2 |
| 消息 | RabbitMQ、Kafka、RocketMQ |
| 运维 | Actuator、日志、健康检查 |
| 工程能力 | 测试、热部署、多环境配置 |
| 高级功能 | AOP、事件、WebSocket、邮件、参数校验 |
简单说,Spring Boot 常用的不只是异步任务和定时任务,完整项目里通常还会用到:
Web 接口
数据库操作
事务
Redis 缓存
权限认证
参数校验
全局异常
日志
文件上传
消息队列
邮件
AOP
Actuator 监控
多环境配置
测试
如果是面试回答,可以这样说:
Spring Boot 的核心是自动配置和 Starter 机制,简化 Spring 应用开发。常用功能包括 Web 开发、配置管理、数据访问、事务管理、异步任务、定时任务、缓存、消息队列、安全认证、参数校验、全局异常处理、日志、Actuator 监控、AOP、事件机制以及测试支持等。
MySQL 中常说的“索引失效”,一般指:明明字段上有索引,但 SQL 执行时没有走这个索引,或者走了索引但效果很差。
常见情况如下。
1. 对索引列使用函数
select * from user where year(create_time) = 2026;
create_time 上即使有索引,也很可能失效,因为数据库要先对每一行执行 year()。
推荐写法:
select * from user
where create_time >= '2026-01-01'
and create_time < '2027-01-01';
2. 对索引列进行计算
select * from user where age + 1 = 19;
age 上的索引可能失效。
推荐写法:
select * from user where age = 18;
3. 使用左模糊查询
select * from user where name like '%张';
select * from user where name like '%张%';
这种情况一般无法利用普通 B+Tree 索引。
可以走索引的情况:
select * from user where name like '张%';
因为前缀是确定的。
4. 字符串类型不加引号,发生隐式类型转换
假设 phone 是 varchar 类型,并且有索引:
select * from user where phone = 13800138000;
可能导致索引失效,因为数据库可能会把 phone 字段转换成数字再比较。
推荐写法:
select * from user where phone = '13800138000';
5. 查询条件中使用 or,但部分字段没有索引
select * from user where name = 'Tom' or age = 18;
如果 name 有索引,但 age 没有索引,可能导致整体不走索引。
优化方式:
select * from user where name = 'Tom'
union
select * from user where age = 18;
或者给 age 也加索引。
6. 联合索引不满足最左前缀原则
假设有联合索引:
index idx_user_name_age_city(name, age, city)
可以走索引:
where name = 'Tom'
where name = 'Tom' and age = 18
where name = 'Tom' and age = 18 and city = '北京'
不一定能充分走索引:
where age = 18
where city = '北京'
where age = 18 and city = '北京'
因为跳过了最左边的 name。
7. 联合索引中范围查询后面的字段无法继续充分利用索引
假设联合索引:
index idx_name_age_city(name, age, city)
SQL:
select * from user
where name = 'Tom'
and age > 18
and city = '北京';
一般情况下:
name 可以用索引
age 可以用索引范围查询
city 可能无法继续用于索引定位
因为 age > 18 是范围查询,后面的 city 很可能无法继续用于精确匹配。
8. 使用 !=、<>、not in、not like
select * from user where age != 18;
select * from user where age <> 18;
select * from user where id not in (1, 2, 3);
select * from user where name not like '张%';
这些条件通常选择性较差,优化器可能放弃索引,直接全表扫描。
注意:不是绝对不走索引,要看数据量、选择性、统计信息和优化器判断。
9. 使用 is null 或 is not null
select * from user where email is null;
select * from user where email is not null;
不一定失效,要看数据分布。
如果 email is null 的数据很少,可能走索引。
如果大量数据都是 null 或 not null,优化器可能认为全表扫描更快。
10. 查询返回数据量太大
即使条件字段有索引,如果查询命中大量数据,优化器也可能不走索引。
例如:
select * from user where gender = '男';
如果表里 90% 都是 男,走索引反而要回表很多次,不如全表扫描。
这种叫索引选择性太低。
11. 使用 select * 导致大量回表
select * from user where age = 18;
如果 age 是普通索引,但查询所有字段,需要通过二级索引找到主键后再回表查询整行数据。
如果命中数据很多,优化器可能放弃索引。
优化方式:
select id, age from user where age = 18;
如果查询字段都在索引里,可以形成覆盖索引。
12. 排序字段和索引顺序不一致
假设有索引:
index idx_age_name(age, name)
可能走索引排序:
select * from user
where age = 18
order by name;
不一定能利用索引排序:
select * from user
order by name;
因为联合索引最左列是 age,不是 name。
13. 分页 offset 太大
select * from user order by id limit 1000000, 10;
虽然可能走 id 索引,但会扫描并丢弃前面大量数据,性能很差。
优化方式:
select * from user
where id > 1000000
order by id
limit 10;
或者先查主键再回表:
select u.*
from user u
join (
select id from user order by id limit 1000000, 10
) t on u.id = t.id;
14. 隐式字符集或排序规则转换
比如两个表关联字段字符集不同:
select *
from user u
join order_info o on u.user_code = o.user_code;
如果 u.user_code 和 o.user_code 的字符集、排序规则不同,可能发生隐式转换,导致索引效果变差。
15. 表数据太少
如果表只有几十行,即使有索引,优化器也可能选择全表扫描。
因为全表扫描成本更低。
16. 统计信息不准确
MySQL 优化器依赖统计信息判断是否走索引。如果统计信息不准,可能选错执行计划。
可以尝试:
analyze table user;
精简版
MySQL 索引失效常见场景包括:对索引列使用函数或计算、发生隐式类型转换、
like左模糊查询、联合索引不满足最左前缀原则、范围查询后面的列无法继续充分利用索引、or条件中部分字段无索引、使用!=、not in、not like、查询返回数据量过大、索引选择性太低、select *导致大量回表、排序字段和索引顺序不一致、字符集隐式转换、统计信息不准确等。最终是否走索引要以explain执行计划为准。
MySQL 事务隔离级别通常分为 4 种:
| 隔离级别 | 中文名 | 可能出现的问题 | 说明 |
|---|---|---|---|
READ UNCOMMITTED |
读未提交 | 脏读、不可重复读、幻读 | 可以读到其他事务未提交的数据,隔离性最低 |
READ COMMITTED |
读已提交 | 不可重复读、幻读 | 只能读到已提交的数据,Oracle 默认级别 |
REPEATABLE READ |
可重复读 | 理论上可能幻读 | MySQL InnoDB 默认级别,同一事务内多次读取结果一致 |
SERIALIZABLE |
串行化 | 基本避免并发问题 | 隔离性最高,事务串行执行,性能最低 |
MySQL InnoDB 默认隔离级别是:
REPEATABLE READ
可以查看当前隔离级别:
SELECT @@transaction_isolation;
简单记忆:
读未提交 < 读已提交 < 可重复读 < 串行化
隔离级别越高,并发性能通常越低,但数据一致性越强。
ConcurrentHashMap
| 场景 | 是否需要线程安全 Map |
|---|---|
| 登录后绑定客户端 | 需要,put |
| Netty 心跳检测 | 需要,更新心跳时间 |
| 定时任务判断超时 | 需要,遍历 + remove |
| 客户端重连替换旧连接 | 需要,put + 关闭旧 Channel |
| 实时接收客户端帧数据 | 需要,可能读取会话状态 |
| 给客户端发送响应 | 需要,取 Channel 后发送 |
| 前端远程控制客户端 | 更需要,业务线程访问 Netty 连接 |

浙公网安备 33010602011771号