Appearance
一、项目概览
kdp-tenants 是一个基于 Spring Boot 的多租户管理微服务,属于KDP平台的一部分。它的核心功能是管理"租户"(Tenant)——即平台上的组织/客户,提供租户的增删改查(CRUD)等 RESTful API。
二、技术栈总览
| 层次 | 技术 | 说明 |
|---|---|---|
| 构建工具 | Maven | pom.xml 管理依赖和构建 |
| 框架 | Spring Boot 2.x | Java 最主流的 Web 框架 |
| ORM | MyBatis / MyBatis-Plus | 数据库访问层 |
| 数据库 | H2(开发)/ MySQL(生产) | 内嵌 H2 方便开发测试 |
| API 文档 | Swagger / Knife4j | 自动生成 API 文档 |
| 安全 | Spring Security + 自定义拦截器 | 认证与授权 |
| 容器化 | Docker + Kubernetes | 部署到云原生环境 |
| JDK | Java 8+ | 基础运行环境 |
三、项目目录结构详解
kdp-tenants/
├── pom.xml # Maven 构建配置(依赖、插件)
├── build-amd64.sh / build-arm64.sh # 多架构 Docker 构建脚本
├── README.md / README.zh-CN.md # 项目说明文档
├── document/
│ ├── docker/
│ │ └── Dockerfile # Docker 镜像构建文件
│ └── kubernetes/
│ ├── kdp-tenants-deployment.yaml # K8s 部署配置
│ └── kdp-tenants-service.yaml # K8s 服务配置
└── src/
├── main/
│ ├── java/com/inspur/kdp/tenants/
│ │ ├── TenantsApplication.java # 🚀 启动类(入口)
│ │ ├── controller/ # 🎮 控制层(接收HTTP请求)
│ │ │ └── TenantController.java
│ │ ├── service/ # 📋 服务层(业务逻辑)
│ │ │ ├── TenantService.java # 接口
│ │ │ └── impl/
│ │ │ └── TenantServiceImpl.java # 实现
│ │ ├── mapper/ # 💾 数据访问层(MyBatis)
│ │ │ └── TenantMapper.java
│ │ ├── entity/ # 📦 实体类(对应数据库表)
│ │ │ └── Tenant.java
│ │ ├── dto/ # 📨 数据传输对象(接收请求参数)
│ │ │ └── TenantDTO.java
│ │ ├── vo/ # 📤 视图对象(返回响应数据)
│ │ │ └── TenantVO.java
│ │ ├── config/ # ⚙️ 配置类
│ │ │ ├── SecurityConfig.java # Spring Security 配置
│ │ │ ├── SwaggerConfig.java # Swagger API 文档配置
│ │ │ └── WebMvcConfig.java # Web MVC 配置(拦截器注册等)
│ │ ├── interceptor/ # 🔐 拦截器
│ │ │ └── AuthInterceptor.java # 认证拦截器
│ │ ├── annotation/ # 🏷️ 自定义注解
│ │ │ └── RequireAuth.java # 需要认证的注解
│ │ ├── common/ # 📐 通用类
│ │ │ └── Result.java # 统一返回结果封装
│ │ ├── exception/ # ❗ 异常处理
│ │ │ ├── BusinessException.java # 业务异常
│ │ │ └── GlobalExceptionHandler.java # 全局异常处理器
│ │ └── util/ # 🔧 工具类
│ │ └── JsonUtil.java
│ └── resources/
│ ├── application.yml # 应用配置文件
│ ├── schema.sql # 数据库建表脚本
│ ├── data.sql # 初始数据脚本
│ └── mapper/
│ └── TenantMapper.xml # MyBatis SQL 映射文件
└── test/ # 测试代码四、核心架构 —— 分层架构(经典三层)
这是 Java 企业级开发最经典的架构模式,强烈建议你从理解这个分层开始学习:
请求流程: 客户端 → Controller → Service → Mapper → 数据库
↓
响应流程: 客户端 ← Controller ← Service ← Mapper ← 数据库4.1 Controller 层(控制层)
- 文件:
TenantController.java - 职责: 接收 HTTP 请求,调用 Service 层处理业务,返回响应
- 关键注解:
@RestController,@RequestMapping,@GetMapping,@PostMapping等 - 学习重点: RESTful API 设计、Spring MVC 注解用法
4.2 Service 层(业务逻辑层)
- 文件:
TenantService.java(接口)+TenantServiceImpl.java(实现) - 职责: 封装业务逻辑,是整个应用的核心
- 关键注解:
@Service,@Transactional - 设计模式: 面向接口编程(接口 + 实现分离)
- 学习重点: 为什么要用接口?事务管理怎么用?
4.3 Mapper 层(数据访问层)
- 文件:
TenantMapper.java+TenantMapper.xml - 职责: 与数据库交互,执行 SQL
- 关键注解:
@Mapper或@MapperScan - 技术: MyBatis 框架
- 学习重点: MyBatis 的 XML 映射 vs 注解方式
4.4 Entity / DTO / VO —— 数据模型的分层
| 类 | 用途 | 流向 |
|---|---|---|
| Entity | 对应数据库表结构 | Mapper ↔ 数据库 |
| DTO (Data Transfer Object) | 接收前端传入的参数 | Controller → Service |
| VO (Value Object) | 返回给前端的数据 | Service → Controller |
这是 Java 实际项目非常重要的设计实践,入门时需要理解为什么不用同一个类贯穿所有层。
五、关键配置文件解析
5.1 pom.xml —— Maven 项目核心
- 定义了项目坐标(groupId, artifactId, version)
- 管理所有依赖:Spring Boot Starter、MyBatis-Plus、Swagger 等
- 配置构建插件
5.2 application.yml —— 应用配置
- 数据库连接信息
- 服务端口
- MyBatis 配置
- 日志级别
- 开发/生产环境 Profile 切换
5.3 schema.sql / data.sql
- H2 内嵌数据库的建表和初始化数据
- 应用启动时自动执行
六、项目特色功能学习点
6.1 统一返回结果封装 (Result.java)
- 所有 API 返回统一格式:
{code, message, data} - 前端可以根据 code 判断请求是否成功
6.2 全局异常处理 (GlobalExceptionHandler)
- 使用
@ControllerAdvice+@ExceptionHandler - 统一捕获异常,避免向客户端暴露堆栈信息
- 区分业务异常 (
BusinessException) 和系统异常
6.3 认证拦截器 (AuthInterceptor)
- 实现
HandlerInterceptor接口 - 通过自定义注解
@RequireAuth标记需要认证的接口 - 在
WebMvcConfig中注册拦截器
6.4 Swagger API 文档 (SwaggerConfig)
- 自动生成在线 API 文档
- 可直接在页面上测试 API
6.5 Docker + Kubernetes 部署
Dockerfile: 将应用打包为 Docker 镜像deployment.yaml: K8s 部署配置service.yaml: K8s 服务暴露配置
七、🚀 推荐学习路径(由浅入深)
第 1 步:环境搭建与运行
- 安装 JDK 8+、Maven、IDE(推荐 IntelliJ IDEA)
- 在项目根目录运行
mvn spring-boot:run - 访问 Swagger 页面查看 API 文档
- 用 Postman 或 curl 测试 API
第 2 步:理解分层架构
- 从
TenantController入手,看一个请求如何进来 - 跟踪到
TenantServiceImpl,理解业务逻辑 - 再跟踪到
TenantMapper,看 SQL 如何执行 - 理解 Entity → DTO → VO 的转换过程
第 3 步:学习 Spring Boot 核心
@RestController/@RequestMapping等 Web 注解@Autowired依赖注入application.yml配置读取@Transactional事务管理
第 4 步:学习 MyBatis
- Mapper 接口的定义
TenantMapper.xml中的 SQL 映射- 动态 SQL 的使用
- MyBatis-Plus 的增强功能
第 5 步:学习项目规范与设计模式
- 统一返回结果封装
- 全局异常处理
- 拦截器与自定义注解
- 接口与实现分离的设计
第 6 步:学习部署(进阶)
- Docker 镜像构建
- Kubernetes 部署与服务暴露
- 多架构构建(AMD64/ARM64)
八、📚 推荐补充学习资源
| 主题 | 推荐资源 |
|---|---|
| Spring Boot 基础 | 官方文档 + 《Spring Boot 实战》 |
| MyBatis | 官方文档 + MyBatis-Plus 文档 |
| RESTful API 设计 | 《RESTful Web Services》 |
| Maven | Maven 官方教程 |
| Docker 基础 | 《Docker 技术入门与实战》 |
| 设计模式 | 《Head First 设计模式》 |
如果你对某个具体模块想深入了解(比如 MyBatis 映射文件的详细写法、Spring Security 的配置原理等),我可以进一步为你展开讲解。也可以告诉我你目前最想先从哪个部分开始,我来给你更详细的代码级解读!
./startup.sh ``` 6. Tomcat 启动时,会自动去解压(War包自动释放)你的 war 包,并将其加载到自己的容器中。此时你访问的路径通常是 http://localhost:8080/my-web-app/。
💡 扩展:面试高频知识点
在面试中,只要聊到部署、打包或者性能优化,面试官非常喜欢拿 jar 和 war 的底层原理来考你:
1. 为什么 java -jar 能够直接运行?它的底层引导原理是什么?
面试常问: “普通的 jar 包是不能直接用
java -jar运行的,为什么 Spring Boot 打出来的 jar 包就可以?你知道解压后的META-INF/MANIFEST.MF文件吗?”
- 底层秘密: 当你解压一个可执行的 Spring Boot Jar 包时,你会发现在
META-INF/MANIFEST.MF文件里写着这样两行核心配置:
Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: com.yourcompany.project.YourApplication- 执行流程:
- 当你输入
java -jar时,JVM 首先启动的并不是你的启动类,而是 Spring Boot 自带的类加载器引导类JarLauncher(即Main-Class)。 JarLauncher负责去解压并加载嵌套在BOOT-INF/lib下的所有第三方插件和内嵌 Tomcat 的类。- 当所有的运行环境和类加载器都准备就绪后,
JarLauncher才会通过反射去调用你手写的那个带有@SpringBootApplication的Start-Class。这就是它能“无中生有”自己跑起来的原因。
- 当你输入
2. 既然 java -jar 这么爽,那传统 war 包部署方式现在还有价值吗?大厂在什么场景下还会用 war 包?
面试常问: “如果你们公司要求把多个不同的 Web 独立项目,部署在同一台服务器上共享内存,你会选择 Jar 还是 War?”
- 适用场景(多应用共享容器):
war包最大的优势在于“多应用隔离与共享”。- 如果使用
jar包,启动 5 个微服务,就会在内存里启动 5 个独立的 JVM 进程和 5 个内嵌 Tomcat,彼此内存完全独立,非常吃服务器资源。 - 而如果使用
war包,你只需要启动 1个 外部独立的 Tomcat(占用 1 个 JVM 进程)。你可以把 5 个不同的war包全部丢进这同一个 Tomcat 里。它们会共享这同一个 Tomcat 的线程池、连接池和内存空间。
- 如果使用
- 总结: 追求高可用、微服务弹性伸缩、云原生(Docker化)时,百分之百选
jar包;如果是传统政企、老旧单体系统、硬件资源极度紧张且需要在一个容器里塞多个应用时,war包依然有其用武之地。