1 技术栈整体选型(企业稳定版)
本手册全套采用企业生产稳定版本,基于 SpringBoot3.x + JDK21 最新生态搭建,所有框架、中间件版本经过兼容性适配,彻底规避版本冲突、功能失效、线上兼容报错等问题,完全适配中小型企业微服务生产落地场景,新手可直接照搬使用。
所有技术选型兼顾稳定性、高性能、易维护、低学习成本,摒弃老旧淘汰组件,统一技术规范,适配后续架构扩容与迭代。
-
基础核心框架:SpringBoot 3.2.5、SpringCloud 2023.0.1、SpringCloudAlibaba 2023.0.1.0(官方适配稳定组合)
-
微服务治理组件:Nacos 2.3.2、Sentinel 1.8.8、Dubbo 3.2.9(服务注册、容错、RPC调用全套治理)
-
分布式事务:Seata 1.7.1(支持AT无侵入、TCC高精度两种模式)
-
消息中间件:RocketMQ 4.9.7(业务解耦)、Kafka 3.6.1(高吞吐日志采集)
-
多层数据存储:MySQL 8.0(主从分库分表)、Redis 7.2(缓存)、ES 8.13(全文检索)、MongoDB 7.0(非结构化数据)、Sharding-JDBC 5.4.1(分片存储)
-
工作流引擎:Flowable 7.2.0(适配各类审批业务)
-
权限认证框架:Sa-Token 1.37.0(主力轻量鉴权)、Spring Security 6.2.4(辅助OAuth2授权)
-
持久层框架:MyBatis-Flex 1.7.5(极简CRUD、无需手写SQL)
-
部署运维架构:Docker、K8s 1.29、Nginx 1.24(容器化、负载均衡全套)
-
缓存与文件存储:Caffeine 3.1.8(本地高性能缓存)、阿里云OSS(大文件存储)
-
监控链路体系:Prometheus、Grafana、SkyWalking、ELK(全链路监控、日志归集)
-
工程规范组件:SonarQube(代码检测)、XXL-Job(分布式定时任务)
2 项目架构与工程搭建(标准化分层)
本项目采用标准化微服务分层架构,按业务职责、技术能力拆分独立模块,统一父工程版本依赖,解决传统单体项目耦合严重、依赖混乱、难以维护、无法独立扩容的问题,结构清晰,小白可快速理解各模块作用。
2.1 工程模块拆分(各司其职)
所有模块职责单一、互不冗余,公共能力统一抽离,业务模块独立开发部署,方便迭代维护。
# 微服务整体工程结构
micro-cloud-alibaba
├── micro-common // 全局公共模块:工具类、常量、统一异常、返回体、通用配置
├── micro-gateway // 统一网关入口:路由转发、限流、跨域、权限拦截
├── micro-system // 基础系统服务:用户、角色、权限、字典、登录认证
├── micro-order // 核心业务服务:订单创建、订单查询、订单状态管理
├── micro-storage // 库存业务服务:商品库存扣减、库存查询、库存冻结
├── micro-message // 消息推送服务:MQ消息收发、短信、站内信通知
├── micro-workflow // 工作流专属服务:各类审批流程发起、审批、驳回
├── micro-file // 文件服务:OSS上传、下载、分片上传、文件管理
├── micro-devops // 运维配置:Docker、K8s、CI/CD配置文件
└── micro-monitor // 监控服务:链路追踪、指标监控、日志归集
2.2 父工程统一依赖管理(根治版本冲突)
通过父工程统一管控所有框架、中间件版本,子模块无需重复定义版本,从根源避免依赖冲突、版本不匹配问题,新手无需手动适配版本。
<?xml version="1.0" encoding="UTF-8"?>
<!-- 微服务父工程:统一版本、统一依赖管理 -->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.micro.cloud</groupId>
<artifactId>micro-cloud-alibaba</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<name>微服务父工程</name>
<!-- 全局统一版本配置 -->
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<spring.boot.version>3.2.5</spring.boot.version>
<spring.cloud.version>2023.0.1</spring.cloud.version>
<spring.cloud.alibaba.version>2023.0.1.0</spring.cloud.alibaba.version>
<mybatis.flex.version>1.7.5</mybatis.flex.version>
<sa.token.version>1.37.0</sa.token.version>
</properties>
<!-- 统一依赖版本管控,子模块直接引用无需写版本 -->
<dependencyManagement>
<dependencies>
<!-- SpringBoot 全家桶统一依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- SpringCloud 微服务核心依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- SpringCloudAlibaba 组件统一依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring.cloud.alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
3 Nacos 服务注册发现与配置中心
Nacos 是微服务核心基础组件,一站式替代传统 Eureka(注册发现)+ Config(配置中心),实现服务自动注册、心跳检测、故障节点剔除、配置动态刷新,大幅简化微服务治理难度,新手开箱即用。测试可用单机,生产必须集群部署保障高可用。
3.1 核心依赖引入(所有业务模块通用)
所有微服务业务模块只需引入以下两个依赖,即可拥有注册发现和配置中心能力。
<!-- Nacos 服务注册与发现:让服务互相感知、远程调用 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- Nacos 配置中心:统一管理配置、动态刷新无需重启服务 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
3.2 生产级配置文件(bootstrap.yml)
使用 bootstrap.yml 优先加载Nacos配置(优先级高于application.yml),配置心跳优化、公共配置共享、动态刷新,适配生产集群场景,小白直接修改地址即可使用。
# Nacos生产级配置
spring:
application:
name: micro-order # 当前服务名称(Nacos注册名称,唯一标识)
cloud:
nacos:
# 服务注册发现配置
discovery:
server-addr: 127.0.0.1:8848 # Nacos服务地址
heartbeat-interval: 5000 # 心跳上报间隔:5秒(主动上报存活)
heartbeat-timeout: 15000 # 心跳超时时间:15秒(超时判定服务死亡)
enabled: true # 开启服务注册发现
# 配置中心配置
config:
server-addr: 127.0.0.1:8848 # Nacos配置中心地址
file-extension: yml # 配置文件格式
# 公共配置共享:所有服务通用配置统一抽取,无需每个服务重复配置
shared-configs[0]:
data-id: micro-common.yml
refresh: true # 公共配置支持动态刷新
refresh-enabled: true # 开启配置动态刷新(改配置不用重启服务)
3.3 启动类开启注册注解
只需在服务启动类添加注解,即可自动完成服务注册,无需多余复杂配置。
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
// 微服务启动核心注解
@SpringBootApplication
@EnableDiscoveryClient // 开启Nacos服务注册与发现
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
}
生产核心要点(必看):1、单机Nacos仅用于本地测试,生产环境必须搭建集群防止单点故障;2、数据库密码、密钥等敏感配置,必须使用Nacos加密配置,禁止代码明文硬编码;3、所有服务统一通过Nacos托管配置,告别本地配置混乱。
4 Sentinel 流量控制与服务容错
微服务调用存在级联故障风险,单服务卡顿、超时会导致整体服务雪崩。Sentinel 专为微服务容错设计,通过限流、熔断、降级三大核心能力,拦截异常流量、隔离故障服务,保证系统整体稳定,配置简单、可视化操作,新手易上手。
4.1 依赖引入
<!-- Sentinel 微服务限流熔断容错核心依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
4.2 生产级配置(规则持久化)
默认Sentinel规则保存在内存,服务重启规则丢失。生产环境将规则持久化到Nacos,永久生效,支持动态修改。
spring:
cloud:
sentinel:
transport:
dashboard: 127.0.0.1:8080 # Sentinel控制台地址
port: 8719 # 客户端监控端口(默认无需修改)
eager: true # 提前初始化Sentinel,避免首次请求拦截
# 限流规则持久化到Nacos
datasource:
flow:
nacos:
server-addr: 127.0.0.8848
data-id: sentinel-flow-rule
rule-type: flow
4.3 自定义降级兜底实现(小白通用模板)
区分限流熔断兜底(系统流量问题)和业务异常兜底(代码逻辑问题),避免全局异常覆盖容错逻辑,适配所有业务接口。
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.stereotype.Service;
@Service
public class OrderService {
// 标记需要限流熔断的核心接口
// blockHandler:流量超限、熔断触发兜底
// fallback:业务代码报错触发兜底
@SentinelResource(value = "createOrder", blockHandler = "createOrderBlockHandler", fallback = "createOrderFallback")
public String createOrder(Long userId) {
// 核心下单业务逻辑
return "订单创建成功";
}
/**
* 限流、熔断兜底方法(系统流量异常、服务故障)
* 参数必须和原方法一致,最后追加BlockException参数
*/
public String createOrderBlockHandler(Long userId, BlockException e) {
return "系统繁忙,请稍后重试";
}
/**
* 业务异常降级兜底方法(代码报错、逻辑异常)
*/
public String createOrderFallback(Long userId) {
return "订单服务异常,暂时无法下单,请稍后重试";
}
}
生产核心要点:1、所有核心下单、支付、查询接口必须配置QPS限流;2、严格区分两种兜底场景,避免异常提示混乱;3、大流量场景开启链路限流,防止下游服务被打垮。
5 Dubbo 高性能RPC远程调用
Dubbo3 是微服务高性能远程调用框架,替代传统Feign调用方式,基于Triple协议,支持HTTP2、流式调用,吞吐量更高、延迟更低、兼容性更强,是企业微服务跨服务调用首选方案,结构简单、调用直观。
5.1 核心依赖引入
<!-- Dubbo3 高性能RPC远程调用依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-dubbo</artifactId>
</dependency>
5.2 服务提供者实现(被调用方)
公共接口统一放在common公共模块,所有服务可依赖引用;实现类通过注解暴露服务,指定版本方便迭代兼容。
// 1、公共接口(存放于micro-common模块,所有服务共享)
public interface StorageDubboService {
// 库存扣减接口
boolean deductStorage(Long goodsId, Integer count);
}
// 2、服务实现类(库存服务micro-storage模块)
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.stereotype.Service;
// 暴露Dubbo服务,指定版本,方便后续迭代升级
@DubboService(version = "1.0.0")
@Service
public class StorageDubboServiceImpl implements StorageDubboService {
// 实现库存扣减业务逻辑
@Override
public boolean deductStorage(Long goodsId, Integer count) {
// 执行库存查询、扣减逻辑
return true;
}
}
5.3 服务消费者调用(调用方)
通过注解直接注入远程服务,像调用本地方法一样调用远程接口,极简用法。
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;
@Service
public class OrderBizService {
// 引用远程Dubbo服务,指定对应版本、负载均衡策略
@DubboReference(version = "1.0.0", loadbalance = "roundrobin")
private StorageDubboService storageDubboService;
// 下单业务,远程调用库存服务
public void createOrder() {
// 远程调用库存扣减,无需手动写HTTP请求
boolean result = storageDubboService.deductStorage(1001L, 1);
}
}
5.4 生产级Dubbo全局配置
# Dubbo生产配置
dubbo:
application:
name: micro-order-dubbo # 当前Dubbo服务名称
protocol:
name: tri # 使用Triple高性能协议
port: -1 # 自动分配端口,避免冲突
registry:
address: nacos://127.0.0.1:8848 # 注册到Nacos
consumer:
timeout: 3000 # 消费者调用超时3秒
retries: 1 # 失败重试1次(读接口可用,写接口慎用)
provider:
timeout: 3000 # 服务提供者超时时间
生产核心要点:1、所有Dubbo服务必须指定版本,接口迭代通过版本区分,不影响旧业务;2、新增、修改、删除等写接口禁止重试,避免重复数据;3、查询接口可配置少量重试,提升容错性。
6 Seata 分布式事务落地(AT/TCC)
微服务跨服务调用时,不同服务数据库独立,会出现数据不一致问题(比如订单创建成功、库存扣减失败)。Seata 专门解决分布式事务问题,提供两种主流模式:AT模式(无侵入、简单通用)、TCC模式(高精度、适配复杂业务)。
6.1 核心依赖引入
<!-- Seata 分布式事务核心依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
6.2 AT模式(无侵入、小白首选)
适用于90%常规增删改业务,无需手动编写事务回滚代码,Seata自动记录undo日志,异常自动回滚,零侵入、上手极快。前置要求:所有业务库必须初始化undo_log数据表。
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.stereotype.Service;
@Service
public class OrderTxService {
// 开启全局分布式事务:任意步骤异常,全部回滚
@GlobalTransactional(rollbackFor = Exception.class)
public void createOrderTx() {
// 1、本地事务:创建订单
orderMapper.insert(order);
// 2、远程事务:调用Dubbo扣减库存
storageDubboService.deductStorage(1001L,1);
// 模拟异常:触发全局事务回滚,订单、库存全部复原
int i = 1/0;
}
}
6.3 TCC模式(高精度复杂事务)
适用于库存冻结、资金预扣、积分变动等高精度业务,手动控制三阶段事务,保证数据绝对一致,需严格遵守幂等、空回滚、防悬挂三大规则。
import io.seata.rm.tcc.api.BusinessActionContext;
import io.seata.rm.tcc.api.BusinessActionContextParameter;
import io.seata.rm.tcc.api.LocalTCC;
import io.seata.rm.tcc.api.TwoPhaseBusinessAction;
// 开启本地TCC事务模式
@LocalTCC
public interface StorageTccService {
/**
* 第一阶段 Try:资源检查+资源冻结
* 冻结库存,不真正扣减,防止超卖
*/
@TwoPhaseBusinessAction(name = "storageTcc", commitMethod = "commit", rollbackMethod = "rollback")
boolean tryDeduct(BusinessActionContext context,
@BusinessActionContextParameter(paramName = "goodsId") Long goodsId,
@BusinessActionContextParameter(paramName = "count") Integer count);
/**
* 第二阶段 Confirm:确认提交
* 业务正常,真正扣减冻结库存
*/
boolean commit(BusinessActionContext context);
/**
* 第二阶段 Cancel:事务回滚
* 业务异常,解冻库存,恢复数据
*/
boolean rollback(BusinessActionContext context);
}
生产核心要点:1、AT模式必须提前创建undo_log表,否则事务失效;2、大事务拆分为小事务,避免锁超时;3、TCC三阶段方法必须实现幂等性,防止重复执行导致数据错乱。
7 消息中间件(RocketMQ/Kafka)实战
消息中间件核心作用:业务解耦、流量削峰、异步通知,避免同步调用卡顿、接口超时。RocketMQ侧重业务可靠投递,Kafka侧重高吞吐日志采集,按需选用,生产核心是保证消息不丢、不重复、可靠消费。
7.1 RocketMQ 业务实战(业务解耦首选)
依赖引入
<!-- RocketMQ 消息队列依赖(SpringCloud Stream标准化用法) -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rocketmq</artifactId>
</dependency>
可靠消息生产者(保证消息不丢)
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class MqProducerService {
@Resource
private RocketMQTemplate rocketMQTemplate;
/**
* 发送订单消息(异步可靠投递)
* 发送失败自动记录日志,可后续重试,杜绝消息丢失
*/
public void sendOrderMsg(OrderDTO orderDTO) {
rocketMQTemplate.asyncSend("order-topic",
MessageBuilder.withPayload(orderDTO).build(),
result -> {
// 回调监听:判断消息是否发送成功
if (!result.isSendStatus()) {
// 投递失败:日志记录、入库、告警、后续重试
}
});
}
}
幂等消费者(杜绝重复消费)
MQ消息可能重复投递,必须做幂等校验,保证同一消息只处理一次。
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Service;
@Service
public class OrderMsgConsumer {
// 监听订单消息队列
@StreamListener("order-topic-input")
public void consume(Message<OrderDTO> message) {
OrderDTO order = message.getPayload();
// 幂等核心:根据订单唯一编号判断是否已处理
if (orderMapper.exists(order.getOrderNo())) {
// 已处理直接跳过,杜绝重复消费
return;
}
// 执行业务消费逻辑:订单状态更新、消息通知等
}
}
7.2 Kafka 高吞吐实战(日志、大数据场景首选)
Kafka主打超高吞吐,适合日志采集、数据流同步、批量消息推送,生产必须手动提交offset、保证消费幂等。
依赖引入
<!-- Kafka 高吞吐消息队列依赖 -->
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
生产级配置
spring:
kafka:
bootstrap-servers: 127.0.0.1:9092
producer:
acks: all # 消息全部落盘才返回成功,保证不丢消息
retries: 3 # 发送失败重试3次
batch-size: 16384 # 批量发送大小,提升吞吐
buffer-memory: 33554432
key-serializer: org.apache.kafka.common.serialization.StringSerializer
value-serializer: org.springframework.kafka.support.serializer.JsonSerializer
consumer:
group-id: micro-order-group
enable-auto-commit: false # 关闭自动提交,手动提交保证消费可靠
auto-offset-reset: earliest
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer
properties:
spring.json.trusted.packages: "*"
listener:
ack-mode: manual_immediate # 消费成功手动提交offset
Kafka生产者工具类
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.support.SendResult;
import org.springframework.stereotype.Service;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureCallback;
import javax.annotation.Resource;
@Service
public class KafkaProducerService {
@Resource
private KafkaTemplate<String, Object> kafkaTemplate;
// 通用消息发送方法
public void sendMsg(String topic, Object data) {
ListenableFuture<SendResult<String, Object>> future = kafkaTemplate.send(topic, data);
// 发送结果回调
future.addCallback(new ListenableFutureCallback<SendResult<String, Object>>() {
@Override
public void onSuccess(SendResult<String, Object> result) {}
@Override
public void onFailure(Throwable ex) {
// 发送失败:日志记录、入库重试、告警
}
});
}
}
Kafka幂等消费者
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.support.Acknowledgment;
import org.springframework.stereotype.Service;
@Service
public class KafkaConsumerService {
// 监听日志消息队列
@KafkaListener(topics = "order-log-topic", groupId = "micro-order-group")
public void consume(ConsumerRecord<String, String> record, Acknowledgment ack) {
String value = record.value();
// 幂等校验:根据消息唯一ID判断是否已消费
String msgId = record.headers().lastHeader("msgId").value().toString();
if (checkMsgExists(msgId)) {
ack.acknowledge(); // 已消费直接提交偏移量
return;
}
// 执行业务消费逻辑
ack.acknowledge(); // 消费成功手动提交
}
// 查询Redis/数据库,判断消息是否已处理
private boolean checkMsgExists(String msgId){
return false;
}
}
生产核心要点:所有消息必须配置幂等校验、失败重试、死信队列,异常消息不丢弃,保证消息最终一致性。
8 二级缓存架构(Caffeine+Redis)
采用本地Caffeine缓存+分布式Redis缓存二级架构,兼顾超高并发性能和集群数据一致性,同时彻底解决缓存穿透、击穿、雪崩三大线上高频问题,新手可直接复用工具类。
8.1 核心依赖
<!-- Caffeine 本地高性能缓存(性能远超Guava) -->
<dependency>
<groupId>com.github.benmanes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>3.1.8</version>
</dependency>
<!-- Redis 分布式缓存 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
8.2 二级缓存通用工具类(可直接复用)
优先查询本地缓存,减少远程Redis请求,双缓存同步更新、同步删除,保证数据一致。
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
@Component
public class DoubleCacheUtil {
// 本地缓存配置:最大1000条、写入5分钟过期
private final Cache<String, Object> localCache = Caffeine.newBuilder()
.maximumSize(1000)
.expireAfterWrite(5, TimeUnit.MINUTES)
.build();
@Resource
private RedisTemplate<String, Object> redisTemplate;
/**
* 查询缓存:优先本地,再分布式
*/
public Object getCache(String key) {
// 1、查本地缓存
Object local = localCache.getIfPresent(key);
if (local != null) {
return local;
}
// 2、本地无数据,查询Redis
Object redis = redisTemplate.opsForValue().get(key);
if (redis != null) {
localCache.put(key, redis);
return redis;
}
return null;
}
/**
* 同步更新双缓存
*/
public void setCache(String key, Object value, long time, TimeUnit unit) {
localCache.put(key, value);
redisTemplate.opsForValue().set(key, value, time, unit);
}
/**
* 同步删除双缓存
*/
public void delCache(String key) {
localCache.invalidate(key);
redisTemplate.delete(key);
}
}
8.3 缓存三大问题解决方案(生产必备)
全覆盖解决缓存穿透、击穿、雪崩问题,代码极简、小白可直接照搬。
// 1、防缓存穿透:缓存空值,避免频繁查询数据库
public Object getGoodsInfo(Long goodsId) {
String key = "goods:" + goodsId;
Object cache = doubleCacheUtil.getCache(key);
if (cache != null) {
return "null".equals(cache) ? null : cache;
}
// 查询数据库
Goods goods = goodsMapper.selectById(goodsId);
if (goods == null) {
// 空值缓存60秒,防止穿透
doubleCacheUtil.setCache(key, "null", 60, TimeUnit.SECONDS);
return null;
}
// 随机过期时间,防止批量过期导致缓存雪崩
long expire = 300 + (long)(Math.random() * 60);
doubleCacheUtil.setCache(key, goods, expire, TimeUnit.SECONDS);
return goods;
}
// 2、防缓存击穿:分布式锁控制热点Key
public Object getHotGoods(Long goodsId) {
String key = "hot:goods:" + goodsId;
Object cache = doubleCacheUtil.getCache(key);
if (cache != null) {
return cache;
}
// 加分布式锁,防止并发击穿
String lockKey = "lock:goods:" + goodsId;
boolean lock = redisTemplate.opsForValue().setIfAbsent(lockKey, "lock", 3, TimeUnit.SECONDS);
if (!lock) {
// 未获取锁,自旋重试
return getHotGoods(goodsId);
}
try {
// 二次查缓存,避免重复查询数据库
cache = doubleCacheUtil.getCache(key);
if (cache != null) {
return cache;
}
Goods goods = goodsMapper.selectById(goodsId);
doubleCacheUtil.setCache(key, goods, 300, TimeUnit.SECONDS);
return goods;
} finally {
// 释放锁
redisTemplate.delete(lockKey);
}
}
9 多层数据存储架构实践
针对不同业务数据特性,采用差异化存储方案:MySQL存核心结构化数据、分库分表应对大数据量、ES做全文检索、MongoDB存日志非结构化数据,各司其职,最大化性能。
9.1 Sharding-JDBC 分库分表配置
解决单表数据量过大、查询缓慢问题,按用户ID分片,均匀分摊数据压力。
spring:
shardingsphere:
datasource:
names: ds0,ds1
ds0:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/db0
username: root
password: 123456
ds1:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/db1
username: root
password: 123456
rules:
sharding:
tables:
# 订单表分表规则
t_order:
actual-data-nodes: ds0.t_order_0,ds0.t_order_1,ds0.t_order_2,ds0.t_order_3,ds1.t_order_0,ds1.t_order_1,ds1.t_order_2,ds1.t_order_3
table-strategy:
standard:
sharding-column: user_id # 分片键
sharding-algorithm-name: table-inline
sharding-algorithms:
table-inline:
type: INLINE
props:
algorithm-expression: t_order_${user_id % 4}
9.2 MyBatis-Flex 极简高效查询
无需手写SQL,链式调用实现CRUD,大幅提升开发效率,小白零学习成本。
import com.mybatisflex.core.query.QueryWrapper;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface OrderMapper extends BaseMapper<Order> {
// 极简链式查询,无SQL、无硬编码
default List<Order> listUserOrder(Long userId) {
return selectList(QueryWrapper.create()
.eq(Order::getUserId, userId) // 等值条件
.orderBy(Order::getCreateTime, false) // 时间倒序
.limit(10)); // 分页限制
}
}
9.3 ElasticSearch 全文检索
弥补MySQL模糊查询性能短板,实现订单、商品关键词模糊检索、高亮展示,适配搜索类业务。
依赖引入
<!-- ES 全文检索依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
ES配置
spring:
elasticsearch:
uris: http://127.0.0.1:9200
username: elastic
password: 123456
检索代码实现
// ES索引实体类
@Data
@Document(indexName = "order_info")
public class OrderES {
@Id
private String orderNo;
private Long userId;
private String goodsName;
private Integer status;
private LocalDateTime createTime;
}
// ES检索业务实现
@Service
public class OrderEsService {
@Resource
private ElasticsearchRestTemplate restTemplate;
// 关键词分页检索+高亮展示
public Page<OrderES> searchOrder(String keyword, int pageNum, int pageSize) {
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
// 多字段模糊匹配
queryBuilder.withQuery(QueryBuilders.multiMatchQuery(keyword, "orderNo","goodsName"));
// 关键词高亮标红
HighlightBuilder highlight = new HighlightBuilder()
.field("goodsName")
.preTags("<span style='color:red'>")
.postTags("</span>");
queryBuilder.withHighlightBuilder(highlight);
// 分页
queryBuilder.withPageable(PageRequest.of(pageNum-1, pageSize));
SearchHits<OrderES> hits = restTemplate.search(queryBuilder.build(), OrderES.class);
return new PageImpl<>(hits.stream().toList(), PageRequest.of(pageNum-1,pageSize), hits.getTotalHits());
}
}
9.4 MongoDB 非结构化数据存储
用于存储操作日志、用户行为记录、临时数据,无需建表,适配高写入、非结构化场景,减轻MySQL压力。
依赖引入
<!-- MongoDB 非结构化数据存储依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
配置与代码实现
spring:
data:
mongodb:
uri: mongodb://127.0.0.1:27017/micro_log
@Service
public class LogMongoService {
@Resource
private MongoTemplate mongoTemplate;
// 保存操作日志
public void saveLog(OperateLog log){
mongoTemplate.save(log);
}
// 条件查询日志
public List<OperateLog> listLog(Long userId, String type){
Query query = new Query();
if(userId != null){
query.addCriteria(Criteria.where("userId").is(userId));
}
if(StringUtils.isNotBlank(type)){
query.addCriteria(Criteria.where("operateType").is(type));
}
return mongoTemplate.find(query, OperateLog.class);
}
}
9.5 MySQL 主从读写分离
主库负责数据写入、更新、删除,从库负责所有查询,分担数据库压力,提升并发查询能力。
spring:
shardingsphere:
masterslave:
load-balance-algorithm-name: round_robin # 从库轮询查询
master-data-source-name: ds0 # 主库
slave-data-source-names: ds1 # 从库
props:
sql-show: true # 打印SQL,方便调试
生产核心要点:1、分库分表禁止跨库联表、跨库事务;2、数据分层存储,各司其职,不混用存储组件;3、主从分离规避读写竞争,大幅提升数据库并发。
10 Flowable 工作流引擎落地
适配订单审批、财务报备、流程审核等各类审批场景,实现流程部署、发起、审批、驳回、查询全流程自动化,无需手动写流程状态机,标准化流程管理。
10.1 依赖引入
<!-- Flowable 工作流引擎依赖 -->
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter</artifactId>
<version>7.2.0</version>
</dependency>
10.2 核心流程操作实现
封装流程发起、审批、驳回通用方法,适配所有审批业务。
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
@Service
public class FlowableService {
@Resource
private RuntimeService runtimeService;
@Resource
private TaskService taskService;
/**
* 发起订单审批流程
*/
public void startOrderFlow(String orderNo) {
Map<String, Object> variables = new HashMap<>();
variables.put("orderNo", orderNo);
variables.put("auditUser", "admin");
// 根据流程定义Key发起流程
runtimeService.startProcessInstanceByKey("order_audit_flow", orderNo, variables);
}
/**
* 审批通过
*/
public void auditPass(String taskId) {
taskService.complete(taskId);
}
/**
* 审批驳回
*/
public void auditReject(String taskId, String reason) {
Map<String, Object> variables = new HashMap<>();
variables.put("rejectReason", reason);
taskService.complete(taskId, variables);
}
}
生产核心要点:流程定义文件统一版本托管,禁止频繁动态修改;流程数据与业务数据双向联动,保证数据一致性。
11 权限认证体系(Sa-Token+Spring Security)
采用Sa-Token为主、Spring Security为辅的权限架构,Sa-Token轻量高效、开箱即用,适配绝大多数后台权限场景,简化传统Security繁琐配置;Spring Security辅助承接OAuth2第三方授权、单点登录能力,二者互补,实现登录认证、角色权限、接口拦截、账号封禁、会话管理全套能力,完全适配企业级权限体系。
11.1 核心依赖引入
<!-- Sa-Token 权限认证核心依赖 -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>satoken-spring-boot3-starter</artifactId>
<version>1.37.0</version>
</dependency>
<!-- Spring Security 辅助授权依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
11.2 生产级Sa-Token配置
配置会话超时、Token有效期、拦截规则、跨域放行,适配微服务集群部署,支持多端登录、单点登录、账号踢出。
# Sa-Token 生产配置
sa-token:
# token 名称(前端请求头携带参数)
token-name: Authorization
# token 有效期 2小时
timeout: 7200
# 临时有效期(无操作自动续期)
activity-timeout: 1800
# 关闭固定token,每次登录刷新token,提升安全性
is-concat: false
# 开启微服务无状态拦截
is-read-cookie: false
# 允许同一账号多端登录
is-multi-login: true
# 退出登录删除token
is-logout-delete-token: true
11.3 全局权限拦截配置
统一配置接口白名单、权限拦截规则,无需每个接口单独注解,全局管控接口访问权限。
import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class SaTokenConfig implements WebMvcConfigurer {
// 注册Sa-Token拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new SaInterceptor(handler -> {
// 放行所有白名单接口
SaRouter.match("/system/login", "/system/register").stop();
// 其余所有接口需要登录认证
SaRouter.match("/**").check(r -> StpUtil.checkLogin());
})).addPathPatterns("/**");
}
}
11.4 登录、登出、权限校验实战
import cn.dev33.satoken.stp.StpUtil;
import org.springframework.stereotype.Service;
@Service
public class AuthService {
// 账号密码登录
public void login(String username, String password) {
// 校验账号密码逻辑
// ...
// 登录成功,创建会话
StpUtil.login(10001L);
// 设置用户角色和权限
StpUtil.getSession().set("role", "admin");
StpUtil.getSession().set("permission", "system:order:*");
}
// 退出登录
public void logout() {
StpUtil.logout();
}
// 校验接口权限
public void checkPermission() {
// 校验是否拥有指定权限
StpUtil.checkPermission("system:order:add");
// 校验是否拥有指定角色
StpUtil.checkRole("admin");
}
}
生产核心要点:1、所有核心业务接口必须配置权限拦截,禁止匿名访问;2、敏感接口细化权限粒度,区分增删改查权限;3、支持在线踢出账号、强制下线、会话查询,适配后台用户管理。
12 JDK21 虚拟线程并发实战
JDK21 正式推出虚拟线程,彻底告别传统线程池线程数量受限、创建销毁开销大、上下文切换频繁的问题,轻量级、高并发、无需手动维护线程池,极大提升接口并发吞吐量,适配微服务高并发场景。
12.1 开启虚拟线程配置
SpringBoot3 原生支持虚拟线程,无需额外引入依赖,仅需配置开启全局虚拟线程调度。
# 全局开启虚拟线程
spring:
threads:
virtual:
enabled: true
12.2 虚拟线程业务实战(高并发查询)
批量异步查询多业务数据,无需手动创建线程池,虚拟线程自动调度、自动回收,零开销。
import org.springframework.stereotype.Service;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
@Service
public class VirtualThreadService {
// 虚拟线程批量并发查询业务
public void batchQueryData() throws Exception {
// 创建虚拟线程执行器
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
// 异步查询用户信息
Future<Object> userFuture = executor.submit(this::getUserInfo);
// 异步查询订单信息
Future<Object> orderFuture = executor.submit(this::getOrderInfo);
// 异步查询库存信息
Future<Object> storageFuture = executor.submit(this::getStorageInfo);
// 获取所有结果
Object user = userFuture.get();
Object order = orderFuture.get();
Object storage = storageFuture.get();
}
}
// 模拟用户查询
private Object getUserInfo() { return null; }
// 模拟订单查询
private Object getOrderInfo() { return null; }
// 模拟库存查询
private Object getStorageInfo() { return null; }
}
生产核心要点:1、IO密集型业务(接口查询、数据库查询、MQ收发)优先使用虚拟线程,性能提升显著;2、CPU密集型业务不推荐使用虚拟线程;3、虚拟线程无需手动池化,框架自动管理,杜绝线程泄露。
13 OSS 大文件分片上传实现
针对大文件上传超时、传输失败、重复上传问题,基于阿里云OSS实现分片上传、断点续传、秒传、文件校验全套能力,适配图片、视频、压缩包等大文件上传场景,生产稳定可用。
13.1 核心依赖引入
<!-- 阿里云OSS文件上传依赖 -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.15.1</version>
</dependency>
13.2 OSS 基础配置
# 阿里云OSS配置
aliyun:
oss:
endpoint: oss-cn-beijing.aliyuncs.com
access-key-id: your-key-id
access-key-secret: your-key-secret
bucket-name: micro-cloud-file
13.3 分片上传核心实现
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.*;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.List;
@Service
public class OssService {
private OSS ossClient;
// 初始化OSS客户端
@PostConstruct
public void initOss() {
ossClient = new OSSClientBuilder()
.build("oss-cn-beijing.aliyuncs.com", "your-key-id", "your-key-secret");
}
/**
* 初始化分片上传
*/
public String initMultipartUpload(String fileName) {
InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest("micro-cloud-file", fileName);
InitiateMultipartUploadResult result = ossClient.initiateMultipartUpload(request);
// 返回分片上传唯一标识uploadId
return result.getUploadId();
}
/**
* 上传单个分片
*/
public UploadPartResult uploadPart(MultipartFile file, String fileName, String uploadId, int partIndex) throws IOException {
UploadPartRequest request = new UploadPartRequest()
.setBucketName("micro-cloud-file")
.setKey(fileName)
.setUploadId(uploadId)
.setPartNumber(partIndex)
.setInputStream(file.getInputStream())
.setPartSize(file.getSize());
return ossClient.uploadPart(request);
}
/**
* 合并所有分片,完成上传
*/
public String completeUpload(String fileName, String uploadId, List<PartETag> partETags) {
CompleteMultipartUploadRequest request = new CompleteMultipartUploadRequest(
"micro-cloud-file", fileName, uploadId, partETags);
CompleteMultipartUploadResult result = ossClient.completeMultipartUpload(request);
// 返回文件完整访问地址
return result.getLocation();
}
}
生产核心要点:1、大文件统一采用分片上传,分片大小建议5MB;2、记录uploadId实现断点续传,避免重复上传;3、上传完成后校验文件MD5,防止文件损坏、篡改。
14 Docker+K8s 容器化部署
所有微服务统一容器化打包、部署、扩容,解决环境不一致、部署繁琐、扩容困难、版本混乱问题,实现一键打包、一键部署、弹性扩容、版本回滚,适配生产集群运维。
14.1 通用Dockerfile模板(所有微服务通用)
# 基础JDK21镜像
FROM openjdk:21-jdk-slim
# 设置工作目录
WORKDIR /app
# 复制打包后的jar包
COPY target/*.jar app.jar
# 开启时区统一
ENV TZ=Asia/Shanghai
# 暴露服务端口
EXPOSE 8080
# 启动命令
ENTRYPOINT ["java","-jar","/app/app.jar"]
14.2 K8s 部署核心配置
配置副本数、资源限制、健康探针、滚动更新策略,实现服务高可用、无损更新、自动重启恢复。
apiVersion: apps/v1
kind: Deployment
metadata:
name: micro-order
spec:
# 启动3个副本,保证高可用
replicas: 3
selector:
matchLabels:
app: micro-order
# 滚动更新策略,无损上线
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: micro-order
spec:
containers:
- name: micro-order
image: micro-cloud/order:1.0.0
ports:
- containerPort: 8080
# 资源限制,防止服务抢占资源
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
# 存活探针,服务异常自动重启
livenessProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
# 就绪探针,启动完成后再接收流量
readinessProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
生产核心要点:1、所有服务至少部署2个副本,杜绝单点故障;2、严格配置资源限制,防止单服务占用全部集群资源;3、开启滚动更新,上线不中断业务。
15 Nginx 负载均衡与反向代理
统一入口转发、静态资源托管、负载均衡、跨域处理、限流拦截,承接前端所有请求,屏蔽后端服务地址,保护内网服务安全,分担网关压力。
15.1 生产级Nginx核心配置
# 全局配置
worker_processes auto;
worker_rlimit_nofile 65535;
events {
use epoll;
worker_connections 65535;
}
http {
# 开启gzip压缩,提升访问速度
gzip on;
gzip_types text/plain text/css application/json application/javascript;
# 后端微服务集群负载均衡
upstream micro_gateway {
server 127.0.0.1:8001 weight=3;
server 127.0.0.1:8002 weight=3;
}
server {
listen 80;
server_name localhost;
# 反向代理到网关
location / {
proxy_pass http://micro_gateway;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# 限流配置,单IP每秒最多10次请求
limit_req_zone $binary_remote_addr zone=all_req:10m rate=10r/s;
limit_req zone=all_req burst=20 nodelay;
}
}
生产核心要点:1、通过权重负载均衡实现流量分发;2、开启IP限流、防刷,拦截恶意高频请求;3、统一配置gzip压缩、超时时间,优化访问性能。
16 Jenkins+GitLab+K8s 全流程CI/CD
实现代码提交自动编译、自动打包、自动构建镜像、自动部署、自动回滚全流程自动化,彻底告别手动部署,提升迭代效率,规范上线流程。
16.1 Jenkins核心流水线配置
pipeline {
agent any
stages {
stage('代码拉取') {
steps {
git url: 'http://gitlab.local/micro-cloud/micro-cloud-alibaba.git', branch: 'main'
}
}
stage('代码编译') {
steps {
sh 'mvn clean package -Dmaven.test.skip=true'
}
}
stage('镜像构建') {
steps {
sh 'docker build -t micro-cloud/order:${BUILD_NUMBER} .'
}
}
stage('推送镜像') {
steps {
sh 'docker push micro-cloud/order:${BUILD_NUMBER}'
}
}
stage('K8s部署更新') {
steps {
sh 'kubectl apply -f k8s-deploy.yaml'
}
}
}
// 构建失败告警
post {
failure {
echo "服务部署失败,请及时排查问题"
}
}
}
生产核心要点:1、区分测试、预发、生产多环境流水线;2、版本号自增管理,方便版本追溯与回滚;3、跳过测试打包可根据场景调整,上线前必须执行单元测试。
17 核心缺失能力补齐(生产刚需)
严格按照需求剔除监控告警、高级架构能力,仅保留分布式核心能力、高频业务场景、性能优化、安全体系、参数校验规范刚需模块,补齐所有生产必备、项目缺失的核心功能,所有代码可直接复用上线。
17.1 分布式锁完整落地(Redisson)
解决高并发抢资源、库存超卖、并发修改数据问题,实现可重入锁、读写锁、自动续期、防死锁,适配所有并发业务场景。
依赖引入
<!-- Redisson 分布式锁核心依赖 -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.27.0</version>
</dependency>
生产级配置
# Redisson分布式锁配置
spring:
redis:
host: 127.0.0.1
port: 6379
redisson:
single-server-config:
address: redis://127.0.0.1:6379
database: 0
# 锁默认等待时间
lock-wait-time: 3000
# 锁超时释放时间(看门狗自动续期)
lock-lease-time: 30000
分布式锁实战代码
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
@Service
public class DistributedLockService {
@Resource
private RedissonClient redissonClient;
// 高并发库存扣减分布式锁
public boolean deductGoodsStock(Long goodsId) {
String lockKey = "lock:goods:" + goodsId;
// 获取可重入锁
RLock lock = redissonClient.getLock(lockKey);
try {
// 尝试加锁,等待3秒,持有锁30秒自动续期
boolean tryLock = lock.tryLock(3, 30, TimeUnit.SECONDS);
if (!tryLock) {
return false;
}
// 执行业务逻辑:库存查询、扣减
return true;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
} finally {
// 释放锁
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
}
17.2 全局接口幂等通用解决方案
解决表单重复提交、接口重复请求、MQ重复消费问题,实现接口幂等、表单防重、订单幂等通用方案,全局生效。
幂等工具类
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
@Component
public class IdempotentUtil {
@Resource
private RedisTemplate<String, Object> redisTemplate;
// 接口幂等校验:key为唯一请求标识(订单号、请求流水号)
public boolean checkIdempotent(String key, long expireTime) {
// 不存在则写入,请求放行;存在则拦截重复请求
Boolean flag = redisTemplate.opsForValue().setIfAbsent(key, "1", expireTime, TimeUnit.SECONDS);
return Boolean.TRUE.equals(flag);
}
// 业务完成后删除幂等key(可选,根据场景适配)
public void delIdempotentKey(String key) {
redisTemplate.delete(key);
}
}
接口防重实战
@RestController
@RequestMapping("/order")
public class OrderController {
@Resource
private IdempotentUtil idempotentUtil;
@Resource
private OrderService orderService;
@PostMapping("/create")
public String createOrder(@RequestParam String orderNo) {
// 幂等校验:5秒内同一订单号禁止重复提交
if (!idempotentUtil.checkIdempotent("order:idempotent:" + orderNo, 5)) {
return "请勿重复提交订单";
}
return orderService.createOrder(orderNo);
}
}
17.3 全局统一异常处理 + 统一返回体
规范项目所有接口返回格式、统一异常拦截、统一错误提示,杜绝前端返回格式混乱、报错信息暴露后端源码问题,生产必备基础能力。
统一全局返回结果封装
import lombok.Data;
@Data
public class Result<T> {
// 响应码:200成功,500失败
private Integer code;
// 响应提示信息
private String msg;
// 响应数据
private T data;
// 成功返回
public static <T> Result<T> success(T data) {
Result<T> result = new Result<>();
result.setCode(200);
result.setMsg("操作成功");
result.setData(data);
return result;
}
// 失败返回
public static <T> Result<T> fail(String msg) {
Result<T> result = new Result<>();
result.setCode(500);
result.setMsg(msg);
return result;
}
}
全局统一异常处理器
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
// 全局未知异常拦截
@ExceptionHandler(Exception.class)
public Result<Void> handleException(Exception e) {
e.printStackTrace();
return Result.fail("系统异常,请稍后重试");
}
// 自定义业务异常拦截
@ExceptionHandler(BizException.class)
public Result<Void> handleBizException(BizException e) {
return Result.fail(e.getMessage());
}
}
17.4 数据脱敏通用实现
实现手机号、身份证、银行卡、邮箱自动脱敏,适配所有接口返回,无需手动处理,保护用户隐私数据。
public class DesensitizeUtil {
// 手机号脱敏 138****1234
public static String phone(String phone) {
if (phone == null || phone.length() != 11) return phone;
return phone.substring(0,3) + "****" + phone.substring(7);
}
// 身份证脱敏 110101********1234
public static String idCard(String idCard) {
if (idCard == null || idCard.length() < 18) return idCard;
return idCard.substring(0,6) + "********" + idCard.substring(14);
}
// 邮箱脱敏 123****@qq.com
public static String email(String email) {
if (email == null || !email.contains("@")) return email;
String[] split = email.split("@");
return split[0].length() > 3 ? split[0].substring(0,3) + "****@" + split[1] : email;
}
}
17.5 接口防刷、防重放安全方案
通过时间戳+随机数校验,拦截恶意重放请求、爬虫高频请求、恶意刷接口,保障接口安全。
// 自定义接口拦截器实现防重放、防刷
@Component
public class RequestSecurityInterceptor implements HandlerInterceptor {
@Resource
private RedisTemplate<String, Object> redisTemplate;
// 请求有效时间 5分钟
private static final long REQUEST_VALID_TIME = 300000;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// 获取请求参数:时间戳、随机数
String timestamp = request.getHeader("timestamp");
String nonce = request.getHeader("nonce");
// 1、参数非空校验
if (StringUtils.isBlank(timestamp) || StringUtils.isBlank(nonce)) {
throw new BizException("非法请求");
}
// 2、校验请求是否过期
long current = System.currentTimeMillis();
if (current - Long.parseLong(timestamp) > REQUEST_VALID_TIME) {
throw new BizException("请求已过期");
}
// 3、校验随机数是否已使用,防重放
String key = "request:nonce:" + nonce;
if (Boolean.TRUE.equals(redisTemplate.hasKey(key))) {
throw new BizException("禁止重复请求");
}
redisTemplate.opsForValue().set(key, "1", 5, TimeUnit.MINUTES);
return true;
}
}
17.6 全局参数校验统一规范实现(刚需)
基于JSR380规范实现全局参数校验、分组校验、统一异常处理,替代手动if判断参数,规范所有接口入参校验,代码极简、统一报错格式。
依赖引入
<!-- JSR380 参数校验核心依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
分组校验接口(适配新增、修改不同校验规则)
// 新增分组
public interface AddGroup {}
// 修改分组
public interface UpdateGroup {}
实体类参数校验注解使用
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Data
public class OrderDTO {
// 新增无需订单号,修改必须传订单号
@NotNull(message = "订单号不能为空", groups = UpdateGroup.class)
private String orderNo;
// 新增、修改都必须传用户ID
@NotNull(message = "用户ID不能为空", groups = {AddGroup.class, UpdateGroup.class})
private Long userId;
// 商品名称非空校验
@NotBlank(message = "商品名称不能为空")
private String goodsName;
}
接口开启参数校验
@RestController
@RequestMapping("/order")
public class OrderController {
// 新增接口:适配新增分组校验
@PostMapping("/add")
public Result<Void> addOrder(@Validated(AddGroup.class) @RequestBody OrderDTO orderDTO) {
// 无需手动校验参数,框架自动拦截
return Result.success(null);
}
// 修改接口:适配修改分组校验
@PostMapping("/update")
public Result<Void> updateOrder(@Validated(UpdateGroup.class) @RequestBody OrderDTO orderDTO) {
return Result.success(null);
}
}
全局参数校验异常统一拦截
整合到全局异常处理器,统一参数报错格式,前端无需单独适配。
// 参数校验异常拦截
@ExceptionHandler(MethodArgumentValidationException.class)
public Result<Void> handleValidException(MethodArgumentValidationException e) {
String message = e.getBindingResult().getFieldError().getDefaultMessage();
return Result.fail(message);
}
生产核心要点:1、所有接口入参必须使用注解校验,禁止手写if判断;2、新增、修改场景使用分组校验,精细化控制校验规则;3、统一参数异常返回格式,前后端对接更规范。
17.7 定时任务XXL-Job完整落地
补齐分布式定时任务能力,实现定时任务新增、执行、重试、日志、分片执行,替代原生SpringTask,适配集群部署、防止任务重复执行。
依赖引入
<!-- XXL-Job 分布式定时任务依赖 -->
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
<version>2.4.0</version>
</dependency>
生产配置
# XXL-Job配置
xxl:
job:
admin:
addresses: http://127.0.0.1:8088/xxl-job-admin
executor:
appname: micro-order-job
port: 9999
log-path: /data/xxl-job/logs
log-retention-days: 7
任务执行器配置 + 任务实战
import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class XxlJobConfig {
@Bean
public XxlJobSpringExecutor xxlJobExecutor() {
XxlJobSpringExecutor executor = new XxlJobSpringExecutor();
executor.setAdminAddresses("http://127.0.0.1:8088/xxl-job-admin");
executor.setAppname("micro-order-job");
executor.setPort(9999);
return executor;
}
}
// 定时任务业务实现
@Component
public class OrderJobHandler {
// 定时关闭超时未支付订单
@XxlJob("closeOverdueOrderJob")
public void closeOverdueOrder() {
// 执行定时任务逻辑:查询超时订单、关闭订单、释放库存
}
}
18 项目总结与生产避坑指南
本手册基于Spring Cloud Alibaba 2023最新稳定生态,完整搭建企业级微服务架构,覆盖服务治理、分布式事务、消息解耦、缓存架构、数据存储、权限体系、容器部署、CI/CD自动化、生产刚需通用能力全套核心能力,剔除非刚需监控、高阶架构内容,聚焦项目落地、线上生产、面试高频场景。
18.1 核心技术亮点总结
-
架构标准化:统一工程分层、依赖管理、代码规范,彻底解决项目混乱、难以维护问题;
-
分布式问题全覆盖:分布式锁、幂等性、分布式事务、消息可靠消费,解决线上核心分布式难题;
-
高并发性能优化:二级缓存、虚拟线程、读写分离、分库分表,全方位提升系统并发能力;
-
生产安全规范:参数校验、数据脱敏、接口防刷、统一异常返回,规避线上安全与规范问题;
-
自动化运维:容器化部署、CI/CD流水线,实现一键上线、弹性扩容、版本回滚。
18.2 线上生产高频避坑指南
-
事务避坑:Seata大事务拆分、TCC严格实现幂等空回滚、写接口禁止Dubbo重试;
-
缓存避坑:必须处理缓存穿透、击穿、雪崩,禁止缓存热点Key过期失效、禁止缓存大量无效数据;
-
消息避坑:所有MQ消息必须幂等、失败重试、死信兜底,杜绝消息丢失、重复消费;
-
并发避坑:高并发场景必须加分布式锁,禁止本地锁管控集群并发资源;
-
参数避坑:所有接口入参统一校验,禁止空参数、非法参数流入业务逻辑;
-
部署避坑:生产禁止单副本部署、禁止关闭健康探针、禁止手动修改线上配置。