Web开发-后端基础篇
与其花时间编写解释你写出的糟糕的代码的注释,不如花时间清理那堆糟糕的代码。
Maven
概述
Maven 是一个 基于 POM(Project Object Model) 的构建工具,它通过一个 pom.xml
文件来管理项目的配置,包括依赖、插件、构建流程等。
Maven的作用包括以下几点:
- 依赖管理 :自动下载并管理项目所需的第三方库(如JUnit,Spring,MySQL驱动),避免手动引入jar包。
- Jar包:用于打包Java类、资源文件和元数据的压缩文件格式。
- 标准化项目结构 :Maven 提倡统一的项目目录结构,关于具体的结构我们下面再讲。
- 构建自动化 :一条命令即可完成编译、测试、打包、安装、部署等流程。
- 插件机制 :支持丰富的插件。
Maven项目结构
1 |
|
Maven Wrapper
Maven Wrapper 是一种让项目自带Maven的“启动器”,它的关键作用是:
- 保证团队成员使用相同版本的Maven,避免版本不一致的尴尬问题
- 不需要预先在系统中全局安装Maven,项目开箱即用
- 常用于CL/CD环境,如GitHub Action,Jenkins,GitLab CL等。
- CL(持续集成):频繁地(每天多次)将代码集成到主分支,并自动构建、测试 ,从而快速发现问题。
- CD(持续交付):CI 之后,自动将构建好的产物发布到“可上线”的环境(如测试、预发布环境)
Maven Wrapper 包含的文件
1 |
|
当你通过mvnw允许命令时:
1 |
|
- 检查
.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 子节点:
1 |
|
配置IDEA
全局Maven配置
全局配置环境需要我们在不打开任何项目时进行配置。
若打开任意项目,进行配置,则为当前项目进行配置,过程一致。
首先点击左下角的齿轮,然后打开设置。
找到Maven设置:
- Maven主路径:选择Maven文件夹的根目录
- 用户设置文件:如果添加了私服等,请重重新选择你的配置文件。
- 或者将你的配置文件放在默认路径下
然后选择运行java程序版本:
最后在Java编译器中也选择相同的Java版本:
创建Maven项目
IDEA中创建Maven项目我们首先新建项目:
填写项目名,以及组织名:
Groupid
和ArtifactId
组成了项目的唯一标识符。- 不同的
Groupid
用来区分不同来源的库。 - 依赖声明:
Groupid
和ArtifactId
是引入依赖的重要依据。
项目创建完成:
依赖管理
添加依赖
我们打开 pom.xml
- 添加标签
<dependencies></dependencies>
:
1 |
|
在
<dependencies>
中使用<dependency>
引入坐标点击刷新按钮,修改生效
Maven仓库:Maven Repository: Search/Browse/Explore
可以在Maven仓库中搜索想要的插件。
依赖传递
直接依赖:在当前项目中通过依赖配置建立的依赖关系。
间接依赖:被依赖的资源如果依赖其他资源,当前项目间接依赖其他资源。
排除依赖
若项目A 依赖项目B,却并不想要导入项目B中的某个依赖,可以使用依赖排除。
- 排除依赖:排除依赖指主动断开依赖的资源,被排除的资源无需指定版本。
1 |
|
导入B包,却排除B包依赖的junit
依赖范围
Maven 依赖的 作用范围 (scope)决定了依赖在 编译、测试、运行、打包 等阶段的可用性。
默认情况下,依赖是 compile
范围,可在任何地方使用。
通过 <scope>...</scope>
标签设置依赖范围。
scope 值 | 主程序 (main) | 测试程序 (test) | 打包/运行 (package) | 示例依赖 | 典型用途 |
---|---|---|---|---|---|
compile (默认) | ✅ 可用 | ✅ 可用 | ✅ 参与 | log4j | 常规依赖,编译、测试、运行都需要 |
test | ❌ 不可用 | ✅ 可用 | ❌ 不参与 | junit | 仅测试阶段需要 |
provided | ✅ 可用 | ❌ 不可用 | ❌ 不参与 | servlet-api | 编译需要,但运行环境会提供 |
runtime | ❌ 不可用 | ❌ 不可用 | ✅ 参与 | JDBC 驱动 | 运行时需要,编译不需要 |
使用示例:
1 |
|
生命周期
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项目。
1 |
|
我们相对于启动类创建java类:controller/HelloSpring.java
1 |
|
直接点击上方启动按钮启动服务:
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.1
POST /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 等)
示例:
1 |
|
GET与POST对比
对比项 | GET | POST |
---|---|---|
数据位置 | URL 查询参数 | 请求体 |
数据长度 | 有限制(取决于浏览器/服务器) | 理论无限制 |
安全性 | 参数暴露在 URL 中 | 参数在请求体中,相对更隐蔽 |
常用场景 | 查询数据 | 提交数据、上传文件 |
HTTP-响应协议
HTTP 响应报文由 响应行 + 响应头 + 响应体 三部分构成。
响应行
- 位置 :响应数据的第一行
- 格式 :
协议版本 状态码 状态描述
- 示例:
1 |
|
- 作用 :告知客户端响应的协议版本、处理结果状态及简要说明
状态码大全: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 数据):
1 |
|
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:
1 |
|
这是由于所有的SpringBoo项目都继承于一个版本的SpringBoot父工程:
1 |
|
在父工程中会自动引入与版本号对应的起步依赖。
请求响应
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请求。通过这个对象,你可以获取到请求的所有信息。
1 |
|
常用方法:
getParameter(String name)
:获取指定名称的请求参数的值(返回String
)。如果参数不存在或有多个同名参数,行为可能不确定。getParameterValues(String name)
: 获取指定名称的所有请求参数的值(返回String[]
)。getParameterMap()
: 获取所有请求参数的Map<String, String[]>
。
使用GET请求:
SpringMVC方法
参数名与形参变量名相同,定义形参即可接收参数。
1 |
|
RequestMapping
允许所有的请求方式
- 当没有客户端没有发送形参名一致的参数时,值为
null
使用post请求:
@RequestParam
如果方法形参名与请求参数名称不匹配,或者需要对于参数进行一些额外配置,可以使用RequestParam。
基本用法:
1 |
|
常用属性:
属性名 | 类型 | 说明 | 默认值 |
---|---|---|---|
value / name |
String |
请求参数名(两者等价,二选一即可) | 必填(除非参数名与方法形参名一致且开启参数名推断) |
required |
boolean |
是否必须提供该参数 | true |
defaultValue |
String |
当参数缺失或为空时使用的默认值,设置后 required 自动失效 |
null |
实体参数
创建实体
实体参数就是将Http请求的参数封装到一个实体对象中。
首先我们创建User类:Model/User.java
1 |
|
要想能够成功封装,一下两个条件满足一个即可:
- 只有一个
public
有参构造函数,若有多个构造方法,Spring不知道该用哪个。- 有无参构造方法(优先使用),以及有对饮成员的set方法。
推荐的方法:将 User 定义成标准 JavaBean
- 提供 public 无参构造器;
- 提供字段的 getter/setter;
- 这样 Spring 的 DataBinder 就能通过无参构造创建实例并按名称填充属性。
1 |
|
实体变量
1 |
|
Spring会自动将参数封装进入变量,没有参数对应的值为null;
实例嵌套
我们再创建一个Address类,并且Address类是User类的一个成员变量:
Model/Address.java
1 |
|
Model/User.java
:
1 |
|
如果没有嵌套类的getter,导致 Spring 无法自动创建并绑定 address,最终为 null。
数组集合参数
数组参数:请求参数名与形参数组名称相同且请求参数为多个,定义数组类型形参即可接收参数
1 |
|
集合参数:请求参数名与形参集合名称相同且请求参数为多个,@RequestParam
绑定参数关系
1 |
|
这里
@RequestParam
用于绑定集合参数。
日期时间类型的参数
请求示例:
1 |
|
控制器示例:
1 |
|
@DateTimeFormat 注解:
- 将请求参数的字符串按指定格式解析为
LocalDateTime
、LocalDate
、LocalTime
等日期类型。 - 常用属性:
pattern
:日期时间格式化模式(必须与请求参数格式一致)。- 常见模式:
yyyy-MM-dd
、yyyy-MM-dd HH:mm:ss
请求参数的日期格式必须与pattern完全一致,否则抛出400错误。
Json参数
postman发送json请求
Sping接收Json数据
首先定义好与Json数据对应数据模型如:User 类,Address类。
1 |
|
@RequestBody
注解用于将请求体中的json数据绑定到Java对象。
路径参数
声明动态参数:
1 |
|
@PathVariable
注解:用于获取路径参数
示例:
1 |
|
响应
@ResponseBody
类型 :方法注解 / 类注解
位置 :
- 方法上 :仅作用于该方法
- 类上 :作用于类中所有方法
功能 :
- 将方法返回值直接写入 HTTP 响应体(Response Body)
- 如果返回值是 实体对象 / 集合 ,会自动序列化为 JSON 格式响应
示例:
1 |
|
如果一整个类的方法都直接返回数据,可以直接使用 @RestController
注解。
等价于:
1 |
|
@Controller
:
- 用于标注一个类是控制器组件(Controller),由SpringMVC扫描并注册到容器中,用来接收和处理前端请求。
统一响应封装
背景问题:
- 不同接口返回类型不一致(
String
、对象、集合),前端解析复杂 - 缺乏统一的响应格式,不便于状态码、提示信息、数据的统一管理
设定一个返回类,所有的返回信息由Result类进行包装:
1 |
|
静态资源
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访问路径 = 应用根路径 + 文件名
例如:
1 |
|
访问:
1 |
|
与Controller的优先级
如果URL同时匹配Controller路径和静态资源路径:
- Controller优先
例如:、
/foo
有一个 Controller 方法/static/foo
下也有一个文件- 访问
/foo
→ 返回 Controller 的结果
默认首页
如果静态资源目录下有index.html,访问 /
会直接返回它。
获取resources文件夹下的资源
ClassLoader方式(简单)
假设我们要读取 src/main/resources/readme.txt
1 |
|
在 Controller
中:
1 |
|
成功读取:
Spring的 ClassPathResource
1 |
|
分层解耦
三层架构
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
才生效
1
2@Autowired
@Qualifier("dogA") // 精确指定注入 dogA
其他相关注解:
@Primary
:指定优先对象。被@Primary
注解修饰的对象将优先注解。1
2@Primary
@Component@Resource
:通过名称Bean进行依赖注入(来源JDK 包)1
2@Resource(name = "dogA")
//无需Autowired注解