SpringCloud入门——微服务调用的方式 RestTemplate的使用 使用nacos的服务名初步(Ribbon负载均衡)

news2024/11/27 4:24:21

目录

  • 引出
  • 微服务之间的调用
    • 几种调用方法
    • spring提供的组件
  • RestTemplate的使用
    • 导入依赖
    • 生产者模块
    • 单个配置的情况
    • 多个配置的情况
      • 没加.yaml的报错【报错】
      • 两个同名配置【细节】
    • 完整代码
      • config配置
      • 主启动类
      • controller层
    • 消费者模块
      • 进行配置
      • restTemplate配置类
      • controller层
  • 使用nacos的服务名【报错】
    • 添加Ribbon负载均衡
    • 改造config
    • controller调用
  • 总结

引出


1.微服务调用的几种方式,异步消息传递,http调用,服务网关调用,服务发现调用nacos;
2.spring提供的restTemplate,发送HTTP请求的客户端工具类;
3.nacos使用服务名报错,需要加Ribbon负载均衡;

微服务之间的调用

在这里插入图片描述

几种调用方法

RPC(Remote Procedure Call)远程过程调用协议,一种通过网络从远程计算机上请求服务,而不需要了解底层网络技术的协议。RPC它假定某些协议的存在,例如TPC/UDP等,为通信程序之间携带信息数据。在OSI网络七层模型中,RPC跨越了传输层和应用层,RPC使得开发,包括网络分布式多程序在内的应用程序更加容易。

在这里插入图片描述

微服务之间的调用可以有以下几种方式:

  1. 同步HTTP调用:微服务可以通过HTTP协议进行同步调用。一个微服务可以发送HTTP请求到另一个微服务的API接口,并等待响应。这种方式简单直接,适用于简单的请求和响应场景。
  2. 异步消息传递:微服务可以通过消息队列或消息中间件进行异步消息传递。一个微服务可以将消息发送到消息队列,另一个微服务可以从队列中接收并处理消息。这种方式可以实现解耦和异步处理,适用于高并发和异步场景。
  3. RPC调用:微服务可以使用远程过程调用(RPC)框架进行调用。RPC框架可以隐藏底层通信细节,使得微服务之间的调用像本地方法调用一样简单。常见的RPC框架有gRPC、Dubbo等。
  4. 服务网关调用:微服务可以通过服务网关进行调用。服务网关作为微服务的入口,可以对外提供统一的API接口,并将请求转发给相应的微服务。服务网关可以实现负载均衡、安全认证等功能。
  5. 服务发现调用:微服务可以通过服务发现机制进行调用。微服务注册到服务注册中心,其他微服务可以通过服务注册中心获取到服务的地址和端口,并进行调用。常见的服务发现工具有Consul、Eureka等。Nacos(全称为"Naming and Configuration Service")是一个开源的动态服务发现、配置管理和服务管理平台。它由阿里巴巴集团开发并开源,旨在帮助开发者更好地构建和管理微服务架构。

spring提供的组件

  • RestTemplate
  • Ribbon+RestTemplate
  • OpenFeign

RestTemplate是Spring Framework提供的一个用于发送HTTP请求的客户端工具类。它简化了在Java应用程序中进行HTTP通信的过程,封装了底层的HTTP连接和请求/响应处理逻辑。

RestTemplate的主要特点和功能包括:

  1. 支持多种HTTP方法:RestTemplate支持常见的HTTP方法,如GET、POST、PUT、DELETE等,可以根据需要选择合适的方法来发送请求。
  2. 提供丰富的请求和响应处理方法:RestTemplate提供了多种方法来处理请求和响应,如添加请求头、设置请求参数、发送请求、获取响应等。开发者可以根据需要选择合适的方法来处理HTTP请求和响应。
  3. 支持请求和响应的序列化和反序列化:RestTemplate可以将请求和响应的数据进行序列化和反序列化,支持多种数据格式,如JSON、XML等。开发者可以根据需要选择合适的序列化和反序列化方式。
  4. 支持错误处理和异常处理:RestTemplate可以处理HTTP请求过程中的错误和异常,如连接超时、请求失败等。开发者可以根据需要进行错误处理和异常处理。
  5. 可扩展性和定制化:RestTemplate提供了一些扩展点和配置选项,可以进行定制化配置。开发者可以根据需要进行扩展和定制,以满足特定的业务需求。

总之,RestTemplate是一个方便易用的HTTP客户端工具类,可以在Java应用程序中发送HTTP请求并处理响应。它是Spring Framework的一部分,与Spring的其他组件集成良好,如Spring Boot、Spring Cloud等。然而,从Spring 5.0版本开始,官方推荐使用WebClient来替代RestTemplate,因为WebClient提供了更强大和灵活的功能。

Ribbon是Netflix开源的一个负载均衡器,它是Spring Cloud中的一个组件,用于在微服务架构中实现客户端的负载均衡。Ribbon可以将客户端请求均匀地分发到多个服务实例上,以提高系统的可用性和性能。

Ribbon的主要特点和功能包括:

  1. 客户端负载均衡:Ribbon可以根据配置的负载均衡策略,将客户端请求分发到多个服务实例上。它支持多种负载均衡算法,如轮询、随机、加权轮询等。
  2. 服务发现和注册:Ribbon集成了服务注册中心,可以自动发现和获取可用的服务实例。它可以与Eureka、Consul等服务注册中心进行集成。
  3. 故障转移和容错:Ribbon可以检测服务实例的健康状态,并在服务不可用时自动切换到其他可用的实例。它还支持熔断机制,可以在服务出现故障时进行快速失败,避免级联故障。
  4. 定制化配置:Ribbon提供了丰富的配置选项,可以根据需要进行定制化配置。开发者可以配置负载均衡策略、超时时间、重试次数等参数。
  5. 与Spring Cloud集成:Ribbon与Spring Cloud的其他组件集成良好,如Eureka、Feign等。它可以作为Feign的默认负载均衡器,实现服务间的调用和负载均衡。

总之,Ribbon是一个强大的负载均衡器,可以在微服务架构中实现客户端的负载均衡。它与Spring Cloud的其他组件紧密结合,为构建和管理微服务架构提供了重要的支持。

OpenFeign是一个声明式的Web服务客户端,它是Spring Cloud中的一个组件,用于简化和优化微服务架构中的服务间调用。OpenFeign基于Netflix的Feign库进行了扩展和增强。

OpenFeign的主要特点和功能包括:

  1. 声明式的API定义:通过使用注解,开发者可以定义和描述服务间的API接口,包括请求方法、路径、参数、请求头等信息。这样可以使得服务间的调用代码更加简洁和易于维护。
  2. 自动化的服务发现和负载均衡:OpenFeign集成了服务注册中心,可以自动发现和调用其他微服务。它还支持负载均衡,可以根据配置的负载均衡策略选择合适的服务实例进行调用。
  3. 内置的请求和响应拦截器:OpenFeign提供了一些内置的拦截器,可以在请求和响应的不同阶段进行拦截和处理。开发者可以自定义拦截器来实现日志记录、错误处理等功能。
  4. 支持多种编码器和解码器:OpenFeign支持多种编码器和解码器,可以处理不同的数据格式,如JSON、XML等。开发者可以根据需要选择合适的编码器和解码器。
  5. 整合了Hystrix和Ribbon:OpenFeign与Hystrix和Ribbon等其他Spring Cloud组件集成,可以实现服务的容错和熔断机制,提高系统的可靠性和稳定性。

总之,OpenFeign简化了微服务架构中的服务间调用,提供了一种简洁、声明式的方式来定义和调用服务API。它与Spring Cloud的其他组件集成良好,是构建和管理微服务架构的重要工具之一。

RestTemplate的使用

微服务之间的调用:

生产者(被使用者) —provider

消费者(应用的服务) — consumer

将两个服务注册到nacos

在这里插入图片描述

导入依赖

在这里插入图片描述

<?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>com.tianju</groupId>
    <artifactId>springcloud-restTemplate</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <modules>
        <module>springcloud-consumer</module>
        <module>springcloud-provider</module>
    </modules>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</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>2.6.13</version>
    </parent>

    <!--    依赖的管理-->
    <dependencyManagement>
        <dependencies>
            <!--整合springcloud -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>2021.0.5</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!--整合springcloud alibaba-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2021.0.5.0</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

<!--        为了让别人发现-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
<!--        注册配置-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

    </dependencies>

</project>

生产者模块

在这里插入图片描述

单个配置的情况

在这里插入图片描述

spring:
  cloud:
    nacos:
      discovery:
        # 能够注册
        register-enabled: true
        server-addr: http://192.168.111.130:8848/
      config:
        server-addr: ${spring.cloud.nacos.discovery.server-addr}
        # namespace的id
        namespace: 57bca93f-1161-4649-aec3-da79c3aa7cc2

#        # 配置单个
        group: DEV
        name: book-cofig
        file-extension: yaml

  application:
    name: springCloud-provider

多个配置的情况

在这里插入图片描述

没加.yaml的报错【报错】

org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘providerController’: Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder ‘book.name’ in value “${book.name}”

Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder ‘book.name’ in value “${book.name}”

在这里插入图片描述

两个同名配置【细节】

在这里插入图片描述

完整代码

在这里插入图片描述

config配置

bootstrap.yml

spring:
  cloud:
    nacos:
      discovery:
        # 能够注册
        register-enabled: true
        server-addr: http://192.168.111.130:8848/
      config:
        server-addr: ${spring.cloud.nacos.discovery.server-addr}
        # namespace的id
        namespace: 57bca93f-1161-4649-aec3-da79c3aa7cc2

#        # 配置单个
#        group: DEV
#        name: book-cofig
#        file-extension: yaml

        # 配置多个 TODO:配置多个的时候,要加上.yaml后缀,nacos中的命名也要加.yaml
        # TODO:如果两个配置里面的值相同,则后面加载进来的会覆盖前面的;
        extension-configs:
#          - data-id: book-cofig
#            group: DEV
#            refresh: true
          - data-id: book-config1.yaml
            group: DEV
            refresh: true
          - data-id: book-config2.yaml
            group: DEV
            refresh: true


  application:
    name: springCloud-provider

application.yml

server:
  port: 9099

主启动类

package com.tianju.cloud.provider;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

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

controller层

package com.tianju.cloud.provider.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/provider")
public class ProviderController {
    @Value("${book.name}")
    private String movieName;

    @Value("${spring.application.name}")
    private String serverId;

    @Value("${server.port}")
    private int port;

    @GetMapping("/hello")
    public String hello(){
        String s = "服务"+serverId+",端口:"+port+",电影名:"+movieName;
        System.out.println(s);
        return s;
    }
}

消费者模块

在这里插入图片描述

进行配置

在这里插入图片描述

spring:
  cloud:
    nacos:
      discovery:
        # 能够注册
        register-enabled: true
        server-addr: http://192.168.111.130:8848/


  application:
    name: springCloud-consumer

restTemplate配置类

package com.tianju.consumer.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestTemplateConfig {
    @Bean(name = "restTemplateA") // 定义名称
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

在这里插入图片描述

controller层

package com.tianju.consumer.controller;

import org.springframework.http.ResponseEntity;
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;


@RestController
@RequestMapping("/api/consumer")
public class ConsumerController {

    @Resource // 根据名称注入
    private RestTemplate restTemplateA;

    @GetMapping("/nihao")
    public String nihao(){
        String url = "http://localhost:9099/api/provider/hello";
        ResponseEntity<String> forEntity = restTemplateA
                .getForEntity(
                    url,
                    String.class
        );
        String body = forEntity.getBody();
        System.out.println("消费者获取生产者提供的数据"+body);
        return body;
    }

}

使用nacos的服务名【报错】

在这里插入图片描述

在这里插入图片描述

添加Ribbon负载均衡

       <!--客户端负载均衡loadbalancer-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>

在这里插入图片描述

改造config

package com.tianju.consumer.config;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestTemplateConfig {
    @Bean(name = "restTemplateA") // 定义名称
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

    @LoadBalanced // 具有软件负载均衡能力
    @Bean(name = "restTemplateWith") // 定义名称
    public RestTemplate restTemplateWith(){
        return new RestTemplate();
    }
}

controller调用

package com.tianju.consumer.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
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;


@RestController
@RequestMapping("/api/consumer")
public class ConsumerController {

    @Resource // 根据名称注入
    private RestTemplate restTemplateA;

    @GetMapping("/nihao")
    public String nihao(){
        String url = "http://localhost:9099/api/provider/hello";
        ResponseEntity<String> forEntity = restTemplateA
                .getForEntity(
                    url,
                    String.class
        );
        String body = forEntity.getBody();
        System.out.println("消费者获取生产者提供的数据"+body);
        return body;
    }

    @Resource
    private RestTemplate restTemplateWith;

    @GetMapping("/nihaox")
    public String nihaoX(){
        String url = "http://springCloud-provider/api/provider/hello";
        ResponseEntity<String> forEntity = restTemplateWith.getForEntity(url, String.class);
        String body = forEntity.getBody();
        System.out.println("消费者获取生产者提供的数据"+body);
        return body;
    }
}

总结

1.微服务调用的几种方式,异步消息传递,http调用,服务网关调用,服务发现调用nacos;
2.spring提供的restTemplate,发送HTTP请求的客户端工具类;
3.nacos使用服务名报错,需要加Ribbon负载均衡;

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

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

相关文章

云渲染对本地电脑要求高不高?对配置有要求吗?

自己本地电脑渲不动&#xff0c;又没有用过云渲染的朋友们一般都会有这样的疑问&#xff1a;云渲染对电脑要求高不高&#xff1f;需要什么样的配置才能用上云渲染&#xff1f; 其实云渲染对本地电脑的配置是完全没有要求的&#xff0c;相反它还能减轻你本地电脑的运行负担&…

Linux驱动——模块化编程

文章目录 模块化编程方法一方法二前提模块化编程模块化编程基本框架&#xff08;重要&#xff09;模块化编程的编译ubantu上操作开发板的文件系统的指令——make超级终端上的模块指令 多模块情况1情况2 传递参数传递单个参数传递数组 模块化编程 方法一 修改kconfig&#xff…

时间序列数据在工厂运营管理中的作用

工业领域中&#xff0c;数据一直扮演着不可或缺的角色&#xff0c;而时间序列数据则因其独特的特性在工厂运营管理中发挥着极其重要的作用。从揭示趋势到支持实时决策&#xff0c;时间序列数据成为工厂智能化的关键组成部分&#xff0c;以下将对时间序列数据在工厂运营管理中的…

Linux - Docker 安装使用教程

Docker 官方文档地址: Get Started | Docker 中文参考手册: https://docker_practice.gitee.io/zh-cn/ 1.什么是 Docker 1.1 官方定义 最新官网首页 # 1.官方介绍 - We have a complete container solution for you - no matter who you are and where you are on your contain…

git difftool对比差异,避免推送不相关内容

问题 在利用git进行版本管理的时候&#xff0c;经常会由于对其他不相关的代码&#xff0c;做了一些小改动&#xff0c;例如删除了一个空行&#xff0c;多了一个缩进等。 为避免将这些不相关的改动也提交到远程&#xff0c;对PR造成不必要的影响&#xff0c;可以利用git diff命…

JVM-性能优化工具 MAT

一、MAT下载和安装 1、概述 MAT&#xff08;Memory Analyzer Tool&#xff09;工具是一款功能强大的]ava堆内存分析器。可以用于查找内存泄漏以及查看内存消耗情况。MAT是基于Eclipse开发的&#xff0c;不仅可以单独使用&#xff0c;还可以作为插件的形式嵌入在Eclipse中使用…

对话iPayLinks:在支付赛道,用技术创新发现出海“潮水的流向”

2023是充满变化和机遇的一年。从突飞猛进的Temu、TikTok Shop等新渠道&#xff0c;到“全托管模式”席卷整个跨境电商行业&#xff0c;以及Chat GPT等人工智能大模型的横空出世&#xff0c;都让出海每一环的从业者感受到“潮水流向的变化”。 不久前&#xff0c;7月及上半年进出…

爬虫项目(一):艺术二维码制作

《Python网络爬虫入门到实战》京东购买地址,这里讲解了大量的基础知识和实战,由本人编著: https://item.jd.com/14049708.html配套代码仓库地址:https://github.com/sfvsfv/Crawer艺术二维码制作 到知数云https://data.zhishuyun.com/services ,申请艺术二维码API,可免费…

【广州华锐互动】AR昆虫认知学习系统实现对昆虫形态的捕捉和还原

随着科技的不断发展&#xff0c;人们对自然界的认识也在不断加深。在这个过程中&#xff0c;AR&#xff08;增强现实&#xff09;技术的出现为人们带来了全新的体验方式。为此&#xff0c;广州华锐互动开发了AR昆虫认知学习系统&#xff0c;本文将为大家详细介绍这款系统的特点…

谷歌发布Gemini以5倍速击败GPT-4

在Covid疫情爆发之前&#xff0c;谷歌发布了MEENA模型&#xff0c;短时间内成为世界上最好的大型语言模型。谷歌发布的博客和论文非常可爱&#xff0c;因为它特别与OpenAI进行了比较。 相比于现有的最先进生成模型OpenAI GPT-2&#xff0c;MEENA的模型容量增加了1.7倍&#xf…

Android 中SettingsActivity(PreferenceFragmentCompat)的简单使用

如果你需要一个简单的APP设置&#xff0c;可以使用sharedPreferences进行存储&#xff0c;我们可以借助AndroidStudio快速创建一个用于设置的Activity&#xff0c;其实它是继承PreferenceFragmentCompat&#xff0c;存储方式用的就是sharedPreferences&#xff0c;只是帮我们节…

一文教你如何防御数据库渗透入侵

前言 前段时间博主在做学校内部项目的时候&#xff0c;项目需要暂时上线测试&#xff0c;没想到上线测试几天&#xff0c;MySQL 数据库数据就被恶意删除&#xff0c;但是当时我们没有太当回事&#xff0c;以为只是一次普通黑客攻击&#xff0c;恢复数据之后仍然可以正常使用。…

『 LeetCode题解 』203. 移除链表元素

题目链接 : 『 LeetCode题解 』203. 移除链表元素 https://leetcode.cn/problems/remove-linked-list-elements/ 目录 &#x1f31f;题目要求&#x1f31f;解题思路&#xff08;动图解析&#xff09;&#x1f9d0;方案一&#x1f601;方案二 &#x1f31f;代码示列 &#x1f31…

海康机器人工业相机SDK MVS安装教程

文章目录 一. 海康机器人介绍二. 工业相机客户端安装教程 一. 海康机器人介绍 海康机器人是面向全球的机器视觉和移动机器人产品及解决方案提供商&#xff0c;业务聚焦于工业物联网、智慧物流和智能制造&#xff0c;构建开放合作生态&#xff0c;为工业和物流领域用户提供服务…

低代码平台如何改变软件开发?低代码平台是否能形成新生态?

低代码平台如何改变软件开发&#xff1f;低代码平台是什么&#xff1f;低代码平台又有什么样的独特价值&#xff1f;在如今的市场环境下&#xff0c;低代码平台又能展现出怎样的生机&#xff1f; 01 什么是低代码开发平台&#xff1f; 低代码开发平台是一种更偏向于赋能技术人…

监管机构新出台的会计法规将对阿里巴巴和其他中概股产生重大影响

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 监管机构出台了新的会计法规 猛兽财经获悉&#xff0c;为规范企业数据资源相关会计处理&#xff0c;强化相关会计信息披露&#xff0c;财政部于2023年8月21日制定并发布了《企业数据资源相关会计处理暂行规定》&#xff0c…

使用Python连接MySQL数据库并查找表信息

使用Python连接MySQL数据库并查找表信息 1.导入MySQLdb包 import MySQLdb如果你的PyCharm中没有MySQLdb&#xff0c;就从Setting-》Project Interpreter查找并下载 2.在MySQL中新建一个连接&#xff0c;取名为python &#xff0c;再新建一个测试表&#xff0c;取名为examples…

FAQ包含哪些内容?

FAQ页面也叫常见问题解答页面&#xff0c;能够帮助回答客户有关你的产品和服务的常见问题&#xff0c;这不仅仅只是一个问题列表&#xff0c;通过解答页面&#xff0c;可以节约销售时间和服务成本&#xff0c;以及可能推动新用户购买。常见问题解答页面可以在整个采购过程中为客…

顺序表链表OJ题(2)->【数据结构】

W...Y的主页 &#x1f60a; 代码仓库分享 &#x1f495; 前言&#xff1a; 单链表的结构常常不完美&#xff0c;没有双向链表那么”优秀“&#xff0c;所以繁衍出很多OJ练习题。今天我们继续来look look数据结构习题。 下面就是OJ时间&#xff01;&#xff01;&#xff01; …

UEditorPlus v3.4.0 全新公式编辑体验,Logo全新发布

UEditor是由百度开发的所见即所得的开源富文本编辑器&#xff0c;基于MIT开源协议&#xff0c;该富文本编辑器帮助不少网站开发者解决富文本编辑器的难点。 UEditorPlus 是有 ModStart 团队基于 UEditor 二次开发的富文本编辑器&#xff0c;主要做了样式的定制&#xff0c;更符…