目录
[第1章 前端与后端:从静态到动态](#第1章 前端与后端:从静态到动态)
[1.1 静态资源:网页的"固定装饰"](#1.1 静态资源:网页的“固定装饰”)
[1.2 动态资源:个性化的"智能服务"](#1.2 动态资源:个性化的“智能服务”)
[1.3 架构模式:BS vs CS](#1.3 架构模式:BS vs CS)
[第2章 SpringBoot入门:让Java开发变简单](#第2章 SpringBoot入门:让Java开发变简单)
[2.1 Spring家族:Java开发的"全家桶"](#2.1 Spring家族:Java开发的“全家桶”)
[2.2 SpringBoot的两大法宝](#2.2 SpringBoot的两大法宝)
[2.3 第一个SpringBoot程序:Hello World](#2.3 第一个SpringBoot程序:Hello World)
[2.4 魔法揭秘:为什么一个main方法就能启动Web服务?](#2.4 魔法揭秘:为什么一个main方法就能启动Web服务?)
[第3章 HTTP协议:浏览器与服务器的"对话规则"](#第3章 HTTP协议:浏览器与服务器的“对话规则”)
[3.1 HTTP是什么?](#3.1 HTTP是什么?)
[3.2 请求协议:浏览器"说的话"](#3.2 请求协议:浏览器“说的话”)
[3.3 响应协议:服务器"回的话"](#3.3 响应协议:服务器“回的话”)
[3.4 常见状态码:服务器的"表情包"](#3.4 常见状态码:服务器的“表情包”)
[第4章 实战案例:用户列表展示](#第4章 实战案例:用户列表展示)
[4.1 项目需求:前后端协作](#4.1 项目需求:前后端协作)
[4.2 代码实现](#4.2 代码实现)
[4.2.1 准备数据文件](#4.2.1 准备数据文件)
[4.2.2 三层架构版本](#4.2.2 三层架构版本)
[4.3 发现的问题:代码"挤在一起"](#4.3 发现的问题:代码“挤在一起”)
[第5章 分层解耦:高内聚低耦合](#第5章 分层解耦:高内聚低耦合)
[5.1 什么是耦合?](#5.1 什么是耦合?)
[5.2 解耦方案:IOC容器](#5.2 解耦方案:IOC容器)
[5.3 DI(依赖注入):Spring的"自动装配"](#5.3 DI(依赖注入):Spring的“自动装配”)
[5.4 三种注入方式](#5.4 三种注入方式)
[5.5 解决"多个实现类"问题](#5.5 解决“多个实现类”问题)
[第6章 总结与最佳实践](#第6章 总结与最佳实践)
[6.1 技术栈回顾](#6.1 技术栈回顾)
[6.2 开发建议](#6.2 开发建议)
[6.3 常见问题快速排查](#6.3 常见问题快速排查)
[6.4 注解总结与扩展](#6.4 注解总结与扩展)
本文系统介绍了前后端开发的核心概念与技术实践。首先对比了静态资源(HTML/CSS/JS)与动态资源(Spring框架)的特性,并分析了BS/CS架构的优劣。重点讲解了SpringBoot的核心优势:自动配置、内嵌服务器和快速开发能力,通过HelloWorld案例演示了其极简开发流程。随后深入剖析了HTTP协议规范、请求响应格式及状态码含义。在实战部分,通过用户列表案例展示了前后端协作流程,并引出分层解耦思想,详细介绍了IOC容器和依赖注入的三种方式(属性/构造器/Setter注入)。最后总结了开发规范、常见问题排查方案及核心注解的使用场景,为构建可维护的JavaWeb应用提供了完整方法论。
第1章 前端与后端:从静态到动态
1.1 静态资源:网页的"固定装饰"
想象一下,你走进一家装修精美的书店。书架、灯光、装饰画------这些都是固定不变的,无论谁来店里,看到的样子都一样。这就是静态资源。
什么是静态资源?
-
前端三剑客:HTML(骨架)、CSS(衣服)、JS(动作)
-
其他资源:图片、音频、视频等
-
特点:存储在服务器上,内容不会改变,谁访问都一样

1.2 动态资源:个性化的"智能服务"
现在想象这家书店有个咖啡角,咖啡师会根据你的口味现场制作咖啡。每次做的可能都不一样------这就是动态资源。
什么是动态资源?
-
传统技术:Servlet、JSP(已基本淘汰)
-
现代技术:Spring家族框架(企业主流)
-
特点:根据用户请求动态生成内容,每次可能不同

1.3 架构模式:BS vs CS
BS架构(Browser/Server)
-
模式:浏览器 ⇄ 服务器
-
优点:维护方便(只需更新服务器)
-
缺点:体验一般(依赖网络和浏览器)
-
举例:网页版邮箱、在线文档
CS架构(Client/Server)
-
模式:客户端程序 ⇄ 服务器
-
优点:体验流畅(本地计算能力强)
-
缺点:开发维护麻烦(需开发多个平台客户端)
-
举例:微信PC版、Photoshop
第2章 SpringBoot入门:让Java开发变简单
2.1 Spring家族:Java开发的"全家桶"
Spring官方说:"Spring makes Java simple"(让Java变简单)。这不是空话,Spring提供了一整套解决方案:
Spring全家桶包括:
-
Spring Framework:核心基础(地基)
-
Spring Boot:快速开发工具(装修队)
-
Spring Cloud:微服务方案(连锁店管理)
-
Spring Security:安全保护(保安系统)
-
Spring Data:数据访问(仓库管理)


2.2 SpringBoot的两大法宝
为什么选择SpringBoot?因为它解决了传统开发的痛点:
| 传统Spring问题 | SpringBoot解决方案 |
|---|---|
| 配置繁琐(几十行XML) | 自动配置(几乎零配置) |
| 启动慢,依赖多 | 内嵌服务器,快速启动 |
| 部署复杂 | 打包即运行,简单部署 |
2.3 第一个SpringBoot程序:Hello World
需求: 浏览器访问 /hello,返回"Hello xxx"
三步搞定:
步骤1:创建项目(联网)
-
访问:start.spring.io(或阿里云start.aliyun.com)
-
选择:Spring Boot版本 + Java版本
-
勾选:Spring Web依赖
-
点击:Generate(生成项目)


步骤2:编写代码
java
@RestController // 告诉Spring:这是处理请求的类
public class HelloController {
@RequestMapping("/hello") // 告诉Spring:这个方法处理/hello请求
public String hello(String name) {
System.out.println("收到请求,名字是:" + name);
return "Hello " + name + " ~";
}
}
步骤3:运行测试
-
运行引导类(带
@SpringBootApplication的类) -
打开浏览器,输入:
http://localhost:8080/hello?name=张三 -
页面显示:
Hello 张三 ~
2.4 魔法揭秘:为什么一个main方法就能启动Web服务?
秘密在于:
-
起步依赖 :
spring-boot-starter-web包含了:-
Web开发所有必要依赖
-
内嵌Tomcat服务器
-
自动配置Spring MVC
-
-
内嵌服务器:
java你的代码 → 打包 → 内嵌Tomcat → 直接运行无需单独安装Tomcat,无需配置war包部署

第3章 HTTP协议:浏览器与服务器的"对话规则"
3.1 HTTP是什么?
HTTP = 超文本传输协议
-
作用:规定浏览器和服务器之间的数据传输格式
-
特点:基于TCP(安全可靠)、请求-响应模式、无状态
无状态是什么意思?
-
好比银行柜员:每次办理业务都像是第一次见面
-
优点:处理快,简单
-
缺点:无法记住用户信息(需要Cookie/Session帮忙)
3.2 请求协议:浏览器"说的话"
请求格式:
java
请求行
请求头
空行
请求体(如果有)
GET请求示例(问路):
java
GET /search?q=springboot HTTP/1.1 ← 请求行
Host: www.baidu.com ← 请求头
User-Agent: Chrome/120.0
Accept: text/html
(空行)
(无请求体)
GET请求特点:
-
参数在地址栏:
?key1=value1&key2=value2 -
长度有限制
-
安全性较低(参数可见)
POST请求示例(寄信):
java
POST /submit HTTP/1.1 ← 请求行
Host: www.example.com ← 请求头
Content-Type: application/json
Content-Length: 45
(空行)
{"username":"张三","age":20} ← 请求体
POST请求特点:
-
参数在请求体中
-
长度无限制
-
安全性较高
Get请求如图所示:

Post请求如图所示:

3.3 响应协议:服务器"回的话"
响应格式:
java
响应行
响应头
空行
响应体
示例:
java
HTTP/1.1 200 OK ← 响应行
Content-Type: text/html;charset=UTF-8 ← 响应头
Content-Length: 1024
(空行)
<html><body>成功!</body></html> ← 响应体
3.4 常见状态码:服务器的"表情包"
| 状态码 | 含义 | 生活比喻 |
|---|---|---|
| 200 | 成功 | ✅ 一切正常 |
| 404 | 找不到 | ❓ 你要找的页面不存在 |
| 500 | 服务器错误 | 💥 服务器出问题了 |
| 401 | 未授权 | 🔒 请先登录 |

第4章 实战案例:用户列表展示
4.1 项目需求:前后端协作
场景: 浏览器显示用户列表
流程:
-
浏览器访问
user.html(前端页面) -
页面发送请求到
/list(后端接口) -
后端读取
user.txt数据文件 -
返回JSON格式的用户数据
-
前端渲染表格展示

4.2 代码实现
4.2.1 准备数据文件
user.txt 内容示例:
java
1,zhangsan,123,张三,23,2023-10-01 10:00:00
2,lisi,456,李四,25,2023-10-02 11:00:00
4.2.2 三层架构版本
第Controller层:在Controller(接待员)创建一个controller包
java
import cn.hutool.core.io.IoUtil;
import cn.hutool.json.JSONConfig;
import cn.hutool.json.JSONUtil;
import com.itheima.pojo.User;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@RestController
public class UserController {
@RequestMapping("/list")
public String list(){
//1.加载并读取文件
InputStream in = this.getClass().getClassLoader().getResourceAsStream("user.txt");
ArrayList<String> lines = IoUtil.readLines(in, StandardCharsets.UTF_8, new ArrayList<>());
//2.解析数据,封装成对象 --> 集合
List<User> userList = lines.stream().map(line -> {
String[] parts = line.split(",");
Integer id = Integer.parseInt(parts[0]);
String username = parts[1];
String password = parts[2];
String name = parts[3];
Integer age = Integer.parseInt(parts[4]);
LocalDateTime updateTime = LocalDateTime.parse(parts[5], DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
return new User(id, username, password, name, age, updateTime);
}).collect(Collectors.toList());
//3.响应数据
//return JSONUtil.toJsonStr(userList, JSONConfig.create().setDateFormat("yyyy-MM-dd HH:mm:ss"));
return userList;
}
}
第Dao层:Dao(仓库管理员)下面创建一个pojo包
java
package com.example.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
/**
* 封装用户信息
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Integer id;
private String username;
private String password;
private String name;
private Integer age;
private LocalDateTime updateTime;
}

4.3 发现的问题:代码"挤在一起"
原始问题:
java
// 所有代码都写在一起!
public String list() {
// 1. 读文件(数据访问)
// 2. 处理数据(业务逻辑)
// 3. 返回结果(响应处理)
// 修改任何一点都要动整个方法!
}
解决方案:分层
-
数据访问层:只关心怎么拿数据
-
业务逻辑层:只关心怎么处理数据
-
控制层:只关心接收请求和响应
第5章 分层解耦:高内聚低耦合
5.1 什么是耦合?
生活比喻:
-
高耦合:你的手机和充电器焊死了,只能用原配
-
低耦合:你的手机用通用Type-C口,各种充电器都能用
5.2 解耦方案:IOC容器
IOC(控制反转):对象的控制权从程序员手中"反转"到容器中
传统方式:
java
程序员 → new对象() → 使用对象
IOC方式:
java
程序员 → 告诉容器需要什么对象
↓
容器 → 创建对象 → 给程序员使用

5.3 DI(依赖注入):Spring的"自动装配"
不用再写:
java
private UserService userService = new UserServiceImpl();
只需写:
java
@Autowired // Spring自动注入合适的对象
private UserService userService;
5.4 三种注入方式
方式1:属性注入(最常用)
java
@Autowired
private UserService userService; // 简洁,快速开发
方式2:构造器注入(官方推荐)
java
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService; // 安全,依赖明确
}
方式3:Setter注入
java
private UserService userService;
@Autowired
public void setUserService(UserService userService) {
this.userService = userService; // 灵活,可重新设置
}
5.5 解决"多个实现类"问题
场景: 有多个UserService实现类,Spring该注入哪个?
解决方案1:@Primary(设为首选)
java
@Primary // 我是默认选择
@Service
public class UserServiceImpl implements UserService { ... }
解决方案2:@Qualifier(指名道姓)
java
@Autowired
@Qualifier("userServiceImpl") // 我要这个具体的
private UserService userService;
解决方案3:@Resource(按名注入)
java
@Resource(name = "userServiceImpl") // JDK提供的方式
private UserService userService;
总结建议
| 场景 | 推荐方式 | 说明 |
|---|---|---|
| 业务Service/Repository | 构造器注入 | 强制依赖,确保不变性 |
| Controller层 | 构造器注入 | 依赖明确,便于测试 |
| 配置类/可选依赖 | Setter注入 | 灵活性高 |
| 快速开发 | 属性注入 | 原型阶段使用 |
| 多实现默认选择 | @Primary | 设为首选实现 |
| 多实现指定选择 | @Qualifier | 按需指定具体实现 |
| 按名称精确注入 | @Resource | 明确使用bean名称 |
核心原则:
-
生产代码优先使用构造器注入
-
保持依赖的不可变性(final字段)
-
明确依赖关系,避免隐式行为
-
合理使用Lombok等工具简化代码
第6章 总结与最佳实践
6.1 技术栈回顾
| 技术 | 作用 | 比喻 |
|---|---|---|
| HTML/CSS/JS | 前端静态页面 | 店铺装修 |
| SpringBoot | 后端快速开发 | 装修队 |
| HTTP协议 | 前后端通信规则 | 对话礼仪 |
| 三层架构 | 代码组织方式 | 公司部门划分 |
| IOC/DI | 解耦依赖 | 招聘中介 |
6.2 开发建议
-
项目结构规范:
javacom.公司名.项目名 ├── controller # 控制层 ├── service # 业务层 ├── dao # 数据层 └── pojo # 实体类 -
注解使用规范:
-
Controller层:
@RestController -
Service层:
@Service -
Dao层:
@Repository -
注入依赖:推荐构造器注入
-
-
学习路径建议:
java基础:SpringBoot入门 → HTTP协议 → 简单案例 进阶:分层架构 → IOC/DI → 数据库整合 高级:缓存 → 安全 → 微服务
6.3 常见问题快速排查
| 问题 | 可能原因 | 解决方案 |
|---|---|---|
| 404错误 | 路径不对/没加注解 | 检查@RequestMapping路径 |
| 无法注入 | 没加@Component相关注解 | 添加@Service等注解 |
| 端口占用 | 8080端口被占用 | 改端口或关闭占用程序 |
| 乱码问题 | 字符集不统一 | 统一使用UTF-8 |
6.4注解总结与扩展
1、声明Bean的注解 (IOC容器管理)
这些注解用于将类的对象实例(Bean)交由Spring的IOC容器创建和管理。
| 注解 | 作用与特点 | 扩展说明 |
|---|---|---|
@Component |
基础注解,标记一个类为"组件",使其成为Spring容器管理的Bean。当类不属于Controller、Service、Dao等明确层时使用。 | 特点 :最通用的Bean声明方式。Spring在扫描到该注解时,会创建该类的实例放入IOC容器。 属性 :value 用于指定Bean的名称(ID),默认为类名首字母小写。 |
@Controller |
@Component的衍生注解 ,专门用于标记控制层(MVC中的C)的类。 |
特点 :在Spring MVC中,被@Controller标记的类才能处理HTTP请求。在SpringBoot Web中,常与@RestController互换,但@Controller通常用于返回视图。 |
@Service |
@Component的衍生注解 ,专门用于标记业务逻辑层(Service层)的类。 |
特点 :在语义上标识业务逻辑组件。虽然功能上与@Component相同,但使用它能使项目结构更清晰,是良好的编程习惯。 |
@Repository |
@Component的衍生注解 ,专门用于标记数据访问层(Dao/Mapper层)的类。 |
特点:1. 语义清晰;2. 其额外好处是能将平台特有的异常(如SQLException)转换为Spring的统一数据访问异常,但此功能在与MyBatis等ORM框架整合时使用较少。 |
@RestController |
组合注解 ,=@Controller + @ResponseBody 。标记的类是一个REST风格的控制器,其所有方法返回值默认序列化为JSON/XML等格式直接写入HTTP响应体。 |
特点 :前后端分离项目开发的首选 。避免了在每个方法上加@ResponseBody的麻烦,专门用于构建RESTful API。 |
@ComponentScan (隐式使用)
-
作用 :指定Spring在哪些包下扫描被
@Component及其衍生注解标记的类。 -
特点 :
@SpringBootApplication注解已包含它,并默认扫描启动类所在包及其所有子包。这是为什么我们将代码放在启动类同级或子包下就能自动生效的原因。
2、依赖注入的注解 (DI)
这些注解用于告知IOC容器,将管理好的Bean自动装配到需要的类中。
| 注解 | 作用与特点 | 扩展说明 |
|---|---|---|
@Autowired |
Spring框架提供的注解 ,用于实现按类型(byType)自动装配。 | 特点 : 1. 默认按类型匹配 :在容器中查找与字段/参数类型匹配的Bean。 2. 注入方式灵活 :可用于属性 、构造器 、Setter方法 上。 3. 构造器注入推荐 :当类中只有一个构造器时,@Autowired可省略。这是Spring官方推荐的注入方式,能明确依赖关系、保证依赖不可变、利于测试。 |
@Qualifier |
需与 @Autowired 配合使用,当容器中存在多个同类型Bean时,通过指定Bean的名称(ID) 来进行精确匹配(byName)。 |
特点 :解决@Autowired按类型匹配时的歧义性问题。 属性 :value 用于指定要注入的Bean的名称。 |
@Primary |
当存在多个同类型Bean时,被标记的Bean将作为默认首选进行注入。 | 特点 :是一种声明式的解决冲突方案,比@Qualifier更温和。通常用于定义默认实现。 |
@Resource |
JDK (JSR-250) 提供的注解 ,Spring也支持。默认按照Bean的名称(byName) 进行装配。 | 特点 : 1. 与@Autowired的核心区别 :来源不同(JDK vs Spring),默认装配策略不同(ByName vs ByType)。 2. 查找顺序 :先按name属性匹配,找不到再按类型匹配。 3. 属性 :name 用于指定Bean的名称。 |
@Autowiredvs@Resource面试题总结:
来源 :
@Autowired来自 Spring 框架;@Resource来自 Java 标准(JSR-250)。默认装配方式 :
@Autowired默认按类型 ;@Resource默认按名称。参数 :
@Autowired可配@Qualifier指定名称;@Resource有name属性。适用场景 :在纯Spring环境中两者皆可,但
@Autowired与Spring生态结合更紧密。需要按名称注入或希望减少对Spring的依赖时,可使用@Resource。
3、Web请求处理注解
| 注解 | 作用与特点 | 扩展说明 |
|---|---|---|
@RequestMapping |
映射HTTP请求到具体的处理器方法或类上。可以指定URL路径、请求方法(GET/POST等)、请求参数等条件。 | 特点 : 1. 功能强大 :是所有请求映射注解的"父"注解。 2. 可放在类或方法上 :类上定义共享路径前缀。 3. 派生注解 :为了更简洁,Spring提供了 @GetMapping, @PostMapping, @PutMapping, @DeleteMapping, @PatchMapping 等,它们等价于 @RequestMapping(method=RequestMethod.XXX)。 |
@ResponseBody |
标记一个方法或类的返回值应直接写入HTTP响应体,而不是解析为视图名称。通常用于返回JSON/XML数据。 | 特点 : 1. 可标记在方法或类上。 2. 返回值会通过 HttpMessageConverter (如Jackson) 转换为指定格式(如JSON)。 3. 已被整合进 @RestController,因此在REST控制器中无需单独使用。 |
总结脉络
-
启动与扫描 :
@SpringBootApplication(内含@ComponentScan) 启动应用并定义Bean扫描范围。 -
声明Bean :在扫描范围内,使用
@Component/@Controller/@Service/@Repository等注解将类声明为Spring管理的Bean。 -
处理请求 :在控制器类(
@RestController)中,使用@RequestMapping或其派生注解将HTTP请求映射到具体的Java方法。 -
依赖组装 :在需要其他Bean的类中(如Controller需要Service),使用
@Autowired(推荐构造器注入)或@Resource进行依赖注入,实现层与层之间的解耦。 -
响应数据 :
@RestController已确保方法返回值自动转换为JSON等格式并写入响应体。
附录:常见状态码
