Spring Cloud课程项目笔记
一、课程项目整体介绍
1.1 项目概述
- 项目名称: Spring Cloud课程查询项目
- 项目规模: 相对较小,但涵盖Spring Cloud所有重要组件
- 学习目标: 掌握Spring Cloud用法、特点及组件间关系
1.2 项目内容
- Spring Cloud简介: 基本概念与用途
- 课程查询项目实践: 实际项目开发,包括模块间调用、断路器、网关等核心内容
- 核心思想: 通过项目实践掌握Spring Cloud的核心思想
1.3 项目价值
- 技术细节: 关注Spring Cloud的技术细节
- 实践应用: 通过实践项目加深理解和应用
二、项目整体设计技术
2.1 设计模块
- 数据流向: 明确数据在系统中的流动路径
- 表设计: 数据库表结构设计
- 项目结构: 完成设计后明确项目的大体结构
三、具体模块开发
3.1 开发流程
- 模块化开发: 使用不同模块实现不同功能,模块间高度独立
- 开发起点: 从课程列表模块开始
3.2 课程列表模块
- 功能: 提供课程列表信息
- 技术: 涉及web项目开发知识
四、课程价格模块开发
4.1 模块重点
- 功能: 课程价格查询和管理
- 接口调用: 需要调用课程列表模块的接口
4.2 服务注册与发现
- 组件: 使用Eureka组件
- 作用: 服务之间能够轻易发现对方
- 调用方式: 配置服务调用,应对地址变化
4.3 负载均衡
- 算法: 不同时段、IP、随机分配等
- 工具: 使用Ribbon实现负载均衡算法
4.4 断路器
- 作用: 服务不可用时返回默认响应,保证用户体验
- 实现: 使用Hystrix实现断路功能
4.5 网关
- 作用: 统一通信,优化管理
- 组件: Spring Cloud Netflix Zuul
- 功能: 提供统一入口,增强安全性,支持过滤器
五、Spring Cloud组件介绍与项目结合
5.1 组件介绍
- 服务发现与注册: Eureka Server和Eureka Client
- 配置管理: 集中管理配置信息
- 服务调用: 支持多种通信协议和负载均衡
- 熔断与降级: 保障系统稳定性和可用性
5.2 项目结合
- 组件开发: 完成组件开发后项目随之完成
- 整体测试: 测试各模块内容、模块间调用、熔断等
六、项目重难点总结
6.1 项目能力
- 开发能力: 掌握Spring Cloud开发项目的能力
- 实践应用: 通过课程查询案例具备实际开发能力
七、Spring Cloud简介
7.1 定位
- 框架定位: 提供多样化工具快速构建分布式系统
7.2 成长路径
- 发展路径: Spring → Spring Boot → Spring Cloud
7.3 家族组件
- 组件丰富: 根据业务需求提供对应组件
八、核心组件
8.1 服务注册中心
- 组件: Spring Cloud Netflix Eureka
- 作用: 服务自动注册与发现
8.2 服务调用方式
- 推荐方式: 使用HTTP
- RESTAPI: 采用Restful风格API
- 工具: 使用Feign和Ribbon
8.3 服务网关
- 组件: Spring Cloud Netflix Zuul
- 作用: 提供统一入口,增强安全性
- 功能: 支持过滤器,处理每个请求
8.4 断路器
- 组件: Hystrix
- 作用: 保证服务在高流量下正常运转
九、知识小结
知识点 | 核心内容 | 考试重点/易混淆点 | 难度系数 |
---|---|---|---|
Spring Cloud简介 | Spring Cloud的基本概念、定位、成长路径和家族组件 | Spring Cloud的定位和成长路径 | 🌟 |
项目实践 | 通过课程查询项目学习Spring Cloud组件,包括模块间调用、断路器、网关等 | Spring Cloud核心思想和组件应用 | 🌟🌟 |
服务注册与发现 | 使用Eureka实现服务的自动注册与发现 | Eureka Server和Client的配合使用 | 🌟🌟 |
负载均衡 | 使用Ribbon实现不同的负载均衡算法 | 负载均衡算法的选择和应用 | 🌟🌟 |
断路器 | 使用Hystrix实现断路功能,保证服务稳定性 | 断路器的工作原理和实现 | 🌟🌟🌟 |
服务网关 | 使用Zuul实现统一入口和安全管理 | 网关的作用和过滤器的使用 | 🌟🌟 |
Spring Cloud项目整体设计与实现笔记
一、项目整体设计
1.1 项目介绍
- 项目目标: 实现一个最小力度的慕课网课程查询项目。
- 主要模块:
- 课程列表模块: 提供课程列表信息。
- 课程价格模块: 提供课程价格信息。
1.2 接口设计
- 课程列表模块接口:
- 功能: 从数据库读取课程列表,处理并返回。
- 课程价格模块接口:
- 单个课程价格接口: 接收课程ID,返回课程价格。
- 整合课程列表和价格的接口:
- 难点: 通过远程调用获取课程列表,涉及远程调用和数据处理。
- 过程: 获取课程列表后,遍历每个课程,调用单个课程价格接口补充价格信息,最终返回完整列表。
1.3 系统数据流向
- 课程列表数据: 存储在数据库中,由课程列表服务读取并展示。
- 课程价格数据: 由课程价格服务获取并读取。
- 服务交互: 课程列表服务与课程价格服务交互,整合数据后对外展示。
1.4 表设计
- course表(课程列表):
- 字段: ID(主键)、course_id(课程ID)、course_name(课程名)、valid(上架状态)。
- 特点: valid字段用于筛选上架课程。
- 课程价格表:
- 字段: ID、course_id(课程ID)、price(价格)。
- 关联: 通过course_id与course表关联。
二、新建项目
2.1 选择新建项目
- 工具: 使用IntelliJ IDEA。
- 项目类型: Spring Initializr,适用于Maven多模块项目。
2.2 填写项目基本信息
- Group: 项目组名(如
com.mukewang
)。 - Artifact: 项目artifact名(如
spring-cloud-course
)。 - 配置: JAVA 8和Maven构建方式。
2.3 选择项目依赖
- 依赖版本: 选择2.1.14或2.1版本。
- 策略: 统一选择一个版本,后续根据需要更改。
2.4 确定项目文件夹
- 位置选择: 用户自定义文件夹位置。
- 自动导入依赖: 启用自动导入,避免手动操作。
2.5 查看项目初始化进度
- 初始化状态: 通过进度条查看。
- 影响因素: 网速、机器性能、包下载时间。
- 完成表现: 左侧显示代码和测试文件夹,文件夹颜色区分(蓝色为代码,绿色为测试)。
2.6 删除第一层的src
- 操作: 删除第一层的src文件夹。
- 后续步骤: 在项目根目录右键选择新建子模块。
2.7 新建子模块
- 删除子模块的src:
- 步骤: 新建子模块后删除其src文件夹。
- 结果: 子模块继承父模块配置。
- 新建子模块课程列表:
- 选择: 确保父模块为正确层级。
- 结果: 创建
course-list
模块,用于存放业务代码。
- 新建子模块课程价格:
- 步骤: 同样选择正确父模块。
- 结果: 创建
course-price
模块。
2.8 查看POM文件
- 最外层POM: 包含所有子模块。
- 子模块POM: 自动更新,显示在父模块的POM文件中。
三、知识小结
知识点 | 核心内容 | 考试重点/易混淆点 | 难度系数 |
---|---|---|---|
项目设计 | 项目整体设计包括项目介绍、接口设计、数据流向和表设计 | 数据流向和表设计的具体实现 | 🌟 |
接口设计 | 课程列表和价格模块的接口设计,特别是整合接口的远程调用和数据处理 | 远程调用的实现和数据整合的难点 | 🌟🌟 |
表设计 | course表和课程价格表的结构及关联关系 | 表之间的关联和valid字段的使用 | 🌟🌟 |
新建项目 | 使用Spring Initializr创建多模块项目,配置基本信息和依赖 | 项目初始化进度和文件夹结构的确认 | 🌟 |
子模块创建 | 删除src文件夹,新建子模块并确认层级结构 | 子模块的继承关系和POM文件的自动更新 | 🌟🌟 |
# Spring Cloud课程列表与价格模块开发笔记
## 一、课程列表模块开发
### 1.1 新建包
- **位置**: `src/main/java`
- **包名**: `com.Imock.course`
### 1.2 写主启动类
- **类名**: `CourseListApplication`
- **注解**: `@SpringBootApplication`
- **主函数**:
```java
public static void main(String[] args) {
SpringApplication.run(CourseListApplication.class, args);
}
1.3 引入依赖
- Spring Boot依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
- My相关依赖:
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.1</version> </dependency>
- Spring Boot Maven插件:
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
1.4 配置文件
- 文件名:
application.properties
- 内容:
server.port=8081 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/course_practice spring.datasource.username=root spring.datasource.password=12345678 spring.application.name=course-list logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} - %msg%n
1.5 完善Controller层
- Controller类:
CourseListController
- 注解:
@RestController
- 方法:
@GetMapping("/courses") public List<Course> crossList() { return courseListService.getCourseList(); }
1.6 完善Service层
- 接口:
CourseListService
public interface CourseListService { List<Course> getCourseList(); }
- 实现类:
CourseListServiceImpl
@Service public class CourseListServiceImpl implements CourseListService { @Autowired private CourseMapper courseMapper; @Override public List<Course> getCourseList() { return courseMapper.findValidCourses(); } }
1.7 完善Mapper层
- Mapper接口:
CourseMapper
@Mapper @Repository public interface CourseMapper { @Select("SELECT * FROM course WHERE valid = 1") List<Course> findValidCourses(); }
1.8 实体类
- 实体类:
Course
public class Course implements Serializable { private Integer id; private Integer courseID; private String courseName; private Integer valid; // Getters and Setters }
二、常见错误排查
2.1 项目最外层pom.xml
- 作用: 管理项目依赖和版本。
- Spring Boot版本: 2.1.2.RELEASE
2.2 启动项目
- 启动过程: 编译构建。
- 测试方式: 浏览器或Postman访问接口。
2.3 访问接口返回404
- 原因: 未配置对应URL。
- 解决: 检查Controller中的URL配置。
2.4 实体类序列化问题
- 错误: 实体类不能被序列化。
- 解决: 实现
Serializable
接口。
2.5 字段匹配问题
- 错误: 类字段缺少get和set方法。
- 解决: 生成get和set方法。
三、课程价格模块开发
3.1 新建包
- 包名:
com.Imock.course
3.2 配置文件
- 修改端口号: 8082
- 应用名:
course-price
3.3 课程价格控制器
- Controller类:
CoursePriceController
@RestController public class CoursePriceController { @Autowired private CoursePriceService coursePriceService; @GetMapping("/price") public Integer getCoursePrice(@RequestParam Integer courseID) { CoursePrice coursePrice = coursePriceService.getCoursePrice(courseID); return coursePrice.getPrice(); } }
3.4 课程价格服务
- 接口:
CoursePriceService
public interface CoursePriceService { CoursePrice getCoursePrice(Integer courseID); }
- 实现类:
CoursePriceServiceImpl
@Service public class CoursePriceServiceImpl implements CoursePriceService { @Autowired private CoursePriceMapper coursePriceMapper; @Override public CoursePrice getCoursePrice(Integer courseID) { return coursePriceMapper.findCoursePrice(courseID); } }
3.5 课程价格Mapper
- Mapper接口:
CoursePriceMapper
@Mapper @Repository public interface CoursePriceMapper { @Select("SELECT * FROM course_price WHERE course_id = #{courseID}") CoursePrice findCoursePrice(@Param("courseID") Integer courseID); }
3.6 课程价格实体类
- 实体类:
CoursePrice
public class CoursePrice implements Serializable { private Integer id; private Integer courseID; private Integer price; // Getters and Setters }
3.7 启动类
- 类名:
CoursePriceApplication
@SpringBootApplication public class CoursePriceApplication { public static void main(String[] args) { SpringApplication.run(CoursePriceApplication.class, args); } }
Eureka服务注册与发现笔记
一、Eureka的作用
1.1 引入背景
- 问题根源: 服务调用中IP地址写死,导致调整困难。
- Eureka作用: 提供服务注册与发现,动态管理服务变化。
1.2 架构概述
- 模块组成: Eureka架构分为Eureka Server、服务提供者和服务调用方。
- 工作流程:
- 服务提供者: 注册服务信息到Eureka Server。
- 服务调用方: 从Eureka Server获取服务地址后进行调用。
二、引入Eureka
2.1 引入步骤
2.1.1 新建模块
- 位置: 根项目中,与业务代码平级。
- 命名:
eureka-server
,区别于Eureka Client。
2.1.2 添加依赖
- 依赖内容:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency>
- 依赖管理: 在最外层pom文件中使用
<dependencyManagement>
标签统一管理版本。
2.1.3 编写配置文件
- 文件名:
application.properties
- 配置内容:
server.port=8000 spring.application.name=eureka-server eureka.instance.hostname=localhost eureka.client.register-with-eureka=false eureka.client.fetch-registry=false eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
2.1.4 编写代码
- 启动类:
@SpringBootApplication @EnableEurekaServer public class EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } }
2.2 启动与验证
- 启动: 运行Eureka Server项目。
- 验证: 浏览器访问
http://localhost:8000
,查看Eureka管理界面。
三、Eureka Client改造
3.1 课程列表模块改造
3.1.1 添加依赖
- 依赖内容:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
3.1.2 配置文件修改
- 文件:
application.properties
- 配置内容:
eureka.client.service-url.defaultZone=http://localhost:8000/eureka/
3.1.3 启动模块
- 启动: 运行课程列表模块。
- 验证: 查看Eureka Server管理界面,确认服务注册成功。
3.2 课程价格模块改造
3.2.1 配置文件修改
- 文件:
application.properties
- 配置内容:
eureka.client.service-url.defaultZone=http://localhost:8000/eureka/
3.2.2 启动模块
- 启动: 运行课程价格模块。
- 验证: 查看Eureka Server管理界面,确认服务注册成功。
四、总结
4.1 Eureka Server
- 作用: 服务注册与发现中心。
- 配置: 端口、服务名、实例主机名等。
- 启动: 成功后可通过管理界面查看服务状态。
4.2 Eureka Client
- 改造步骤: 添加依赖、配置服务地址、启动模块。
- 验证: 通过Eureka Server管理界面确认服务注册成功。
4.3 服务交互
- 流程: 服务提供者注册到Eureka Server,服务调用方从Eureka Server获取地址后进行调用。
Spring Cloud服务间调用、负载均衡与断路器整合笔记
一、服务间调用
1.1 HTTP请求
- 作用: 服务间调用的默认方式。
- 特点: 参数指定繁琐,结果需要解析。
- 目的: 提高程序效率,简化远程服务调用。
1.2 Feign
- 诞生原因: 满足服务间调用需求。
- 使用效果: 远程服务调用如同本地方法调用。
- 功能特点: 参数传递与返回值解析已封装。
- 主要作用: 提高服务间调用的开发效率。
1.3 集成Feign
1.3.1 引入依赖
- 目标模块: 课程价格模块。
- 依赖内容:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
- 操作: Maven重新导入依赖。
1.3.2 配置文件
- 基本配置: 无需复杂配置,后续将介绍负载均衡配置。
1.3.3 添加注解
- 主类注解: 在主类上添加
@EnableFeignClients
。 - 创建客户端: 新建
CourseListClient
接口。 - 定义接口: 参考原接口定义,引入课程列表模块。
- 配置客户端: 标明客户端并配置服务名。
- 调用远程服务: 在控制器中实现远程调用逻辑。
- 测试服务: 启动Eureka Server、课程列表和价格模块,验证服务间调用。
二、负载均衡策略
2.1 策略概述
- 轮询策略: 逐个调用,循环往复。
- 随机策略: 随机选择服务实例。
2.2 加权策略
- 定义: 根据响应时间分配权重。
- 作用: 评估节点性能,合理分配请求。
- 实例: 根据CPU速度差异调整请求分配。
2.3 配置负载均衡
2.3.1 Price模块配置
- 配置文件: 在
application.properties
中设置。 - 指定策略: 配置
loadbalance.rule
。 - 实操配置: 在价格模块中添加配置行,选择Ribbon。
2.3.2 LoadBalancerRule
- 概念: 定义负载均衡策略。
- 策略类型: 如轮询、随机、加权等。
- 选择依据: 根据业务需求和节点性能选择。
2.3.3 完成配置
- 选择策略: 如
RoundRobinRule
。 - 配置完成: 实现负载均衡配置。
三、断路器Hystrix
3.1 为什么需要Hystrix
- 服务稳定性: 无法保证每个服务100%稳定。
- 故障影响: 一个服务故障可能导致整个系统不可用。
- Hystrix作用: 作为保护伞,防止错误扩散,采取降级手段保证部分功能可用。
3.2 Hystrix集成
3.2.1 添加依赖
- 位置: 课程价格模块。
- 依赖内容:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency>
3.2.2 配置文件
- 启用Hystrix: 设置
feign.hystrix.enabled=true
。
3.2.3 主类注解
- 添加注解:
@EnableCircuitBreaker
。
3.2.4 编写断路逻辑
- Fallback类: 实现
CourseListClient
接口,提供默认课程列表。 - 兜底逻辑: 返回默认课程列表,避免报错。
- 简化返回: 业务简单时可直接返回空列表。
3.2.5 运行程序
- 启动服务: 启动Eureka Server、课程列表和价格模块。
- 解决冲突: 添加
@Primary
注解解决组件冲突。 - 测试断路: 关闭课程列表服务,验证断路功能。
四、服务整合
4.1 编写接口
- 目的: 整合课程列表和价格信息。
- 方法:
GET /courses-and-price
。 - 返回内容: 包含课程和价格的整合对象列表。
4.2 生成实体类
- 位置:
entity
包。 - 类名:
CourseAndPrice
。 - 属性: 包括ID、课程ID、名称、价格。
- 方法: 生成get和set方法。
4.3 编写服务方法
- 目标: 在
CoursePriceService
中新增方法。 - 方法:
getCoursesAndPrice
。 - 实现:
- 获取课程列表。
- 遍历列表,查询每个课程的价格。
- 组装
CourseAndPrice
对象。 - 返回整合后的列表。
4.4 启动程序
- 步骤: 重启价格服务和课程列表服务。
- 结果: 接口正常返回,完成服务整合。
五、总结
- 服务间调用: 使用Feign简化远程调用。
- 负载均衡: 配置不同策略,如轮询、随机、加权。
- 断路器: 使用Hystrix保证服务稳定性。
- 服务整合: 通过Feign整合课程列表和价格服务。
以上内容总结了Spring Cloud中服务间调用、负载均衡与断路器整合的核心知识点,为后续的微服务架构开发提供了坚实的基础。
Spring Cloud Zuul网关笔记
一、网关Zuul的作用
1.1 统一身份验证
- 作用: 将身份验证逻辑集中到网关,避免每个服务重复实现。
- 好处: 简化服务开发,提高安全性。
1.2 安全处理
- 作用: 网关统一处理安全问题,如拦截异常IP。
- 好处: 提高系统整体安全性,减少服务开发负担。
二、网关Zuul的集成
2.1 注册到Eureka
- 步骤: 将Zuul注册到Eureka注册中心。
- 目的: 使其他服务能够发现和调用Zuul。
2.2 引入依赖
- 依赖:
- Eureka Client: 用于与Eureka注册中心通信。
- Zuul网关: 实现网关功能。
- 示例:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-zuul</artifactId> </dependency>
2.3 配置路由地址
- 方法: 在配置文件中设置路由规则。
- 示例:
zuul.routes.course-list.path=/list/** zuul.routes.course-list.service-id=course-list
2.4 启动网关
- 步骤: 编写启动类并运行。
- 注解:
@SpringBootApplication
@EnableZuulProxy
2.5 访问服务
- 方式: 通过网关访问注册在Eureka上的服务。
- 默认路由: 网关提供默认路由地址。
2.6 自定义配置
- 前缀配置: 为网关配置统一前缀(如
/imooc
)。 - 路径和服务名配置: 为模块配置独立路径和服务名。
- 示例:
zuul.prefix=/imooc zuul.routes.course-list.path=/list/** zuul.routes.course-list.service-id=course-list
2.7 重启网关
- 必要性: 修改配置后需重启网关以生效。
- 验证: 检查新地址是否可用。
三、网关过滤器
3.1 过滤器类型
- pre: 请求前运行,用于权限校验。
- post: 请求后运行,用于统计请求时长。
- error: 请求出错时运行。
3.2 前置过滤器编写
- 注解:
@Component
- 继承:
ZuulFilter
- 方法实现:
filterType()
: 返回FilterConstants.PRE_TYPE
。filterOrder()
: 指定执行顺序(如5)。shouldFilter()
: 返回true
表示所有请求都经过此过滤器。run()
: 实现具体逻辑,如打印请求URL。
3.3 后置过滤器编写
- 复制前置过滤器: 修改描述和类型。
- 类型修改:
filterType()
返回FilterConstants.POST_TYPE
。 - 执行顺序: 使用
SEND_RESPONSE_FILTER_ORDER - 1
。 - 业务逻辑: 打印返回状态码。
3.4 效果展示
- 启动服务: 启动网关服务并访问接口。
- 前置过滤器输出: 打印请求URL。
- 后置过滤器输出: 打印响应状态码。
四、知识小结
知识点 | 核心内容 | 考试重点/易混淆点 | 难度系数 |
---|---|---|---|
网关作用 | 统一身份验证和安全处理 | 网关如何统一处理身份验证和安全问题 | 🌟🌟 |
网关集成 | 注册到Eureka,引入依赖,配置路由地址 | 路由地址配置的方法和个性化设置 | 🌟🌟🌟 |
过滤器类型 | pre、post、error过滤器及其使用场景 | 区分pre和post的使用场景 | 🌟🌟 |
前置过滤器编写 | 使用@Component 注解,继承ZuulFilter ,实现抽象方法 |
过滤器类别指定和shouldFilter 方法的实现 |
🌟🌟🌟 |
后置过滤器编写 | 修改过滤器类型为post,调整执行顺序,实现具体逻辑 | 过滤器类别修改和返回状态码的获取 | 🌟🌟 |
过滤器执行顺序 | 数字越大执行越晚,pre先执行,post后执行 | 理解过滤器执行顺序的重要性 | 🌟🌟 |
实际测试 | 启动服务,访问接口,验证过滤器是否按预期工作 | 验证过滤器是否正确打印URL和状态码 | 🌟🌟🌟 |
五、总结
- 网关作用: 提供统一身份验证和安全处理。
- 网关集成: 注册到Eureka,引入依赖,配置路由地址。
- 过滤器: 实现前置、后置和错误过滤,灵活处理请求和响应。
- 自定义配置: 配置网关前缀和模块路径,提高路由灵活性。
以上内容总结了Spring Cloud Zuul网关的核心知识点,为后续的微服务架构开发提供了坚实的基础。