与其花时间编写解释你写出的糟糕的代码的注释,不如花时间清理那堆糟糕的代码。
Maven
概述
Maven 是一个 基于 POM(Project Object Model) 的构建工具,它通过一个 pom.xml 文件来管理项目的配置,包括依赖、插件、构建流程等。
Maven的作用包括以下几点:
- 依赖管理 :自动下载并管理项目所需的第三方库(如JUnit,Spring,MySQL驱动),避免手动引入jar包。
- Jar包:用于打包Java类、资源文件和元数据的压缩文件格式。
- 标准化项目结构 :Maven 提倡统一的项目目录结构,关于具体的结构我们下面再讲。
- 构建自动化 :一条命令即可完成编译、测试、打包、安装、部署等流程。
- 插件机制 :支持丰富的插件。

Maven项目结构
your-project/
├── pom.xml <-- Maven 项目的核心配置文件
├── src/
│ ├── main/
│ │ ├── java/ <-- 应用/库的源代码(包结构从这里开始)
│ │ ├── resources/ <-- 配置文件、资源文件(会被打包到类路径)
│ │ └── webapp/ <-- (可选)Web 应用的资源,如 HTML、JSP、WEB-INF(用于 Web 项目)
│ └── test/
│ ├── java/ <-- 测试代码(与 main/java 平行的包结构)
│ └── resources/ <-- 测试所需的资源文件
└── target/ <-- 构建输出目录(编译后的类、打包文件等)
Maven Wrapper
Maven Wrapper 是一种让项目自带Maven的“启动器”,它的关键作用是:
- 保证团队成员使用相同版本的Maven,避免版本不一致的尴尬问题
- 不需要预先在系统中全局安装Maven,项目开箱即用
- 常用于CL/CD环境,如GitHub Action,Jenkins,GitLab CL等。
- CL(持续集成):频繁地(每天多次)将代码集成到主分支,并自动构建、测试 ,从而快速发现问题。
- CD(持续交付):CI 之后,自动将构建好的产物发布到“可上线”的环境(如测试、预发布环境)
Maven Wrapper 包含的文件
my-project/
├── mvnw <-- Unix/Linux/Mac 系统用的 shell 脚本
├── mvnw.cmd <-- Windows 系统用的批处理脚本
└── .mvn/
└── wrapper/
├── maven-wrapper.jar <-- 启动器的核心代码
└── maven-wrapper.properties <-- 配置使用的 Maven 版本
当你通过mvnw允许命令时:
./mvnw clean install
- 检查
.mvn/wrapper/maven-wrapper.properties中指定的 Maven 版本。 - 如果没有这个Maven版本,自动下载。
- 使用对应版本的Maven执行
clean install<span> </span>命令
所以在拿到手一个新的Maven项目时,可以优先使用mvnw命令,以确保使用相同的版本减少错误的发生。
Maven配置
Maven官网:Welcome to Apache Maven – Maven
Maven的安装包解压后目录如下:

- 我们需要将
bin目录添加到环境变量中 conf中存储的为Maven的全局配置文件- 如果想要用户等级的配置文件,在目录
${user.home}/.m2/settings.xml
- 如果想要用户等级的配置文件,在目录
配置阿里云公共镜像
代开maven的配置文件 conf/settings.xml,在 <mirrors></mirrors>标签中添加 mirror 子节点:
<mirror>
<id>aliyunmaven</id>
<mirrorOf>*</mirrorOf>
<name>阿里云公共仓库</name>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>
配置IDEA
全局Maven配置
全局配置环境需要我们在不打开任何项目时进行配置。
若打开任意项目,进行配置,则为当前项目进行配置,过程一致。
首先点击左下角的齿轮,然后打开设置。

找到Maven设置:

- Maven主路径:选择Maven文件夹的根目录
- 用户设置文件:如果添加了私服等,请重重新选择你的配置文件。
- 或者将你的配置文件放在默认路径下
然后选择运行java程序版本:

最后在Java编译器中也选择相同的Java版本:

创建Maven项目
IDEA中创建Maven项目我们首先新建项目:

填写项目名,以及组织名:

Groupid和ArtifactId组成了项目的唯一标识符。- 不同的
Groupid用来区分不同来源的库。 - 依赖声明:
Groupid和ArtifactId是引入依赖的重要依据。
项目创建完成:

依赖管理
添加依赖
我们打开 pom.xml
- 添加标签
<dependencies></dependencies>:
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.5.18</version>
</dependency>
</dependencies>
-
在
<dependencies>中使用<dependency>引入坐标 -
点击刷新按钮,修改生效

Maven仓库:Maven Repository: Search/Browse/Explore
可以在Maven仓库中搜索想要的插件。
依赖传递
直接依赖:在当前项目中通过依赖配置建立的依赖关系。
间接依赖:被依赖的资源如果依赖其他资源,当前项目间接依赖其他资源。

排除依赖

若项目A 依赖项目B,却并不想要导入项目B中的某个依赖,可以使用依赖排除。
- 排除依赖:排除依赖指主动断开依赖的资源,被排除的资源无需指定版本。
<dependency>
<groupld>com.itheima</groupld>
<artifactld>maven-projectB</artifactld>
<version>1.0-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupld>junit</groupld>
<artifactld>junit</artifactld>
</exclusion>
</exclusions>
</dependency>
导入B包,却排除B包依赖的junit
依赖范围
Maven 依赖的 作用范围 (scope)决定了依赖在 编译、测试、运行、打包 等阶段的可用性。
默认情况下,依赖是 compile 范围,可在任何地方使用。
通过 <scope>...</scope> 标签设置依赖范围。
| scope 值 | 主程序 (main) | 测试程序 (test) | 打包/运行 (package) | 示例依赖 | 典型用途 |
|---|---|---|---|---|---|
| compile (默认) | ✅ 可用 | ✅ 可用 | ✅ 参与 | log4j | 常规依赖,编译、测试、运行都需要 |
| test | ❌ 不可用 | ✅ 可用 | ❌ 不参与 | junit | 仅测试阶段需要 |
| provided | ✅ 可用 | ❌ 不可用 | ❌ 不参与 | servlet-api | 编译需要,但运行环境会提供 |
| runtime | ❌ 不可用 | ❌ 不可用 | ✅ 参与 | JDBC 驱动 | 运行时需要,编译不需要 |
使用示例:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
生命周期
Maven 构建生命周期包含三个基本的生命周期:
- clean:清理项目
- default(build):核心构建流程
- site:生成项目文档

在Maven中,当你执行生命周期中的任意一个阶段时,都会顺序执行该阶段前面的所有阶段。
但是三大生命周期之间的关系是独立的,例如执行 site不会执行 build和 clean。
常用阶段:
| 生命周期阶段 | 作用 |
|---|---|
| clean | 移除上一次构建生成的文件 |
| compile | 编译项目源代码。 |
| test | 运行单元测试。 |
| package | 将项目打包成可分发的文件,如 .jar或 .war。 |
| install | 将打包文件安装到本地仓库。 |
运行生命周期
方式一:在IDEA中直接双击对应生命周期

方式二:终端中直接输入 mvn + clean周期 + build周期 + site周期

生命周期的运行原理
生命周期本都是一个个抽象的概念,本身并不执行任何操作。其所有的操作都是由绑定的插件来完成的。

Web入门
spring 官网:Spring | Home
Spring 是一个 轻量级、开源的 Java 企业级应用开发框架 ,目标是通过 IoC(控制反转) 和 AOP(面向切面编程) 简化企业应用开发,提升代码的可维护性与扩展性。
常见子项目:
| 子项目 | 作用 |
|---|---|
| Spring Boot | 快速构建独立可运行应用 |
| Spring Data | 简化数据库访问 |
| Spring Security | 安全与权限控制 |
| Spring Cloud | 微服务架构支持 |
| Spring Batch | 批处理任务 |
Spring发展到今天已经形成一种开发生态圈,Spring提供了若干子项目,每个项目用于完成特定的功能。
SpringBoot入门
Spring Boot 是 基于 Spring 框架的快速开发框架 ,旨在 简化 Spring 应用的创建、配置与部署 ,让开发者专注于业务逻辑,而不是繁琐的环境搭建与配置。
创建SpringBoot项目

我们不直接创建Maven项目,而是直接创建SpringBoot项目。然后点击下一步:

这里我们选择一些我们需要安装的包,这里我只选择了Spring Web包。
创建完毕:

简单体验SpringBoot
文件 SpringbootQuickStartApplication.java是SpringBoot的启动类。我们通过该类启动SpringBoot项目。
package top.ulna520.springbootquickstart;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringbootQuickStartApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootQuickStartApplication.class, args);
}
}
我们相对于启动类创建java类:controller/HelloSpring.java
package top.ulna520.springbootquickstart.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController //将返回值直接写入HTTP响应体
public class HelloSpring {
@RequestMapping("/hello") //定义请求路径的映射
public String sayHello() {
return "Hello Spring Boot!";
}
}
直接点击上方启动按钮启动服务:

web服务器默认监听端口:8080

Http协议
Http概述
HTTP (Hyper Text Transfer Protocol,超文本传输协议)
- 定义:规定了 浏览器 与 服务器 之间数据传输的规则
- 作用:用于传输 HTML、JSON、图片、视频等各种资源
核心特点:
| 特点 | 说明 | 影响 |
|---|---|---|
| 基于 TCP 协议 | 面向连接,数据传输可靠 | 需要三次握手,安全性高 |
| 请求-响应模型 | 一次请求对应一次响应 | 客户端主动发起,服务端被动响应 |
| 无状态协议 | 不记录事务处理的上下文 | - 缺点:多次请求间无法共享数据“- 优点:处理速度快、资源占用少 |

Http-请求协议
HTTP 请求报文由 请求行 + 请求头 + 请求体 组成。

请求行(Request Line)
- 格式:
请求方法 请求路径 协议版本 - 示例:
GET /brand/findAll?name=OPPO&status=1 HTTP/1.1POST /brand HTTP/1.1
- 作用:告诉服务器要做什么(方法)、访问哪个资源(路径)、使用哪个协议版本
常见请求方法:
- GET :获取资源
- POST :提交数据
- PUT :更新资源(整体替换)
- PATCH :部分更新资源
- DELETE :删除资源
请求头(Request Headers)
- 从第二行开始,格式为
Key: Value - 用于传递客户端环境信息、请求参数、数据格式等
常见请求头:
| 请求头 | 说明 |
|---|---|
| Host | 请求的主机名 |
| User-Agent | 浏览器版本,例如 Chrome 浏览器的标识类似 Mozilla/5.0 ... Chrome/79,IE 浏览器的标识类似 Mozilla/5.0 (Windows NT ...) like Gecko |
| Accept | 表示浏览器能接受的资源类型,如 text/*、image/* 或 */* 表示所有 |
| Accept-Language | 表示浏览器偏好的语言,服务器可以据此返回不同语言的网页 |
| Accept-Encoding | 表示浏览器可以支持的压缩类型,例如 gzip、deflate 等 |
| Content-Type | 请求主体的数据类型 |
| Content-Length | 请求主体的大小(单位:字节) |
请求体
- 仅在部分方法(如 POST、PUT、PATCH)中存在
- 用于传递数据(表单、JSON、XML 等)
示例:
{
"status": 1,
"brandName": "黑马",
"companyName": "黑马程序员",
"id": "",
"description": "黑马程序员"
}
GET与POST对比
| 对比项 | GET | POST |
|---|---|---|
| 数据位置 | URL 查询参数 | 请求体 |
| 数据长度 | 有限制(取决于浏览器/服务器) | 理论无限制 |
| 安全性 | 参数暴露在 URL 中 | 参数在请求体中,相对更隐蔽 |
| 常用场景 | 查询数据 | 提交数据、上传文件 |
HTTP-响应协议
HTTP 响应报文由 响应行 + 响应头 + 响应体 三部分构成。

响应行
- 位置 :响应数据的第一行
- 格式 :
协议版本 状态码 状态描述 - 示例:
HTTP/1.1 200 OK
- 作用 :告知客户端响应的协议版本、处理结果状态及简要说明
状态码大全:HTTP 响应状态码
状态码分类:
| 状态码范围 | 分类 | 说明 |
|---|---|---|
| 1xx | 临时状态码 | 请求已接收,提示客户端继续请求或忽略 |
| 2xx | 成功 | 请求已成功接收并处理完成 |
| 3xx | 重定向 | 需要客户端发起新的请求以完成处理 |
| 4xx | 客户端错误 | 请求有误,责任在客户端(如资源不存在、未授权、禁止访问等) |
| 5xx | 服务器错误 | 处理出错,责任在服务端(如程序异常) |
响应头
- 从第二行开始,格式为
Key: Value - 用于描述响应的元信息(数据类型、长度、连接方式等)
常见响应头:
| 响应头 | 说明 |
|---|---|
| Content-Type | 响应内容的类型,例如 text/html、application/json |
| Content-Length | 响应内容的长度(字节数) |
| Content-Encoding | 响应内容的压缩算法,例如 gzip |
| Cache-Control | 缓存策略,例如 max-age=300 表示最多缓存 300 秒 |
| Set-Cookie | 设置 Cookie 到浏览器,用于会话或状态管理 |
响应体
- 位于响应头之后的空行后
- 存放实际返回的数据内容(HTML、JSON、图片等)
示例(JSON 数据):
[
{
"id": 1,
"brandName": "阿里巴巴",
"companyName": "腾讯计算机系统有限公司",
"description": "玩玩玩"
}
]
HTTP-协议解析
Http协议解析用于解析客户端发送的HTTP请求,并发送标准的Http响应。通常我们并不自己手动完成这一部分。我们可以直接借助于第三方Web服务器解析http请求,如Tomcat、Jetty、WebLogic、WebSphere等
Web服务器
一种软件程序,对 HTTP 协议 的操作进行封装,使开发者无需直接处理协议细节,从而简化 Web 开发。
核心作用:
- 协议封装 :屏蔽底层 HTTP 请求/响应的复杂性。
- 资源提供 :向客户端(浏览器)提供 HTML、CSS、JS、图片等资源。
- 动态处理 :与后端应用(如 Servlet、PHP、Node.js)协作,生成动态内容。
Tomcat
Tomcat官网:Apache Tomcat® - Welcome!
Tomcat是Apache软件基金会一个核心项目,是一个开源免费的轻量级Web服务器,支持Servlet/JSP少量JavaEE规范。
Tomcat也被称为Web容器、Servlet容器。Servlet程序需要依赖于Tomcat才能运行。
Tomcat安装目录:

启动:执行 bin/start.bat脚本
关闭:
- 直接关闭窗口
- 执行
bin/shutdown.bat - Ctrl + C
端口配置:
conf/server:(默认8080)

HTTP协议默认端口号为80,如果将Tomcat端口号改为80,则将来访问Tomcat时,将不用输入端口号。
部署应用程序:将项目放在webapps目录下即可。
SpringBoot中的依赖
起步依赖
Spring Boot 提供了 Starter 机制,利用maven的依赖传递,将常用依赖打包成一个统一入口,简化配置。
| 依赖名 | 版本 | 作用 |
|---|---|---|
spring-boot-starter-web | 2.7.4 | Web 应用开发的核心依赖,包含 Spring MVC、JSON 处理、内嵌 Tomcat 等 |
spring-boot-starter-test | 2.7.4 | 单元测试依赖,包含 JUnit、Mockito、Spring Test 等 |
SpringBoot-Web程序的启动依赖于内置Tomcat服务器。
所有的起步依赖:Spring Boot Reference Documentation
在SpringBoot中,起步依赖的的引入无需指定版本version:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
这是由于所有的SpringBoo项目都继承于一个版本的SpringBoot父工程:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
在父工程中会自动引入与版本号对应的起步依赖。
请求响应
SpringMVC流程
SpringBoot本身只是一个Spring 应用的快速开发脚手架,真正负责处理Web请求的是SpringBoot起步依赖 start-web包中的SpringMVC框架。


流程:
| 阶段 | 主要参与者 | 关键动作 | 备注 |
|---|---|---|---|
| 1. 请求进入 | 浏览器 → Tomcat | 浏览器发起 HTTP 请求 | URL 可能包含路径参数、查询参数 |
| 2. 封装请求 | Tomcat | 创建 HttpServletRequest / HttpServletResponse 对象 | 由 Servlet 容器负责 |
| 3. 前端控制器 | DispatcherServlet | 统一入口,拦截请求 | 在 web.xml 或 Java Config 中注册 |
| 4. 查找处理器 | HandlerMapping | 根据 URL 找到对应的 Handler(通常是 Controller 方法) | 支持多种映射策略(注解、XML 等) |
| 5. 调用处理器 | HandlerAdapter | 适配并调用目标 Controller 方法 | 负责参数绑定、类型转换 |
| 6. 返回结果 | Controller | 返回 ModelAndView 或其他类型(如 @ResponseBody) | REST 接口可能直接返回 JSON |
| 7. 视图解析 | ViewResolver | 将视图名解析为具体视图(JSP、Thymeleaf 等) | REST 场景可跳过 |
| 8. 渲染视图 | 视图对象 | 将模型数据渲染为 HTML/JSON | 输出写入 HttpServletResponse |
| 9. 响应返回 | Tomcat | 将响应发送给浏览器 | HTTP 状态码、响应头、响应体 |
BS架构:浏览器 / 服务器架构
CS架构:客户端 / 服务器架构
Postman
postman官网:Postman
Postman是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件。
作用:常用于进行接口测试。

可以模拟浏览器发送各种请求,用来测试程序API
获取简单参数
原始方式
HttpServletRequest 对象代表了客户端发送给Servlet的HTTP请求。通过这个对象,你可以获取到请求的所有信息。
package top.ulna520.springbootquickstart.controller;
//import...
@RestController
public class UserController {
@RequestMapping("/user")
public String getNameAndAge(HttpServletRequest request) {
String name = request.getParameter("name");
String age = request.getParameter("age");
int ageInt = Integer.parseInt(age);
System.out.println("name:" + name + ",age:" + ageInt);
return "name:" + name + ",age:" + ageInt;
}
}
常用方法:
getParameter(String name):获取指定名称的请求参数的值(返回String)。如果参数不存在或有多个同名参数,行为可能不确定。getParameterValues(String name): 获取指定名称的所有请求参数的值(返回String[])。getParameterMap(): 获取所有请求参数的Map<String, String[]>。
使用GET请求:

SpringMVC方法
参数名与形参变量名相同,定义形参即可接收参数。
package top.ulna520.springbootquickstart.controller;
// import...
@RestController
public class UserController {
@RequestMapping("/user")
public String getNameAndAge(String name, Integer age) {
System.out.println("name:" + name + ",age:" + age);
return "name:" + name + ",age:" + age;
}
}
RequestMapping允许所有的请求方式
- 当没有客户端没有发送形参名一致的参数时,值为
null
使用post请求:

@RequestParam
如果方法形参名与请求参数名称不匹配,或者需要对于参数进行一些额外配置,可以使用RequestParam。
基本用法:
@GetMapping("/hello")
public String hello(@RequestParam("name") String username) {
return "Hello, " + username;
}
常用属性:
| 属性名 | 类型 | 说明 | 默认值 |
|---|---|---|---|
value / name | String | 请求参数名(两者等价,二选一即可) | 必填(除非参数名与方法形参名一致且开启参数名推断) |
required | boolean | 是否必须提供该参数 | true |
defaultValue | String | 当参数缺失或为空时使用的默认值,设置后 required 自动失效 | null |
实体参数
创建实体
实体参数就是将Http请求的参数封装到一个实体对象中。
首先我们创建User类:Model/User.java
package top.ulna520.springbootquickstart.Model;
public class User {
private String name;
private Integer age;
public User(Integer age, String name) {
this.age = age;
this.name = name;
}
}
要想能够成功封装,一下两个条件满足一个即可:
- 只有一个
public有参构造函数,若有多个构造方法,Spring不知道该用哪个。- 有无参构造方法(优先使用),以及有对饮成员的set方法。
推荐的方法:将 User 定义成标准 JavaBean
- 提供 public 无参构造器;
- 提供字段的 getter/setter;
- 这样 Spring 的 DataBinder 就能通过无参构造创建实例并按名称填充属性。
package top.ulna520.springbootquickstart.Model;
public class User {
private String name;
private Integer age;
public void setAge(Integer age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
}
实体变量
@RestController
public class UserController {
@RequestMapping("/user")
public String getNameAndAge(User user) {
System.out.println(user);
return user.toString();
}
}
Spring会自动将参数封装进入变量,没有参数对应的值为null;

实例嵌套
我们再创建一个Address类,并且Address类是User类的一个成员变量:
Model/Address.java
package top.ulna520.springbootquickstart.Model;
public class Address {
private String province;
private String city;
private String street;
public void setProvince(String province) {
this.province = province;
}
public void setCity(String city) {
this.city = city;
}
public void setStreet(String street) {
this.street = street;
}
}
Model/User.java:
package top.ulna520.springbootquickstart.Model;
public class User {
private String name;
private Integer age;
private Address address;
public void setAge(Integer age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public void setAddress(Address address) {
this.address = address;
}
public Address getAddress() { //嵌套类必须要有grtter
return address;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", address=" + address +
'}';
}
}
如果没有嵌套类的getter,导致 Spring 无法自动创建并绑定 address,最终为 null。

数组集合参数
数组参数:请求参数名与形参数组名称相同且请求参数为多个,定义数组类型形参即可接收参数
// 3. 数组集合参数
@RequestMapping("/arrayParam")
public String arrayParam(String[] hobby) {
System.out.println(Arrays.toString(hobby));
return "OK";
}
集合参数:请求参数名与形参集合名称相同且请求参数为多个,@RequestParam绑定参数关系
@RequestMapping("/listParam")
public String listParam(@RequestParam List<String> hobby) {
System.out.println(hobby);
return "OK";
}
这里
@RequestParam用于绑定集合参数。
日期时间类型的参数
请求示例:
http://localhost:8080/dateParam?updateTime=2022-12-12 10:05:45
控制器示例:
@RequestMapping("/dateParam")
public String dateParam(
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime updateTime
){
System.out.println(updateTime);
return "OK";
}
@DateTimeFormat 注解:
- 将请求参数的字符串按指定格式解析为
LocalDateTime、LocalDate、LocalTime等日期类型。 - 常用属性:
pattern:日期时间格式化模式(必须与请求参数格式一致)。- 常见模式:
yyyy-MM-dd、yyyy-MM-dd HH:mm:ss
请求参数的日期格式必须与pattern完全一致,否则抛出400错误。
Json参数
postman发送json请求

Sping接收Json数据
首先定义好与Json数据对应数据模型如:User 类,Address类。
@RestController
public class UserController {
@RequestMapping("/user")
public String getNameAndAge(@RequestBody User user) {
System.out.println(user);
return user.toString();
}
}
@RequestBody注解用于将请求体中的json数据绑定到Java对象。
路径参数
声明动态参数:
@RequestMapping("/path/{id}") //声明动态参数
public String pathParam(@PathVariable Integer id) {
System.out.println(id);
return "OK";
}
@PathVariable注解:用于获取路径参数
示例:
@GetMapping("/{year}/{month}/{day}/{filename}/")
public Message returnBlogByPath(
@PathVariable int year,
@PathVariable int month,
@PathVariable int day,
@PathVariable String filename)
响应
@ResponseBody
-
类型 :方法注解 / 类注解
-
位置 :
- 方法上 :仅作用于该方法
- 类上 :作用于类中所有方法
-
功能 :
- 将方法返回值直接写入 HTTP 响应体(Response Body)
- 如果返回值是 实体对象 / 集合 ,会自动序列化为 JSON 格式响应
示例:
@RequestMapping("/hello")
@ResponseBody
public String hello() {
System.out.println("Hello World~");
return "Hello World~";
}
如果一整个类的方法都直接返回数据,可以直接使用 @RestController注解。
等价于:
@Controller
@ResponseBody
@Controller:
- 用于标注一个类是控制器组件(Controller),由SpringMVC扫描并注册到容器中,用来接收和处理前端请求。
统一响应封装
背景问题:
- 不同接口返回类型不一致(
String、对象、集合),前端解析复杂 - 缺乏统一的响应格式,不便于状态码、提示信息、数据的统一管理
设定一个返回类,所有的返回信息由Result类进行包装:
public class Result {
// 响应码:1 成功;0 失败
private Integer code;
// 提示信息
private String msg;
// 返回数据
private Object data;
// getter/setter/构造方法...
}
静态资源
static目录作用:
- 存放静态资源 (无需 Controller 处理,直接由 Spring MVC 静态资源处理器返回)
- 常见文件类型:
- HTML、CSS、JavaScript
- 图片(JPG、PNG、GIF…)
- 字体文件(TTF、WOFF…)
- 其他前端静态资源
默认静态资源目录(优先级)
Spring Boot 内置了静态资源映射,默认会从以下位置查找(优先级从高到低):
classpath:/META-INF/resources/classpath:/resources/classpath:/static/← 最常用classpath:/public/${user.dir}/public/(运行目录下的public)
优先级规则 :同名文件会返回优先级高的目录中的版本。
访问规则
URL访问路径 = 应用根路径 + 文件名
例如:
src/main/resources/static/logo.png
访问:
http://localhost:8080/logo.png
与Controller的优先级
如果URL同时匹配Controller路径和静态资源路径:
- Controller优先
例如:、
/foo有一个 Controller 方法/static/foo下也有一个文件- 访问
/foo→ 返回 Controller 的结果
默认首页
如果静态资源目录下有index.html,访问 /会直接返回它。
获取resources文件夹下的资源
ClassLoader方式(简单)
假设我们要读取 src/main/resources/readme.txt
This is a great way to get
在 Controller中:
@RestController
public class ContentController {
@RequestMapping("/content")
public String getContent(@RequestBody User user) {
String file = getClass().getClassLoader().getResource("readme.txt").getPath();
String content = "";
try {
InputStreamReader isr = new InputStreamReader(new FileInputStream(file), "UTF-8");
BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null) {
content += line;
}
} catch (Exception e) {
e.printStackTrace();
}
return content;
}
}
成功读取:

Spring的 ClassPathResource
@RestController
public class ContentController {
@RequestMapping("/content")
public String getContent(@RequestBody User user) {
ClassPathResource resource = new ClassPathResource("readme.txt");
String content = "";
try {
InputStreamReader isr = new InputStreamReader(resource.getInputStream(), "UTF-8");
BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null) {
content += line;
}
} catch (Exception e) {
e.printStackTrace();
}
return content;
}
}
分层解耦
三层架构

controller:控制层,接收前端发送的请求,对请求进行处理,并返回响应数据service:业务逻辑层,处理具体的业务逻辑dao:数据访问层 / 持久层, 负责数据访问操作,包括数据的增、删、改、查(CRUD)
IOC & DI
对象的创建与依赖管理交给外部容器,而不是由代码自己 new 出来。
| 概念 | 全称 | 定义 | 作用 |
|---|---|---|---|
| IOC | Inversion of Control(控制反转) | 对象的创建控制权由程序自身转移到外部容器 | 降低代码耦合度,让对象的依赖关系由容器管理 |
| DI | Dependency Injection(依赖注入) | 容器在运行时将应用所需的依赖资源注入到对象中 | 让对象无需自己创建依赖,专注于业务逻辑 |
| Bean | - | IOC 容器中创建和管理的对象 | 统一生命周期管理,可被注入到其他对象中 |
没有IOC/DI时:
- 每个 Controller 可能会自己
new一个 Service 实例
- 结果:
- 对象创建分散、重复
- 耦合度高(Controller 依赖具体实现类)
- Service 的状态和配置无法统一管理
有IOC/DI时:
- Service对象 由 IOC 容器 创建并管理(通常是单例 Bean)。
- 多个 Controller 只需声明依赖(
@Autowired),容器会自动将依赖注入。 - 容器会在运行时将同一个 Service 实例注入到不同的 Controller 中。
IOC/DI入门
@Component
作用
- 声明一个类是 Spring 管理的 Bean
- 相当于告诉 IOC 容器:“这个类需要被扫描、实例化,并纳入容器管理”
- 默认 Bean 名是类名首字母小写(可通过
@Component("beanName")自定义)
衍生注解:
| 注解 | 说明 | 位置 |
|---|---|---|
| @Component | 声明 bean 的基础注解 | 不属于以下三类时,用此注解 |
| @Controller | @Component 的衍生注解 | 标注在控制器类上 |
| @Service | @Component 的衍生注解 | 标注在业务类上 |
| @Repository | @Component 的衍生注解 | 标注在数据访问类上(由于与 MyBatis 整合,用的少) |
针对经典的三层架构,Spring已经预设了经典的类型注解,平时我们优先使用 @Controller 、@Service、@Repository
不属于这几类我们再使用:@Component
@Autowired注解
作用
- 自动注入依赖对象 (DI 的实现方式之一)
- 告诉 Spring:在容器中找到匹配的 Bean,并注入到当前字段、构造器或 Setter 方法中
注入规则
-
默认按类型(byType)匹配
- 容器中必须有且只有一个该类型的 Bean
-
若有多个同类型 Bean
- 再按名称(byName)匹配(字段名或参数名)
-
可配合
@Qualifier("beanName")- 精确指定要注入的 Bean
- 默认按类型注解,有多个同类型注解
@Qualifier才生效
@Autowired @Qualifier("dogA") // 精确指定注入 dogA
其他相关注解:
-
@Primary:指定优先对象。被@Primary注解修饰的对象将优先注解。@Primary @Component -
@Resource:通过名称Bean进行依赖注入(来源JDK 包)@Resource(name = "dogA") //无需Autowired注解