- 新增 deploy/docker/:Docker 本机模拟部署,含 Dockerfile、docker-compose、deploy.sh 一键脚本 - 新增 deploy/remote/:远程服务器部署,含 SSH 自动上传、重启、回滚脚本 - 新增 deploy/README.md:完整使用手册,含现状分析、落地调整工作清单、命令速查 - 新增 build.sh/start.sh:本地构建和启动脚本(含飞书通知) - 新增前端 .env.docker 环境配置,API 指向测试服务器 - 前端 package.json 新增 build-docker 命令 - 更新 .gitignore:排除 IDE 配置、SQL 数据、Docker 敏感文件 - 前端 UI 样式优化(多个页面组件) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
359 lines
18 KiB
Markdown
359 lines
18 KiB
Markdown
# 后端技术术语详解 - 写给前端工程师
|
||
|
||
> 用前端类比的方式,帮助前端同学理解后端架构和术语
|
||
|
||
---
|
||
|
||
## 一、框架与运行环境
|
||
|
||
### Spring Boot
|
||
**类比**:相当于前端的 Vite + Vue 全家桶的脚手架。
|
||
**解释**:Java 后端的"一站式开发框架",帮你把 Web 服务器、数据库连接、配置管理等都自动配置好,开箱即用。就像 Vite 帮你配好了 webpack、热更新、打包一样,Spring Boot 帮后端配好了 Tomcat 服务器、数据库连接池等。
|
||
|
||
### WAR 包 / ROOT.war
|
||
**类比**:相当于前端 `npm run build` 打出来的 `dist` 文件夹。
|
||
**解释**:后端代码编译打包后的产物,是一个压缩包(类似 zip)。`ROOT.war` 部署到 Tomcat 服务器上运行,就像你把 `dist` 丢到 Nginx 上一样。
|
||
|
||
### Tomcat
|
||
**类比**:相当于前端的 Nginx。
|
||
**解释**:Java Web 应用的运行容器/服务器。前端用 Nginx 托管静态文件,后端用 Tomcat 运行 Java 代码。
|
||
|
||
### Maven / pom.xml
|
||
**类比**:Maven = npm,pom.xml = package.json。
|
||
**解释**:Java 的包管理工具。`mvn install` 类似 `npm install`,`mvn clean package` 类似 `npm run build`。pom.xml 里定义了项目依赖(类似 dependencies)和构建配置(类似 scripts)。
|
||
|
||
### mvn clean install
|
||
**类比**:`rm -rf node_modules && npm install && npm run build`
|
||
**解释**:清除旧的编译产物(clean),重新编译并安装到本地仓库(install),供其他模块引用。
|
||
|
||
---
|
||
|
||
## 二、项目分层架构
|
||
|
||
后端代码是分层的,**请求从上往下走,响应从下往上回**:
|
||
|
||
```
|
||
前端请求
|
||
↓
|
||
Controller ← 相当于前端的路由 (Router),定义 URL 和接收参数
|
||
↓
|
||
Service ← 相当于前端的 Vuex actions / 业务逻辑层
|
||
↓
|
||
Mapper ← 相当于前端的 ApiService,负责跟数据库"通信"
|
||
↓
|
||
MySQL ← 相当于前端的后端 API(但这次是真正的数据存储)
|
||
```
|
||
|
||
### Controller(控制器)
|
||
**类比**:Vue Router 的路由定义 + 页面组件的入口方法。
|
||
**解释**:定义 API 接口地址(如 `POST /task/pageList`),接收前端传来的参数,调用 Service 处理,返回结果。你在 `api.js` 里写的每个接口地址,后端都有一个 Controller 方法与之对应。
|
||
|
||
```
|
||
前端: api.js 里定义 /task/pageList
|
||
后端: TaskController.java 里有个方法处理这个请求
|
||
```
|
||
|
||
### Service(服务层)
|
||
**类比**:Vuex 的 actions + 复杂的业务逻辑函数。
|
||
**解释**:处理业务逻辑的地方。比如"创建任务"不只是往数据库插一条数据,还要检查权限、分配人员、发通知等,这些逻辑都在 Service 里。
|
||
|
||
### Mapper(数据访问层)
|
||
**类比**:前端的 `ApiService/*.js`,但操作对象是数据库而非 HTTP 接口。
|
||
**解释**:负责跟 MySQL 数据库交互,执行增删改查 SQL。每个 Mapper 对应一张数据库表。
|
||
|
||
### Entity / Model(实体类)
|
||
**类比**:TypeScript 的 `interface` 或 `type` 定义。
|
||
**解释**:定义数据结构。比如 `TaskInfo` 实体就是定义了任务表有哪些字段(id、name、status...),类似前端定义的:
|
||
```typescript
|
||
// 前端 TypeScript 的写法
|
||
interface TaskInfo {
|
||
id: number;
|
||
name: string;
|
||
status: number;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 三、数据库相关
|
||
|
||
### MySQL
|
||
**类比**:一个超大的、持久化的、结构化的 JSON 数据仓库。
|
||
**解释**:关系型数据库,数据按表(Table)存储。一张表就像一个 Excel 表格,有固定的列(字段),每一行是一条数据。跟前端的 localStorage 不同,MySQL 可以存海量数据、支持复杂查询、多人并发访问。
|
||
|
||
### 数据源 / DataSource
|
||
**类比**:前端 axios 实例配置不同的 `baseURL`。
|
||
**解释**:本项目有两个数据库(DB1 基础信息、DB2 业务数据),后端配置了两个数据源,不同的 Mapper 连接不同的数据库。就像前端可能有多个 axios 实例,一个请求 `api.example.com`,另一个请求 `auth.example.com`。
|
||
|
||
### MyBatis-Plus
|
||
**类比**:一个帮你自动写 SQL 的工具,类似前端用 Axios 封装了 fetch。
|
||
**解释**:Java 的 ORM 框架(对象关系映射)。不用手写 SQL,直接操作 Java 对象就能完成数据库增删改查。比如 `mapper.selectById(1)` 自动生成 `SELECT * FROM task_info WHERE id = 1`。
|
||
|
||
### Mapper XML
|
||
**类比**:复杂的 GraphQL 查询定义文件。
|
||
**解释**:当自动生成的 SQL 不够用时(比如多表关联查询),在 XML 文件里手写 SQL 语句。类似前端遇到复杂请求时要手动拼接参数。
|
||
|
||
### QueryWrapper
|
||
**类比**:前端拼接 URL 查询参数的工具函数。
|
||
**解释**:用代码构造 SQL 查询条件。比如:
|
||
```java
|
||
// 后端
|
||
wrapper.eq("status", 1).like("name", "保洁")
|
||
// 等同于 SQL: WHERE status = 1 AND name LIKE '%保洁%'
|
||
|
||
// 类比前端
|
||
params = { status: 1, name: '保洁' } // 传给后端做筛选
|
||
```
|
||
|
||
### IPage(分页)
|
||
**类比**:前端 `el-pagination` 组件的 `currentPage` 和 `pageSize`。
|
||
**解释**:后端分页查询对象,包含页码、每页条数、总数、数据列表。前端传 `pageNum` 和 `pageSize`,后端返回对应页的数据。
|
||
|
||
### Druid 连接池
|
||
**类比**:浏览器的 HTTP 连接复用(HTTP/2 多路复用)。
|
||
**解释**:数据库连接的"缓存池"。创建数据库连接很耗时(类似 TCP 握手),连接池预先创建一批连接放着,用完归还而不是销毁,下次直接取用,提升性能。
|
||
|
||
### 事务 / Transaction
|
||
**类比**:前端表单提交时的"全部成功才提交,否则全部撤销"。
|
||
**解释**:保证多个数据库操作要么全部成功,要么全部回滚。比如"创建任务"要同时插入 task_info、task_user、task_scenes 三张表,如果 task_scenes 插入失败,前面两张表的数据也要撤销,保持数据一致。
|
||
|
||
### 软删除 / soft_delete
|
||
**类比**:前端列表中的"隐藏"而非"删除"。
|
||
**解释**:删除数据时不是真的从数据库删掉,而是把 `soft_delete` 字段从 0 改为 1。查询时自动过滤 `soft_delete=1` 的记录。好处是数据可恢复。
|
||
|
||
---
|
||
|
||
## 四、Redis 相关
|
||
|
||
### Redis
|
||
**类比**:一个超级强化版的 `sessionStorage`,速度极快,支持多种数据结构,多个服务可以共享。
|
||
**解释**:内存数据库,数据存在内存中所以读写极快。本项目用 Redis 做三件事:
|
||
1. **缓存** - 避免频繁查数据库(类似前端用变量缓存 API 响应)
|
||
2. **消息队列** - 服务之间传递消息(类似前端的 EventBus)
|
||
3. **分布式锁** - 防止并发冲突(类似前端的防重复点击)
|
||
|
||
### Redis DB4 / DB5
|
||
**类比**:localStorage 和 sessionStorage 的区别,两个独立的存储空间。
|
||
**解释**:Redis 支持 16 个独立数据库(编号 0-15),本项目用了 DB4 和 DB5,存放不同类型的数据,互不干扰。
|
||
|
||
### Redis 数据类型
|
||
|
||
| Redis 类型 | 前端类比 | 说明 |
|
||
|-----------|---------|------|
|
||
| **String** | `localStorage.setItem('key', 'value')` | 最简单的键值对,存一个字符串值 |
|
||
| **List** | JavaScript 数组 `[]`,支持 push/pop | 有序列表,常用作消息队列(先进先出) |
|
||
| **Set** | JavaScript `new Set()` | 无序集合,元素不重复 |
|
||
| **Hash** | JavaScript 对象 `{}` | 键值对的集合,类似一个小型的 JSON 对象 |
|
||
| **ZSet** | 带排序分数的 Set | 有序集合,每个元素有一个分数,按分数排序 |
|
||
|
||
### Redis 消息队列
|
||
**类比**:前端的 EventBus / Vuex 的 dispatch。
|
||
**解释**:用 Redis 的 List 当消息队列:
|
||
- **生产者**用 `LPUSH` 往列表左边塞消息(类似 `eventBus.$emit`)
|
||
- **消费者**用 `RPOP` 从列表右边取消息(类似 `eventBus.$on`)
|
||
- 实现了 Web 服务和 Task 服务之间的异步通信
|
||
|
||
```
|
||
// 类比前端
|
||
// Web 服务(生产者)
|
||
eventBus.$emit('taskPushQueue', { taskId: 123, type: '新任务' })
|
||
|
||
// Task 服务(消费者,每秒轮询)
|
||
setInterval(() => {
|
||
const msg = eventBus.popMessage('taskPushQueue')
|
||
if (msg) sendPushNotification(msg)
|
||
}, 1000)
|
||
```
|
||
|
||
### Redis 分布式锁
|
||
**类比**:前端按钮的 `loading` + `disabled` 防重复点击,但是跨服务器生效。
|
||
**解释**:用 Redis 的 `SETNX`(Set if Not Exists)命令实现。多个请求同时到达时,只有第一个能设置成功(获得锁),其他的被拒绝。30秒后锁自动过期释放。
|
||
|
||
### TTL(Time To Live)
|
||
**类比**:`setTimeout(() => localStorage.removeItem('key'), 30000)` — 数据过期自动删除。
|
||
**解释**:Redis 数据的过期时间。设置 TTL=30秒,30秒后这个 Key 自动消失。用于登录 Token 过期、临时缓存清理等。
|
||
|
||
### Dictionary Hash
|
||
**类比**:前端 Vuex Store 里的全局配置 state。
|
||
**解释**:Redis 里存了一个叫 `Dictionary` 的 Hash,里面存各种系统开关和配置项(如 `UserAppointFlag`、`AutoOffWorkTime`),后端需要时直接从 Redis 读取,不用每次查数据库。
|
||
|
||
---
|
||
|
||
## 五、定时任务相关
|
||
|
||
### XXL-Job
|
||
**类比**:一个可视化的 `setInterval` 管理平台。
|
||
**解释**:分布式定时任务调度中心。你可以在管理界面上创建定时任务,设置执行时间(比如每天早上8点),它会自动触发后端的方法执行。比前端的 `setInterval` 强大很多:支持 cron 表达式、失败重试、集群分发等。
|
||
|
||
### @Scheduled
|
||
**类比**:写在代码里的 `setInterval`。
|
||
**解释**:Spring 框架提供的定时任务注解,直接写在方法上。比如 `@Scheduled(fixedRate = 1000)` 表示每 1 秒执行一次。与 XXL-Job 的区别是:@Scheduled 写死在代码里,XXL-Job 可以在管理界面动态调整。
|
||
|
||
### Cron 表达式
|
||
**类比**:一种描述"什么时候执行"的规则字符串。
|
||
**解释**:格式为 `秒 分 时 日 月 周`。例如:
|
||
```
|
||
* * * * * ? → 每秒执行(类似 setInterval(fn, 1000))
|
||
0 0 8 * * ? → 每天早上8点执行
|
||
0 0 8 ? * MON → 每周一早上8点执行
|
||
6 6 6 28 12 ? → 每年12月28日 6:06:06 执行
|
||
```
|
||
|
||
---
|
||
|
||
## 六、消息通信相关
|
||
|
||
### MQTT
|
||
**类比**:WebSocket,但更轻量,专为物联网设备设计。
|
||
**解释**:一种消息通信协议,用于手表等 IoT 设备和服务器之间的实时双向通信。跟 WebSocket 类似,建立长连接后可以互相推送消息。区别是 MQTT 有"主题"(Topic)概念,设备订阅特定主题接收消息。
|
||
|
||
```
|
||
// 类比前端 WebSocket
|
||
// WebSocket
|
||
ws.send(JSON.stringify({ type: 'task', data: {...} }))
|
||
ws.onmessage = (msg) => { ... }
|
||
|
||
// MQTT
|
||
mqtt.publish('watch_IMEI_123', JSON.stringify({ messageType: 1, ... }))
|
||
mqtt.subscribe('watch_IMEI_123', (msg) => { ... })
|
||
```
|
||
|
||
### MQTT Topic(主题)
|
||
**类比**:WebSocket 里的消息 `type` 字段 / 前端路由路径。
|
||
**解释**:消息的"频道"。设备订阅某个 Topic 后,只会收到发到这个 Topic 的消息。比如手表订阅自己的 IMEI 号作为 Topic,服务器往这个 Topic 发消息,只有这块手表能收到。
|
||
|
||
### MQTT QoS(服务质量等级)
|
||
**类比**:HTTP 请求的重试策略。
|
||
**解释**:
|
||
- QoS 0:发了就不管了(类似 `fetch` 不处理失败)
|
||
- QoS 1:至少送达一次,可能重复(类似 `fetch` + 自动重试)
|
||
- QoS 2:恰好送达一次(最可靠但最慢)
|
||
- 本项目用 QoS 1。
|
||
|
||
### MQTT Broker
|
||
**类比**:WebSocket 服务器 / 消息中转站。
|
||
**解释**:MQTT 的中心服务器,所有设备和后端都连接到 Broker,由它负责消息的转发。类似一个邮局,发件人投到邮局,邮局派送给收件人。
|
||
|
||
### 个推 / GeTui
|
||
**类比**:浏览器的 `Notification API` / PWA 推送通知。
|
||
**解释**:第三方手机 APP 推送服务。后端调用个推 SDK,个推通过 APNs(苹果)/ FCM(谷歌)/ 各厂商通道把通知推送到用户手机。就像浏览器推送通知,但是走的是手机系统级通道。
|
||
|
||
---
|
||
|
||
## 七、认证与安全
|
||
|
||
### Interceptor(拦截器)
|
||
**类比**:Axios 的请求/响应拦截器。
|
||
**解释**:在请求到达 Controller 之前先经过拦截器,做统一处理(如认证检查、日志记录)。跟前端 Axios 拦截器一模一样的概念,只是在后端执行。
|
||
|
||
```
|
||
// 前端 Axios 拦截器
|
||
axios.interceptors.request.use(config => { /* 加 token */ })
|
||
|
||
// 后端 Interceptor
|
||
public boolean preHandle(request, response) { /* 验证签名 */ }
|
||
```
|
||
|
||
### AOP(面向切面编程)
|
||
**类比**:Vue 的全局混入(mixin)/ 全局前置守卫。
|
||
**解释**:在不修改业务代码的情况下,给方法"织入"额外逻辑。比如 `@RepeatSubmit` 注解加在 Controller 方法上,自动加上防重复提交逻辑,不用每个方法手动写。类似前端用装饰器或全局 mixin 给所有组件加统一行为。
|
||
|
||
### UUID
|
||
**类比**:前端 `sessionStorage` 里的 `token`。
|
||
**解释**:登录成功后后端生成的唯一标识符(一串随机字符),存在 Redis 中(30天有效期)。前端每次请求都带上 UUID,后端据此识别用户身份。
|
||
|
||
### 签名 / Signature
|
||
**类比**:前端请求的防篡改校验。
|
||
**解释**:前端把 UUID + 时间戳 + 手机号通过 MD5 算法生成一个签名字符串,放在请求头里。后端用同样的算法重新计算,对比一致则说明请求没被篡改。类似前端某些支付场景的签名验证。
|
||
|
||
### MD5
|
||
**类比**:一种"指纹"算法。
|
||
**解释**:把任意长度的字符串转换成固定长度(32位)的字符串。同样的输入永远得到同样的输出,但无法从输出反推输入。常用于签名验证、密码存储(但不推荐用于安全场景,因为已被破解)。
|
||
|
||
---
|
||
|
||
## 八、Java 特有概念
|
||
|
||
### 注解 / Annotation(@xxx)
|
||
**类比**:前端的装饰器 `@decorator` / Vue 的指令 `v-xxx`。
|
||
**解释**:Java 用 `@` 开头的标记给代码添加元信息。常见的:
|
||
- `@Controller` → 标记这个类处理 HTTP 请求
|
||
- `@PostMapping("/task/pageList")` → 标记这个方法处理 POST /task/pageList
|
||
- `@Autowired` → 自动注入依赖(类似 Vue 的 `inject`)
|
||
- `@TableName("task_info")` → 标记这个类对应数据库的 task_info 表
|
||
|
||
### Lombok
|
||
**类比**:TypeScript 的自动生成 getter/setter。
|
||
**解释**:Java 的代码简化工具。加个 `@Data` 注解就自动生成 getter、setter、toString 等方法,不用手写。类似 TypeScript 的 `class` 可以直接访问属性。
|
||
|
||
### Bean / IoC / 依赖注入
|
||
**类比**:Vue 的 `provide/inject` 或 Vuex Store 的全局共享。
|
||
**解释**:Spring 框架帮你创建和管理对象(Bean),需要用的时候自动"注入"进来,不用手动 `new`。类似 Vue 的 `inject` 可以直接使用祖先组件 `provide` 的数据。
|
||
|
||
```java
|
||
// 后端:Spring 自动注入
|
||
@Autowired
|
||
private TaskService taskService; // 不用自己 new
|
||
|
||
// 类比前端:Vue inject
|
||
const taskStore = inject('taskStore') // 不用自己创建
|
||
```
|
||
|
||
### profile(环境配置)
|
||
**类比**:前端的 `.env.develop` / `.env.test` / `.env.production`。
|
||
**解释**:后端的环境区分。`application-test.yml` 存测试环境配置,`application-prod.yml` 存生产环境配置。启动时通过 `--spring.profiles.active=test` 指定用哪个配置,跟前端 `npm run dev` 和 `npm run build` 类似。
|
||
|
||
---
|
||
|
||
## 九、日志与监控
|
||
|
||
### Log4j
|
||
**类比**:前端的 `console.log`,但更强大。
|
||
**解释**:Java 的日志框架。可以控制日志级别(DEBUG/INFO/WARN/ERROR)、输出位置(控制台/文件)、格式等。相当于 `console.log` 的高级版本,支持自动按日期分割日志文件。
|
||
|
||
### Swagger
|
||
**类比**:自动生成的 API 文档,可以在线调试。
|
||
**解释**:后端加注解后自动生成 API 文档网页,能看到所有接口的地址、参数、返回值,还能直接在页面上发请求测试。访问 `/doc.html` 查看。相当于一个自动生成的 Postman。
|
||
|
||
---
|
||
|
||
## 十、部署相关
|
||
|
||
### 连接池 vs 直连
|
||
**类比**:
|
||
```javascript
|
||
// 直连(每次都新建)
|
||
async function query() {
|
||
const conn = await createConnection() // 耗时操作
|
||
const result = await conn.query(sql)
|
||
conn.close()
|
||
}
|
||
|
||
// 连接池(复用连接)
|
||
const pool = createPool({ max: 100 }) // 预先创建
|
||
async function query() {
|
||
const conn = pool.getConnection() // 直接取,很快
|
||
const result = await conn.query(sql)
|
||
conn.release() // 归还,不关闭
|
||
}
|
||
```
|
||
|
||
### 多模块依赖
|
||
**类比**:npm 的 monorepo(如 lerna / pnpm workspace)。
|
||
**解释**:本项目有 3 个子模块:
|
||
```
|
||
public (公共模块) ← 类似前端的 @shared/utils 包
|
||
↑ ↑
|
||
| |
|
||
web task ← 类似前端的 @app/admin 和 @app/worker
|
||
```
|
||
修改 public 后需要先 `mvn install`(发布到本地),web 和 task 才能用到最新代码。类似 monorepo 里改了 shared 包要先 build。
|
||
|
||
### Lettuce
|
||
**类比**:Axios 之于 HTTP,Lettuce 之于 Redis。
|
||
**解释**:Java 连接 Redis 的客户端驱动。负责跟 Redis 服务器建立连接、发送命令、接收结果。你不需要关心它,只需要知道后端通过它操作 Redis。
|
||
|
||
### Elasticsearch / BBoss
|
||
**类比**:一个超级强大的全文搜索引擎,类似浏览器的 Ctrl+F 但能搜索海量数据。
|
||
**解释**:目前项目中这部分代码被注释掉了(`#`),暂未启用。如果启用,可以实现类似"模糊搜索任务名称"的功能,比数据库的 `LIKE` 查询快得多。
|