1 . 微服务架构
1.1 单体应用架构
优点: 1:部署简单:由于是完整的结构体,可以直接部署在一个服务器上即可。 2:技术单一:项目不需要复杂的技术栈,往往一套熟悉的技术栈就可以完成开发。
缺点: 1:系统启动慢,一个进程包含了所有的业务逻辑,涉及到的启动模块过多,导致系统的启动、重启时间周期过长;
2:系统错误隔离性差、可用性差,任何一个模块的错误均可能造成整个系统的宕机;
3:可伸缩性差:系统的扩容只能只对这个应用进行扩容,无法结合业务模块的特点进行伸缩。
4: 线上问题修复周期长:任何一个线上问题修复需要对整个应用系统进行全面升级。
5: 跨语言程度差
6: 不利于安全管理,所有开发人员都拥有全量代码。
小型项目适合单体应用架构. 比如:OA办公系统。管理类的项目 仓库管理系统。
1.2 微服务应用 大约70%使用
微服务微服务架构是一项在云中部署应用和服务的新技术。大部分围绕微服务的争论都集中在容器或其他技术是否能很好的实施微服务,而红帽说API应该是重点。
微服务可以在“自己的程序”中运行,并通过“轻量级设备与HTTP型API进行沟通”。关键在于该服务可以在自己的程序中运行。通过这一点我们就可以将服务公开与微服务架构(在现有系统中分布一个API)区分开来。在服务公开中,许多服务都可以被内部独立进程所限制。如果其中任何一个服务需要增加某种功能,那么就必须缩小进程范围。在微服务架构中,只需要在特定的某种服务中增加所需功能,而不影响整体进程的架构。
解读微服务特点: 1:微服务是一种==项目架构思想==(风格)
2:微服务架构是一系列小服务的组合(组件化与多服务)
3:任何一个微服务,都是一个独立的进程(独立开发、独立维护、独立部署)
4:轻量级通信http协议(跨语言,跨平台)
5:服务粒度(围绕业务功能拆分---模块拆分【系统管理服务】【日志服务】【焦虑测试】【抑郁测试系统】)
6:去中心化管理(去中心化"地治理技术、去中心化地管理数据)
1.3 微服务架构的优势
1.易于开发和维护 一个微服务只关注一个特定的业务功能,所以它的业务清晰、代码量较少。开发和维护单个微服务相对比较简单,整个应用是由若干个微服务构建而成,所以整个应用也会维持在可控状态;
⒉.单个微服务启动较快 单个微服务代码量较少,所以启动会比较快;
3.局部修改容易部署 单体应用只要有修改,就要重新部署整个应用,微服务解决了这样的问题。一般来说,对某个微服务进行修改,只需要重新部署这个服务即可;
4.技术栈不受限 在微服务中,我们可以结合项目业务及团队的特点,合理地选择技术栈
5.按需伸缩
焦虑系统访问量大,只需要对焦虑系统进行扩展
1.4:微服务架构的缺点(挑战)
1、服务太多,导致服务间的依赖错综复杂,运维难度大
2、微服务放大了分布式架构的系列问题
-
分布式事务(seata)
-
分布式锁怎么处理(redisson) ,
-
服务注册与发现(nacos) .
-
依赖服务不稳定(sentinel)导致服务雪崩怎么办?
3、运维复杂度陡增,部署数量多、监控进程多导致整体运维复杂度提升。
springcloud来解决上面微服务面临的挑战
1.5. SpringCloud与微服务关系
-
Springcloud为微服务思想提供了完美的解决方案
-
Springcloud是一些列框架的集合体(服务的注册与发现【注册中心】、服务间远程调用、服务降级、服务熔断、服务限流、分布式事务等)
一般我们说springc1oud 其实指的是Springc1oud-netflix,Springcloud并不是造轮子,只是把Netflix公司的组件做二次开发。
1.6 . SpringBoot和SpringCloud关系
-
SpringBoot专注于快速方便的开发单个个体微服务。
-
SpringCloud是关注全局的微服务协调、整理、治理的框架,它将SpringBoot开发的单体整合并管理起来。
-
SpringBoot可以离开SpringCloud独立使用开发项目,但是SpringCloud离不开SpringBoot,属于依赖关系。
2. 创建微服务工程
2.1 创建一个父工程
(1)依赖
<?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.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.12.RELEASE</version>
</parent>
<groupId>com.aaa</groupId>
<artifactId>qy163-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<!--父工程那么它的打包方式必须为pom打包-->
<packaging>pom</packaging>
<!--定义版本号-->
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-cloud.version>Hoxton.SR8</spring-cloud.version>
<spring-cloud-alibaba.version>2.2.3.RELEASE</spring-cloud-alibaba.version>
</properties>
<dependencyManagement>
<!--管理了cloud版本-->
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--alibaba的版本-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
src:可以删除
package:改成pom打包
2.2 公共模块
(1)依赖
<?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>qy163-parent</artifactId>
<groupId>com.aaa</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springcloud-common</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.56</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
</dependencies>
</project>
(2)
product实体类
@Data
@TableName(value = "shop_product")
public class Product {
@TableId(value = "pid",type = IdType.AUTO)
private Integer pid;
private String pname;
//小数必须使用 BigDecimal类型
private BigDecimal pprice;
private Integer stock;
}
order 实体类
@Data
@TableName(value = "shop_order")
public class Order {
@TableId(value = "oid",type = IdType.AUTO)
private Integer oid;
private Integer uid;
private String username;
private Integer pid;
private String pname;
private BigDecimal pprice;
private Integer number;
}
2.3 创建 product商品微服务
(1) 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">
<parent>
<artifactId>qy163-parent</artifactId>
<groupId>com.aaa</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-product</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.aaa</groupId>
<artifactId>springcloud-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.aaa</groupId>
<artifactId>springcloud-common</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
(2)配置文件
#???:8080~8089 []
server.port=8080
#???
spring.datasource.url=jdbc:mysql://localhost:3306/spring_cloud?serverTimezone=Asia/Shanghai
spring.datasource.password=abc123
spring.datasource.username=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#??sql??
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
(3) 主启动类 ProductApp
@SpringBootApplication
@MapperScan(basePackages = "com.dxh.product.dao")
public class ProductApp {
public static void main(String[] args) {
SpringApplication.run (ProductApp.class, args);
}
}
(4) dao层
public interface ProductDao extends BaseMapper<Product> {
}
(5) service 层
public interface ProductService {
public Product selectById(Integer pid);
}
@Service
public class ProductServiceImpl implements ProductService {
@Resource
private ProductDao productDao;
public Product selectById(Integer pid){
return productDao.selectById (pid);
}
}
(6)controller 层
@RestController
@RequestMapping("product")
public class ProductController {
@Resource
private ProductService productService;
@GetMapping("getById/{pid}")
public Product selectById(@PathVariable Integer pid){
return productService.selectById (pid);
}
}
进行 测试 :
2.4 创建 order订单微服务
(1) 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">
<parent>
<artifactId>qy163-parent</artifactId>
<groupId>com.aaa</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-order</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.aaa</groupId>
<artifactId>springcloud-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.aaa</groupId>
<artifactId>springcloud-common</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
(2) 配置文件
#???:8090~8099 []
server.port=8091
#???
spring.datasource.url=jdbc:mysql://localhost:3306/spring_cloud?serverTimezone=Asia/Shanghai
spring.datasource.password=abc123
spring.datasource.username=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#??sql??
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
(3) 主启动类
/**
* @program: springcloud_02
* @author: ♥丁新华
* @create: 2023-05-13 00:03
**/
@SpringBootApplication
@MapperScan(basePackages = "com.dxh.order.dao")
public class OrderApp {
public static void main(String[] args) {
SpringApplication.run (OrderApp.class,args);
}
//注入resttemplate
@Bean
public RestTemplate restTemplate(){
return new RestTemplate ();
}
}
(4) dao层
public interface OrderDao extends BaseMapper<Order> {
}
(5) service层
public interface OrderService {
public Integer save(Order order);
}
@Service
public class OrderServiceImpl implements OrderService {
@Resource
private OrderDao orderDao;
@Override
public Integer save(Order order) {
return orderDao.insert (order);
}
}
(6) controller层
package com.dxh.order.controller;
import com.dxh.order.service.OrderService;
import om.dxh.pojo.Order;
import om.dxh.pojo.Product;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
/**
* @program: springcloud_02
* @author: ♥丁新华
* @create: 2023-05-13 00:12
**/
@RestController
@RequestMapping("order")
public class OrderController {
@Resource
private OrderService orderService;
@Resource
private RestTemplate restTemplate;
@GetMapping("save")
public String save(Integer pid, Integer num){
Order order = new Order ();
order.setUid (1);
order.setUsername ("阿林");
order.setNumber (num);
Product product = restTemplate.getForObject ("http://localhost:8081/product/getById/" + pid,Product.class);
//判断
if (product==null){
return "订单失败";
}
order.setPid (product.getPid ());
order.setPname (product.getPname ());
order.setPprice (product.getPprice ());
orderService.save (order);
return "订单成功";
}
}
测试 :
3. 服务治理
思考 :
通过上一章的操作,我们已经可以实现微服务之间的调用。但是我们把服务提供者的网络地址
(ip,端口)等硬编码到了代码中,这种做法存在许多问题:
l 一旦服务提供者地址变化,就需要手工修改代码
l 一旦是多个服务提供者,无法实现负载均衡功能
l 一旦服务变得越来越多,人工维护==调用关系==困难
那么应该怎么解决呢, 这时候就需要通过注册中心动态的实现服务治理。
什么时服务治理:
服务治理可以说是微服务中最为核心和基础的模块,主要来实现各个微服务的自动化注册和发现。
服务治理都围绕着服务注册和服务发现机制来完成对微服务应用实例的自动化管理。
- 服务注册:在服务治理框架中,通常都会构建一个注册中心,每个服务单元向注册中心登记自己提供的服务,将主机、端口号 、版本号、通信协议等一些附加信息告知注册中心。服务注册中心还需要以心跳的方式去检测清单中的服务是否可用,若不可用要从清单中剔除。
- 服务发现:由于服务治理框架的运作,服务间的调用不再通过指定具体的实例地址来实现,而是向服务注册中心咨询服务,并获取所有服务的实例清单,以实现对具体服务实例的访问。注意:仅仅是获取服务实例清单,具体选择哪个服务是Ribbon去负责服务消费。
3.1 常见服务治理组件
eureka: 它是netflix公司提供的一款组件,这款组件已经停止更新。
nacos: 它是阿里巴巴提供的一款服务治理组件。 主流
zookeeper: 它是apache公司提供的服务治理组件。
consul: 服务治理的组件
3.2 安装nacos治理组件
修改startup.cmd
双击运行startup.cmd
访问:
账号和密码:
nacos/nacos
3.3 微服务注册到注册中心
(1) 引入nacos的依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
(2)修改配置文件
#zhuce zhongxin dizhi
spring.cloud.nacos.discovery.server-addr=localhost:8848
#qi ming
spring.application.name=qy163.product
(3) 修改订单微服务的代码
package com.dxh.order.controller;
import com.dxh.order.service.OrderService;
import com.dxh.pojo.Order;
import com.dxh.pojo.Product;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import java.util.List;
/**
* @program: springCloud
* @author: ♥丁新华
* @create: 2023-05-12 17:44
**/
@RestController
@RequestMapping("order")
public class OrderController {
@Resource
private OrderService orderService;
@Resource
private RestTemplate restTemplate;
@Resource
private DiscoveryClient discoveryClient;
@GetMapping("save")
public String Save(Integer pid,Integer num){
Order order = new Order ();
order.setUid (1);
order.setUsername ("王建");
order.setNumber (num);
//获取注册中心指定清单列表
List<ServiceInstance> instances = discoveryClient.getInstances ("qy163-product");
//获取第一个
ServiceInstance serviceInstance = instances.get (0);
String path = serviceInstance.getUri ().toString ();
//商品信息的设置: 远程调用商品微服务的接口。 基于Http协议进行远程调用。
//两种基于http调用的方式: 第一种: 可以使用httclient工具jar 自己封装工具类
// 第二种方式: spring框架中提供了一个工具类。RestTemplate.
Product product = restTemplate.getForObject (path + "/product/getById/"+pid, Product.class);
if (product == null){
return "下单失败";
}
order.setPid (product.getPid ());
order.setPname (product.getPname ());
order.setPprice (product.getPprice ());
orderService.Save (order);
if (product.getStock () >= num){
return "下单成功";
}else {
return "下单失败";
}
}
}
测试 :
4. 实现负载均衡
4.1 什么是负载均衡
通俗的讲, 负载均衡就是将负载(工作任务,访问请求)进行分摊到多个操作单元(服务器,组件)上进行执行。
可以手动完成负载均衡。
在网站创立初期,我们一般都使用单台机器对台提供集中式服务,但随着业务量越来越大,无论性能还是稳定性上都有了更大的挑战。这时候我们就会想到通过扩容的方式来提供更好的服务。我们一般会把多台机器组成一个集群对外提供服务。然而,我们的网站对外提供的访问入口都是一个的,比如http://www.taobao.com。那么当用户在浏览器输入http://www.taobao.com的时候如何将用户的请求分发到集群中不同的机器上呢,这就是负载均衡在做的事情。
软件负载解决的两个核心问题是:选谁、转发,其中最著名的是LVS(Linux Virtual Server)
修改Order调用方
4.2 使用ribbon完成负载均衡
---思考: 上面的负载均衡,是不是自己写的代码。缺点: 代码比较复杂。 如果想改变复杂均衡的策略,必须都是修改order的代码。
什么是ribbon :
Ribbon是一套客户端负载均衡工具,供一系列的完善的配置,如超时,重试等。通过Load Balancer获取到服务提供的所有机器实例, Ribbon会自动基于某种规则(轮询,随机)去调用这些服务。Ribbon也可以实现我们自己的负载均衡算法。
使用ribbon:
(1)再RestTemplate类上加个注解@LoadBalance
(2)修改controller层代码
package com.dxh.order.controller;
import com.dxh.order.service.OrderService;
import com.dxh.pojo.Order;
import com.dxh.pojo.Product;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import java.util.List;
import java.util.Random;
/**
* @program: springCloud
* @author: ♥丁新华
* @create: 2023-05-12 17:44
**/
@RestController
@RequestMapping("order")
public class OrderController {
@Resource
private OrderService orderService;
@Resource
private RestTemplate restTemplate;
/* @Resource
private DiscoveryClient discoveryClient;*/
@GetMapping("save")
public String Save(Integer pid,Integer num){
Order order = new Order ();
order.setUid (1);
order.setUsername ("王建");
order.setNumber (num);
/*//获取注册中心指定清单列表
List<ServiceInstance> instances = discoveryClient.getInstances ("qy163-product01");
//随机负载均衡
int i = new Random ().nextInt (instances.size ());
ServiceInstance serviceInstance = instances.get (i);
String path = serviceInstance.getUri ().toString ();*/
//商品信息的设置: 远程调用商品微服务的接口。 基于Http协议进行远程调用。
//两种基于http调用的方式: 第一种: 可以使用httclient工具jar 自己封装工具类
// 第二种方式: spring框架中提供了一个工具类。RestTemplate.
Product product = restTemplate.getForObject ("http://qy163-project01/product/getById/"+pid, Product.class);
if (product == null){
return "下单失败";
}
order.setPid (product.getPid ());
order.setPname (product.getPname ());
order.setPprice (product.getPprice ());
orderService.Save (order);
if (product.getStock () >= num){
return "下单成功";
}else {
return "下单失败";
}
}
}
演示: ribbon默认采用的是轮询策略。 是否可以修改负载均衡策略
ribbon内置的负载均衡策略
Ribbon内置了多种负载均衡策略,内部负载均衡的顶级接口为 com.netflix.loadbalancer.IRule , 具体的负载策略如下图所示:
如何改变ribbon的负载均衡策略
修改order的配置文件
使用ribbon完成了从nacos自动拉取服务,并完成负载均衡功能。
5. 使用Openfeign完成远程调用
上面服务之间的调用 使用的是RestTemplate. 使用Resttemplate远程调用,它不符合我们的编程习惯。Controller---Service---Dao 再Controller注入一个service对象,然后调用service中的方法,根据方法传递相应的参数以及接受方法的返回的结果。
我们可以使用Openfeign组件来完成。
什么是OpenFeign:
- Feign是一个声明式的web服务客户端,让编写web服务客户端变得非常容易
- 只需创建一个接口并在接口上添加注解即可
Feign旨在使编写Java Http客户端变得更容易
前面在使用Ribbon+RestTemplate时,利用RestTemplate对http请求的封装处理,形成了一套模板化的调用方法。但是在实际开发中,由于对服务依赖的调用可能不止一处,往往一个接口会被多处调用,所以通常都会针对每个微服务自行封装一些客户端类来包装这些依赖服务的调用。所以,Feign在此基础上做了进一步封装,由它来帮助我们定义和实现依赖服务接口的定义。在Feign的实现下,我们只需要创建一个接口并使用注解的方式来配置它(以前是Dao接口上面标注Mapper注解,现在是一个微服务接口上面标注一个Feign即可),即可完成对服务提供方的接口绑定,简化了使用Spring Cloud Ribbon时,自动封装服务调用客户端的开发量
Feign集成了Ribbon,通过feign只需要定义服务绑定接口并且以声明式的方法,优雅而简单的实现了服务调用
Feign和OpenFeign的区别
Feign是Spring Cloud组件中的一个轻量级RESTful的HTTP服务客户端,Feign内置了Ribbon,用来做客户端负载均衡,去调用服务注册中心的服务。Feign的使用方式是:使用Feign的注解定义接口,调用这个接口,就可以调用服务注册中心的服务
OpenFeign是Spring Cloud在Feign的基础上支持了SpringMVC的注解,如@RequestMaping等等。OpenFeign的@FeignClient可以解析SpringMVC的@RequestMaping注解下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务
5.2 如何使用openfeign
(1 )导入依赖
<!--openfeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
(2)定义接口并添加@FeignClient(value="服务提供者的名")注解
@FeignClient(value = "qy163-product01")
public interface ProductFeign {
@GetMapping("/product/getById/{pid}")
public Product getById(@PathVariable Integer pid);
}
(3)再主启动类开启openfeign注解驱动
(4)再使用的类中注入Openfeign注解
package com.dxh.order.controller;
import com.dxh.order.feign.ProductFeign;
import com.dxh.order.service.OrderService;
import com.dxh.pojo.Order;
import com.dxh.pojo.Product;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import java.util.List;
import java.util.Random;
/**
* @program: springCloud
* @author: ♥丁新华
* @create: 2023-05-12 17:44
**/
@RestController
@RequestMapping("order")
public class OrderController {
@Resource
private OrderService orderService;
@Resource
//注入openfeign接口
private ProductFeign productFeign;
/* @Resource
private DiscoveryClient discoveryClient;*/
@GetMapping("save")
public String Save(Integer pid,Integer num){
Order order = new Order ();
order.setUid (1);
order.setUsername ("王建");
order.setNumber (num);
//商品信息的设置: 远程调用商品微服务的接口。 基于Http协议进行远程调用。
//两种基于http调用的方式: 第一种: 可以使用httclient工具jar 自己封装工具类
// 第二种方式: spring框架中提供了一个工具类。RestTemplate.
Product product = productFeign.getById (pid);
if (product == null){
return "下单失败";
}
order.setPid (product.getPid ());
order.setPname (product.getPname ());
order.setPprice (product.getPprice ());
orderService.Save (order);
if (product.getStock () >= num){
return "下单成功";
}else {
return "下单失败";
}
}
}