[Spring] SpringCloud概述与环境工程搭建

🌸个人主页:https://blog.csdn.net/2301_80050796?spm=1000.2115.3001.5343
🏵️热门专栏:
🧊 Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm=1001.2014.3001.5482
🍕 Collection与数据结构 (93平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm=1001.2014.3001.5482
🧀线程与网络(96平均质量分) https://blog.csdn.net/2301_80050796/category_12643370.html?spm=1001.2014.3001.5482
🍭MySql数据库(93平均质量分)https://blog.csdn.net/2301_80050796/category_12629890.html?spm=1001.2014.3001.5482
🍬算法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12676091.html?spm=1001.2014.3001.5482
🍃 Spring(97平均质量分)https://blog.csdn.net/2301_80050796/category_12724152.html?spm=1001.2014.3001.5482
🎃Redis(97平均质量分)https://blog.csdn.net/2301_80050796/category_12777129.html?spm=1001.2014.3001.5482
🐰RabbitMQ(97平均质量分) https://blog.csdn.net/2301_80050796/category_12792900.html?spm=1001.2014.3001.5482
感谢点赞与关注~~~
在这里插入图片描述

目录

  • 1. 认识微服务
    • 1.1 单体架构
    • 1.2 集群和分布式架构
      • 区分集群和分布式
    • 1.3 微服务架构
      • 分布式和微服务
    • 1.4 微服务带来的挑战
      • 优势
      • 挑战
  • 2. 微服务解决方案-SpringCould
    • 2.1 什么是SpringCould
    • 2.2 SpringCould版本
      • SpringCould和SpringBoot的关系
    • 2.3 SpringCould的实现方案
      • SpringCould Netflix
      • SpringCould Alibaba
      • Spring Could实现对比
  • 3. 环境与工程搭建
    • 3.1 环境搭建
    • 3.2 案例介绍与工程搭建
      • 3.2.1 需求
      • 3.2.2 服务拆分
        • 服务拆分示例
    • 3.3 数据准备
    • 3.4 工程搭建
      • 3.4.1 创建父工程
        • DependencyManagement和Dependencies
        • SpringCould版本
      • 3.4.2 创建子项目-订单服务
      • 3.4.3 创建子项目-商品服务
      • 3.4.4 完善订单服务
      • 3.4.5 完善商品服务
      • 3.4.6 远程调用
        • 需求
        • 实现

1. 认识微服务

在学习SpringCould之前,我们需要先来了解一下什么是微服务.下图表示的是从单体架构转化为微服务的过程.
在这里插入图片描述

1.1 单体架构

我们之前学习的很多项目,包括好多创业公司早起或者是传统企业会把业务的所有功能都会打包在一个项目中,这就是单体架构.
比如一个电商系统,我们都会把所有的模块都写在一个web项目中,然后统一部署到一个web服务器中.
在这里插入图片描述
单体架构开发简单,部署简单,一个项目中就包含了一个系统的所有功能,省去了多个项目之间的交互的调用消耗.直接部署在一个服务器上即可.

1.2 集群和分布式架构

当用户量越来越大的时候,需求也会越来越大,流量也会越来越大,服务就有可能面临一些问题.我们在对项目进行优化的时候,会考虑从两方面优化:

  • 横向优化: 添加服务器,把单台机器变为多台机器的集群,每一个服务器都具备这个系统的完整功能.
  • 纵向优化: 把一个应用,按照业务进行拆分,拆分为多个项目,这个架构也叫做垂直架构.
    在这里插入图片描述

区分集群和分布式

  • 集群是将一个系统完整地部署到多个服务器上,每个服务器都能够提供系统的所有服务,多个服务器通过负载均衡调度完成任务.每个服务器称为集群的结点/
  • 分布式是将一个系统拆分为多个子系统,每个子系统部署在多个服务器上,多个服务器的子系统协同合作完成一个特定任务.

举例说明:
一个饭店一开始只有一个厨师,这个厨师负责备菜,洗菜,切菜,炒菜,这就是单体架构.随着这个饭店的生意越来越好,这个厨师开始忙不过来了,饭店又招聘了一个厨师,和原来的厨师做同样的事情,这两个厨师的关系就是集群.
后来为了让厨师专心炒菜,饭店又请了一个配菜师,负责备菜,洗菜,切菜,厨师和配菜师的关系就是分布式,后来一个配菜师也忙不过来了,有请了一个配菜师,这两个配菜师的关系就是集群.
在这里插入图片描述

  • 从概念上,集群是多个计算机做同样的事情,分布式是多个计算机做不同的事情.从功能上
  • 从功能上,集群的每一个节点的功能都是相同的,并且是可以代替的,分布式也是多个节点组成的系统,但是每个节点完成的业务是不同的,一个结点出现问题,这个业务就不可访问了.
  • 从关系上.分布式和集群在实践中,很多时候是配合使用的.素以实际的分布式架构设计中并不会把分布式和集群单独区分,而是统称为:分布式架构.

1.3 微服务架构

从图上可以看出,按照业务进行拆分之后,会有一些重复的功能开发,比如订单系统,电商平台和支付系统都会涉及.
在分布式架构下,当部署的服务越来越多的时候,重复的代码就会越来越多,服务的调用关系也会越来越复杂,我们可以把一些通用的,会被多个上层服务调用的共享业务,提取为独立的共享业务,提取成独立的基础服务,组成一个个微小的服务,这就是微服务.简单来说,微服务就是很小的服务,小到一个服务值对对应一个单一的功能,只做一件事.这个服务可以单独部署运行.
在这里插入图片描述
微服务之间可以使用REST和RPC协议进行通信.
从这个角度来看,微服务架构是分布式架构的一种拓展,这种架构模式下拆分的粒度更小,服务更加独立.可以理解为,微服务是一种经过良好架构设计的分布式架构方案,也就是微服务架构一定是分布式架构,分布式架构不一定是微服务架构.

分布式和微服务

分布式: 服务拆分,拆开即可,对拆分的粒度和服务没有要求.
微服务: 值非常微小的服务,更细粒度的垂直拆分,通常指的是不能再拆分的服务.
分布式架构侧重于压力的分散,强调的是服务的分散化.微服务侧重于能力的分散,更强调服务的专业化和惊细分工.

1.4 微服务带来的挑战

微服务架构带来好处的同时,也面临着⼀些挑战,从单体服务转向微服务意味着管理更加复杂.接下来我们从优势和挑战两个方面分析一下微服务架构.

优势

  • 易开发和易维护.每个微服务负责的业务比较清晰,体量较小,开发和维护成本较低.
  • 容错性高,一个服务发生故障,可以是故障隔离在一个单体服务中,不会引起整体服务的故障.
  • 扩展性好.每个服务都是独立运行的,我们可以结合项目实际情况进行扩展,按需求伸缩.
  • 技术选型灵活.每个服务都是单独的团队来开发运维,可以根据业务特点和团队特点,选择适合的技术栈.

挑战

虽然微服务具备很多的优势,但是由于服务数的增加,服务的治理也是我们面临的巨大挑战.

  • 服务依赖.随着服务的数量增多,服务之间的关系也会变得更加复杂.一个服务的更改,需要考虑对其.他服务的影响.
  • 运维成本.⼀个业务流程会涉及多个微服务共同完成,有更多的服务需要编译,部署,运行,甚至可能是不同的编程语言,不同的运行环境,当然也需要集群来处理故障转移等.这对于运维人员而言,挑战是巨大的.
  • 开发和测试.⼀个业务流程可能涉及多个微服务共同完成,服务调用引入网络延迟,不可靠的网络,如何进行容错处理等问题.这对开发和测试而言,难度也会提升.
  • 服务监控.在⼀个单体结构中,很容易实现服务的监控.因为所有功能都在⼀个服务中,微服务架构下,不仅需要对整个链路进行监控,还需要对每⼀个服务实现监控.
  • 负载均衡.微服务架构中的服务实例数量可能非常庞大,因此需要有效的服务发现和负载均衡机制来管理请求流量和保证高可可性.

微服务架构,在java领域,最引人注目的就是SpringCloud了.

2. 微服务解决方案-SpringCould

2.1 什么是SpringCould

简单来说,SpringCould是分布式微服务架构的一站式解决方案,是微服务架构落地的多种技术的集合.
比如:

  • Distributed/versioned configuration 分布式版本配置
  • Service registration and discovery 服务注册和发现
  • Routing 路由
  • Service-to-service calls 服务调用
  • Load balancing 负载均衡
  • Circuit Breakers 断路器
  • Distributed messaging 分布式消息

SpringCould并不是Spring团队研发的一种框架,他只是把一些比较优秀的解决微服务架构中常见问题的开源框架基于SpringCould的规范进行整合.并基于SpringBoot的风格,对这些组件进行封装,屏蔽掉了复杂的配置的实现原理,为开发者提供了开箱即用的微服务开发体验.
这些开源技术的框架是由各个提供这些框架的公司来维护的,SpringCould就是这些微服务的大管家.

就相当于我们在装修的时候,需要买各种家电,但是家电的品牌各有各的好,这时候就有一个企业出了一些套餐,比如海尔洗衣机,美的电冰箱,格力空调,西门子烤箱等等.这些家电并不是这个企业提供的,而是由第三方公司提供,这个公司只负责对这些好用的家电进行整合.

2.2 SpringCould版本

Spring Cloud是⼀个由很多子项目组成的庞大项目,这些子项目由各个公司来维护的,所以发布阶段也是不同的.为了管理主项目和子项目的依赖关系,以及为了避免和子项目版本的冲突,主项目版本命名并没有采用和子项目数字版本化的形式,而是采用了英文名称.这个英文版本名称也比较有趣,Spring Cloud采用了英国伦敦地铁站的名称来命名,并由地铁站名称字母A-Z依次类推的形式来发布迭代版本.
• Angel
• Brixton
• Camden
• Dalston
• Edgware
• Finchley
• Greenwich
• Hoxton
但是英文的版本号过于复杂,从Hoxton版本之后,Spring Cloud的版本就变成了2020.0.0这样的日期版本号了
• 2020.0.x aka Ilford
• 2021.0.x aka Jubilee
• 2022.0.x aka Kilburn
• 2023.0.x aka Leyton

SpringCould和SpringBoot的关系

SpringCould中的所有子项目(组件)都依赖SpringBoot,所以SpringBoot和SpringCould(其中所包含的组件)的版本之间也存在一定的对应关系.
在这里插入图片描述
如果我们有一个SpringBoot项目,我们希望在这个项目中添加SpringCould的一些组件,需要根据当前项目的SpringBoot版本,选择SpringCould的其中的组件版本.

2.3 SpringCould的实现方案

在SpringCould的规范之下,不仅仅有官方自己的实现,其他的一些公司也有很多的实现,其中最为出名的是:

  • SpringCould Netflix
  • SpringCould Alibaba

SpringCould Netflix

SpringCould Netflix是Netflix OSS公司在SpringCould的规范下的一种实现.包含的组件以及重要的功能大致如下:
• Eureka:服务注册和发现
• Zuul:服务网关
• Ribbon:负载均衡
• Feign:服务调用组件
• Hystrix:断路器,提供服务熔断和限流
• Hystrix Dashboard:监控面板
• …

然而,这些组件在2018年的时候Netflix公司宣布其核心组件Hystrix、Ribbon、Zuul等

SpringCould Alibaba

Spring Cloud Alibaba是阿里巴巴集团下的开源组件和云产品在SpringCloud规范下的实现.
虽然Spring Cloud Alibaba目前并不是Spring Cloud官方推荐的默认方案,但是Spring Cloud Alibaba是阿里中间件团队主导的⼀个新生项目,正处于高速迭代中.甚至在Alibaba的开源组件还没有织入SpringCloud生态之前,就已经在各大公司广泛使用了.

如果说SpringCouldNetflix是SpringCould的第一代实现,那么SpringCouldAlibaba就是SpringCould的第二代实现,主要由Nacos,Sentinel,Seata等组件组成.
在这里插入图片描述
自Spring Cloud Netflix进入停更维护后,Spring Cloud Alibaba逐渐代替它成为主流的微服务框架.

Spring Could实现对比

在这里插入图片描述

3. 环境与工程搭建

3.1 环境搭建

在搭建工程之前,我们首先需要搭建我们的开发环境,我们需要安装JDK17和MySQL两个环境.

3.2 案例介绍与工程搭建

3.2.1 需求

实现一个简单的电商平台,首先我们需要对电商平台的服务进行拆分,拆分之后才可以各自开发.

3.2.2 服务拆分

微服务到底多小才算得上"微",并没有明确的规定.服务越小,微服务的独立性就会越来越高,所以服务拆分也需要考虑场景.
微服务拆分一般遵循的是一下的原则:

  1. 单一职责原则
    在微服务架构中,一个微服务应该只负责一个功能或者多个业务的领域,每个服务应该有清晰的定义和边界,值关注自己的特定业务领域.
    比如电商系统可以拆分为如下的服务:
    在这里插入图片描述
  2. 服务自治
    服务自治是每个微服务都应该具备高度自治的能力,即每个服务都能做到独立开发,独立测试,独立构建,独立部署,独立运行.
    以上面的电商系统为例,每个微服务都应该有自己的存储,配置,在进行开发构建,部署,运行和测试的时候,并不需要关注其他的微服务的状态和数据.
    在这里插入图片描述
  3. 单向依赖
    微服务之间需要做到单向依赖,严禁循环依赖,双向依赖.如果必须出现循环依赖或者是双向依赖,我们想办法使用其他的方案代替.
    在这里插入图片描述

微服务架构并无具体的标准,适合自身的就是最好的.

服务拆分示例

以电商系统的订单列表为例:
在这里插入图片描述
简单来看,这个页面提供了一下的信息:

  1. 订单列表
  2. 商品信息
    根据服务的单一职责原则,我们需要把服务拆分为:订单服务,商品服务.
  • 订单服务: 提供订单id,获取订单详细信息
  • 商品服务: 根据商品id,返回商品的详细信息.
    在这里插入图片描述

3.3 数据准备

根据服务自治的原则,每个服务都应该有自己独立的数据库

  • 订单服务
-- 订单服务-- 建库
create database if not exists cloud_order charset utf8mb4;use cloud_order;
-- 订单表
DROP TABLE IF EXISTS order_detail;
CREATE TABLE order_detail (`id` INT NOT NULL AUTO_INCREMENT COMMENT '订单id',`user_id` BIGINT ( 20 ) NOT NULL COMMENT '用户ID',`product_id` BIGINT ( 20 ) NULL COMMENT '产品id',`num` INT ( 10 ) NULL DEFAULT 0 COMMENT '下单数量',`price` BIGINT ( 20 ) NOT NULL COMMENT '实付款',`delete_flag` TINYINT ( 4 ) NULL DEFAULT 0,`create_time` DATETIME DEFAULT now(),`update_time` DATETIME DEFAULT now(),
PRIMARY KEY ( id )) ENGINE = INNODB DEFAULT CHARACTER
SET = utf8mb4 COMMENT = '订单表';-- 数据初始化
insert into order_detail (user_id,product_id,num,price)
values
(2001, 1001,1,99), (2002, 1002,1,30), (2001, 1003,1,40),
(2003, 1004,3,58), (2004, 1005,7,85), (2005, 1006,7,94);
  • 商品服务
-- 建库
create database if not exists cloud_order charset utf8mb4;
-- 订单表
DROP TABLE IF EXISTS order_detail;
CREATE TABLE order_detail (`id` INT NOT NULL AUTO_INCREMENT COMMENT '订单id',`user_id` BIGINT ( 20 ) NOT NULL COMMENT '⽤⼾ID',`product_id` BIGINT ( 20 ) NULL COMMENT '产品id',`num` INT ( 10 ) NULL DEFAULT 0 COMMENT '下单数量',`price` BIGINT ( 20 ) NOT NULL COMMENT '实付款',`delete_flag` TINYINT ( 4 ) NULL DEFAULT 0,`create_time` DATETIME DEFAULT now(),`update_time` DATETIME DEFAULT now(),
PRIMARY KEY ( id )) ENGINE = INNODB DEFAULT CHARACTER
SET = utf8mb4 COMMENT = '订单表';
-- 数据初始化
insert into order_detail (user_id,product_id,num,price)
values
(2001, 1001,1,99), (2002, 1002,1,30), (2001, 1003,1,40),
(2003, 1004,3,58), (2004, 1005,7,85), (2005, 1006,7,94);create database if not exists cloud_product charset utf8mb4;
-- 产品表
DROP TABLE IF EXISTS product_detail;
CREATE TABLE product_detail (`id` INT NOT NULL AUTO_INCREMENT COMMENT '产品id',`product_name` varchar ( 128 ) NULL COMMENT '产品名称',`product_price` BIGINT ( 20 ) NOT NULL COMMENT '产品价格',`state` TINYINT ( 4 ) NULL DEFAULT 0 COMMENT '产品状态 0-有效 1-下架',`create_time` DATETIME DEFAULT now(),`update_time` DATETIME DEFAULT now(),
PRIMARY KEY ( id )) ENGINE = INNODB DEFAULT CHARACTER
SET = utf8mb4 COMMENT = '产品表';
-- 数据初始化
insert into product_detail (id, product_name,product_price,state)
values
(1001,"T恤", 101, 0), (1002, "短袖",30, 0), (1003, "短裤",44, 0),
(1004, "卫衣",58, 0), (1005, "马甲",98, 0),(1006,"羽绒服", 101, 0),
(1007, "冲锋衣",30, 0), (1008, "袜子",44, 0), (1009, "鞋子",58, 0),
(10010, "毛衣",98, 0)

3.4 工程搭建

3.4.1 创建父工程

  1. 创建一个空的Maven项目,删除所有代码,只保留pom.xml.
    在这里插入图片描述
  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>spring-cloud-demo</artifactId><packaging>pom</packaging><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>
DependencyManagement和Dependencies
  1. dependenice: 将所依赖的jar直接加载到项目中.子项目也会继承该依赖.
    在这里插入图片描述
  2. dependencyManagement: 只是声明依赖,并不实现jar包引入.如果子项目需要用到相关依赖,需要显示声明,如果子项目中没有指定具体版本,会从父项目中读取version.如果子项目中指定了版本号,就会使用子项目中指定的jar版本,此外父工程的打包方式应该是pom,不是jar,这里需要手动使用packing来声明.
    在这里插入图片描述
    在这里插入图片描述
    比如上面的两段代码,lombok会直接被继承进入子项目中,但是springframework.cloud想要在子项目中使用,子项目在继承的时候必须显式声明.如果子项目在声明依赖的时候没有声明版本相关的信息,那么就从父工程中引入.
SpringCould版本

SpringCould是基于SpringBoot搭建的,所以他们的版本必须对应.
现在我们的项目中使用的SpringBoot版本是3.1.6,对应的SpringCould版本应为2022版本.

3.4.2 创建子项目-订单服务

  1. 在父工程之下新建一个模块.
    在这里插入图片描述
  2. 声明项目依赖和项目构建插件
<?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>spring-cloud-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></build>
</project>

3.4.3 创建子项目-商品服务

  1. 创建模块
    在这里插入图片描述
  2. 声明项目依赖和项目构建插件
<?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>spring-cloud-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></build>
</project>

3.4.4 完善订单服务

  1. 启动类
package com.jrj.order;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class OrderServiceApplication {public static void main(String[] args) {SpringApplication.run(OrderServiceApplication.class,args);}
}
  1. 配置文件
server:port: 8080
spring:datasource:url: jdbc:mysql://127.0.0.1:3306/cloud_order?characterEncoding=utf8&useSSL=falseusername: rootpassword: rootdriver-class-name: com.mysql.cj.jdbc.Driver
mybatis:configuration: # 配置打印 MyBatis⽇志log-impl: org.apache.ibatis.logging.stdout.StdOutImplmap-underscore-to-camel-case: true #配置驼峰⾃动转换
  1. 业务代码
    实体类
@Data
public class OrderInfo {public Integer id;public Integer userId;public Integer productId;public Integer num;public Integer price;public Integer deleteFlag;public Date createTime;public Date updateTime;
}

Mapper,根据订单id查询订单信息

@Mapper
public interface OrderMapper {@Select("select * from order_detail where id = #{id}")OrderInfo selectOrderById(Integer id);
}

Service

@Service
public class OrderService {@Autowiredprivate OrderMapper orderMapper;public OrderInfo selectOrder(Integer id){return orderMapper.selectOrderById(id);}
}

Controller

@RequestMapping("/order")
@RestController
public class OrderController {@Autowiredprivate OrderService orderService;@RequestMapping("/select")public OrderInfo selectOrder(Integer id){return orderService.selectOrder(id);}
}

运行测试
GET http://127.0.0.1:8080/order/select?id=1
在这里插入图片描述

3.4.5 完善商品服务

  1. 启动类
@SpringBootApplication
public class ProductServiceApplication {public static void main(String[] args) {SpringApplication.run(ProductServiceApplication.class,args);}
}
  1. 配置文件
server:port: 9090
spring:datasource:url: jdbc:mysql://127.0.0.1:3306/cloud_product?characterEncoding=utf8&useSSL=falseusername: rootpassword: qwe123524driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:configuration: # 配置打印 MyBatis⽇志log-impl: org.apache.ibatis.logging.stdout.StdOutImplmap-underscore-to-camel-case: true #配置驼峰⾃动转换
  1. 业务代码
    实体类
@Data
public class ProductInfo {public Integer id;public String productName;public Integer productPrice;public Integer state;public Date createTime;public Date updateTime;
}

Mapper

@Mapper
public interface ProductMapper {@Select("select * from product_detail where id = #{id}")ProductInfo selectProductById(Integer id);
}

Service

@Service
public class ProductService {@Autowiredprivate ProductMapper productMapperpublic ProductInfo selectById(Integer id){return productMapper.selectProductById(id);}
}

Controller

@RestController
@RequestMapping("/product")
public class ProductController {@Autowiredprivate ProductService productService;@RequestMapping("/select")public ProductInfo selectById(Integer id){return productService.selectById(id);}
}

测试
在这里插入图片描述

3.4.6 远程调用

需求

订单查询信息时,根据订单里的产品id获取产品的详细信息
在这里插入图片描述

实现

实现思路: order-service服务向product-service发送一个http请求,把得到的返回结果和订单结果融合在一起,返回给调用方.
实现方式: 采用Spring提供的RestTemplate

  1. 定义RestTemplate,并注入IOC容器
@Configuration
public class BeanConfig {@Beanpublic RestTemplate restTemplate(){return new RestTemplate();}
}
  1. 修改order-service中的OrderService和OrderInfo对象(首先需要把ProductInfo对象复制到Product子项目中),给product服务发送http请求,并接收相应的对象.
@Data
public class OrderInfo {public Integer id;public Integer userId;public Integer productId;public Integer num;public Integer price;public Integer deleteFlag;public Date createTime;public Date updateTime;public ProductInfo productInfo;
}
@Service
public class OrderService {@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate RestTemplate restTemplate;public OrderInfo selectOrder(Integer id){OrderInfo orderInfo =  orderMapper.selectOrderById(id);String url = "http://127.0.0.1:9090/product/select?id"+ orderInfo.getProductId();//使用RestTemplate获取相应的对象ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class);orderInfo.setProductInfo(productInfo);return orderInfo;}
}
  1. 测试
    在这里插入图片描述
    以下一篇博客是对RestTemplate的详细解释:
    https://www.cnblogs.com/54chensongxia/p/11414923.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/68156.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mobaxterm内置编辑器中文出现乱码如何解决:直接更换编辑器为本地编辑器

诸神缄默不语-个人CSDN博文目录 使用场景是我需要用mobaxterm通过SSH的方式登录服务器&#xff0c;进入服务器之后我就直接打开代码文件&#xff0c;mobaxterm会直接用内置的编辑器&#xff08;MobaTextEditor&#xff09;打开&#xff0c;但这会导致中文编程乱码。 我一开始是…

机器学习与人工智能的关系

机器学习与人工智能的关系 一、人工智能二、机器学习2.1 机器学习与人工智能的关系2.2 机器学习的本质 三、其他玩艺 曾几何时&#xff0c;人工智能还是个科幻名词&#xff0c;仿佛只属于未来世界。如今&#xff0c;它已经渗透到了我们生活的方方面面&#xff0c;成为顶流。我们…

一些常见的Java面试题及其答案

Java基础 1. Java中的基本数据类型有哪些&#xff1f; 答案&#xff1a;Java中的基本数据类型包括整数类型&#xff08;byte、short、int、long&#xff09;、浮点类型&#xff08;float、double&#xff09;、字符类型&#xff08;char&#xff09;和布尔类型&#xff08;boo…

构建高性能网络服务:从 Socket 原理到 Netty 应用实践

1. 引言 在 Java 网络编程中&#xff0c;Socket 是实现网络通信的基础&#xff08;可以查看我的上一篇博客&#xff09;。它封装了 TCP/IP 协议栈&#xff0c;提供了底层通信的核心能力。而 Netty 是在 Socket 和 NIO 的基础上&#xff0c;进一步封装的高性能、异步事件驱动的…

Docker PG流复制搭建实操

目录标题 制作镜像1. 删除旧的容器2. 创建并配置容器3. 初始化数据库并启动 主库配置参数4. 配置主库5. 修改 postgresql.conf 配置 备库配置参数6. 创建并配置备库容器7. 初始化备库 流复制8. 检查主库复制状态9. 检查备库配置 优化建议问题1&#xff1a;FATAL: using recover…

Elasticsearch 批量导入数据(_bluk方法)

官方API&#xff1a;https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html 建议先看API POST /<索引名>/_bulk 格式要求&#xff1a; POST _bulk { "index" : { "_index" : "test", "_id" : &q…

Active Prompting with Chain-of-Thought for Large Language Models

题目 大型语言模型的思维链主动提示 论文地址&#xff1a;https://arxiv.org/abs/2302.12246 项目地址&#xff1a;https://github.com/shizhediao/active-prompt 摘要 大型语言模型(LLM)规模的不断扩大为各种需要推理的复杂任务带来了涌现能力&#xff0c;例如算术和常识推理…

Windows图形界面(GUI)-QT-C/C++ - QT控件创建管理初始化

公开视频 -> 链接点击跳转公开课程博客首页 -> ​​​链接点击跳转博客主页 目录 控件创建 包含对应控件类型头文件 实例化控件类对象 控件设置 设置父控件 设置窗口标题 设置控件大小 设置控件坐标 设置文本颜色和背景颜色 控件排版 垂直布局 QVBoxLayout …

04、Redis深入数据结构

一、简单动态字符串SDS 无论是Redis中的key还是value&#xff0c;其基础数据类型都是字符串。如&#xff0c;Hash型value的field与value的类型&#xff0c;List型&#xff0c;Set型&#xff0c;ZSet型value的元素的类型等都是字符串。redis没有使用传统C中的字符串而是自定义了…

traceroute原理探究

文章中有截图&#xff0c;看不清的话&#xff0c;可以把浏览器显示比例放大到200%后观看。 linux下traceroute的原理 本文通过抓包观察一下linux下traceroute的原理 环境&#xff1a;一台嵌入式linux设备&#xff0c;内网ip是192.168.186.195&#xff0c;其上有192.168.202.…

无源器件-电容

电容器件的参数 基本概念由中学大学物理或电路分析内容获得&#xff0c;此处不做过多分析。 电容的产量占全球电子元器件产品的40%以上。 单位&#xff1a;法拉 F&#xff1b;1F10^6uF&#xff1b;电路中常见的104电容就是10*10^4pF100nF0.1uF C为电容&#xff0c;Rp为绝缘电…

自动连接校园网wifi脚本实践(自动网页认证)

目录 起因执行步骤分析校园网登录逻辑如何判断当前是否处于未登录状态&#xff1f; 书写代码打包设置开机自动启动 起因 我们一般通过远程控制的方式访问实验室电脑&#xff0c;但是最近实验室老是断电&#xff0c;但重启后也不会自动连接校园网账户认证&#xff0c;远程工具&…

知识图谱抽取分析中,如何做好实体对齐?

在知识图谱抽取分析中&#xff0c;实体对齐是将不同知识图谱中的相同实体映射到同一表示空间的关键步骤。为了做好实体对齐&#xff0c;可以参考以下方法和策略&#xff1a; 基于表示学习的方法&#xff1a; 使用知识图谱嵌入技术&#xff0c;如TransE、GCN等&#xff0c;将实体…

FFmpeg硬件解码

使用FFmpeg进行硬件解码时&#xff0c;通常需要结合FFmpeg的API和硬件加速API&#xff08;如CUDA、VAAPI、DXVA2等&#xff09;。以下是一个简单的C代码示例&#xff0c;展示如何使用FFmpeg进行硬件解码。这个示例使用了CUDA作为硬件加速的后端。 1. 安装FFmpeg和CUDA 确保你…

Python----Python高级(函数基础,形参和实参,参数传递,全局变量和局部变量,匿名函数,递归函数,eval()函数,LEGB规则)

一、函数基础 1.1、函数的用法和底层分析 函数是可重用的程序代码块。 函数的作用&#xff0c;不仅可以实现代码的复用&#xff0c;更能实现代码的一致性。一致性指的是&#xff0c;只要修改函数的代码&#xff0c;则所有调用该函数的地方都能得到体现。 在编写函数时&#xf…

win32汇编环境,窗口程序中对按钮控件常用操作的示例

;运行效果 ;win32汇编环境&#xff0c;窗口程序中对按钮控件常用操作的示例 ;常用的操作&#xff0c;例如创建按钮控件&#xff0c;使其无效&#xff0c;改变文本&#xff0c;得到文本等。 ;将代码复制进radasm软件里&#xff0c;直接就可以编译运行。重点部分加备注。 ;>&g…

支付宝租赁小程序提升租赁行业效率与用户体验

内容概要 在当今数字化的世界里&#xff0c;支付宝租赁小程序的出现构建了一种新的租赁模式&#xff0c;使得用户在使用过程中体验更加流畅。想象一下&#xff0c;你在寻找租赁服务时&#xff0c;不再需要繁琐的流程和冗长的等待&#xff0c;只需通过手机轻松点击几下&#xf…

ffmpeg 编译遇到的坑

makeinfo: error parsing ./doc/t2h.pm: Undefined subroutine &Texinfo::Config::set_from_init_file called at ./doc/t2h.pm line 24. 编译选项添加&#xff1a; --disable-htmlpages

day06_Spark SQL

文章目录 day06_Spark SQL课程笔记一、今日课程内容二、DataFrame详解&#xff08;掌握&#xff09;5.清洗相关的API6.Spark SQL的Shuffle分区设置7.数据写出操作写出到文件写出到数据库 三、Spark SQL的综合案例&#xff08;掌握&#xff09;1、常见DSL代码整理2、电影分析案例…

element-ui dialog弹窗 设置点击空白处不关闭

需求&#xff1a;点击空白处不关闭弹窗 实现&#xff1a;:close-on-click-modal“false” 需求&#xff1a;点击Esc不关闭弹窗 实现&#xff1a;:close-on-press-escape“false” https://blog.csdn.net/qq_33911541/article/details/132708890