【后端开发】尚硅谷 SpringCloud 学习笔记

news2024/11/15 21:55:48

文章目录

  • 一、cloud组件
  • 二、环境搭建
    • 2.1 创建父工程
    • 2.2 支付模块构建
    • 2.3 消费者模块构建
      • 2.3.1 引入RestTemplate
      • 2.3.2 远程调用支付模块
  • 三、Eureka
    • 3.1 基础知识
    • 3.2 单机版Eureka安装
    • 3.3 服务注册
    • 3.4 Eureka集群
      • 3.4.1 Eureka端配置
      • 3.4.2 微服务端配置
      • 3.4.3 restTemplate负载均衡
      • 3.4.4 主机名修改和ip地址显示
    • 3.5 服务发现Discovery
    • 3.6 Rureka自我保护机制
    • 3.7 禁止Eureka自我保护
  • 四、Zookeeper
  • 五、Consul
    • 5.1 简介
    • 5.2 安装
    • 5.3 搭建项目
  • 六、三个注册中心的异同点
  • 七、Ribbon
    • 7.1 入门介绍
    • 7.2 使用Ribbon
    • 7.3 RestTemplate类
    • 7.4 Ribbon常用负载均衡算法
    • 7.5 Ribbon负载均衡规则替换
    • 7.6 轮询算法原理
    • 7.7 源码分析
    • 7.8 手写轮询算法
  • 八、OpenFeign
    • 8.1 什么是OpenFeign
    • 8.2 OpenFeign服务调用


一、cloud组件

image-20220420215503372

二、环境搭建

2.1 创建父工程

image-20220420221138947

2.2 支付模块构建

image-20220420223559508

2.3 消费者模块构建

2.3.1 引入RestTemplate

@Configuration
public class ApplicationContextConfig {
    // 配置bean 不然后面没法依赖注入,就像以前ssm整合时配置依赖注入一样,
    // 需要在配置文件配置之后,代码中才可以依赖注入
    // 当前文件就是spring的配置文件
    @Bean
//    @LoadBalanced //让这个RestTemplate在请求时拥有客户端负载均衡的能力  //将此注解注释掉,使用自己的轮询算法不使用默认的
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
}

2.3.2 远程调用支付模块

@RestController
public class OrderController {

    public static final String PAYMENT_URL = "http://localhost:8001";

    public static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE";

    @Resource
    private RestTemplate restTemplate;

    @GetMapping("/testRPC/{id}")
    public CommonResult<Payment> getPayment(@PathVariable("id") String id) {
        return restTemplate.getForObject(PAYMENT_URL + "/test/" + id, CommonResult.class);
    }
    
}

三、Eureka

3.1 基础知识

前面我们没有服务注册中心,也可以服务间调用,为什么还要服务注册?

当服务很多时,单靠代码手动管理是很麻烦的,需要一个公共组件,统一管理多服务,包括服务是否正常运行,等

Eureka用于**服务注册,目前官网已经停止更新**

3.2 单机版Eureka安装

image-20220421135836067

创建项目cloud-eureka-server-7001

引入依赖

<dependencies>
    <!-- 服务注册中心的服务端 eureka-server -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
    </dependency>

</dependencies>

yml配置文件

server:
  port: 7001

# 单机版
eureka:
  instance:
    hostname: localhost  #eureka服务端的实例名字
  client:
    register-with-eureka: false    #表示不向注册中心注册自己
    fetch-registry: false   #表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务
    service-url:
      #设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址
      defaultZone: http://${eureka.instance.hostname}:${server.port}

启动类

/**
 * @author WSKH
 * @date 2020/12/19 14:12
 * @description 注册中心
 */
@SpringBootApplication
@EnableEurekaServer // 启动Eureka服务
public class CloudEurekaServer7001Application {
    public static void main(String[] args) {
        SpringApplication.run(CloudEurekaServer7001Application.class, args);
        System.out.println("启动成功!");
    }
}

3.3 服务注册

引入依赖

<!-- 服务注册中心的客户端端 eureka-client -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

yaml配置

server:
  port: 8001

spring:
  application:
    name: cloud-payment-service
    
eureka:
  client:
    register-with-eureka: true #是否向注册中心注册自己
    fetchRegistry: true #是否从注册中心抓取已有的注册信息 默认true,集群必须设置为true
    service-url:
      #      设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址
            defaultZone: http://localhost:7001 #单机版
  instance:
    instance-id: payment8001
    prefer-ip-address: true  #访问路径可以显示IP地址
#    Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认是30秒)
#    lease-renewal-interval-in-seconds: 1
#    Eureka服务端在收到最后一次心跳后等待时间上限,单位为秒(默认是90秒),超时将剔除服务
#    lease-expiration-duration-in-seconds: 2

启动类

@SpringBootApplication
@EnableEurekaClient // 指定成为Eureka客户端
@EnableDiscoveryClient // 开启服务发现
@Slf4j
public class CloudProviderPayment8001Application {
    public static void main(String[] args) {
        SpringApplication.run(CloudProviderPayment8001Application.class, args);
        log.info("cloud-provider-payment-8001 启动成功!");
    }
}

3.4 Eureka集群

单机版注册中心会出现单点故障,故一般都采用集群

image-20220421142643610

两台或以上的Rureka互相注册,相互守望,对外暴露端口

3.4.1 Eureka端配置

image-20220421142246104

7001的yaml配置

server:
  port: 7001
  
#集群版
eureka:
  instance:
    hostname: eureka7001    #eureka服务端的实例名字(实际好像不起作用,DS Replicas是直接截取URL中冒号前面的部分,当作队友名,如http://localhost:7001,那就截取localhost当作队友名)
  client:
    register-with-eureka: false    #表示不向注册中心注册自己
    fetch-registry: false   #表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务
    service-url:
      #设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址
#      defaultZone: http://eureka7001.com:7001
      defaultZone: http://localhost:7002  #这个是集群版开启 互相注册
#  server:
##    关闭自我保护机制,保证不可用服务被及时踢除
#    enable-self-preservation: false
#    eviction-interval-timer-in-ms: 2000

7002的yaml配置

server:
  port: 7002

#集群版
eureka:
  instance:
    hostname: eureka7002    #eureka服务端的实例名字(实际好像不起作用,DS Replicas是直接截取URL中冒号前面的部分,当作队友名,如http://localhost:7001,那就截取localhost当作队友名)
  client:
    register-with-eureka: false    #表识不向注册中心注册自己
    fetch-registry: false   #表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务
    service-url:
      #设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址
      defaultZone: http://localhost:7001

3.4.2 微服务端配置

image-20220421142428598

server:
  port: 80

spring:
  application:
    name: cloud-order-service

eureka:
  client:
    register-with-eureka: true #是否向注册中心注册自己
    fetchRegistry: true #是否从注册中心抓取已有的注册信息 默认true,集群必须设置为true
    service-url:
      #设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址
      defaultZone: http://localhost:7001,http://localhost:7002  #集群版

image-20220421142518868

server:
  port: 8001

spring:
  application:
    name: cloud-payment-service

eureka:
  client:
    register-with-eureka: true #是否向注册中心注册自己
    fetchRegistry: true #是否从注册中心抓取已有的注册信息 默认true,集群必须设置为true
    service-url:
      #      设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址
      defaultZone: http://localhost:7001,http://localhost:7002  #集群版
  instance:
    instance-id: payment8001
    prefer-ip-address: true  #访问路径可以显示IP地址
#    Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认是30秒)
#    lease-renewal-interval-in-seconds: 1
#    Eureka服务端在收到最后一次心跳后等待时间上限,单位为秒(默认是90秒),超时将剔除服务
#    lease-expiration-duration-in-seconds: 2

image-20220421144600272

3.4.3 restTemplate负载均衡

加入@LoadBalanced注解即可开启负载均衡

@Configuration
public class ApplicationContextConfig {

    // 配置bean 不然后面没法依赖注入,就像以前ssm整合时配置依赖注入一样,
    // 需要在配置文件配置之后,代码中才可以依赖注入
    // 当前文件就是spring的配置文件
    @Bean
    @LoadBalanced //让这个RestTemplate在请求时拥有客户端负载均衡的能力  //将此注解注释掉,使用自己的轮询算法不使用默认的
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
}

测试

@RestController
public class OrderController {

    // http://服务名大写
    public static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE";

    @Resource
    private RestTemplate restTemplate;

    @GetMapping("/testLoadBalancedRpc/{id}")
    public CommonResult<Payment> testLoadBalancedRpc(@PathVariable("id") String id) {
        return restTemplate.getForObject(PAYMENT_URL + "/test/"+id, CommonResult.class);
    }

}

image-20220421150453650

最后发送请求 http://127.0.0.1:80/testLoadBalancedRpc/id=123 进行测试

发现会自动均衡地访问8001和8002

3.4.4 主机名修改和ip地址显示

image-20220421151024477

image-20220421151050724

3.5 服务发现Discovery

开启服务发现

image-20220421151614870

使用DiscoveryClient完成服务发现

// 注入DiscoveryClient对象
@Resource
DiscoveryClient discoveryClient;

@GetMapping("/testDiscoveryClient")
public void testDiscoveryClient(){
    // 从注册中心获取所有服务的名称
    List<String> services = discoveryClient.getServices();
    services.forEach(System.out::println);
    // 根据服务名称找到其下的所有实例
    List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
    // 遍历输出实例信息
    instances.forEach(instance -> {
        System.out.println(instance.getServiceId() + "\t" + instance.getHost() + "\t" + instance.getPort() + "\t" + instance.getUri());
    });
}

测试 http://127.0.0.1:8001/testDiscoveryClient

image-20220421151934129

3.6 Rureka自我保护机制

image-20220421152240967

image-20220421152305485

image-20220421152553928

image-20220421152705265

image-20220421152733179

3.7 禁止Eureka自我保护

image-20220421152930424

#集群版
eureka:
  instance:
    hostname: eureka7001    #eureka服务端的实例名字
  client:
    register-with-eureka: false    #表示不向注册中心注册自己
    fetch-registry: false   #表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务
    service-url:
      #设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址
#      defaultZone: http://eureka7001.com:7001/eureka/
      defaultZone: http://localhost:7002  #这个是集群版开启 互相注册
#  server:
##    关闭自我保护机制,保证不可用服务被及时踢除
#    enable-self-preservation: false
#    eviction-interval-timer-in-ms: 2000

image-20220421153115868

四、Zookeeper

五、Consul

5.1 简介

image-20220423190903685

image-20220423190923102

5.2 安装

中文官网: https://www.spring.cloud.cc/spring-cloud-consul.html

英文官网:https://www.consul.io

需要下载一个安装包

image-20220423192943494

查看版本

image-20220423193722948

启动是一个命令行界面,需要输入consul agent -dev启动

http://localhost:8500

image-20220423194820358

5.3 搭建项目

引入依赖

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

yaml配置

server:
  port: 8006

spring:
  application:
    name: consul-provider-payment
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        service-name: ${spring.application.name}

启动类

@SpringBootApplication
@EnableDiscoveryClient //该注解用于向使用consul或者zookeeper作为注册中心时注册服务
public class CloudProviderconsulPayment8006Application {

    public static void main(String[] args) {
        SpringApplication.run(CloudProviderconsulPayment8006Application.class, args);
        System.out.println("启动成功");
    }

}

启动App,查看服务注册情况

六、三个注册中心的异同点

image-20220423200325820

七、Ribbon

7.1 入门介绍

image-20220423201010799

image-20220423201229679

7.2 使用Ribbon

默认我们使用eureka的新版本时,它默认集成了ribbon:

image-20220423201847659

这个starter中集成了reibbon了

我们也可以手动引入ribbon

7.3 RestTemplate类

image-20220423201929555

RestTemplate:
        xxxForObject()方法,返回的是响应体中的数据
        xxxForEntity()方法.返回的是entity对象,这个对象不仅仅包含响应体数据,还包含响应体信息(状态码等)

7.4 Ribbon常用负载均衡算法

IRule接口,Riboon使用该接口,根据特定算法从所有服务中,选择一个服务,

Rule接口有7个实现类,每个实现类代表一个负载均衡算法

image-20220423202655644

7.5 Ribbon负载均衡规则替换

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jqERrsdi-1686926847827)(…/…/AppData/Roaming/Typora/typora-user-images/image-20220423202944560.png)]

image-20220423203006329

配置类

@Configuration
public class MySelfRule {
    @Bean
    public IRule myRule() {
        // 此处将ribbon默认使用的轮询策略改为随机策略
        return new RandomRule();
    }
}

启动类

@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
// 启动CLOUD-PAYMENT-SERVICE服务时去加载自定义的ribbon配置
@RibbonClient(name = "CLOUD-PAYMENT-SERVICE", configuration = MySelfRule.class)
@Slf4j
public class CloudConsumerOrder80Application {

    public static void main(String[] args) {
        SpringApplication.run(CloudConsumerOrder80Application.class, args);
        log.info("cloud-consumer-order-80 启动成功!");
    }

}

7.6 轮询算法原理

image-20220423203635111

7.7 源码分析

image-20220423203909554

image-20220423203934127

7.8 手写轮询算法

image-20220423213247841

public interface MyLoadBalancer {

    /**
     * 收集服务器总共有多少台能够提供服务的机器,并放到list里面
     *
     * @param serviceInstances
     * @return ServiceInstance
     * @author WSKH
     * @date 2020/12/23 9:24
     */
    ServiceInstance instances(List<ServiceInstance> serviceInstances);
}
@Component
public class MyLB implements MyLoadBalancer {
    // 原子类
    private final AtomicInteger atomicInteger = new AtomicInteger(0);

    /**
     * @author WSKH
     * @date 2020/12/23 10:07
     * @description 判断时第几次访问
     */
    public final int getAndIncrement() {
        int current;
        String a = "current";
        int next = 0;
        do {
            current = atomicInteger.get();
            // 防止越界
            next = current >= Integer.MAX_VALUE ? 0 : current + 1;
        } while (!atomicInteger.compareAndSet(current, next));
        System.out.println("*****第几次访问,次数next: " + next);
        return next;
    }

    /**
     * 负载均衡算法:rest接口第几次请求数 % 服务器集群总数量 = 实际调用服务器位置下标, 每次服务重启动后rest接口计数从1开始。1
     *
     * @param serviceInstances
     * @return ServiceInstance
     * @author WSKH
     * @date 2020/12/23 9:51
     */
    @Override
    public ServiceInstance instances(List<ServiceInstance> serviceInstances) {
        int index = getAndIncrement() % serviceInstances.size();

        return serviceInstances.get(index);
    }

}
// 注入自定义的负载均衡规则
@Resource
private MyLoadBalancer myLoadBalancer;

@Resource
private DiscoveryClient discoveryClient;
/**
 * @author WSKH
 * @date 2020/12/23 10:27
 * @description 测试自定义的负载均衡规则
 */
@GetMapping(value = "/payment/lb")
public String getPaymentLB() {
    List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");

    if (instances == null || instances.isEmpty()) {
        return null;
    }

    // 调用自定义的负载均衡策略
    ServiceInstance serviceInstance = myLoadBalancer.instances(instances);
    URI uri = serviceInstance.getUri();
    return restTemplate.getForObject(uri + "/payment/lb", String.class);

}

八、OpenFeign

8.1 什么是OpenFeign

image-20220530091905945

image-20220530092051129

image-20220530092209979

8.2 OpenFeign服务调用

未完待续...

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

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

相关文章

如何让ChatGPT制作XMind思维导图

一、使用ChatGPT辅助生成内容 给大家一个思路&#xff0c;比如我想制作《股神巴菲特给儿女的一生忠告》相关的思维导图&#xff0c;那我们可以在ChatGPT上提问“请使用markdown格式写出股神巴菲特给儿女的一生忠告的思维导图&#xff0c;以代码格式输出”。 生成后&#xff0…

teleport堡垒机的一些问题

teleport文件下载&#xff0c;将teleport服务映射到公网&#xff0c;权限已经分派好了&#xff0c;但无法ssh&#xff0c;这是什么原因呢&#xff1f; 注意teleport助手的版本要跟部署的是一致的&#xff0c;否则会检测不到状态 出现下面的问题&#xff0c;应该还是在防火墙的端…

奇舞周刊第496期:ChatGPT 的工作原理,这篇文章说清楚了!

记得点击文章末尾的“ 阅读原文 ”查看哟~ 下面先一起看下本期周刊 摘要 吧~ 奇舞推荐 ■ ■ ■ ChatGPT 的工作原理&#xff0c;这篇文章说清楚了&#xff01; ChatGPT 能够自动生成一些读起来表面上甚至像人写的文字的东西&#xff0c;这非常了不起&#xff0c;而且出乎意料。…

DM3E,雷赛步进驱动器

0x6040&#xff1a; 0x6041&#xff1a; 状态流&#xff1a; 0x60608; //设置伺服模式 8CSP&#xff0c;6回零模式&#xff0c;3速度模式6040流&#xff1a; 00初始》06上电》07使能》0F待命&#xff08;可操作&#xff09; 快停流&#xff1a; 02快停》0F命令生效 参数保…

Vue全家桶(三):Vuex状态管理(State、Getters、Mutations、Actions)

目录 Vuex1. 理解Vuex1.1 组件之间共享数据的方式1.2 Vuex是什么1.2 什么时候使用Vuex1.3 Vuex的工作原理图 2 使用Vuex2.1 搭建Vuex环境 2.2 Vuex基本使用2.2.1 State2.2.2 Getters2.2.3 Mutations2.2.4 Actions2.2.5 Modules 模块化命名空间 3 求和案例3.1 使用纯vue编写3.2 …

Property ‘code‘ does not exist on type ‘AxiosResponse<any, any>‘ 的解决办法

原文链接 : Property ‘xxx’ does not exist on type ‘AxiosResponse<any, any>’ 的解决办法 vue3 ts 中 调用接口时&#xff1a; const loginOut () > {loginOutApi().then(res > {const { code } resif(code 0){ }})}报了如下错误&#xff1a; Property…

Python基础(3)——PyCharm介绍

Python基础&#xff08;3&#xff09;——PyCharm介绍 文章目录 Python基础&#xff08;3&#xff09;——PyCharm介绍课程目标一. PyCharm的作用二. 下载和安装2.1 下载2.2 安装 三. PyCharm基本使用3.1 新建项目3.2 新建文件并书写代码3.3 运行文件 四. PyCharm的基本设置4.1…

基于Hexo和Butterfly创建个人技术博客,(10) 使用Butterfly的Tags Plugin插件增强博客文章内容和视觉表现力

Butterfly官方网站&#xff0c;请 点击进入 说明&#xff1a; 前面已经提过Hexo自创了Tag Plugin内容标签&#xff0c;Butterflay主题在此基础上又扩展了一些。本文就详细讲解下这些标签带来哪些额外的功能和UI方面的强化&#xff1b; 本章目标&#xff1a; 掌握butterfly扩展…

LightningChart .NET 10.5.1 Crack LightningChart 2023

LightningChart .NET v.10.5.1 已经发布&#xff01; DataCursor 和 3D TransparencyRenderMode 现在可用。 为所有 3D、Polar 和 Smith 系列启用 DataCursor 在早期阶段&#xff0c;LightningChart 提供了不同的工具&#xff0c;需要用户编写额外的代码才能启用数据跟踪功能。…

phpstudy免费下载

phpstudy免费下载 phpstudy是一个可以在本地建站的php环境软件链接: https://pan.baidu.com/s/1vfi-gy3juYBUjGz_Cq2gHg 提取码: 1234链接: http://120.26.240.154:8888/down/5Sx9yB0s0HS3.zip phpstudy是一个可以在本地建站的php环境软件 百度网盘分享 链接: https://pan.ba…

Session和Cookie,你真的弄清了吗?

Session和Cookie Session和Cookie Session和Cookiecookiecookie的生命周期cookie作用域 Sessionsession的生命周期session作用域 cookie和session安全性 为什么需要cookie和session&#xff1f;在web系统发展变迁时&#xff0c;web发展时随着需求的不断增多&#xff0c;交互的存…

Ceph:关于Ceph 集群中池管理的一些笔记

写在前面 准备考试&#xff0c;整理 Ceph 相关笔记博文内容涉及, Ceph 中的 两种 pool 介绍&#xff0c;创建操作管理池理解不足小伙伴帮忙指正 对每个人而言&#xff0c;真正的职责只有一个&#xff1a;找到自我。然后在心中坚守其一生&#xff0c;全心全意&#xff0c;永不停…

java公益网站系统Myeclipse开发mysql数据库web结构jsp编程计算机网页项目wap

一、源码特点 java 公益网站系统是一套完善的java web wap信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0&…

Ceph:关于Ceph 集群管理的一些笔记

写在前面 准备考试&#xff0c;整理ceph 相关笔记博文内容涉及&#xff0c;Ceph 管理工具 cephadm&#xff0c;ceph 编排器&#xff0c;Ceph CLI 和 Dashboard GUI 介绍理解不足小伙伴帮忙指正 对每个人而言&#xff0c;真正的职责只有一个&#xff1a;找到自我。然后在心中坚守…

Android插件化框架-Shadow原理解析

作者&#xff1a;dennyz 1、前言 所谓插件化&#xff0c;是实现动态化的一种具体的技术手段。 对于移动端的App而言&#xff0c;无论是Android还是iOS&#xff0c;都存在一个共同的问题&#xff0c;那就是更新的周期较长。 当我们希望快速为App更新功能时&#xff0c;必须经…

Docker Desktop启动失败解决方案(亲侧出坑总结)

现在有些东西网上资料开始变少了。需要自己去总结。有些技术呢又因为分享变得门槛低。今天这个是关于windows下的docker desktop无法启动的问题集锦。卷吧。 背景&#xff1a;应业务需要所以需要在个人电脑上安装docker环境。desktop docker是官方标准的windows下安装工具。 …

6.7面向对象的多态

7. 面向对象特征三&#xff1a;多态性 概念 多态是面向对象程序设计&#xff08;OOP&#xff09;的一个重要特征&#xff0c;指同一个实体同时具有多种形式&#xff0c;即同一个对象&#xff0c;在不同时刻&#xff0c;代表的对象不一样&#xff0c;指的是对象的多种形态。 变…

副业变现:Midjourney绘画赚钱的6种方式

今年被称为AI元年&#xff0c;其中最火的两款AI工具非ChatGpt和Midjourney莫属。究其原因&#xff0c;无非两点&#xff1a;第一&#xff0c;它提高了生产力&#xff0c;之前需要两年完成的工作&#xff0c;使用ChatGpt两天就完成。 第二&#xff0c;它带来了副业收入&#xff…

短视频seo源代码部署步骤

一、 部署短视频SEO矩阵系统源代码&#xff0c;您需要遵循以下步骤&#xff1a; 准备服务器环境 首先&#xff0c;您需要准备一个服务器环境来托管源代码。您可以选择云服务器&#xff08;例如AWS&#xff0c;阿里云等&#xff09;或自己的私人服务器。 安装所需软件 在服务器…

Android系统Binder详解

Android系统启动篇 1&#xff0c;《android系统启动流程简介》 2&#xff0c;《android init进程启动流程》 3&#xff0c;《android zygote进程启动流程》 4&#xff0c;《Android SystemServer进程启动流程》 5&#xff0c;《android launcher启动流程》 6&#xff0c;…