前言:首先感谢尚硅谷周阳老师的讲解,让我对springcloud有了很好的理解,周阳老师的讲课风格真的很喜欢,内容充实也很幽默,随口一说就是一个段子,我也算是周阳老师的忠实粉丝啦。
先说说课程总体内容
SpringCloud Eureka 服务注册与发现
Zookeeper服务注册与发现
SpringCloud Consul 服务注册与发现
SpringCloud Ribbon 负载均衡服务调用
SpringCloud OpenFeign 服务接口调用
SpringCloud Hystrix 断路器
SpringCloud Gateway 网关
SpringCloud Config 分布式配置中心
SpringCloud Bus 消息总线
SpringCloud Stream 消息驱动
SpringCloud Sleuth 分布式请求链路跟踪
SpringCloud Alibaba Nacos服务注册和配置中心
SpringCloud Alibaba Sentinel 实现熔断与限流
SpringCloud Alibaba Seata 解决分布式事务问题
目录
一、SpringCloud介绍
SpringCloud版本选择
课程所用软件版本
Cloud各种组件的停更/升级/替换
二、微服务架构编码构建
(一)构建父工程
1、微服务cloud整体聚合父工程Project
2、父工程pom配置
3、Maven工程落地细节复习
(二)Rest微服务工程构建
1、支付Module模块8001
热部署配置devtools
2、消费者订单Module模块80
RestTemplate介绍
3、工程重构
SpringCloud 是微服务一站式服务解决方案,微服务全家桶。它是微服务开发的主流技术栈。它采用了名称,而非数字版本号。
SpringCloud 和 springCloud Alibaba 目前是最主流的微服务框架组合。
选用 springboot 和 springCloud 版本有约束,不按照它的约束会有冲突。
Cloud Release Train | Boot Version |
---|---|
Hoxton | 2.2.x, 2.3.x (Starting with SR5) |
Greenwich | 2.1.x |
Finchley | 2.0.x |
Edgwj | 1.5.x |
Dalston | 1.5.x |
查看版本对ces应关系:https://start.spring.io/actuator/info
cloud | Hoxton.SR1 |
boot | 2.2.2.RELEASE |
cloud alibaba | 2.1.0.RELEASE |
java | java8 |
maven | 3.5及以上 |
mysql | 5.7及以上 |
题外话:boot版已经到2.2.4为最新,为什么选2.2.2?
以前:
现在(2020年):
1,Eureka停用,可以使用zk作为服务注册中心
2,服务调用,Ribbon准备停更,代替为LoadBalance
3,Feign改为OpenFeign
4,Hystrix停更,改为resilence4j,或者阿里巴巴的sentienl
5.Zuul改为gateway
6,服务配置Config改为 Nacos
7,服务总线Bus改为Nacos
参考资料:
SpringCloud:
SpringBoot:
约定 > 配置 > 编码
构建父工程,后面的项目模块都在此工程中:
设置编码:Settings -> File Encodings
注解激活:
Java版本确定:
4.0.0
springcloud
cloud2020
1.0-SNAPSHOT
pom
UTF-8
1.8
1.8
4.12
1.2.17
1.16.18
5.1.47
1.1.16
1.3.0
org.apache.maven.plugins
maven-project-info-reports-plugin
3.0.0
org.springframework.boot
spring-boot-dependencies
2.2.2.RELEASE
pom
import
org.springframework.cloud
spring-cloud-dependencies
Hoxton.SR1
pom
import
com.alibaba.cloud
spring-cloud-alibaba-dependencies
2.1.0.RELEASE
pom
import
mysql
mysql-connector-java
${mysql.version}
runtime
com.alibaba
druid
${druid.version}
org.mybatis.spring.boot
mybatis-spring-boot-starter
${mybatis.spring.boot.version}
junit
junit
${junit.version}
log4j
log4j
${log4j.version}
org.springframework.boot
spring-boot-maven-plugin
true
true
dependencyManagement说明:
Maven 使用dependencyManagement 元素来提供了一种管理依赖版本号的方式。通常会在一个组织或者项目的最顶层的父POM 中看到dependencyManagement 元素。使用pom.xml 中的dependencyManagement 元素能让所有在子项目中引用一个依赖而不用显式的列出版本号。Maven 会沿着父子层次向上走,直到找到一个拥有dependencyManagement 元素的项目,然后它就会使用这个dependencyManagement 元素中指定的版本号。
dependencyManagement里只是声明依赖,并不实现引入,因此子项目需要显示的声明需要用的依赖。如果不在子项目中声明依赖,是不会从父项目中继承下来的;只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且version和scope都读取自父pom。如果子项目中指定了版本号,那么会使用子项目中指定的jar版本。
好处:如果有多个子项目都引用同一样依赖,则可以避免在每个使用的子项目里都声明一个版本号,这样当想升级或切换到另一个版本时,只需要在顶层父容器里更新,而不需要一个一个子项目的修改 ;另外如果某个子项目需要另外的一个版本,只需要声明version就可。
maven中跳过单元测试
父工程创建完成执行mvn:install将父工程发布到仓库方便子工程继承
新建模块cloud-provider-payment8001
pom文件
cloud2020
springcloud
1.0-SNAPSHOT
4.0.0
cloud-provider-payment8001
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-actuator
org.mybatis.spring.boot
mybatis-spring-boot-starter
com.alibaba
druid-spring-boot-starter
1.1.10
mysql
mysql-connector-java
org.springframework.boot
spring-boot-starter-jdbc
org.springframework.boot
spring-boot-devtools
runtime
true
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
application.yml
server:
port: 8001
spring:
application:
name: cloud-payment-service # 项目名,也是注册的名字
datasource:
type: com.alibaba.druid.pool.DruidDataSource #当前数据源操作类型
driver-class-name: org.gjt.mm.mysql.Driver #mysql驱动包
url: jdbc:mysql://localhost:3306/db2019?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
username: root
password: 12345
mybatis:
mapper-locations: classpath:mapper/*.xml
# 所有Entity 别名类所在包
type-aliases-package: com.atguigu.springcloud.entities
主启动类
@SpringBootApplication
public class PaymentMain8001 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain8001.class,args);
}
}
建表SQL
create table `payment`(
`id` bigint(20) not null auto_increment comment 'ID',
`serial` varchar(200) default '',
PRIMARY KEY (`id`)
)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
select * from payment;
实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Payment implements Serializable {
private long id; //数据库是bigint
private String serial;
}
返回给前端的通用json数据串
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CommonResult {
private Integer code;
private String message;
private T data;
public CommonResult(Integer id,String message){
this(id,message,null);
}
}
dao
@Mapper
public interface PaymentDao {
public int create(Payment payment);
public Payment getPaymentById(@Param("id") Long id);
}
resource下创建mapper文件夹,新建mapper.xml。在yml里有所有entity别名类所在包,所有payment不用写全类名
insert into payment(serial) values(#{serial})
service
public interface PaymentService {
public int create(Payment payment);
public Payment getPaymentById(@Param("id") Long id);
}
@Service
public class PaymentServiceImpl implements PaymentService {
@Resource
private PaymentDao paymentDao;
@Override
public int create(Payment payment){
return paymentDao.create(payment);
}
@Override
public Payment getPaymentById(Long id){
return paymentDao.getPaymentById(id);
}
}
controller
@RestController
@Slf4j
public class PaymentController {
@Resource
private PaymentService paymentService;
@PostMapping(value = "/payment/create")
public CommonResult create(@RequestBody Payment payment){
int result = paymentService.create(payment);
log.info("***********插入结果:"+result);
if (result > 0){
return new CommonResult(200,"插入数据库成功",result);
}else {
return new CommonResult(444,"插入数据库失败",null);
}
}
@GetMapping(value = "/payment/get/{id}")
public CommonResult getPaymentById(@PathVariable("id") Long id){
Payment payment = paymentService.getPaymentById(id);
log.info("***********查询结果:"+payment+"\t"+"oo哈哈");
if (payment!=null){
return new CommonResult(200,"查询成功",payment);
}else {
return new CommonResult(444,"查询失败",null);
}
}
}
使用Postman测试
json字符串
{"id": 2,"serial": "cdf"}
代码改动后希望自动生效
1、具体模块里添加Jar包到工程中,上面的pom文件已经添加上了
org.springframework.boot
spring-boot-devtools
runtime
true
2、添加plugin到父工程的pom文件中:上面也已经添加好了
org.springframework.boot
spring-boot-maven-plugin
true
true
shift + ctrl + alt + / 四个按键一块按,选择Reg项:
重启IDEA
热部署只允许在开发阶段使用
新建模块cloud-consumer-order80
消费者现在只模拟调用提供者的Controller方法,没有持久层配置,只有Controller和实体类
当然也要配置主启动类和启动端口
pom文件
cloud2020
springcloud
1.0-SNAPSHOT
4.0.0
cloud-consumer-order80
org.springframework.cloud
spring-cloud-starter-zipkin
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-actuator
org.springframework.boot
spring-boot-devtools
runtime
true
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
application.yml
server:
port: 80
主启动类
@SpringBootApplication
public class OrderMain80 {
public static void main(String[] args) {
SpringApplication.run(OrderMain80.class,args);
}
}
实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Payment implements Serializable {
private long id;
private String serial;
}
返回给前端的通用json数据串
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult {
private Integer code;
private String message;
private T data;
public CommonResult(Integer code, String message) {
this(code, message, null);
}
}
RestTemplate提供了多种便捷访问远程Http服务的方法, 是一种简单便捷的访问restful服务模板类,是Spring提供的用于访问Rest服务的客户端模板工具集。
官网地址
https://docs.spring.io/spring-framework/docs/5.2.2.RELEASE/javadoc-api/org/springframework/web/client/RestTemplate.html
使用
使用restTemplate访问restful接口非常的简单粗暴无脑。(url, requestMap, ResponseBean.class)这三个参数分别代表 REST请求地址、请求参数、HTTP响应转换被转换成的对象类型。
config配置类
@Configuration
public class ApplicationContextConfig {
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
controller
@Slf4j
@RestController
public class OrderController {
//远程调用的地址
public static final String PAYMENT_URL="http://localhost:8001";
@Resource
private RestTemplate restTemplate;
@PostMapping("/consumer/payment/create")
public CommonResult create(@RequestBody Payment payment){
return restTemplate.postForObject(PAYMENT_URL+"/payment/create",//请求地址
payment,//请求参数
CommonResult.class);//返回类型
}
@GetMapping("/consumer/payment/get/{id}")
public CommonResult getPaymentById(@PathVariable("id")Long id){
return restTemplate.getForObject(PAYMENT_URL+"/payment/get/"+id,//请求地址
CommonResult.class);//返回类型
}
}
测试远程调用
json字符串
{"id": 3,"serial": "cdf"}
系统中有重复部分
新建模块cloud-api-commons
pom文件
cloud2020
springcloud
1.0-SNAPSHOT
4.0.0
cloud-api-commons
org.springframework.boot
spring-boot-devtools
runtime
true
org.projectlombok
lombok
true
cn.hutool
hutool-all
5.1.0
实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Payment implements Serializable {
private long id;
private String serial;
}
CommonResult通用封装类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CommonResult {
private Integer code;
private String message;
private T data;
public CommonResult(Integer id,String message){
this(id,message,null);
}
}
maven命令clean install
订单80和支付8001分别改造,删除各自的原先有过的entities文件夹,分别粘贴
springcloud
cloud-api-commons
${project.version}