JavaWeb 后端开发学习手册------一篇讲透 Maven + SpringBootWeb + MySQL(从零开始)
宝子们好呀 👋
今天咱们来盘一盘 JavaWeb 后端开发最核心的三块地基:Maven 构建 、SpringBootWeb 、还有 MySQL 数据库。
这篇文章是我结合课程笔记整理出来的,里面有些老师没展开、但考试和面试常考的坑(依赖冲突、scope、约束、数据类型、HTTP 状态码全表......)我都给补上了 📌,保证你学完这一篇,后端入门直接起飞 🚀。
ok,那咱们直接开始!👇
一、Maven 基础
1.1 初识 Maven
一句话总结:Maven 就是一款管理和构建 Java 项目的工具。
它有三大作用,咱们用表格捋一下 👇
| 作用 | 说明 |
|---|---|
| 依赖管理 | 方便快捷地管理项目依赖的 jar 包,避免版本冲突。使用前:手动下载 jar 包导入项目;使用后:只需在 pom.xml 中加一段坐标配置,Maven 自动下载。 |
| 项目构建 | 提供标准化、跨平台的自动化构建:编译(compile)、测试(test)、打包(package)、发布(deploy),一条命令搞定。 |
| 统一项目结构 | 无论 Eclipse / IDEA 创建,基于 Maven 的项目目录结构完全一致,可互相导入。 |
Maven 标准目录结构长这样:
项目根目录
├─ src
│ ├─ main # 源代码目录
│ │ ├─ java # 源代码 java 文件
│ │ └─ resources # 源代码配置文件
│ └─ test # 测试代码目录
│ ├─ java # 测试代码 java 文件
│ └─ resources # 测试代码配置文件
└─ target # 编译、打包生成的文件存放目录
1.2 Maven 概述
Apache Maven 是基于**项目对象模型(POM, Project Object Model)**概念的项目管理和构建工具,通过一小段描述信息管理项目的构建、报告和文档。官网:https://maven.apache.org/
Maven 三大模型:
| 模型 | 说明 |
|---|---|
| 项目对象模型 (POM) | 把自己的项目抽象成一个对象模型,有专属坐标 |
| 依赖管理模型 (Dependency) | 使用坐标描述当前项目依赖哪些第三方 jar 包 |
| 构建生命周期/阶段 (Build lifecycle & phases) | 编译插件、打包插件等完成标准化构建流程 |
📌 坐标 是资源(jar 包)的唯一标识,由三部分组成:groupId(组织名)+ artifactId(模块名)+ version(版本号)。
Maven 仓库 :仓库本质就是一个目录(文件夹),用来存储所有依赖(jar 包)和插件。
| 仓库类型 | 说明 |
|---|---|
| 本地仓库 | 自己计算机上的一个目录,用来存储 jar 包 |
| 中央仓库 | Maven 团队维护的全球唯一仓库:https://repo1.maven.org/maven2/ |
| 远程仓库(私服) | 一般由公司团队搭建的私有仓库 |
jar 包查找顺序:本地仓库 → 远程仓库(私服)→ 中央仓库
(无私服时:本地仓库 → 中央仓库,找到后下载到本地仓库缓存)
1.3 Maven 安装与配置
-
解压安装 :解压
apache-maven-3.9.4-bin.zip到无中文、无特殊字符的路径(如E:\develop)。bin:可执行命令(重点关注mvn命令)conf:配置文件(settings.xml需修改)lib:Maven 自身依赖的 jar 包
-
配置本地仓库 :新建一个目录作为本地仓库,编辑
conf/settings.xml,在注释外添加:xml<localRepository>E:\develop\maven_repo</localRepository> -
配置阿里云私服 (中央仓库在国外,下载慢):
xml<mirror> <id>alimaven</id> <name>aliyun maven</name> <url>http://maven.aliyun.com/nexus/content/groups/public/</url> <mirrorOf>central</mirrorOf> </mirror> -
配置环境变量 :新建系统变量
MAVEN_HOME= Maven 解压目录;Path 中添加%MAVEN_HOME%\bin;命令行执行mvn -v验证。 -
(可选)配置关联 JDK 版本 :在
<profiles>中配置 jdk-17 的 profile,设置maven.compiler.source/target = 17。
1.4 IDEA 集成 Maven
全局设置 :IDEA 欢迎页 File → Close Project → Customize → All settings → Build,Execution,Deployment → Build Tools → Maven,配置 Maven 主路径、settings.xml、本地仓库,并设置编译版本为 17(此处为全局配置,之后新建项目默认使用)。
pom.xml 详解:
xml
<project>
<!-- POM模型版本,目前固定为 4.0.0 -->
<modelVersion>4.0.0</modelVersion>
<!-- 当前项目坐标 -->
<groupId>com.itheima</groupId>
<artifactId>maven-project01</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 项目的JDK版本及编码 -->
<properties>
<maven.compiler.source>17</maven.compiler.source> <!-- 编译JDK版本 -->
<maven.compiler.target>17</maven.compiler.target> <!-- 运行JDK版本 -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
坐标组成:
| 元素 | 含义 | 示例 |
|---|---|---|
| groupId | 组织名称(通常域名反写) | com.itheima |
| artifactId | 项目/模块名称 | order-service |
| version | 版本号:SNAPSHOT (快照版,开发中不稳定)/ RELEASE(发行版,稳定) | 1.0-SNAPSHOT |
导入 Maven 项目的两种方式:
- 方式一:
File → Project Structure → Modules → Import Module → 选择 pom.xml - 方式二:
Maven 面板 → +(Add Maven Projects)→ 选择 pom.xml
1.5 依赖管理
基本配置:
xml
<dependencies>
<!-- 依赖 : spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.1.4</version>
</dependency>
</dependencies>
- 每次新增/修改依赖后,记得点击刷新按钮重新加载。
- 本地仓库没有该依赖时会联网下载,耐心等待。
- 不知道坐标可去中央仓库搜索:
https://mvnrepository.com/
依赖传递 :A 依赖 B,B 依赖 C,C 依赖 D → 在 A 项目中也会有 C、D 依赖,依赖会传递。
排除依赖 :主动断开传递下来的、不需要的依赖,被排除的资源无需指定版本:
xml
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.1.4</version>
<!-- 排除依赖 -->
<exclusions>
<exclusion>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-observation</artifactId>
</exclusion>
</exclusions>
</dependency>
📌 依赖冲突调解原则(补充): 当同一个 jar 包出现多个版本时,Maven 按以下原则选版本------
- 路径最短者优先:A→B→C→X(1.0) 与 A→D→X(2.0),选路径更短的 X(2.0)。
- 路径相同时,先声明者优先:pom.xml 中先声明的依赖路径下的版本生效。
- 也可用
<exclusions>排除冲突版本,或用<dependencyManagement>统一锁定版本。
1.6 Maven 生命周期
Maven 将项目构建的生命周期划分为 3 套相互独立的生命周期:
| 生命周期 | 职责 |
|---|---|
| clean | 清理工作 |
| default | 核心工作:编译、测试、打包、安装、部署等 |
| site | 生成报告、发布站点等 |
需要重点关注的 5 个阶段:
clean(清理) → compile(编译) → test(单元测试) → package(打包 jar/war) → install(安装到本地仓库)
⚠️ 关键规则: 同一套生命周期中,执行后面的阶段时,前面的阶段都会自动执行。
思考题:运行
package时,clean、compile会不会执行?→
clean不会(不同套),compile会(同一套)。
Maven 生命周期是抽象的,本身不做实际工作,实际任务都交由插件完成。
两种执行方式:
- IDEA 右侧 Maven 工具栏,双击对应生命周期
- 命令行:
mvn cleanmvn compilemvn testmvn packagemvn install
1.7 单元测试 JUnit
测试阶段划分:
| 阶段 | 说明 | 测试人员 |
|---|---|---|
| 单元测试 | 对软件最小组成单位(方法)进行测试 | 开发人员 |
| 集成测试 | 将已通过测试的单元组合成子系统再测试 | 开发人员 |
| 系统测试 | 对集成好的系统做彻底测试(功能、性能) | 测试人员 |
| 验收测试 | 针对用户需求、业务流程的交付测试 | 客户/需求方 |
测试方法:
- 白盒测试:清楚内部结构和代码逻辑,验证代码正确性
- 黑盒测试:不关心内部实现,验证功能、兼容性等
- 灰盒测试:结合两者特点
JUnit 入门: 在 main 方法中测试的弊端:测试代码与源代码未分开难维护;一个失败影响后面;无法自动化生成报告。JUnit 可解决这些问题。
① pom.xml 引入依赖:
xml
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.9.1</version>
<scope>test</scope>
</dependency>
② test/java 下创建测试类,方法上加 @Test:
java
@Test
public void testGetAge(){
Integer age = new UserService().getAge("110002200505091218");
System.out.println(age);
}
③ 运行:绿色 = 通过,红色 = 失败
📌 命名规范:测试类 XxxxTest;测试方法 public void xxx(){...}
📌 常用断言方法(补充):
| 方法 | 作用 |
|---|---|
assertEquals(expected, actual) |
断言两个值相等 |
assertNotEquals(unexpected, actual) |
断言两个值不相等 |
assertSame(expected, actual) |
断言是同一个对象(引用相等 ==) |
assertTrue(condition) / assertFalse(condition) |
断言条件为真 / 为假 |
assertNull(obj) / assertNotNull(obj) |
断言对象为 null / 不为 null |
assertArrayEquals(a, b) |
断言两个数组内容相等 |
assertThrows(XxxException.class, () -> ...) |
断言抛出指定异常 |
常见注解:
| 注解 | 作用 | 备注 |
|---|---|---|
@Test |
标识测试方法 | 每个方法独立运行 |
@BeforeEach |
每个测试方法执行前运行 | --- |
@AfterEach |
每个测试方法执行后运行 | --- |
@BeforeAll |
所有测试方法前运行一次 | 必须是 static 方法 |
@AfterAll |
所有测试方法后运行一次 | 必须是 static 方法 |
@DisplayName("名称") |
自定义测试类/方法的显示名 | --- |
@ParameterizedTest |
参数化测试(代替 @Test) | 配合 @ValueSource 等 |
@ValueSource(...) |
为参数化测试提供数据源 | 支持 strings/ints 等 |
@Disabled |
禁用该测试方法 | 补充 |
java
@DisplayName("测试-学生业务操作")
public class UserServiceTest {
@BeforeEach
public void testBefore(){ System.out.println("before..."); }
@AfterEach
public void testAfter(){ System.out.println("after..."); }
@BeforeAll // 该方法必须被 static 修饰
public static void testBeforeAll(){ System.out.println("before all ..."); }
@AfterAll // 该方法必须被 static 修饰
public static void testAfterAll(){ System.out.println("after all..."); }
@DisplayName("测试-获取性别3")
@ParameterizedTest
@ValueSource(strings = {"612429198904201611","612429198904201631","612429198904201626"})
public void testGetGender3(String idcard){
String gender = new UserService().getGender(idcard);
System.out.println(gender);
}
}
1.8 依赖范围 scope
通过 <scope>...</scope> 限制依赖的作用范围(主程序 main / 测试程序 test / 是否参与打包运行)。
📌 scope 常见取值表(补充完整):
| scope 取值 | 主程序(main) | 测试程序(test) | 打包运行 | 典型例子 |
|---|---|---|---|---|
| compile(默认) | ✔ | ✔ | ✔ | spring-context、logback |
| test | ✘ | ✔ | ✘ | junit-jupiter |
| provided | ✔ | ✔ | ✘ | servlet-api(运行时由 Tomcat 提供) |
| runtime | ✘(编译不需) | ✔ | ✔ | mysql-connector-j 驱动 |
| system(少用) | ✔ | ✔ | ✘ | 本地指定路径的 jar |
| import | 仅用于 dependencyManagement 中导入 BOM 清单 | --- | --- | spring-boot-dependencies |
1.9 Maven 常见问题:依赖报红
现象: 依赖未正确下载,Maven 面板报红,reload 也不重新下载。
原因: 网络原因导致下载不完整,仓库中生成了 xxx.lastUpdated 文件,不删除就不会再下载。
解决方案:
- 找到仓库中对应的
xxx.lastUpdated文件删除,重新加载项目 - 批量删除:命令行执行
del /s *.lastUpdated(或使用 del.bat 脚本双击递归删除) - 仍报红则重启 IDEA 重新加载项目
📌 第 1 章要点小结: Maven = 依赖管理 + 统一结构 + 标准构建;坐标三要素 groupId/artifactId/version;仓库查找顺序 本地→私服→中央;生命周期分 clean/default/site 三套,同套内后面阶段执行时前面自动执行;依赖可传递、可排除、可用 scope 限制范围。
二、SpringBootWeb 基础
2.1 Web 架构基础
- 静态资源:HTML、CSS、JS、图片、音视频等,服务器上存储的不变数据,不随请求变化。
- 动态资源 :根据用户请求动态生成、每次请求内容可能不同。早期用 Servlet、JSP(已淘汰),现在企业开发基于 Spring 体系框架。
- Java 动态资源通常部署在 Tomcat 这样的 Web 服务器中运行,浏览器与服务器基于 HTTP 协议通信。
BS 架构 vs CS 架构:
| 架构 | 全称 | 优点 | 缺点 |
|---|---|---|---|
| BS | Browser/Server 浏览器/服务器 | 维护方便(只需浏览器) | 体验一般 |
| CS | Client/Server 客户端/服务器 | 体验不错 | 需单独开发维护客户端,麻烦 |
2.2 SpringBoot 入门
Spring 已形成开发生态圈(Spring 全家桶 ),其中最基础核心的是 SpringFramework (提供依赖注入、事务管理、web 开发支持、数据访问等)。直接用 SpringFramework 开发存在配置繁琐、入门难度大 两个问题,因此官方推荐从 SpringBoot 入手:
- SpringBoot 两大特点:简化配置、快速开发
- 直接基于 SpringBoot 构建项目是官方推荐方式,也是企业开发主流
入门程序(3 步):
-
创建 SpringBoot 工程(联网,基于官方脚手架 start.spring.io;连不上可换阿里云
https://start.aliyun.com),勾选 Web 依赖 -
定义 HelloController:
java@RestController // 标识当前类是一个请求处理类 public class HelloController { @RequestMapping("/hello") // 标识请求路径 public String hello(String name){ System.out.println("HelloController ... hello: " + name); return "Hello " + name; } } -
运行引导类(
@SpringBootApplication注解的类),浏览器访问http://localhost:8080/hello?name=itheima
入门解析:为什么一个 main 方法就能启动 Web 应用?
spring-boot-starter-web(起步依赖) ─依赖传递→ spring-boot-starter-tomcat(内嵌 Tomcat) → main 方法启动内嵌 Tomcat(占用 8080 端口)
📌 起步依赖(Starter) :一组预定义的依赖项集合,提供特定场景下开发所需的全部库和配置。如 spring-boot-starter-web(web 开发)、spring-boot-starter-test(单元测试)。
2.3 HTTP 协议
HTTP(Hyper Text Transfer Protocol,超文本传输协议):规定浏览器与服务器之间数据传输的规则,是互联网应用最广泛的网络协议。
三大特点:
- 基于 TCP 协议:面向连接(三次握手)、可靠、安全
- 基于请求-响应模型:一次请求对应一次响应,先请求后响应
- 无状态协议 :对数据没有记忆能力,每次请求-响应独立。缺点:多次请求间不能共享数据(如购物车问题);优点:速度快。解决方案:会话技术(Cookie、Session)
HTTP 请求协议(请求行 + 请求头 + 请求体):
请求行: GET /brand/findAll?name=OPPO&status=1 HTTP/1.1
请求头: Host: localhost:8080
User-Agent: Mozilla/5.0 ...
Accept: text/html,...
请求体: (GET 请求无请求体,参数在请求行 ? 后面;POST 请求参数在请求体)
- 请求行 :请求方式 + 资源路径 + 协议/版本。
?前是请求路径,后是请求参数(key=value,多个用&连接) - 请求头:key: value 格式,携带浏览器自身信息
- 请求体 :存储 POST 请求参数;与请求头之间有一个空行隔开
GET 与 POST 的区别(高频面试题):
| 区别 | GET | POST |
|---|---|---|
| 请求参数位置 | 请求行中(?key=value) | 请求体中 |
| 参数长度 | 有限制(因浏览器而异) | 无限制 |
| 安全性 | 低(参数暴露在地址栏) | 相对高 |
📌 更多常见请求方式(RESTful 风格基础): GET(查询)、POST(新增)、PUT(修改/更新)、DELETE(删除)、PATCH(局部更新)、HEAD(只获取响应头)、OPTIONS(预检请求)。
获取请求数据(HttpServletRequest):
java
@RequestMapping("/request")
public String request(HttpServletRequest request){
// 1.获取请求参数
String name = request.getParameter("name");
// 2.获取请求路径
String uri = request.getRequestURI();
String url = request.getRequestURL().toString();
// 3.获取请求方式
String method = request.getMethod();
// 4.获取请求头
String header = request.getHeader("User-Agent");
return "request success";
}
HTTP 响应协议(响应行 + 响应头 + 响应体):
响应行: HTTP/1.1 200 OK (协议版本 + 状态码 + 状态码描述)
响应头: Content-Type: text/html;charset=utf-8
Content-Length: 1024
响应体: <html>...</html> (与响应头之间有空行隔开)
核心状态码先记住三个:200 OK 成功、404 Not Found 资源不存在、500 Internal Server Error 服务端错误(完整分类见附录)。
设置响应数据(两种方式):
java
// 方式一:HttpServletResponse 手动设置
@RequestMapping("/response")
public void response(HttpServletResponse response) throws IOException {
response.setStatus(401); // 1.状态码
response.setHeader("name","itcast"); // 2.响应头
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("<h1>hello response</h1>"); // 3.响应体
}
// 方式二:ResponseEntity(推荐,更简洁)
@RequestMapping("/response2")
public ResponseEntity<String> response2() {
return ResponseEntity.status(401)
.header("name","itcast")
.body("<h1>hello response</h1>");
}
📌 无特殊要求时,状态码和响应头通常不手动设置,服务器会根据处理逻辑自动设置。
2.4 SpringBootWeb 案例 & @ResponseBody
案例:访问 user.html 静态页面 → 发送 ajax 请求 /list → 服务端读取 user.txt → 响应 JSON → 前端渲染表格。
@ResponseBody 注解:
- 类型:方法注解、类注解
- 作用 :将方法返回值直接响应给浏览器;返回值是实体对象/集合时,自动转为 JSON 格式再响应
- @RestController = @Controller + @ResponseBody,类上加了 @RestController,就相当于所有方法都加了 @ResponseBody
📌 前后端分离项目中,直接在请求处理类上加 @RestController 即可。
案例中的问题 :数据解析、逻辑处理、数据响应代码全部堆在 Controller 中 → 复用性差、难维护。解决思路:分层开发。
2.5 三层架构
设计原则:单一职责原则------一个类或一个方法只做一件事,只管一块功能。
Controller 控制层 ← 接收前端请求,处理请求,响应数据
↓ 调用 ↑ 返回结果
Service 业务逻辑层 ← 处理具体的业务逻辑
↓ 调用 ↑ 返回数据
Dao 数据访问层(持久层)← Data Access Object,负责数据的增删改查
执行流程: 前端请求 → Controller 接收 → 调用 Service 处理逻辑 → Service 调用 Dao 获取数据 → Dao 操作数据后逐级返回 → Controller 响应给前端。
📌 三层架构的好处: 复用性强、便于维护、利于扩展。对 Service 层变更不会影响 Controller 和 Dao 层。
包结构约定:com.itheima.controller / com.itheima.service(.impl) / com.itheima.dao(.impl) / com.itheima.pojo(实体类)。
2.6 分层解耦 IOC & DI
问题分析 :代码中直接 new UserServiceImpl(),一旦要切换实现类(如改为 UserServiceImpl2),就得修改 Controller 代码 ------ 层与层之间耦合了。
- 内聚:软件中各个功能模块内部的功能联系
- 耦合:衡量软件中各个层/模块之间依赖、关联的程度
- 软件设计原则:高内聚、低耦合(提高可重用性、移植性)
解耦思路(两步):
- 不要在 Controller 中 new 对象
- 提供一个容器存储对象,程序用到时直接从容器中获取
Spring 两大核心概念:
| 概念 | 全称 | 含义 |
|---|---|---|
| 控制反转 IOC | Inversion Of Control | 对象的创建控制权由程序自身转移到外部容器。容器称为 IOC 容器 / Spring 容器 |
| 依赖注入 DI | Dependency Injection | 容器为应用程序提供运行时所依赖的资源(对象) |
| bean 对象 | --- | IOC 容器中创建、管理的对象 |
IOC & DI 入门(两步):
- 将 Service / Dao 实现类交给 IOC 容器管理 :类上加
@Component - 注入运行时依赖的对象 :成员变量上加
@Autowired,删除 new 操作
java
@Component // 把当前类的对象交给 IOC 容器管理
public class UserServiceImpl implements UserService {
@Autowired // 从容器中注入 UserDao 类型的 bean
private UserDao userDao;
// ...
}
@RestController
public class UserController {
@Autowired
private UserService userService;
// ...
}
2.7 IOC / DI 详解
Bean 的声明(@Component 及衍生注解):
| 注解 | 说明 | 使用位置 |
|---|---|---|
@Component |
声明 bean 的基础注解 | 不属于以下三类时使用 |
@Controller |
@Component 衍生注解 | 控制层类 |
@Service |
@Component 衍生注解 | 业务层类 |
@Repository |
@Component 衍生注解 | 数据访问层(与 MyBatis 整合后用得少) |
- 可通过 value 属性指定 bean 名,不指定则默认为类名首字母小写
- 声明控制器 bean 只能用
@Controller(@RestController 已内含)
⚠️ 组件扫描 :四大注解声明的 bean 不一定生效 ------还需被 @ComponentScan 扫描到。该注解已隐含在 @SpringBootApplication 中,默认只扫描启动类所在包及其子包。所以所有业务类要放在启动类所在包的子包下。
@Autowired 三种注入方式:
| 方式 | 写法 | 优点 | 缺点 |
|---|---|---|---|
| ① 属性注入 | 属性上加 @Autowired | 简洁、快速 | 隐藏依赖关系、破坏封装性 |
| ② 构造器注入(官方推荐) | 构造函数参数注入(只有一个构造函数时 @Autowired 可省略) | 依赖关系清晰、安全性高、可配 final | 参数多时构造函数臃肿 |
| ③ setter 注入 | setter 方法上加 @Autowired | 保持封装性 | 代码量大 |
@Autowired 默认按类型自动装配(去 IOC 容器中找该类型的对象注入)。
容器中同类型 bean 有多个时(启动报错)的三种解决方案:
| 方案 | 用法 | 说明 |
|---|---|---|
@Primary |
加在实现类上:@Primary @Service |
确定默认注入的实现 |
@Qualifier |
@Qualifier("userServiceImpl") @Autowired |
指定 bean 名注入,不能单独使用,须配合 @Autowired |
@Resource |
@Resource(name = "userServiceImpl") |
按 bean 名称注入 |
📌 面试题:@Autowired 与 @Resource 的区别
① @Autowired 是 Spring 框架提供的注解,@Resource 是 JDK 提供的注解;
② @Autowired 默认按类型 注入,@Resource 默认按名称注入。
📌 第 2 章要点小结: SpringBoot 简化配置快速开发,起步依赖内嵌 Tomcat;HTTP 无状态、请求/响应各三部分(行/头/体);GET 参数在请求行、POST 在请求体;@RestController = @Controller + @ResponseBody;三层架构 Controller→Service→Dao;IOC 控制反转 + DI 依赖注入实现解耦;同类型多 bean 用 @Primary / @Qualifier / @Resource 解决。
三、数据库 MySQL
3.1 数据库相关概念
| 概念 | 简称 | 说明 |
|---|---|---|
| 数据库 | DB (DataBase) | 存储和管理数据的仓库 |
| 数据库管理系统 | DBMS | 操作和管理数据库的大型软件(如 MySQL 服务端) |
| SQL | Structured Query Language | 结构化查询语言,操作关系型数据库的统一标准 |
程序员(编写 SQL) → DBMS(数据库管理系统) → DB(数据库中的数据)
主流数据库:
| 数据库 | 特点 |
|---|---|
| Oracle | 大型收费数据库,价格昂贵 |
| MySQL | 开源免费的中小型数据库(本课程学习对象,互联网公司最流行);分社区版(免费)和商业版(收费) |
| SQL Server | 微软推出的收费中型数据库,C#/.NET 常用 |
| PostgreSQL | 开源免费的中小型数据库 |
| DB2 | IBM 大型收费数据库 |
| SQLite | 嵌入式微型数据库,Android 内置 |
| MariaDB | MySQL 的开源分支,兼容性好 |
📌 学会 SQL 即可操作任意关系型数据库(MySQL / Oracle / SQL Server 通用)。
3.2 MySQL 概述
- 官网:
https://dev.mysql.com/;课程采用社区版 8.0.34 - 版本:商业版(收费,有技术支持)/ 社区版(免费,无技术支持)
连接 MySQL:
sql
mysql -u用户名 -p密码 [-h数据库服务器IP -P端口号]
-h不加默认连接本地 127.0.0.1;-P不加默认端口 3306- 推荐
-p后回车再输密码(明文跟在命令行不安全)
关系型数据库(RDBMS)与数据模型:
- 关系型数据库:建立在关系模型基础上,由多张相互连接的二维表(行 + 列)组成的数据库。
- 非关系型数据库:不基于二维表存储,如 Redis
- 二维表优点:格式统一便于维护;SQL 操作标准统一,支持复杂查询
📌 数据模型层次: 一个数据库服务器 → 可建多个数据库(相互独立)→ 一个库中可建多张表 → 一张表中可存多行记录。存数据顺序:先建库 → 再建表 → 再存数据。
图形化工具:主流:DataGrip(已集成进 IDEA)、Navicat、SQLyog、DBeaver。命令行敲 SQL 的三大痛点:无代码提示、操作繁琐、代码无法保存 → 开发中用图形化工具提效。
3.3 SQL 分类总览
| 分类 | 全称 | 作用 |
|---|---|---|
| DDL | Data Definition Language 数据定义语言 | 定义数据库对象(数据库、表) |
| DML | Data Manipulation Language 数据操作语言 | 对表中数据增、删、改 |
| DQL | Data Query Language 数据查询语言 | 查询表中记录(SELECT) |
| DCL | Data Control Language 数据控制语言 | 创建用户、控制访问权限(见 3.7 补充) |
3.4 DDL(数据库 & 表操作)
数据库操作:
sql
show databases; -- 查询所有数据库
select database(); -- 查询当前数据库
create database [ if not exists ] 数据库名; -- 创建(MySQL8 默认字符集 utf8mb4)
use 数据库名; -- 切换/使用数据库
drop database [ if exists ] 数据库名; -- 删除
📌 语法中的 database 可替换为 schema,如 create schema db01;、show schemas;
表操作 - 创建:
sql
create table tb_user (
id int primary key auto_increment comment 'ID,唯一标识',
username varchar(20) not null unique comment '用户名',
name varchar(10) not null comment '姓名',
age int comment '年龄',
gender char(1) default '男' comment '性别'
) comment '用户表';
📌 注意:[ ] 内为可选;最后一个字段后没有逗号 。auto_increment 主键自增:每次插入自动生成主键值,从 1 开始自增。
📌 MySQL 约束一览(补充完整):
| 约束 | 关键字 | 说明 |
|---|---|---|
| 非空约束 | NOT NULL |
字段值不能为 NULL |
| 唯一约束 | UNIQUE |
字段值不能重复 |
| 主键约束 | PRIMARY KEY |
一行数据的唯一标识 = 非空 + 唯一,一张表只能有一个主键 |
| 默认约束 | DEFAULT |
未指定值时使用默认值 |
| 检查约束 | CHECK |
保证字段值满足条件(MySQL 8.0.16+ 真正生效) |
| 外键约束 | FOREIGN KEY |
建立两表之间的关联,保证引用完整性 |
| 自动增长 | AUTO_INCREMENT |
(非严格意义的约束)主键值自动生成 |
📌 数据类型(补充):
数值类型:
| 类型 | 字节 | 范围(有符号) | 说明 |
|---|---|---|---|
| TINYINT | 1 | -128 ~ 127 | 小整数 |
| SMALLINT | 2 | -32768 ~ 32767 | --- |
| MEDIUMINT | 3 | 约 ±838 万 | --- |
| INT / INTEGER | 4 | 约 ±21 亿 | 常用整数 |
| BIGINT | 8 | 极大 | 大整数 |
| FLOAT | 4 | --- | 单精度浮点(有精度损失) |
| DOUBLE | 8 | --- | 双精度浮点,如 double(4,1) |
| DECIMAL(M,D) | 变长 | --- | 精确小数,金额必须用它 |
字符串类型:
| 类型 | 说明 |
|---|---|
| CHAR(n) | 定长字符串,定多长就占多少,性能更高。适合手机号 char(11) |
| VARCHAR(n) | 变长字符串,n 为最大长度。适合用户名 varchar(50) |
| TINYTEXT / TEXT / MEDIUMTEXT / LONGTEXT | 长文本 |
| BLOB 系列 | 二进制数据(图片、文件,一般存路径而非直接存库) |
日期时间类型:
| 类型 | 格式 | 用途 |
|---|---|---|
| DATE | YYYY-MM-DD | 生日、入职日期 |
| TIME | HH:MM:SS | 时间 |
| YEAR | YYYY | 年份 |
| DATETIME | YYYY-MM-DD HH:MM:SS | 创建时间等(不随时区变) |
| TIMESTAMP | YYYY-MM-DD HH:MM:SS | 时间戳(随时区自动转换,范围到 2038 年) |
表结构设计案例(员工表 emp):
sql
create table emp(
id int unsigned primary key auto_increment comment 'ID,主键',
username varchar(20) not null unique comment '用户名',
password varchar(32) not null comment '密码',
name varchar(10) not null comment '姓名',
gender tinyint unsigned not null comment '性别, 1:男, 2:女',
phone char(11) not null unique comment '手机号',
job tinyint unsigned comment '职位, 1:班主任,2:讲师,3:学工主管,4:教研主管,5:咨询师',
salary int unsigned comment '薪资',
image varchar(255) comment '头像',
entry_date date comment '入职日期',
create_time datetime comment '创建时间',
update_time datetime comment '修改时间'
) comment '员工表';
📌 设计表流程: ① 读页面原型及需求文档 → ② 确定原型字段(类型、长度、约束)→ ③ 增加业务基础字段(id、create_time 记录插入时间、update_time 记录最后更新时间)。
表操作 - 查询 / 修改 / 删除:
sql
-- 查询
show tables; -- 当前库所有表
desc 表名; -- 查看表结构
show create table 表名; -- 查看建表语句
-- 修改
alter table tb_emp add qq varchar(11) comment 'QQ号码'; -- 添加字段
alter table tb_emp modify qq varchar(13); -- 修改字段类型
alter table tb_emp change qq qq_num varchar(13); -- 修改字段名+类型
alter table tb_emp drop qq_num; -- 删除字段
rename table emp to tb_emp; -- 修改表名
-- 删除
drop table [ if exists ] 表名; -- 删除表(表中数据一并删除!)
3.5 DML(增删改)
① 添加数据 INSERT:
sql
-- 指定字段
insert into 表名 (字段1, 字段2) values (值1, 值2);
-- 全部字段
insert into 表名 values (值1, 值2, ...);
-- 批量添加
insert into emp(username, name, gender, phone, create_time, update_time)
values ('Tom1', '汤姆1', 1, '13309091231', now(), now()),
('Tom2', '汤姆2', 1, '13309091232', now(), now());
📌 注意:① 字段顺序与值一一对应;② 字符串和日期要用引号;③ 数据大小在字段规定范围内。
② 修改数据 UPDATE:
sql
update 表名 set 字段1 = 值1, 字段2 = 值2 [ where 条件 ];
update emp set name='张三', update_time=now() where id=1;
⚠️ ① 没有 where 条件会修改整张表 所有数据!② 修改数据时一般要同时更新公共字段 update_time。
③ 删除数据 DELETE:
sql
delete from 表名 [ where 条件 ];
delete from emp where id = 1;
⚠️ ① 没有条件会删除整张表所有数据!② DELETE 不能删除某个字段的值(可用 UPDATE 置为 NULL)。
3.6 DQL(查询,最重要)
完整语法结构(执行顺序 ≠ 书写顺序):
sql
SELECT 字段列表
FROM 表名列表
WHERE 条件列表
GROUP BY 分组字段列表
HAVING 分组后条件列表
ORDER BY 排序字段列表
LIMIT 分页参数
① 基本查询:
sql
select name, entry_date from emp; -- 查询多个字段
select * from emp; -- 所有字段(开发中尽量少用)
select name as '姓名', entry_date as '入职日期' from emp; -- 别名(as 可省略)
select distinct job from emp; -- 去除重复记录
② 条件查询 WHERE:
📌 比较运算符(补充):
| 运算符 | 功能 |
|---|---|
> >= < <= = |
大小比较、等于 |
<> 或 != |
不等于 |
BETWEEN ... AND ... |
在某个范围之内(含两端) |
IN(...) |
在 in 之后的列表中的值,多选一 |
LIKE 占位符 |
模糊匹配:_ 匹配任意单个字符,% 匹配任意个字符(0~多个) |
IS NULL / IS NOT NULL |
是 NULL / 不是 NULL |
逻辑运算符:AND 或 &&(并且)、OR 或 ||(或者)、NOT 或 !(取反)
sql
select * from emp where name = '杨逍'; -- 字符串用 '' 或 ""
select * from emp where salary <= 5000;
select * from emp where job is null; -- 判断 NULL 不能用 = null!
select * from emp where password <> '123456'; -- != 也可以
select * from emp where entry_date between '2000-01-01' and '2010-01-01';
select * from emp where job in (2,3,4);
select * from emp where name like '__'; -- 姓名为两个字
select * from emp where name like '张%'; -- 姓张
select * from emp where name like '%二%'; -- 名字含"二"
⚠️ 查询 NULL 值时必须用 is null / is not null,不能用 = null 或 != null!
③ 聚合函数(纵向计算,会忽略 NULL 值):
📌 常用聚合函数(补充):
| 函数 | 功能 |
|---|---|
| COUNT(列名) | 统计行数(该列为 NULL 的行不计入) |
| SUM(列名) | 求和(非数值类型结果为 0) |
| MAX(列名) | 最大值 |
| MIN(列名) | 最小值 |
| AVG(列名) | 平均值 |
sql
select count(id) from emp; -- 30
select count(job) from emp; -- 29(job 有 NULL 不计入)
select count(*) from emp; -- 推荐写法,MySQL 底层有优化
select avg(salary), min(salary), max(salary), sum(salary) from emp;
④ 分组查询 GROUP BY:
sql
-- 按性别分组统计人数
select gender, count(*) from emp group by gender;
-- 2015年前入职的员工,按职位分组,取人数 >= 2 的职位
select job, count(*)
from emp
where entry_date <= '2015-01-01' -- 分组前条件
group by job -- 分组
having count(*) >= 2; -- 分组后条件
📌 面试题:where 与 having 的区别
① 执行时机:where 在分组前 过滤,不满足的不参与分组;having 在分组后 对结果过滤。
② 判断条件:where 不能 对聚合函数判断,having 可以 。
执行顺序:where > 聚合函数 > having。分组后查询字段一般只写分组字段和聚合函数,查其他字段无意义。
⑤ 排序查询 ORDER BY:
sql
select * from emp order by entry_date asc; -- 升序(默认,可省略 ASC)
select * from emp order by entry_date desc; -- 降序
select * from emp order by entry_date asc, update_time desc; -- 多字段
⑥ 分页查询 LIMIT:
sql
select * from emp limit 0, 5; -- 第1页:从索引0开始取5条
select * from emp limit 5; -- 第1页可简写:limit 条数
select * from emp limit 5, 5; -- 第2页
select * from emp limit 10, 5; -- 第3页
📌 ① 起始索引从 0 开始,公式:起始索引 = (页码 - 1) × 每页记录数;② LIMIT 是 MySQL 方言;③ 查第一页时起始索引可省略。
📌 SELECT 完整执行顺序(补充):
FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT
📌 第 3 章要点小结: SQL 分 DDL/DML/DQL/DCL 四类;建表三要素:类型 + 约束 + 注释;char 定长 varchar 变长;DML 增删改不带 where 会动全表;DQL 六部分 SELECT-FROM-WHERE-GROUP BY-HAVING-ORDER BY-LIMIT;NULL 判断用 is null;count(*) 推荐;where 分组前过滤、having 分组后过滤且可用聚合函数;分页公式 (页码-1)×每页条数。
3.7 DCL 与进阶预告
📌 DCL 数据控制语言(补充核心用法):
sql
-- 用户管理
create user '用户名'@'主机名' identified by '密码'; -- 创建用户(% 表示任意主机)
alter user '用户名'@'主机名' identified with mysql_native_password by '新密码';
drop user '用户名'@'主机名';
select * from mysql.user; -- 查询所有用户
-- 权限控制(常用权限:ALL / SELECT / INSERT / UPDATE / DELETE / ALTER / DROP 等)
show grants for '用户名'@'主机名'; -- 查询权限
grant 权限列表 on 数据库名.表名 to '用户名'@'主机名'; -- 授予权限
revoke 权限列表 on 数据库名.表名 from '用户名'@'主机名'; -- 撤销权限
📌 后续进阶知识预告(先建立概念):
- 多表设计:表与表的关系有一对多(部门-员工)、多对多(学生-课程,需中间表)、一对一;通过**外键约束(FOREIGN KEY)**维护关联。
- 多表查询:内连接(INNER JOIN,查交集)、左/右外连接(LEFT/RIGHT JOIN)、子查询(嵌套查询)。
- 事务 :一组操作的集合,要么全部成功要么全部失败。ACID 四大特性 :原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。核心语句:
start transaction/commit/rollback。 - 索引 :帮助数据库高效获取数据的数据结构(MySQL 默认 InnoDB 使用 B+ 树),可大幅提升查询速度,但会占用空间、拖慢增删改。
附录
附录 A:常见 HTTP 状态码
📌 状态码分类(补充完整):
| 分类 | 含义 | 常见状态码 |
|---|---|---|
| 1xx | 信息性(请求已接收,继续处理) | 100 Continue |
| 2xx | 成功 | 200 OK 请求成功;201 Created 已创建;204 No Content 无内容 |
| 3xx | 重定向 | 301 永久重定向;302 临时重定向;304 Not Modified 缓存有效 |
| 4xx | 客户端错误 | 400 请求参数有误;401 未认证;403 无权限;404 Not Found 资源不存在;405 请求方式不支持 |
| 5xx | 服务端错误 | 500 Internal Server Error 服务器内部错误;502 网关错误;503 服务不可用 |
附录 B:速查清单
Maven 命令:
| 命令 | 作用 |
|---|---|
mvn -v |
查看版本,验证安装 |
mvn clean |
清理 target 目录 |
mvn compile |
编译源代码 |
mvn test |
运行单元测试 |
mvn package |
打包(jar/war) |
mvn install |
安装到本地仓库 |
SpringBoot 常用注解:
| 注解 | 作用 |
|---|---|
@SpringBootApplication |
启动类注解(内含组件扫描,扫描启动类所在包及子包) |
@RestController |
= @Controller + @ResponseBody,请求处理类 |
@RequestMapping("/path") |
映射请求路径 |
@Component / @Service / @Repository / @Controller |
声明 bean 交给 IOC 容器 |
@Autowired |
按类型自动注入 |
@Primary / @Qualifier / @Resource |
解决同类型多 bean 注入冲突 |
MySQL 高频语句:
| 场景 | 语句 |
|---|---|
| 建库 | create database if not exists 库名; |
| 切库 | use 库名; |
| 增 | insert into 表名(字段) values(值); |
| 删 | delete from 表名 where 条件; |
| 改 | update 表名 set 字段=值 where 条件; |
| 查 | select 字段 from 表名 where 条件 group by 分组 having 条件 order by 排序 limit 起始,条数; |
结语
ok,到这里咱们的 JavaWeb 后端学习手册 就全部盘完啦 🎉
从 Maven 构建 (依赖、生命周期、scope)到 SpringBootWeb (HTTP、三层架构、IOC/DI),再到 MySQL 数据库(DDL/DML/DQL、约束、数据类型、分页),这三块是后端开发的绝对地基,地基打牢了,后面学 MyBatis、Spring Boot 整合、各种框架才会顺风顺水 👍
如果这篇文章对你有帮助,记得点个免费的赞和收藏,你们的支持就是我最大的动力 💪
咱们下一篇见~
#java #spring boot #mysql #maven #后端 #学习笔记