当前位置: 首页 > news >正文

spring-cloud微服务openfeign

Spring Cloud openfeign对Feign进行了增强,使其支持Spring MVC注解,另外还整合了Ribbon和Nacos,从而使得Feign的使用更加方便

优势,openfeign可以做到使用HTTP请求远程服务时就像洞用本地方法一样的体验,开发者完全感知不到这是远程方法,更感知不到这是个 http请求,它像 Dubbo一样,consumer 直接洞用接口方法调用 povider,,而不需要通过常规的 Htp Client构造请求再解析返回数据。它解决了让开发者调用远程接口就跟调用本地方法一样,无需关注与远程的交互细节,更无需关注分布式环境开发

pom导入依赖

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

在bootstrap.yml中增加OpenFeign对Sentinel的支持,增加feign.sentinel.enabled配置项

server:port: 9001
spring:application:name: consumer # 应用名cloud:nacos:discovery:server-addr: localhost:8848 # nacos服务地址sentinel:transport:port: 8719 # 启动http server,并且该服务与Sentinel仪表板进行交互,使sentinel可以控制应用,若端口占用则8719+1依次扫描dashboard: 127.0.0.1:8080 # 仪表版访问地址
feign:	# 增加对sentinel的支持sentinel:enabled: true

这里说一下如果不加feign.sentinel.enabled=true的配置,那么在@FeignClient中定的fallback属性定义的异常、限流等自定义的处理逻辑不会生效

将FeignClient抽取为独立模块,并且把接口有关的POJO(实体类)、默认的Feign配置都放到这个模块中,提供给所有消费者使用,将其做成公共模块,其他服务只需要依赖该jar包

在主启动类上加入@EnableFeignClients注解,标记为启用OpenFeign,具体如下:

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class OrderNacosApplication{public static void main(String[] args) {SpringApplication.run(OrderNacosApplication.class, args);}
}

假如是分布式项目,将openfeign抽取为一个单独的服务模块时,可能出现我openfeign中的包名和其他模块不一致,可以自己声明FeignClient组件的basePackages设置一下FeignClient的扫描路径。示例如下:

@SpringBootApplication
@EnableDiscoveryClient
//这种方式是精准打击,只拿指定的类
//@EnableFeignClients(clients = {UserDemo.class})
//这种方式会将指定包下的所有东西都拿过来
@EnableFeignClients(basePackages = "com.alibaba.provider.feigns")
public class OrderNacosApplication{public static void main(String[] args) {SpringApplication.run(OrderNacosApplication.class, args);}
}

OpenFeign的超时配置

Ps:OpenFeign早期版本(例如 2020版本以前 )要求服务提供方在1秒内处理业务逻辑并返回响应。如果超过1秒没有返回,OpenFeign会直接报错,不会等待服务执行。随着版本的更新,OpenFeign已经对此做出了调整或优化(例如 2021.0.1)

方法一:修改超时时间:在远程调用方的 application.yml 中配置,指定某个服务提供方的调用超时时间

feign:client:config:product-service: # 服务名connect-timeout: 5000 # 配置指定服务连接超时时间read-timeout: 5000 # 配置指定服务等待超时时间stock-nacos: # 服务名connect-timeout: 5000 # 配置指定服务连接超时时间read-timeout: 5000 # 配置指定服务等待超时时间

在远程调用方的 application.yml 中配置,指定所有服务提供方的调用超时时间

feign:client:config:default: # 所有服务connect-timeout: 5000 # 配置指定服务连接超时时间read-timeout: 5000 # 配置指定服务等待超时时间

方法二;配置类

package com.test.order.config;import feign.Request;
import org.springframework.context.annotation.Bean;/*** @Description:* @Author: xu* @Data: 2024-2024/4/10-21* @Version: V1.0*///@Configuration
//注意: 此处配置@configuration注解就会全局生效,如果想指定对应微服务生效,就不能配置
public class FeignTimeOutConfig {@Beanpublic Request.Options options() {return new Request.Options(5000, 10800);}
}

OpenFeign日志有以下几个级别

  • NONE:无记录,默认的
  • BASIC:只记录请求方法和url及响应状态代码和执行时间
  • HEADERS:只记录基本信息及请求和响应头
  • FULL:记录请求和响应的头文件,正文和元数据,信息最全

方法一:配置文件方式设置OpenFeign日志(要查看openfeign日记设置开启openfeign日记和设置feign配置日记级别缺一不可)(推荐)

#开启 openfeign 日志
logging:level:com.test.order.feign: debug  #这样打印的就只有openfeign的debug日记#全局生效
feign:client:config:default: # 所有服务生效logger-level: FULL
#局部生效
feign:client:config:product-service:  #服务名logger-level: basicstock-nacos:      #服务名logger-level: full

如果配置类设置,配置文件也设置,谁设置全局就是日记级别

方法二:java代码方式设置OpenFeign日志

package com.test.order.config;import feign.Logger;
import org.springframework.context.annotation.Bean;/*** @Description:* @Author: xu* @Data: 2024-2024/4/10-17* @Version: V1.0*/
//@Configuration
//注意: 此处配置@configuration注解就会全局生效,如果想指定对应微服务生效,就不能配置
public class FeignClientConfiguration {@Beanpublic Logger.Level feignLogLevel(){return Logger.Level.FULL;  //一般使用 BASIC 级别,因为太多的日志信息影响效率}
}

在这里插入图片描述

全局设置OpenFeign日志级别(如果FeignClientConfiguration类加了注解@Configuration就无需设置以下的defaultConfiguration 属性)

@EnableFeignClients(defaultConfiguration = FeignClientConfiguration.class) 

指定服务,设置OpenFeign日志级别(如果FeignClientConfiguration类加了注解@Configuration就无需设置以下的configuration 属性)

@FeignClient(value = "stock-nacos",path = "/stock",configuration = {FeignClientConfiguration.class})
public interface StockFeignService {@RequestMapping("/reduce")String reduce();}

Feign 的性能优化:

Feign 的底层客户端实现:

  • URLConnection:默认实现,不支持连接池
  • Apache HttpClient :支持连接池
  • OKHttp:支持连接池

因此优化Feign的性能主要包括:

  • 使用连接池代替默认的URLConnection
  • 日志级别,最好用basic或none
  • 因此使用 HttpClient 或 OKHttp 代替 URLConnection

引入依赖

<!--httpClient的依赖 -->
<dependency><groupId>io.github.openfeign</groupId><artifactId>feign-httpclient</artifactId>
</dependency>

配置连接池

feign:client:config:default: # default全局的配置loggerLevel: BASIC # 日志级别,BASIC就是基本的请求和响应信息 httpclient:enabled: true # 开启feign对HttpClient的支持max-connections: 200 # 最大的连接数max-connections-per-route: 50 # 每个路径的最大连接数

实现负载均衡,OpenFeign也具有负载均衡的功能,多个服务端时,采用对应的算法寻找一个服务端进行请求

具体的添加@LoadBalancerClient注解:在调用服务的Service类上添加@LoadBalancerClient注解,并指定服务名。这样,负载均衡器将根据配置的属性来选择合适的服务实例进行调用。例如

/**
* name:指定调用rest接口所对应的服务名
* path 指定调用rest接口所在的stockController指定的eRequestMapping
* 类上无需添加@Component注解
*/
@FeignClient(value = "stock-nacos", path = "/stock") 
public interface StockFeignService{  @RequestMapping("/reduce")String reduce();
}
package com.test.order.config;import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.loadbalancer.core.RandomLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;public class CustomLoadBalancerConfiguration {@BeanReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,LoadBalancerClientFactory loadBalancerClientFactory) {String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);return new RandomLoadBalancer(loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class),name);}}

在你提供的代码示例中,CustomLoadBalancerConfiguration 类并没有标记 @Configuration 注解,但它仍然可以作为一个配置类,并且被 @LoadBalancerClients 注解指定的负载均衡客户端所引用。这是因为 Spring Cloud 在处理 @LoadBalancerClients 注解时会扫描指定的配置类,并且将其中的 @Bean 方法注册为 bean。因此,虽然 CustomLoadBalancerConfiguration 类没有标记 @Configuration 注解,但它仍然被识别为一个配置类,并且其中的 @Bean 方法会被注册为 bean。这样做的好处是,你可以将负载均衡的配置与负载均衡客户端的注册分开,使得代码更加清晰和模块化。

package com.test.order;import com.test.order.config.CustomLoadBalancerConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients;
import org.springframework.cloud.openfeign.EnableFeignClients;/*** @Description:* @Author: xu* @Data: 2024-2024/3/29-16* @Version: V1.0*/
@SpringBootApplication
@EnableFeignClients
@LoadBalancerClients({@LoadBalancerClient(value = "stock-nacos", configuration = {CustomLoadBalancerConfiguration.class})})
public class OrderOpenFeignApplication {public static void main(String[] args) {SpringApplication.run(OrderOpenFeignApplication.class, args);}
}

修改契约配置,支持Feign原生的注解(注意:修改契约配置后,OrderFeignService 不再支持springmvc的注解,需要使用Feign原生的注解)

package com.test.order.config;import feign.Contract;
import org.springframework.context.annotation.Bean;/*** @Description:* @Author: xu* @Data: 2024-2024/4/10-21* @Version: V1.0*/@Component不要使用该注解,会变成全局
public class ContractConfig {@Beanpublic Contract feigncontract() {return new Contract.Default();}
}

方法一:局部配置那个服务使用锲约


@FeignClient(value = "stock-nacos", path = "/stock" ,configuration = {ContractConfig.class})
public interface StockFeignService {@RequestLine("GET /reduce")String reduce();}

方法二:配置文件设置指定服务使用锲约

#局部生效
feign:client:config:product-service:logger-level: basicstock-nacos:logger-level: fullcontract: feign.Contract.Default  #指定Feign原生注解契约配置

openfeign拦截器

定义openfeign拦截器继承RequestInterceptor 接口

package com.test.order.interceptor;import feign.RequestInterceptor;
import feign.RequestTemplate;/*** @Description:* @Author: xu* @Data: 2024-2024/4/10-21* @Version: V1.0*/
public class CustomFeignAuthRequestInterceptor implements RequestInterceptor {@Overridepublic void apply(RequestTemplate requestTemplate) {System.out.println("openfeign拦截器执行了");requestTemplate.header("token","888");}
}

方法一:使用配置类实现openfeign的拦截器

package com.test.order.config;import com.test.order.interceptor.CustomFeignAuthRequestInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** @Description:* @Author: xu* @Data: 2024-2024/4/10-21* @Version: V1.0*/
//@Configuration
//注意: 此处配置@configuration注解就会全局生效,如果想指定对应微服务生效,就不能配置
public class FeignInterceptorConfig {@Beanpublic CustomFeignAuthRequestInterceptor feignAuthRequestInterceptor(){return new CustomFeignAuthRequestInterceptor();}
}

全局设置OpenFeign拦截器(如果FeignClientConfiguration类加了注解@Configuration就无需设置以下的defaultConfiguration 属性)

@EnableFeignClients(defaultConfiguration = FeignInterceptorConfig .class) 

指定服务,设置OpenFeign拦截器(如果FeignInterceptorConfig 类加了注解@Configuration就无需设置以下的configuration 属性)

@FeignClient(value = "stock-nacos",path = "/stock",configuration = {FeignInterceptorConfig .class})
public interface StockFeignService {@RequestMapping("/reduce")String reduce();}

方法二:配置文件的yml实现openfeign的拦截器

feign:client:config:stock-nacos:request-interceptors:- com.test.order.interceptor.CustomFeignAuthRequestInterceptor

相关文章:

spring-cloud微服务openfeign

Spring Cloud openfeign对Feign进行了增强&#xff0c;使其支持Spring MVC注解&#xff0c;另外还整合了Ribbon和Nacos&#xff0c;从而使得Feign的使用更加方便 优势&#xff0c;openfeign可以做到使用HTTP请求远程服务时就像洞用本地方法一样的体验&#xff0c;开发者完全感…...

小程序变更主体需要多久?

小程序迁移变更主体有什么作用&#xff1f;小程序迁移变更主体的好处有很多哦&#xff01;比如可以获得更多权限功能、公司变更或注销时可以保证账号的正常使用、收购账号后可以改变归属权或使用权等等。小程序迁移变更主体的条件有哪些&#xff1f;1、新主体必须是企业主体&am…...

19 Games101 - 笔记 - 相机与透镜

**19 ** 相机与透镜 目录 摘要一 照相机主要部分二 小孔成像与视场(FOV)三 曝光(Exposure)四 景深(Depth of Field)总结 摘要 虽说照相机与透镜属于相对独立的话题&#xff0c;但它们的确是计算机图形学当中的一部分知识。在过往的十多篇笔记中&#xff0c;我们学习的都是如…...

Flink入门学习 | 大数据技术

⭐简单说两句⭐ ✨ 正在努力的小新~ &#x1f496; 超级爱分享&#xff0c;分享各种有趣干货&#xff01; &#x1f469;‍&#x1f4bb; 提供&#xff1a;模拟面试 | 简历诊断 | 独家简历模板 &#x1f308; 感谢关注&#xff0c;关注了你就是我的超级粉丝啦&#xff01; &…...

Arthas实战教程:定位Java应用CPU过高与线程死锁

引言 在Java应用开发中&#xff0c;我们可能会遇到CPU占用过高和线程死锁的问题。本文将介绍如何使用Arthas工具快速定位这些问题。 准备工作 首先&#xff0c;我们创建一个简单的Java应用&#xff0c;模拟CPU过高和线程死锁的情况。在这个示例中&#xff0c;我们将编写一个…...

HTML制作跳动的心形网页

作为一名码农 也有自己浪漫的小心思嗷~ 该网页 代码整体难度不大 操作性较强 祝大家都幸福hhhhh 效果成品&#xff1a; 全部代码&#xff1a; <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML><HEAD><TITLE> 一个…...

如何在Odoo 17 销售应用中使用产品目录添加产品

Odoo&#xff0c;作为一个知名的开源ERP系统&#xff0c;发布了其第17版&#xff0c;新增了多项功能和特性。Odoo 17包中的一些操作简化了&#xff0c;生产力提高了&#xff0c;用户体验也有了显著改善。为了为其用户提供新的和改进的功能&#xff0c;Odoo不断进行改进和增加新…...

为什么pdf拆分出几页之后大小几乎没有变化

PDF 文件的大小在拆分出几页之后几乎没有变化可能有几个原因&#xff1a; 图像压缩: 如果 PDF 文件中包含图像&#xff0c;而这些图像已经被压缩过&#xff0c;拆分后的页面依然会保留这些压缩设置&#xff0c;因此文件大小可能不会显著变化。 文本和矢量图形: PDF 文件中的文…...

如何在 VM 虚拟机中安装 OpenEuler 操作系统保姆级教程(附链接)

一、VMware Workstation 虚拟机 若没有安装虚拟机的可以参考下篇文章进行安装&#xff1a; 博客链接https://eclecticism.blog.csdn.net/article/details/135713915 二、OpenEuler 镜像 点击链接前往官网 官网 选择第一个即可 三、安装 OpenEuler 打开虚拟机安装 Ctrl …...

(六)PostgreSQL的组织结构(3)-默认角色和schema

PostgreSQL的组织结构(3)-默认角色和schema 基础信息 OS版本&#xff1a;Red Hat Enterprise Linux Server release 7.9 (Maipo) DB版本&#xff1a;16.2 pg软件目录&#xff1a;/home/pg16/soft pg数据目录&#xff1a;/home/pg16/data 端口&#xff1a;57771 默认角色 Post…...

DockerFile定制镜像

dockerfile 简介 Dockerfile 是⼀个⽤来构建镜像的⽂本⽂件&#xff0c;⽂本内容包含了⼀条条构建镜像所需的指令和 说明&#xff0c;每条指令构建⼀层&#xff0c;最终构建出⼀个新的镜像。 docker镜像的本质是⼀个分层的⽂件系统 centos的iso镜像⽂件是包含bootfs和rootfs…...

Java8中JUC包同步工具类深度解析(Semaphore,CountDownLatch,CyclicBarrier,Phaser)

个人主页&#xff1a; 进朱者赤 阿里非典型程序员一枚 &#xff0c;记录平平无奇程序员在大厂的打怪升级之路。 一起学习Java、大数据、数据结构算法&#xff08;公众号同名&#xff09; 引言 在Java中&#xff0c;并发编程一直是一个重要的领域&#xff0c;而JDK 8中的java.u…...

岛屿个数(dfs)

[第十四届蓝桥杯省B 岛屿个数] 小蓝得到了一副大小为 M N MN MN 的格子地图&#xff0c;可以将其视作一个只包含字符 0 0 0&#xff08;代表海水&#xff09;和 1 1 1&#xff08;代表陆地&#xff09;的二维数组&#xff0c;地图之外可以视作全部是海水&#xff0c;每个岛…...

【C++造神计划】运算符

1 赋值运算符 赋值运算符的功能是将一个值赋给一个变量 int a 5; // 将整数 5 赋给变量 a 运算符左边的部分叫作 lvalue&#xff08;left value&#xff09;&#xff0c;右边的部分叫作 rvalue&#xff08;right value&#xff09; 左边 lvalue 必须是一个变量 右边 rval…...

Cortex-M3/M4处理器的bit-band(位带)技术

ARM Cortex-M3/M4的位带&#xff08;Bit-Band&#xff09;技术是一种内存映射技术&#xff0c;它允许对单个位进行直接操作&#xff0c;而不需要对整个字&#xff08;通常是32位&#xff09;进行操作。这项技术主要用于对特定的位进行高效的读写&#xff0c;特别是在需要对GPIO…...

【TOP】IEEE旗下1区,影响因子将破8,3个月录用,CCF推荐,性价比高!

计算机类 ● 好刊解读 IEEE出版社、中科院2区TOP&#xff0c;CCF推荐&#xff0c;今天推荐的期刊可谓buff叠满&#xff0c;好刊质量靠谱&#xff0c;有意向评职晋升毕业作者可重点关注&#xff1a; 01 期刊简介 ✅出版社&#xff1a;IEEE ✅影响因子&#xff1a;7.5-8.0 ✅…...

赚钱游戏 2.0.1 版 (资源免费)

没有c编辑器的可以直接获取资源来玩 #include <iostream> #include <string> #include <windows.h> #include <conio.h> #include <fstream> #include <ctime> #include <time.h> #include <stdio.h> #include <cstring&g…...

服务调用-微服务小白入门(4)

背景 各个服务应用&#xff0c;有很多restful api&#xff0c;不论是用哪种方式发布&#xff0c;部署&#xff0c;注册&#xff0c;发现&#xff0c;有很多场景需要各个微服务之间进行服务的调用&#xff0c;大多时候返回的json格式响应数据多&#xff0c;如果是前端直接调用倒…...

代码随想录算法训练营第三十六天| 435. 无重叠区间、 763.划分字母区间、56. 合并区间

435 题目&#xff1a; 给定一个区间的集合 intervals &#xff0c;其中 intervals[i] [starti, endi] 。返回 需要移除区间的最小数量&#xff0c;使剩余区间互不重叠 。 题目链接&#xff1a;435. 无重叠区间 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; …...

【AIGC调研系列】rerank3是什么

Rerank 3是一个针对企业搜索和检索辅助生成&#xff08;RAG&#xff09;系统优化的新型基础模型&#xff0c;它支持多语种、多结构数据搜索&#xff0c;并提供高精度的语义重排。通过这种方式&#xff0c;Rerank 3能够大幅提升响应准确度和降低延迟&#xff0c;同时大幅降低成本…...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 &#xff09;⽤户级环境变量与系统级环境变量 全局属性&#xff1a;环境变量具有全局属性&#xff0c;会被⼦进程继承。例如当bash启动⼦进程时&#xff0c;环 境变量会⾃动传递给⼦进程。 本地变量限制&#xff1a;本地变量只在当前进程(ba…...

React第五十七节 Router中RouterProvider使用详解及注意事项

前言 在 React Router v6.4 中&#xff0c;RouterProvider 是一个核心组件&#xff0c;用于提供基于数据路由&#xff08;data routers&#xff09;的新型路由方案。 它替代了传统的 <BrowserRouter>&#xff0c;支持更强大的数据加载和操作功能&#xff08;如 loader 和…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

LLM基础1_语言模型如何处理文本

基于GitHub项目&#xff1a;https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken&#xff1a;OpenAI开发的专业"分词器" torch&#xff1a;Facebook开发的强力计算引擎&#xff0c;相当于超级计算器 理解词嵌入&#xff1a;给词语画"…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包

文章目录 现象&#xff1a;mysql已经安装&#xff0c;但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时&#xff0c;可能是因为以下几个原因&#xff1a;1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

在Ubuntu24上采用Wine打开SourceInsight

1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器

拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件&#xff1a; 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...

6个月Python学习计划 Day 16 - 面向对象编程(OOP)基础

第三周 Day 3 &#x1f3af; 今日目标 理解类&#xff08;class&#xff09;和对象&#xff08;object&#xff09;的关系学会定义类的属性、方法和构造函数&#xff08;init&#xff09;掌握对象的创建与使用初识封装、继承和多态的基本概念&#xff08;预告&#xff09; &a…...