day8
计划
- SpringBootWeb入门
- HTTP协议学习
- SpringBootWeb案例
- 分层解耦与IOC/DI
笔记
1.SpringBootWeb入门
Spring家族简介
- SpringFramework:Spring家族最基础、最核心的框架,提供依赖注入、事务管理、Web开发支持等功能
- SpringBoot:简化配置、快速开发,是企业开发的主流方式
- Spring全家桶:Spring家族旗下一系列技术,解决不同领域的问题
起步依赖
- spring-boot-starter-web:包含Web应用开发所需的常见依赖,内嵌Tomcat服务器
- spring-boot-starter-test:包含单元测试所需的常见依赖
- 起步依赖本质:预定义的依赖项集合,提供特定场景下开发所需的所有库和配置
入门程序
1 2 3 4 5 6 7 8 9
| @RestController public class HelloController {
@RequestMapping("/hello") public String hello(String name){ System.out.println("HelloController ... hello: " + name); return "Hello " + name; } }
|
- @RestController:组合注解,包含
@Controller和@ResponseBody
- @RequestMapping:映射请求路径
- 启动类:带有
@SpringBootApplication注解的类,运行main方法启动内嵌Tomcat
2.HTTP协议
HTTP概述
- HTTP:超文本传输协议,规定浏览器与服务器之间数据传输的规则
- 特点:
- 基于TCP协议:面向连接,安全
- 基于请求-响应模型:一次请求对应一次响应
- 无状态协议:对数据没有记忆能力,每次请求-响应独立
HTTP请求协议
- 请求行:请求方式、资源路径、协议/版本
- 请求头:key: value形式,包含浏览器信息等
- 请求体:存储请求参数(POST请求使用)
| 请求头 |
含义 |
| Host |
请求的主机名 |
| User-Agent |
浏览器版本 |
| Accept |
浏览器能接收的资源类型 |
| Content-Type |
请求主体的数据类型 |
GET vs POST请求
| 区别 |
GET请求 |
POST请求 |
| 请求参数位置 |
请求行中 |
请求体中 |
| 请求参数长度 |
有限制 |
无限制 |
| 安全性 |
低(暴露在地址栏) |
相对高 |
获取请求数据
1 2 3 4 5 6 7 8 9
| @RequestMapping("/request") public String request(HttpServletRequest request){ String name = request.getParameter("name"); String uri = request.getRequestURI(); String url = request.getRequestURL().toString(); String method = request.getMethod(); String header = request.getHeader("User-Agent"); return "request success"; }
|
HTTP响应协议
- 响应行:协议/版本、响应状态码、状态码描述
- 响应头:key: value形式
- 响应体:存储响应数据
响应状态码
| 分类 |
说明 |
| 1xx |
临时状态码,表示请求已接受 |
| 2xx |
成功,表示请求已被成功接收处理 |
| 3xx |
重定向,让客户端再发起请求 |
| 4xx |
客户端错误 |
| 5xx |
服务器端错误 |
常用状态码:
200 OK:请求成功
404 Not Found:请求资源不存在
500 Internal Server Error:服务器发生错误
设置响应数据
1 2 3 4 5 6 7 8 9 10 11 12 13
| @RequestMapping("/response") public void response(HttpServletResponse response) throws IOException { response.setStatus(404); response.setHeader("name", "zhang"); response.getWriter().write("<h1>hello springboot</h1>"); }
@RequestMapping("/response01") public ResponseEntity<String> response01() { return ResponseEntity.status(200).header("name", "li").body("hello springboot"); }
|
3.SpringBootWeb案例
需求说明
基于SpringBoot开发Web程序,完成用户列表的渲染展示:
- 前端页面发送ajax请求(/list)
- 服务端加载user.txt文件数据
- 返回JSON格式数据给前端
- 前端渲染展示在表格中
代码实现
1). 实体类User
1 2 3 4 5 6 7 8 9 10 11
| @Data @AllArgsConstructor @NoArgsConstructor public class User { private Integer id; private String username; private String password; private String name; private Integer age; private LocalDateTime updateTime; }
|
2). Controller层
1 2 3 4 5 6 7 8
| @RestController public class UserController { @RequestMapping("/list") public List<User> list() { return userList; } }
|
@ResponseBody注解:
- 将方法返回值直接响应给浏览器
- 如果返回值是实体对象/集合,会自动转换为JSON格式
@RestController包含@ResponseBody,无需单独使用
4.三层架构
架构介绍
- Controller(控制层):接收前端请求,处理请求,响应数据
- Service(业务逻辑层):处理具体业务逻辑
- Dao(数据访问层):负责数据访问操作(增删改查)
执行流程:前端请求 → Controller → Service → Dao → 文件/数据库
优势:
- 复用性强
- 便于维护
- 利于扩展
代码拆分
1). Controller层
1 2 3 4 5 6 7 8 9 10
| @RestController public class UserController { private UserService userService = new UserServiceImpl();
@RequestMapping("/list") public List<User> list() { List<User> userList = userService.findAll(); return userList; } }
|
2). Service层(接口+实现类)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public interface UserService { List<User> findAll(); }
public class UserServiceImpl implements UserService { private UserDao userDao = new UserDaoImpl();
@Override public List<User> findAll() { List<String> lines = userDao.findAll(); return userList; } }
|
3). Dao层(接口+实现类)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public interface UserDao { List<String> findAll(); }
public class UserDaoImpl implements UserDao { @Override public List<String> findAll() { InputStream in = this.getClass().getClassLoader().getResourceAsStream("user.txt"); List<String> lines = IoUtil.readLines(in, StandardCharsets.UTF_8, new ArrayList<>()); return lines; } }
|
5.IOC&DI(控制反转与依赖注入)
问题分析
直接new对象会导致层与层之间耦合,难以维护和扩展。
软件设计原则:高内聚低耦合
解耦思路
- 将对象交给容器管理(IOC容器)
- 程序运行时从容器中获取依赖对象(依赖注入)
核心概念:
- IOC(控制反转):对象的创建控制权由程序自身转移到外部容器
- DI(依赖注入):容器为应用程序提供运行时所依赖的资源
- Bean对象:IOC容器中创建、管理的对象
Bean的声明
使用@Component及其衍生注解将类交给IOC容器管理:
| 注解 |
说明 |
位置 |
| @Component |
声明bean的基础注解 |
不属于以下三类时使用 |
| @Controller |
@Component的衍生注解 |
控制层类 |
| @Service |
@Component的衍生注解 |
业务层类 |
| @Repository |
@Component的衍生注解 |
数据访问层类 |
组件扫描
@ComponentScan:扫描指定包及其子包下的bean
@SpringBootApplication包含@ComponentScan,默认扫描启动类所在包及其子包
依赖注入(@Autowired)
方式1:属性注入
1 2 3 4 5
| @RestController public class UserController { @Autowired private UserService userService; }
|
- 优点:代码简洁
- 缺点:隐藏依赖关系,可能破坏封装性
方式2:构造函数注入(推荐)
1 2 3 4 5 6 7 8 9
| @RestController public class UserController { private final UserService userService;
@Autowired public UserController(UserService userService) { this.userService = userService; } }
|
方式3:setter注入
1 2 3 4 5 6 7 8 9
| @RestController public class UserController { private UserService userService;
@Autowired public void setUserService(UserService userService) { this.userService = userService; } }
|
多个相同类型Bean的解决方案
方案1:@Primary
1 2 3 4
| @Primary @Service public class UserServiceImpl implements UserService { }
|
方案2:@Qualifier
1 2 3 4 5 6
| @RestController public class UserController { @Qualifier("userServiceImpl") @Autowired private UserService userService; }
|
方案3:@Resource
1 2 3 4 5
| @RestController public class UserController { @Resource(name = "userServiceImpl") private UserService userService; }
|
@Autowired与@Resource的区别
| 区别 |
@Autowired |
@Resource |
| 所属框架 |
Spring框架 |
JDK提供 |
| 默认注入方式 |
按类型注入 |
按名称注入 |
6.完整代码示例
最终项目结构
1 2 3 4 5 6 7 8 9 10 11 12
| springboot-web-04/ ├── src/main/java/com/zhang/ │ ├── controller/UserController.java #控制层 │ ├── service/UserService.java #业务层接口 │ ├── service/impl/UserServiceImpl.java #业务层实现 │ ├── dao/UserDao.java #数据访问层接口 │ ├── dao/impl/UserDaoImpl.java #数据访问层实现 │ ├── pojo/User.java #实体类 │ └── SpringbootWeb04Application.java #启动类 └── src/main/resources/ ├── user.txt #数据文件 └── application.properties #配置文件
|
UserController(最终版本)
1 2 3 4 5 6 7 8 9 10 11
| @RestController public class UserController { @Autowired @Qualifier("userServiceImpl") private UserService userService;
@RequestMapping("/list") public List<User> list() { return userService.findAll(); } }
|
UserServiceImpl(最终版本)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| @Service public class UserServiceImpl implements UserService { @Autowired private UserDao userDao;
@Override public List<User> findAll() { List<String> lines = userDao.findAll(); return lines.stream().map(line -> { String[] parts = line.split(","); return new User( Integer.parseInt(parts[0]), parts[1], parts[2], parts[3], Integer.parseInt(parts[4]), LocalDateTime.parse(parts[5], DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) ); }).toList(); } }
|
UserDaoImpl(最终版本)
1 2 3 4 5 6 7 8
| @Repository public class UserDaoImpl implements UserDao { @Override public List<String> findAll() { InputStream in = this.getClass().getClassLoader().getResourceAsStream("user.txt"); return IoUtil.readLines(in, StandardCharsets.UTF_8, new ArrayList<>()); } }
|
7.核心知识点总结
| 知识点 |
说明 |
| @RestController |
组合注解,包含@Controller和@ResponseBody |
| @RequestMapping |
映射请求路径 |
| @ResponseBody |
将返回值转为JSON响应给浏览器 |
| @Service |
声明业务层Bean |
| @Repository |
声明数据访问层Bean |
| @Autowired |
自动装配,按类型注入依赖 |
| @Qualifier |
按名称选择注入的Bean |
| @Primary |
指定默认主Bean |
| @Resource |
JDK提供,按名称注入 |
| IOC |
控制反转,对象由容器管理 |
| DI |
依赖注入,容器提供依赖对象 |
| 三层架构 |
Controller→Service→Dao |