SpringCloud 学习之环境工程搭建 - 1
目录
案例介绍
需求
服务拆分
工程搭建
构建父子工程
创建子项目 - 订单服务
创建子项目 - 商品服务
完善订单服务
完善商品服务
远程调用
RestTemplate
REST:
RESTful
问题:
完!
案例介绍
需求
实现一个电商平台 demo
例如京东,里面有极多功能,如果将这些功能全部都卸载一个服务中,这个服务将是巨大的。此时微服务架构就是一个较好的选择。
微服务应用开发的第一步,就是服务拆分,拆分后才能实现各自开发。
服务拆分
在实际工作中,微服务并不是越小越好,服务越小,微服务架构的有点和缺点也会越明显。
服务越小,微服务的独立性就会越高。但同时,随着微服务的数量增多,管理这些微服务的难度也会提高,所以服务拆分需要考虑场景。
服务拆分原则:
1. 单一职责原则:
该原则原本是面向对象设计中的原则,指的是一个类应该专注于单一功能。
在微服务架构中,一个微服务也应该只负责一个功能或业务领域。每个服务之间应该有清晰的定义和边界,只关注自己的特定业务领域。
2. 服务自治:
服务资质是指微服务都应该具有高度自治的能力,每个微服务都能做到独立开发,测试,构建,部署,运行。服务之间不需要过多的关注其他服务的状态和数据。
3. 单向依赖:
微服务之间严禁循环依赖,双向依赖。
服务拆分示例:
此处是为了学习 SpringCloud 解决微服务架构中遇到的问题。
订单列表为例:
简单拆分看,这个页面提供了:
1. 订单列表
2. 商品信息
根据单一职责原则, 将服务进行拆分为订单服务和商品服务。
订单服务:根据订单 ID,获取订单详细信息。
商品服务:根据商品 ID,获取商品详细信息。
工程搭建
构建父子工程
创建一个空的 Maven 项目,只保留 pom.xml
完善 pom.xml 文件。使用 properties 来进行版本号的统一管理,使用 dependencyManagement 来管理依赖,声明父工程的打包方式为 pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>spring-cloud-demo</artifactId><version>1.0-SNAPSHOT</version><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.1.6</version><relativePath/> <!-- lookup parent from repository --></parent><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><java.version>17</java.version><mybatis.version>3.0.3</mybatis.version><mysql.version>8.0.33</mysql.version><spring-cloud.version>2022.0.3</spring-cloud.version></properties><dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>${mybatis.version}</version></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><version>${mysql.version}</version></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter-test</artifactId><version>${mybatis.version}</version><scope>test</scope></dependency></dependencies></dependencyManagement>
</project>
DependeycyManagement 和 Dependencies:
1. dependencies: 将所依赖的 jar 包直接添加到项目中,子项目也会继承该依赖
2. dependeycyManagement:只是声明依赖,并不实现 jar 包的引入。如果子项目需要相关依赖,需要再显示声明。如果子项目中华没有指定具体的版本,会从父项目中读取 version。如果子项目中指定了版本号,就会使用子项目中的 jar 版本。此外父工程的打包方式应该是 pom,不是 jar,此处需要手动声明。
Spring Cloud 版本
Spring Cloud 版本与 SpringBoot 版本有对应关系
创建子项目 - 订单服务
声明项目依赖和构建插件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>spring-cloud-demo</artifactId><groupId>org.example</groupId><version>1.0-SNAPSHOT</version><packaging>pom</packaging></parent><modelVersion>4.0.0</modelVersion><artifactId>order-service</artifactId><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId></dependency><!--mybatis--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
创建子项目 - 商品服务
声明项目依赖和构建插件入如订单服务。
完善订单服务
完善启动类,配置文件
业务代码:
model 层:
controller 层:
service 层:
mapper 层:
测试访问 http://127.0.0.1:8080/order/1
页面返回结果:
完善商品服务
完善启动类,配置文件
注意该项目是另一个服务了,所以配置文件中的端口号应该发生变化
业务代码:
model 层:
controller 层:
service 层:
mapper 层:
测试:访问 url:http://htttp://127.0.0.1:9090/product/1001
远程调用
需求:
根据订单查询订单信息时,根据订单里面的产品 ID,获取产品的详细信息
实现
思路:order-service 服务向 product-service 服务发送一个 http 请求,把得到的返回结果,和订单结果融合在一起,返回给调用方。
实现方式:采用 Spring 提供的 RestTemplate
1. 定义 RestTemplate
在 order-service 中进行定义,config 层:
2. 在 order-service 中的 model 将 ProductInfo 复制一份进来,同时将 ProductInfo 作为 OrderInfo 的属性
2. 修改 order-service 中的 OrderService
3. 将两个子项目分别启动
测试:
访问 url:http://127.0.0.1:8080/order/1
RestTemplate
RestTemplate 是从 Spring3.0 开始支持的一个 HTTP 请求工具,是一个同步的 REST API 客户端,提供了常见的 REST 请求方案的模板
REST:
REST:表现层资源状态转移。
REST 主要是一种软件架构风格。
此处有三个概念需要理解:
1. 资源:网络上所有的事务都可以抽象成资源u你,每个资源都有一个唯一的资源标识符(URL)
2. 表现层:资源的表现形式,比如文本作为资源,可以用 txt 格式表现,也可以通过 HTML,XML,JSON 格式来表示,甚至以二进制的格式表现
3. 状态转移:访问 URL。当客户端和服务器进行交互过程。客户端用到的手段,只能是 HTTP 协议,这个过程中,会涉及到数据状态的变化,比如对数据的增删改查,都是状态的转移。
REST 是一种设计风格,表示资源在网络中以某种表现形式进行状态转移。其本身并不适用,适用的是如何设计 RESTful API(REST 风格的网络接口)
RESTful
满足 REST 架构风格的接口
RESTful 风格的特征:
1. 资源:可以是一个图片音频等网络上的一个实体,除了一些二进制的资源外,普通的文本资源更多以 JSON 为载体,面向用户的一组数据(从数据库查询)
2. 通一接口:对资源的操作,比如获取,创建,删除。这些操作正好对应 HTTP 协议中的 GET POST PUT DELETE 方法。如果适用 RESTful 风格的接口,从接口上,只能定位其资源,但是无法知晓它具体进行了什么操作。需要从 HTTP 请求方法的类型上进行判断,到底发生了什么操作。
这些内容都是通过 HTTP 协议来呈现的,所有 RESTful 是基于 HTTP 协议的
RestTemplate 是 Spring 提供,封装 HTTP 调用,并强制使用 RESTful 风格。它会自动处理 HTTP 请求和关闭,只需要开发者这提供资源的地址和参数即可。
问题:
远程调用中,URL 中的 IP 和端口号都是写死的,127.0.0.1,9090,如果需要更换 IP,需要大量重复的修改大妈。
多机部署,如何分摊压力。
远程调用的 URL 复用性不高
所有服务都可以调用该接口,风险存在。
后面的篇章,会研究使用 SpringCloud 来解决这些问题。