一.开发环境推荐
JDK建议使用JDK17。
因为SpringCloud是基于SpringBoot进行开发的,SpringBoot3.X以下的版本,Spring官方已经不再维护了(还可以继续使用),SpringBoot3.X的版本使用的JDK版本基线是17,而且17比较稳定。
二.案例介绍
这篇博客我们是想实现一个电商平台(简单的,不是真实实现)
但是一个电商平台有很多很多功能,该如何实现呢?
如果将所有功能写在一个服务里,这个服务就是巨大的。那么微服务架构就是最好的选择
1.服务拆分
1.1服务拆分原则
微服务到底要多小?不是越小越好
服务越小,微服务的独立性就越高,但同时,微服务的数量就越多,管理这些服务的难度就越大。所以不能够盲目拆分,要遵循如下原则:
1.单一职责原则
单一职责原则原本是面向对象设计中的一个基本原则,它指的是一个类应该专注于单一的功能,不要存在多于一个导致类变更的原因。而在微服务中,就是说一个微服务也只负责一个功能或业务领域,每一个服务都应该有清晰的边界,只关注自己的特定业务领域。
比如电商系统中,有用户服务,商品服务,订单服务,物流服务……
2.服务自治
服务自治指的是每一个微服务都应该具备高度自治的能力,即每一个服务要做到能够独立开发,独立测试,独立构建,独立部署,独立运行。不受其他服务的影响。
对于电商系统,每一个微服务都应该有自己的存储,配置,在进行开发、构建、部署、运行和测试的时候,并不需要过多的关注其他微服务的状态和数据。
比如企业管理,每一个部门负责每一个部门的事情,并且尽可能少受其他团队的影响
3.单向依赖
微服务之间要做到单项依赖,严禁双向依赖循环依赖(循环依赖:A->B->C->A;双向依赖:A->B B->A。)
1.2服务拆分示例
这篇文章中,我们主要分两个服务,一个商品服务,一个订单服务
商品服务:提供商品id,返回商品的详情
订单服务:提供订单id,获取订单详情;再希望根据订单中的商品id获取到商品信息
三.数据准备
商品表,订单表,放到数据库中
四.构建父子工程
注意,springcloud的学习与项目的创建方式无关
有两种创建方式
法一:采用javaEE进阶的方式,每一个项目都是独立的,每一个idea窗口只显示一个项目(这样不方便学习,还得来回切换)
法二:采用父子工程搭建的方式(与继承类似)
4.1构建父工程
1.先创建一个maven项目
把src删除,因为它没啥用,所以就直接删除就好了
2.完善pom文件
使用<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>SpringCloud-demo</artifactId><version>1.0-SNAPSHOT</version><packaging>pom</packaging><modules><module>order-service</module><module>product-service</module></modules><!-- 打包方式记得改成pom的方式--><!--本身自带的这些要删除的--><!-- <properties>--><!-- <maven.compiler.source>17</maven.compiler.source>--><!-- <maven.compiler.target>17</maven.compiler.target>--><!-- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>--><!-- </properties>--><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.1.6</version><!-- 基于SPringboot3.16版本创建的--><relativePath/> <!-- lookup parent from repository --></parent><properties><!-- 声明了Maven,JDK,Mybaits,MySQL的版本--><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><!-- 将所依赖的jar直接加到项⽬中. ⼦项⽬也会继承该依赖.--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency></dependencies><dependencyManagement><!-- 只是声明依赖, 并不实现Jar包引⼊. 如果⼦项⽬需要⽤到相关依赖,需要显式声明.如果⼦项⽬没有指定具体版本, 会从⽗项⽬中读取version. 如果⼦项⽬中指定了版本号,就会使⽤⼦项⽬中指定的jar版本.此外⽗⼯程的打包⽅式应该是pom,不是jar, 这⾥需要⼿动使⽤ packaging 来声明 --><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><!-- spring-cloud的版本要和SPringboot的版本对应上来,SpringCloud2022.0.x和SpringBoot3.0.x,3.1.x对应--><type>pom</type><scope>import</scope></dependency><!-- 其余依赖的版本也要与SPringboot版本对应起来--><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>
打包方式pom
springcloud是基于springboot的,两者的版本号要对应
properties里面是对各种依赖的版本号的管理,上面就是Maven,JDK,Mybatis,Mysql的版本
dependencies中是父工程会用到的依赖,比如这里父工程只用到lombok,所以引入了lombok的依赖
dependencyManagement里面和dependencies又有区别,dependencies是将依赖引入了,该工程可以使用,而dependencyManagement则是将依赖进行声明,而没有将依赖引入,它们是给子工程使用的,子工程使用的时候就不用在进行版本的规定了,因为在父工程里面有版本号的指定(就是在properties中,properties里面可以定义用户自己的属性值,这些属性值可以在POM文件的任何地方同通过${x}
的方式来引用)。但要是子工程中使用的版本号和父工程声明的不一样,就要写版本号
4.2创建子项目-订单服务
1.鼠标放在项目名称上,如下,new module
2.resource里面创建application.yml文件,进行配置
如上,端口号8080,配置数据源,也就是mysql数据库访问路径;还有mybatis的一些配置。看自己需要什么。
3.配置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><parent><groupId>org.example</groupId><artifactId>SpringCloud-demo</artifactId><!-- --><version>1.0-SNAPSHOT</version></parent><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><resources><resource><directory>src/main/resources</directory><filtering>true</filtering><includes><include>**/**</include></includes></resource></resources></build></project>
声明父工程
一些属性要求
依赖注入,使用的就是父工程中声明的依赖以及版本
4.3创建子项目-商品服务
和上面同理
<?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><parent><groupId>org.example</groupId><artifactId>SpringCloud-demo</artifactId><version>1.0-SNAPSHOT</version></parent><artifactId>product-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><resources><resource><directory>src/main/resources</directory><filtering>true</filtering><includes><include>**/**</include></includes></resource></resources></build></project>
4.4完善订单服务
1.完善启动类
2.实体类
3.controller,service,mapper
测试:127.0.0.1:8080/order/1
4.5完善商品服务
原理都一样,最后访问127.0.0.1:8081/product/1001
五.远程调用
前面说了,希望根据订单里面的商品id获取到商品的详细信息。
实现思路:order-service服务向product-service服务发送一个http请求,把得到的返回结果,和订单结构一起返回给调用方
5.1实现-采用Spring提供的RestTemplate
1.定义RestTemplate
在order-service的config包中创建一个BeanConfig类,加上@configuration注释
Spring的@Bean注解用于告诉方法,产生一个Bean对象,然后这个Bean对象交给Spring管理
2.修改orderInfo
productinfo复制一份放到order中
orderinfo中加一个productinfo
3.修改orderservice
4.测试:127.0.0.1:8080/order/1
5.2RestTemplate理解
RestTemplate是从Spring3.0开始支持的一个HTTP请求工具。
什么是REST?
Representational State Transfer,表现层资源状态转移
资源:网络上的所有事物都可以抽象为资源,比如网上的图片视频文本等。每一个资源都有为一个资源标识符,及URL
表现层:资源的表现形式,比如文本资源可以使用txt格式,图片使用jpg,还有json,xml
状态转移:我们通过网络访问资源,对资源进行修改(增删改),都会引起资源状态的转移
REST是一个设计风格,指资源在网络上以某种表现形式进行状态转移
什么是RestFul?
满足rest设计风格的程序或接口称之为restful。而restful api就是满足rest风格的接口
restful风格有以下几个主要特征:
1.资源:资源可以是上面提到的任意
2.统一接口:对资源的操作,比如获取,创建,修改删除等,这些操作正好对应HTTP协议提供的GET、POST、DELETE等方法。也就是说,如果使用restful风格的接口,从接口上可能只能定位其资源,但是无法知晓它具体进行了什么操作,需要具体了解其发生什么操作就要从其HTTP请求方法上进行判断
比如同一个url:
GET/blog/{blogid}
DELETE/blog/{blogid}
都是blog/{blogid},但一个是获取信息,一个是删除