Tlias后端模块化学习笔记
0. 后端学习总路线
Java Web 后端可以按下面路线理解:
1 | Maven 项目管理 |
后端开发的核心目标是:
1 | 接收请求 → 处理业务 → 操作数据库 → 返回结果 → 保证安全、稳定、可维护 |
第一模块:Maven 项目管理
1.1 Maven 的三大作用
| 作用 | 说明 |
|---|---|
| 依赖管理 | 不手动复制 jar,通过 pom.xml 统一声明依赖 |
| 统一项目结构 | 所有 Maven 项目目录规范一致 |
| 标准化构建 | 用命令完成编译、测试、打包、安装 |
标准目录:
1 | project |
1.2 Maven 坐标
Maven 通过坐标唯一定位一个依赖:
1 | <dependency> |
| 标签 | 含义 |
|---|---|
groupId |
组织或公司名,通常域名反写 |
artifactId |
项目或模块名 |
version |
版本号 |
1.3 仓库体系
依赖查找顺序:
1 | 本地仓库 → 私服仓库 → 中央仓库 |
如果依赖下载失败,常见原因:
- 网络问题。
- 镜像源配置错误。
- 本地仓库中存在
.lastUpdated失败缓存文件。 - 坐标写错。
1.4 生命周期
Maven 常用生命周期阶段:
1 | clean → compile → test → package → install |
| 命令 | 作用 |
|---|---|
mvn clean |
清理 target |
mvn compile |
编译主代码 |
mvn test |
运行测试 |
mvn package |
打包 |
mvn install |
安装到本地仓库 |
同一套生命周期中,执行后面的阶段会自动执行前面的阶段。
1.5 依赖范围 scope
| scope | 编译 | 测试 | 运行 | 打包 | 典型场景 |
|---|---|---|---|---|---|
| compile | 是 | 是 | 是 | 是 | 默认 |
| test | 否 | 是 | 否 | 否 | JUnit |
| provided | 是 | 是 | 否 | 否 | Servlet API |
| runtime | 否 | 是 | 是 | 是 | 数据库驱动 |
第二模块:SpringBoot Web 基础
2.1 SpringBoot 解决什么问题
传统 Spring 项目配置较多,SpringBoot 的目标是:
- 快速创建项目。
- 内嵌 Tomcat。
- 自动配置常用组件。
- 用起步依赖简化 jar 管理。
- 让开发者更关注业务代码。
启动类示例:
1 |
|
2.2 Controller 入门
Controller 用来接收浏览器或前端发来的请求。
1 |
|
重点:
@RestController=@Controller+@ResponseBody。@ResponseBody表示方法返回值直接作为响应体返回。- SpringBoot 默认会把对象转换为 JSON。
2.3 HTTP 协议
HTTP 是前后端通信协议。
请求包括:
1 | 请求行:请求方式、请求路径、协议版本 |
响应包括:
1 | 状态行:状态码 |
常见状态码:
| 状态码 | 含义 |
|---|---|
| 200 | 成功 |
| 400 | 请求参数错误 |
| 401 | 未登录或 token 无效 |
| 403 | 无权限 |
| 404 | 资源不存在 |
| 500 | 服务器内部错误 |
2.4 REST 风格接口
REST 风格强调:用 URL 表示资源,用 HTTP 方法表示操作。
| 操作 | 方法 | 路径示例 |
|---|---|---|
| 查询 | GET | /depts、/emps/{id} |
| 新增 | POST | /depts |
| 修改 | PUT | /depts |
| 删除 | DELETE | /depts/{id} |
这样前后端接口更统一、更容易维护。
第三模块:三层架构与 IOC/DI
3.1 三层架构
后端业务通常分三层:
1 | Controller 控制层:接收请求、返回响应 |
示例调用链:
1 | 前端请求 /depts |
3.2 分层的好处
- 职责清晰。
- 代码更容易维护。
- 便于测试。
- 业务规则不和请求细节混在一起。
- 数据库访问可以替换实现。
3.3 IOC 控制反转
IOC 的意思是:对象不再由程序员手动 new,而是交给 Spring 容器创建和管理。
常见 Bean 注解:
| 注解 | 常用位置 | 含义 |
|---|---|---|
@Component |
普通组件 | 通用 Bean |
@Controller |
控制层 | 接收请求 |
@RestController |
REST 控制层 | 返回 JSON |
@Service |
业务层 | 业务逻辑 |
@Repository |
持久层 | 数据访问 |
@Mapper |
MyBatis 接口 | Mapper 代理对象 |
3.4 DI 依赖注入
DI 是 Spring 容器把需要的对象注入进来。
推荐构造器注入:
1 |
|
常见问题:
- Bean 不在启动类所在包或子包下,扫描不到。
- 同一接口有多个实现类时,需要
@Qualifier或@Primary。 @Autowired字段注入能用,但可测试性和不可变性不如构造器注入。
第四模块:MySQL 与 SQL
4.1 SQL 分类
| 分类 | 名称 | 常用语句 |
|---|---|---|
| DDL | 数据定义语言 | create、alter、drop |
| DML | 数据操作语言 | insert、update、delete |
| DQL | 数据查询语言 | select |
| DCL | 数据控制语言 | grant、revoke |
| TCL | 事务控制语言 | commit、rollback |
4.2 DDL:表结构操作
1 | CREATE TABLE dept ( |
常见字段设计:
| 字段 | 说明 |
|---|---|
id |
主键 |
create_time |
创建时间 |
update_time |
修改时间 |
is_deleted |
逻辑删除标记,可选 |
4.3 DML:增删改
1 | INSERT INTO dept(name, create_time, update_time) |
注意:update 和 delete 一定要写 where,否则会影响整张表。
4.4 DQL:查询
1 | SELECT id, name, create_time, update_time |
查询执行逻辑可以这样理解:
1 | from → where → group by → having → select → order by → limit |
4.5 多表关系
常见关系:
| 关系 | 示例 | 设计方式 |
|---|---|---|
| 一对多 | 部门 - 员工 | 多的一方加外键 |
| 多对多 | 学生 - 课程 | 中间表 |
| 一对一 | 用户 - 用户详情 | 任一方加唯一外键 |
4.6 多表查询
内连接
只查询两张表都匹配的数据。
1 | SELECT e.name, d.name AS dept_name |
左外连接
左表全部保留,右表匹配不到则为 null。
1 | SELECT e.name, d.name AS dept_name |
4.7 事务与 ACID
事务保证一组操作要么全部成功,要么全部失败。
ACID:
| 特性 | 含义 |
|---|---|
| Atomicity 原子性 | 要么全成功,要么全失败 |
| Consistency 一致性 | 事务前后数据状态合法 |
| Isolation 隔离性 | 并发事务互不干扰 |
| Durability 持久性 | 提交后永久保存 |
典型场景:新增员工时同时保存员工基本信息和员工工作经历,如果其中一个失败,应全部回滚。
4.8 索引
索引用于提升查询效率,底层常见结构是 B+Tree。
适合建索引的字段:
- 经常作为查询条件的字段。
- 经常排序的字段。
- 经常用于连接的字段。
不适合建索引:
- 区分度很低的字段。
- 经常频繁更新的字段。
- 数据量很小的表。
第五模块:JDBC、连接池与 MyBatis
5.1 JDBC 基本流程
JDBC 是 Java 操作数据库的基础 API。
1 | 注册驱动 |
真实项目很少直接手写 JDBC,因为代码重复且容易出错。
5.2 PreparedStatement
相比 Statement,PreparedStatement 更推荐:
- 防止 SQL 注入。
- 预编译 SQL,性能更好。
- 参数设置更清晰。
1 | PreparedStatement ps = conn.prepareStatement("select * from emp where username = ?"); |
5.3 连接池
数据库连接创建成本高,连接池用于复用连接。
常见连接池:
- HikariCP:SpringBoot 默认。
- Druid:国内常见。
连接池核心思想:
1 | 启动时创建一批连接 |
5.4 MyBatis 入门
MyBatis 简化 JDBC,让开发者主要写 SQL 和结果映射。
Mapper 示例:
1 |
|
调用链:
1 | Service 调用 Mapper 接口 |
5.5 #{} 和 ${} 区别
| 写法 | 本质 | 是否安全 | 场景 |
|---|---|---|---|
#{} |
预编译参数占位符 | 安全 | 普通参数 |
${} |
字符串拼接 | 不安全 | 表名、排序字段等少数场景 |
绝大多数情况下使用 #{}。
5.6 XML 映射
复杂 SQL 通常写在 XML 中:
1 | <mapper namespace="com.tlias.mapper.EmpMapper"> |
XML 三要素:
namespace对应 Mapper 接口全类名。id对应 Mapper 方法名。- 参数和返回值要匹配。
5.7 动态 SQL
动态 SQL 根据条件拼接 SQL。
1 | <select id="list" resultType="Emp"> |
常用标签:
| 标签 | 作用 |
|---|---|
if |
条件判断 |
where |
自动处理 where 和 and |
set |
自动处理 update 逗号 |
foreach |
遍历集合,常用于批量删除 |
sql / include |
SQL 片段复用 |
第六模块:统一结果与 RESTful CRUD
6.1 统一响应结果
前后端联调时,建议后端统一返回结构:
1 | public class Result { |
示例 JSON:
1 | { |
好处:
- 前端处理更统一。
- 成功失败有标准。
- 方便扩展错误信息。
6.2 部门管理 CRUD
| 功能 | 请求方式 | 路径 |
|---|---|---|
| 查询部门 | GET | /depts |
| 删除部门 | DELETE | /depts/{id} |
| 新增部门 | POST | /depts |
| 修改部门 | PUT | /depts |
Controller 示例:
1 |
|
6.3 参数接收
| 注解 | 接收位置 | 示例 |
|---|---|---|
@PathVariable |
路径参数 | /depts/{id} |
@RequestParam |
查询参数 | ?name=Tom |
@RequestBody |
JSON 请求体 | 新增、修改对象 |
@RequestHeader |
请求头 | token |
6.4 时间字段处理
新增数据时:
1 | createTime = now |
修改数据时:
1 | updateTime = now |
常见错误是只保存业务字段,忘记维护创建时间和修改时间。
第七模块:分页、条件查询与多表业务
7.1 分页查询
分页核心参数:
| 参数 | 含义 |
|---|---|
page |
当前页码 |
pageSize |
每页条数 |
total |
总记录数 |
rows |
当前页数据 |
统一分页返回:
1 | public class PageBean<T> { |
7.2 PageHelper 分页
典型流程:
1 | PageHelper.startPage(page, pageSize); |
注意:PageHelper.startPage 必须紧跟查询语句,中间不要夹杂其他查询。
7.3 条件分页查询
员工查询常见条件:
- 姓名。
- 性别。
- 入职开始时间。
- 入职结束时间。
- 部门 ID。
SQL 要点:
- 条件为空时不能拼接。
- 日期范围要处理开始和结束。
- 多表查询要避免字段名冲突。
7.4 多表结果封装
员工表中有 dept_id,页面需要展示部门名称,通常使用连接查询:
1 | SELECT e.*, d.name AS dept_name |
Java 对象中可以额外定义 deptName 字段接收查询结果。
第八模块:项目实战业务模块
8.1 部门管理
核心逻辑:
1 | Controller 接收请求 |
注意事项:
- 删除部门前可考虑是否有关联员工。
- 修改部门要更新
updateTime。 - 查询时注意字段驼峰映射。
8.2 员工管理
员工模块比部门复杂,包含:
- 条件分页查询。
- 新增员工。
- 删除员工。
- 修改员工。
- 查询回显。
- 员工信息统计。
- 员工工作经历。
新增员工典型流程:
1 | 接收员工基本信息和经历列表 |
8.3 班级管理
班级模块常见功能:
- 查询班级列表。
- 新增班级。
- 修改班级。
- 删除班级。
- 根据班级状态展示信息。
班级通常与学员是一对多关系。
8.4 学员管理
学员模块常见功能:
- 分页查询学员。
- 新增学员。
- 修改学员。
- 删除学员。
- 违纪处理。
业务注意:
- 学员属于班级。
- 查询时要展示班级名称。
- 新增/修改要校验班级是否存在。
8.5 统计报表
统计接口通常返回图表需要的数据:
- 员工职位人数统计。
- 员工性别统计。
- 学员学历统计。
- 班级人数统计。
返回结构可以根据前端图表组件设计,例如:
1 | public class JobOption { |
第九模块:事务管理
9.1 为什么需要事务
当一个业务包含多条 SQL 时,只成功一部分会导致数据不一致。
例:新增员工时:
1 | 插入 emp 成功 |
如果没有事务,就会出现员工存在但经历不存在的不完整数据。
9.2 Spring 事务
在业务方法上加:
1 |
|
重点:
@Transactional通常加在 Service 层。- 默认遇到运行时异常回滚。
- 方法必须由 Spring 管理的 Bean 调用才生效。
9.3 事务失效常见原因
| 原因 | 说明 |
|---|---|
| 方法不是 public | 代理可能不生效 |
| 同类内部方法调用 | 没经过代理对象 |
| 异常被捕获未抛出 | Spring 不知道失败 |
| 抛出受检异常 | 默认不回滚,需配置 rollbackFor |
| 类没有交给 Spring 管理 | 没有事务代理 |
第十模块:文件上传
10.1 上传流程
1 | 前端选择文件 |
Controller 示例:
1 |
|
10.2 文件名处理
不能直接使用原文件名,可能重复或包含特殊字符。
推荐:
1 | UUID + 原文件后缀 |
10.3 本地存储 vs 对象存储
| 方式 | 优点 | 缺点 |
|---|---|---|
| 本地存储 | 简单 | 不适合多服务器,迁移麻烦 |
| OSS | 稳定、可公网访问 | 需要配置密钥、Bucket |
第十一模块:异常处理与参数校验
11.1 为什么要统一异常处理
如果每个 Controller 都手动 try-catch,代码会重复且混乱。
统一异常处理可以:
- 集中处理系统异常。
- 返回统一错误格式。
- 避免把堆栈信息暴露给前端。
11.2 全局异常处理
1 |
|
常见可以细分处理:
- 参数校验异常。
- 业务异常。
- 数据库异常。
- 未登录异常。
11.3 参数校验思路
后端不能只依赖前端校验,重要字段要在后端再次校验:
- 必填字段不能为空。
- 日期范围是否合法。
- ID 是否存在。
- 用户是否有权限操作。
第十二模块:日志系统 Logback
12.1 为什么需要日志
日志用于:
- 查看程序运行状态。
- 定位错误。
- 记录关键业务操作。
- 线上问题排查。
12.2 日志级别
1 | TRACE < DEBUG < INFO < WARN < ERROR |
常用:
- 开发环境:
DEBUG。 - 生产环境:
INFO或WARN。 - 异常:
ERROR。
12.3 日志使用方式
1 | private static final Logger log = LoggerFactory.getLogger(DeptController.class); |
注意:
- 不要用
System.out.println代替日志。 - 日志不要输出密码、密钥等敏感信息。
- 高频接口日志要控制数量。
第十三模块:登录认证、JWT、Filter、Interceptor
13.1 登录认证流程
1 | 用户提交用户名密码 |
13.2 JWT 结构
JWT 由三部分组成:
1 | Header.Payload.Signature |
| 部分 | 说明 |
|---|---|
| Header | 算法和 token 类型 |
| Payload | 用户信息、过期时间等声明 |
| Signature | 签名,防止篡改 |
JWT 特点:
- 服务端可以无状态校验。
- token 中不要存敏感信息。
- 必须设置过期时间。
13.3 Filter 过滤器
Filter 属于 Servlet 规范,执行位置更靠前。
1 | 请求 → Filter → DispatcherServlet → Controller |
适合处理:
- 登录校验。
- 编码处理。
- 通用请求日志。
13.4 Interceptor 拦截器
Interceptor 属于 SpringMVC。
1 | 请求 → DispatcherServlet → Interceptor → Controller |
常用方法:
| 方法 | 时机 |
|---|---|
preHandle |
Controller 执行前 |
postHandle |
Controller 执行后,视图渲染前 |
afterCompletion |
请求完成后 |
13.5 Filter 和 Interceptor 区别
| 对比 | Filter | Interceptor |
|---|---|---|
| 规范 | Servlet | SpringMVC |
| 执行时机 | 更早 | DispatcherServlet 之后 |
| 管理范围 | 几乎所有请求 | SpringMVC 请求 |
| 依赖 Spring | 不一定 | 是 |
第十四模块:AOP 面向切面编程
14.1 AOP 解决什么问题
AOP 用来处理与业务无关但很多地方都需要的横切逻辑。
例如:
- 操作日志。
- 权限校验。
- 性能统计。
- 事务管理。
- 异常监控。
不使用 AOP:每个方法都写重复代码。
使用 AOP:把重复逻辑抽到切面中统一处理。
14.2 AOP 核心概念
| 概念 | 含义 |
|---|---|
| JoinPoint | 连接点,可被增强的方法 |
| Pointcut | 切入点,真正要增强的方法范围 |
| Advice | 通知,增强逻辑 |
| Aspect | 切面,切入点 + 通知 |
| Target | 目标对象 |
| Proxy | 代理对象 |
14.3 通知类型
| 通知 | 执行时机 |
|---|---|
@Before |
方法执行前 |
@After |
方法执行后,无论成功失败 |
@AfterReturning |
方法成功返回后 |
@AfterThrowing |
方法抛异常后 |
@Around |
环绕通知,最强大 |
14.4 操作日志案例
常见做法:
1 | 自定义 @LogOperation 注解 |
环绕通知伪代码:
1 |
|
第十五模块:SpringBoot 配置与原理
15.1 配置文件
SpringBoot 常用配置文件:
1 | application.properties |
推荐使用 application.yml,层级清晰:
1 | server: |
15.2 配置优先级
常见优先级从低到高:
1 | application.yaml |
命令行参数优先级最高。
15.3 Bean 作用域
| 作用域 | 说明 |
|---|---|
| singleton | 默认,容器中一个实例 |
| prototype | 每次获取创建新实例 |
| request | 每个请求一个实例 |
| session | 每个会话一个实例 |
| application | Web 应用级别共享 |
大多数业务 Bean 使用默认单例即可。
15.4 第三方 Bean
第三方类不能直接加 @Component,可以用 @Bean 注册:
1 |
|
15.5 @SpringBootApplication
它是组合注解:
1 | @SpringBootConfiguration |
作用:
- 声明当前类是配置类。
- 扫描当前包及子包 Bean。
- 开启自动配置。
15.6 起步依赖原理
例如引入:
1 | <dependency> |
会通过 Maven 依赖传递自动引入:
- SpringMVC。
- 内嵌 Tomcat。
- JSON 处理。
- 参数校验等相关依赖。
起步依赖本质:帮你把一组常用依赖打包管理。
15.7 自动配置原理
自动配置大致流程:
1 | @SpringBootApplication |
常见条件注解:
| 注解 | 含义 |
|---|---|
@ConditionalOnClass |
类路径下有某个类才生效 |
@ConditionalOnMissingBean |
容器中没有某个 Bean 才生效 |
@ConditionalOnProperty |
配置属性满足条件才生效 |
第十六模块:Maven 高级与多模块项目
16.1 为什么分模块
当项目变大后,一个模块会出现:
- 代码混杂。
- 依赖混乱。
- 复用困难。
- 打包部署不清晰。
分模块可以按职责拆分,例如:
1 | tlias-parent |
16.2 继承
父工程统一管理版本:
1 | <parent> |
自定义父工程一般设置:
1 | <packaging>pom</packaging> |
16.3 dependencyManagement
dependencyManagement 只管理版本,不会真正引入依赖。
子模块要使用依赖,仍然需要写:
1 | <dependency> |
16.4 聚合
父工程通过 modules 聚合子模块:
1 | <modules> |
执行父工程打包时,会按模块依赖顺序构建。
16.5 私服
私服用于公司内部依赖管理:
- 提升下载速度。
- 管理内部 jar。
- 控制依赖版本。
- 支持发布 SNAPSHOT/RELEASE。
第十七模块:部署、Linux 与 Docker
17.1 后端部署基本流程
1 | 本地开发完成 |
启动命令:
1 | java -jar tlias.jar |
后台启动:
1 | nohup java -jar tlias.jar > app.log 2>&1 & |
17.2 Linux 常用命令
| 命令 | 作用 |
|---|---|
ls |
查看目录 |
cd |
切换目录 |
pwd |
当前目录 |
mkdir |
创建目录 |
rm |
删除 |
cp |
复制 |
mv |
移动/重命名 |
tail -f |
实时查看日志 |
ps -ef |
查看进程 |
kill |
结束进程 |
17.3 Docker 基础
Docker 把应用和运行环境打包成镜像,通过容器运行。
核心概念:
| 概念 | 说明 |
|---|---|
| 镜像 Image | 程序运行模板 |
| 容器 Container | 镜像运行实例 |
| Dockerfile | 构建镜像的脚本 |
| Docker Compose | 多容器编排工具 |
17.4 Dockerfile 示例
1 | FROM eclipse-temurin:17-jre |
17.5 Docker Compose 部署
一个 Java Web 项目常见容器:
1 | nginx 前端静态资源代理 |
docker-compose.yml 负责统一启动这些服务。
常用命令:
1 | docker compose up -d --build |
第十八模块:MySQL 远程连接排查
MySQL 远程连接不上时按顺序排查:
1 | MySQL 服务是否启动 |
常见命令:
1 | SELECT user, host FROM mysql.user; |
配置监听地址:
1 | bind-address = 0.0.0.0 |
第十九模块:后端高频易错点
19.1 Maven 易错点
| 问题 | 解决 |
|---|---|
| 依赖下载失败 | 检查网络、镜像、坐标,删除 .lastUpdated |
| 子模块找不到父工程 | 检查 relativePath |
| 父工程打包失败 | 检查 packaging 是否为 pom |
dependencyManagement 依赖不可用 |
子模块还需要真正声明依赖 |
19.2 SpringBoot 易错点
| 问题 | 原因 |
|---|---|
| Bean 扫描不到 | 不在启动类包或子包下 |
| 接口 404 | 请求路径或方法不匹配 |
| JSON 接收失败 | 缺少 @RequestBody 或字段名不匹配 |
| 参数为 null | 注解用错或前端参数名不一致 |
19.3 MyBatis 易错点
| 问题 | 原因 |
|---|---|
| SQL 找不到 | XML namespace 或 id 不匹配 |
| 字段封装失败 | 下划线和驼峰未映射 |
| SQL 注入风险 | 错用 ${} |
动态 SQL 多出 and |
没用 where 标签 |
| 批量删除失败 | foreach 参数名不对 |
19.4 事务易错点
| 问题 | 原因 |
|---|---|
| 事务不回滚 | 异常被捕获或不是运行时异常 |
| 注解不生效 | 方法不是通过代理对象调用 |
| 加在 Controller 层 | 职责不清,推荐加 Service 层 |
19.5 登录认证易错点
| 问题 | 原因 |
|---|---|
| 401 | token 没传、过期或签名错误 |
| 登录接口被拦截 | 拦截器没有放行登录路径 |
| 前端跨域拿不到 token | 请求头配置或跨域配置问题 |
| token 存敏感信息 | JWT payload 可被解码查看 |
第二十模块:后端知识关系图
1 | Maven |
第二十一模块:看完应掌握的能力清单
学完后端部分,应该能做到:
- 能看懂 Maven
pom.xml,知道依赖、坐标、生命周期。 - 能创建并运行 SpringBoot Web 项目。
- 能设计 REST 风格接口。
- 能按 Controller、Service、Mapper 三层编写代码。
- 能编写 MySQL 基础 SQL、多表查询、分页查询。
- 能使用 MyBatis 注解和 XML 操作数据库。
- 能完成部门、员工、班级、学员 CRUD。
- 能使用事务保证多表操作一致性。
- 能完成文件上传到本地或 OSS。
- 能使用全局异常处理统一返回错误。
- 能使用日志定位问题。
- 能实现 JWT 登录认证。
- 能理解 Filter 和 Interceptor 的区别。
- 能使用 AOP 实现操作日志。
- 能理解 SpringBoot 起步依赖和自动配置原理。
- 能拆分 Maven 多模块项目。
- 能使用 Linux、Docker、Docker Compose 部署 Java 项目。
第二十二模块:后端复习建议
建议按下面顺序复习:
1 | 1. Maven 坐标、依赖、生命周期 |
记忆口诀:
1 | Maven 管依赖,Boot 起项目; |