Web 框架、SpringMVC、Spring、MyBatis 与 Spring Boot
第一章.Web 核心概念
1.1 Web 项目是什么
1.Web 项目: 通过浏览器、App、小程序等客户端访问服务器资源的项目。 2.服务器端: 负责接收请求、处理业务、访问数据库、返回响应。 3.客户端: 负责展示页面、收集用户输入、发起请求。浏览器 / App / 小程序 | | HTTP 请求 v Web 服务器 / 后端程序 | | 查询数据库 / 调用服务 v 数据库 / 其他系统1.2 C/S 和 B/S
| 架构 | 全称 | 说明 | 示例 |
|---|---|---|---|
| C/S | Client/Server | 客户端需要安装专门软件 | QQ、微信桌面端 |
| B/S | Browser/Server | 使用浏览器访问系统 | 电商后台、管理系统 |
1.C/S: 客户端功能强,但安装和升级成本高。 2.B/S: 用户只需要浏览器,部署和升级集中在服务器端。 3.Java Web 学习主要围绕 B/S 架构。1.3 静态资源和动态资源
| 类型 | 说明 | 示例 |
|---|---|---|
| 静态资源 | 内容固定,服务器直接返回 | HTML、CSS、JS、图片 |
| 动态资源 | 服务器运行程序后生成结果 | Controller 接口、查询数据库结果 |
1.静态资源: 不需要执行后端业务逻辑。 2.动态资源: 需要 Java 程序处理请求,再生成响应数据。1.4 HTTP 协议
1.HTTP: HyperText Transfer Protocol,超文本传输协议。 2.作用: 规定客户端和服务器之间请求、响应的数据格式。 3.特点: a.基于请求和响应 b.客户端主动发起请求 c.服务器处理后返回响应1.5 Web 服务器
1.Web 服务器: 接收 HTTP 请求,管理 Web 应用,返回 HTTP 响应。 2.常见服务器: Tomcat Jetty Undertow 3.Spring Boot: 内置 Tomcat,可以直接启动 Web 项目。第二章.Spring、Spring Framework 和 Spring Boot
2.1 Spring 是什么
1.Spring: Java 企业级开发生态。 2.Spring Framework: Spring 生态的基础框架,提供 IoC、AOP、事务、MVC 等能力。 3.Spring Boot: 基于 Spring Framework 的快速开发脚手架。 通过自动配置和场景启动器简化项目搭建。2.2 三者关系
Spring 生态 ├── Spring Framework │ ├── IoC / DI │ ├── AOP │ ├── 声明式事务 │ └── SpringMVC └── Spring Boot ├── 自动配置 ├── 场景启动器 ├── 内置服务器 └── 快速部署2.3 Spring Boot Web 快速体验
依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>启动类
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class WebApplication { public static void main(String[] args) { SpringApplication.run(WebApplication.class, args); } }Controller
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { @GetMapping("/hello") public String hello() { return "Hello Spring Boot"; } }访问:
http://localhost:8080/hello2.4 场景启动器
1.starter: Spring Boot 提供的场景依赖集合。 2.spring-boot-starter-web: 自动引入 SpringMVC、Jackson、Tomcat 等 Web 开发依赖。 3.好处: 不需要手动维护一堆依赖版本。第三章.HTTP 协议
3.1 HTTP 请求格式
请求行 请求头 空行 请求体示例:
POST /users HTTP/1.1 Host: localhost:8080 Content-Type: application/json {"username":"tom","age":18}1.请求行: 包含请求方式、请求路径、协议版本。 2.请求头: 描述客户端、内容类型、认证信息等。 3.请求体: POST、PUT 等请求常用来提交 JSON 或表单数据。3.2 HTTP 响应格式
响应行 响应头 空行 响应体示例:
HTTP/1.1 200 OK Content-Type: application/json {"code":200,"message":"成功","data":null}3.3 常见请求方式
| 请求方式 | 语义 | 常见用途 |
|---|---|---|
| GET | 查询资源 | 查询列表、详情 |
| POST | 新增资源 | 新增用户 |
| PUT | 整体更新资源 | 修改用户全部信息 |
| PATCH | 局部更新资源 | 修改用户部分字段 |
| DELETE | 删除资源 | 删除用户 |
3.4 常见状态码
| 状态码 | 含义 | 说明 |
|---|---|---|
| 200 | OK | 请求成功 |
| 201 | Created | 创建成功 |
| 400 | Bad Request | 请求参数错误 |
| 401 | Unauthorized | 未登录或认证失败 |
| 403 | Forbidden | 没有权限 |
| 404 | Not Found | 资源不存在 |
| 405 | Method Not Allowed | 请求方式不支持 |
| 500 | Internal Server Error | 服务器内部错误 |
第四章.SpringMVC 接收请求数据
4.1 SpringMVC 的作用
1.SpringMVC: Spring Framework 中的 Web 层框架。 2.主要职责: a.接收 HTTP 请求 b.解析请求参数 c.调用业务层 d.返回响应数据4.2 Controller 基础注解
| 注解 | 作用 |
|---|---|
@Controller | 标记控制层组件,通常返回页面 |
@RestController | @Controller + @ResponseBody,通常返回 JSON |
@RequestMapping | 映射请求路径 |
@GetMapping | 映射 GET 请求 |
@PostMapping | 映射 POST 请求 |
@PutMapping | 映射 PUT 请求 |
@DeleteMapping | 映射 DELETE 请求 |
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/users") public class UserController { @GetMapping public String list() { return "查询用户列表"; } }4.3 QueryString 参数接收
请求:
GET /users?username=tom&age=18代码:
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController public class UserController { @GetMapping("/users") public String list(@RequestParam String username, @RequestParam Integer age) { return username + ":" + age; } }1.@RequestParam: 接收查询字符串参数或表单参数。 2.如果参数名和形参名一致: 简单场景可以省略 @RequestParam。4.4 路径参数接收
请求:
GET /users/1001代码:
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @RestController public class UserController { @GetMapping("/users/{id}") public String detail(@PathVariable Long id) { return "查询用户:" + id; } }4.5 JSON 参数接收
请求体:
{ "username": "tom", "password": "123456", "age": 18 }实体类:
public class User { private Long id; private String username; private String password; private Integer age; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }Controller:
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @RestController public class UserController { @PostMapping("/users") public String save(@RequestBody User user) { return "保存用户:" + user.getUsername(); } }@RequestBody: 把请求体中的 JSON 数据转换成 Java 对象。4.6 请求头接收
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RestController; @RestController public class HeaderController { @GetMapping("/token") public String token(@RequestHeader("Authorization") String token) { return token; } }4.7 原生请求对象
import jakarta.servlet.http.HttpServletRequest; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class NativeController { @GetMapping("/native") public String nativeRequest(HttpServletRequest request) { return request.getMethod() + ":" + request.getRequestURI(); } }第五章.SpringMVC 响应数据
5.1 前后端分离和混合开发
| 模式 | 后端返回 | 前端职责 |
|---|---|---|
| 前后端分离 | JSON 数据 | 独立前端项目渲染页面 |
| 混合开发 | 页面或模板 | 后端负责页面渲染 |
当前主流: 前后端分离,后端主要返回 JSON。5.2 返回 JSON
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class UserController { @GetMapping("/user") public User user() { User user = new User(); user.setId(1L); user.setUsername("tom"); return user; } }1.@RestController: 方法返回值会直接写入响应体。 2.Jackson: Spring Boot Web 默认引入,负责 Java 对象和 JSON 转换。5.3 统一返回结果
public class Result<T> { private Integer code; private String message; private T data; public Result() { } public Result(Integer code, String message, T data) { this.code = code; this.message = message; this.data = data; } public static <T> Result<T> success(T data) { return new Result<>(200, "成功", data); } public static <T> Result<T> fail(String message) { return new Result<>(500, message, null); } public Integer getCode() { return code; } public String getMessage() { return message; } public T getData() { return data; } }使用:
@GetMapping("/users/{id}") public Result<User> detail(@PathVariable Long id) { User user = new User(); user.setId(id); user.setUsername("tom"); return Result.success(user); }5.4 转发和重定向
| 方式 | 说明 | 地址栏是否变化 | 是否共享 request |
|---|---|---|---|
| 转发 | 服务器内部跳转 | 不变 | 是 |
| 重定向 | 浏览器重新发请求 | 变化 | 否 |
@GetMapping("/forward") public String forward() { return "forward:/index.html"; } @GetMapping("/redirect") public String redirect() { return "redirect:/index.html"; }5.5 ResponseEntity
import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class ResponseController { @GetMapping("/response") public ResponseEntity<Result<String>> response() { return ResponseEntity .status(HttpStatus.CREATED) .body(Result.success("创建成功")); } }ResponseEntity: 可以同时控制响应状态码、响应头和响应体。第六章.RESTFul 风格
6.1 RESTFul 的介绍
1.RESTFul: 一种接口设计风格。 2.核心思想: 使用 URL 表示资源。 使用 HTTP 请求方式表示操作。 3.示例资源: /users /users/{id}6.2 RESTFul 接口设计
| 操作 | 请求方式 | 路径 | 说明 |
|---|---|---|---|
| 查询用户列表 | GET | /users | 查询多个 |
| 查询用户详情 | GET | /users/{id} | 查询一个 |
| 新增用户 | POST | /users | 新增 |
| 修改用户 | PUT | /users/{id} | 更新 |
| 删除用户 | DELETE | /users/{id} | 删除 |
6.3 RESTFul Controller 案例
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/users") public class UserRestController { @GetMapping public Result<String> list() { return Result.success("查询用户列表"); } @GetMapping("/{id}") public Result<String> detail(@PathVariable Long id) { return Result.success("查询用户:" + id); } @PostMapping public Result<String> save(@RequestBody User user) { return Result.success("新增用户:" + user.getUsername()); } @PutMapping("/{id}") public Result<String> update(@PathVariable Long id, @RequestBody User user) { return Result.success("修改用户:" + id); } @DeleteMapping("/{id}") public Result<String> delete(@PathVariable Long id) { return Result.success("删除用户:" + id); } }第七章.SpringMVC 高级扩展
7.1 全局异常处理
1.问题: Controller 中到处写 try...catch 会导致代码重复。 2.解决: 使用 @RestControllerAdvice + @ExceptionHandler 统一处理异常。import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; @RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(Exception.class) public Result<Void> handleException(Exception e) { return Result.fail("服务器异常:" + e.getMessage()); } @ExceptionHandler(MethodArgumentNotValidException.class) public Result<Void> handleValidException(MethodArgumentNotValidException e) { String message = e.getBindingResult().getFieldError().getDefaultMessage(); return Result.fail(message); } }7.2 参数校验
依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>实体类:
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; public class UserSaveParam { @NotBlank(message = "用户名不能为空") private String username; @NotBlank(message = "密码不能为空") private String password; @NotNull(message = "年龄不能为空") private Integer age; public String getUsername() { return username; } public String getPassword() { return password; } public Integer getAge() { return age; } }Controller:
import jakarta.validation.Valid; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @RestController public class UserValidController { @PostMapping("/valid/users") public Result<String> save(@Valid @RequestBody UserSaveParam param) { return Result.success("保存成功"); } }7.3 拦截器
1.拦截器: SpringMVC 提供的请求拦截机制。 2.常见用途: a.登录校验 b.权限检查 c.接口耗时统计 3.执行位置: 进入 Controller 前后。拦截器:
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor; public class LoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token = request.getHeader("Authorization"); if (token == null || token.isBlank()) { response.setStatus(401); return false; } return true; } }配置:
import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor()) .addPathPatterns("/users/**") .excludePathPatterns("/login"); } }7.4 过滤器和拦截器对比
| 对比 | Filter | Interceptor |
|---|---|---|
| 所属体系 | Servlet 规范 | SpringMVC |
| 拦截范围 | 更底层,可拦截更多资源 | 主要拦截 Controller 请求 |
| 获取 Spring Bean | 不如拦截器方便 | 更方便 |
| 常见用途 | 编码、跨域、通用过滤 | 登录、权限、业务拦截 |
第八章.MVC 模式和三层架构
8.1 MVC 设计模式
1.Model: 模型,负责业务数据和业务处理。 2.View: 视图,负责页面展示。 3.Controller: 控制器,负责接收请求、调用模型、选择响应。8.2 三层架构
| 层 | 常见命名 | 职责 |
|---|---|---|
| 表现层 | Controller | 接收请求、返回响应 |
| 业务层 | Service | 处理业务逻辑 |
| 数据访问层 | DAO / Mapper | 操作数据库 |
Controller ↓ Service ↓ DAO / Mapper ↓ Database8.3 MVC 和三层架构区别
1.MVC: 更偏向 Web 表现层设计模式。 2.三层架构: 更偏向整体后端代码分层。 3.实际开发: Controller 属于 MVC 中的 C, 同时也是三层架构中的表现层。8.4 用户模块三层拆分示例
Mapper:
public interface UserMapper { List<User> selectList(); User selectById(Long id); int insert(User user); int update(User user); int deleteById(Long id); }Service:
public interface UserService { List<User> list(); User detail(Long id); void save(User user); void update(Long id, User user); void delete(Long id); }Controller:
@RestController @RequestMapping("/users") public class UserController { private final UserService userService; public UserController(UserService userService) { this.userService = userService; } @GetMapping public Result<List<User>> list() { return Result.success(userService.list()); } }第九章.Spring IoC 和 DI
9.1 IoC 的介绍
1.IoC: Inversion of Control,控制反转。 2.传统方式: 自己 new 对象,自己维护依赖关系。 3.Spring 方式: 对象交给 Spring 容器创建和管理。 4.核心好处: 降低对象之间的耦合。9.2 DI 的介绍
1.DI: Dependency Injection,依赖注入。 2.作用: Spring 把一个对象需要的依赖自动注入进来。9.3 组件管理注解
| 注解 | 常见位置 | 说明 |
|---|---|---|
@Component | 通用组件 | 不好归类时使用 |
@Controller | 表现层 | Controller |
@Service | 业务层 | Service |
@Repository | 数据访问层 | DAO / Mapper |
@Service public class UserServiceImpl implements UserService { }9.4 包扫描
1.Spring Boot 默认扫描启动类所在包及其子包。 2.组件类要放在启动类同包或子包下。 3.否则需要使用 @ComponentScan 指定扫描范围。@SpringBootApplication public class WebApplication { public static void main(String[] args) { SpringApplication.run(WebApplication.class, args); } }9.5 属性注入
构造方法注入
@Service public class UserServiceImpl implements UserService { private final UserMapper userMapper; public UserServiceImpl(UserMapper userMapper) { this.userMapper = userMapper; } }@Autowired 注入
@Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; }@Resource 注入
@Service public class UserServiceImpl implements UserService { @Resource private UserMapper userMapper; }推荐: 业务代码优先使用构造方法注入, 依赖更清晰,也更方便测试。9.6 读取配置参数
application.properties:
app.name=student-web app.version=1.0.0代码:
import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @Component public class AppInfo { @Value("${app.name}") private String name; @Value("${app.version}") private String version; }第十章.Spring Boot 测试
10.1 测试依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>10.2 测试 Spring 组件
import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest public class UserServiceTest { @Autowired private UserService userService; @Test public void testList() { System.out.println(userService.list()); } }10.3 测试 Web 接口
import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.web.servlet.MockMvc; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @SpringBootTest @AutoConfigureMockMvc public class UserControllerTest { @Autowired private MockMvc mockMvc; @Test public void testList() throws Exception { mockMvc.perform(get("/users")) .andExpect(status().isOk()); } }