Dubbo学习

Dubbo 前言

1.1 大型互联网项目架构目标

Dubbo学习

Dubbo学习

Dubbo学习

Dubbo学习

1.2 集群和分布式

概念

  • 集群:很多”人”一起,干一样的事。
  • 一个业务模块,部署在多台服务器上。
  • 分布式:很多”人”一起,干不一样的事。这些不一样的事,合起来是一件大事。
  • 一个大的业务系统,拆分为小的业务模块,分别部署在不同的机器上。

厨师例子

Dubbo学习

编程实际

Dubbo学习

Dubbo学习

1.3 架构演进

Dubbo学习

Dubbo学习

Dubbo学习

Dubbo学习

Dubbo学习

Dubbo学习

Dubbo概述

Dubbo是阿里巴巴公司开源的一个高性能、轻量级的Java RPC框架。致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。

官网: http://dubbo.apache.org

Dubbo学习

Zookeeper安装

1.1 下载安装

1、环境准备

ZooKeeper服务器是用Java创建的,它运行在JVM之上。需要安装JDK 7或更高版本。

2、上传

将下载的ZooKeeper放到/usr/local/ZooKeeper目录下

#上传zookeeper alt+p
#打开 opt目录
cd /usr/local/zooKeeper
#创建zooKeeper目录
mkdir  zooKeeper
#将zookeeper安装包移动到 /opt/zooKeeper
mv apache-zookeeper-3.5.6-bin.tar.gz /usr/local/zooKeeper

3、解压

将tar包解压到/usr/local/zookeeper目录下

tar -zxvf apache-ZooKeeper-3.5.6-bin.tar.gz

1.2 配置启动

1、配置zoo.cfg

进入到conf目录拷贝一个zoo_sample.cfg并完成配置

#进入到conf目录
cd /usr/local/zooKeeper/apache-zooKeeper-3.5.6-bin/conf/
#拷贝
cp  zoo_sample.cfg  zoo.cfg

修改zoo.cfg

#打开目录
cd /usr/local/zooKeeper
#创建zooKeeper存储目录
mkdir  zkdata
#修改zoo.cfg
vim /usr/local/zooKeeper/apache-zooKeeper-3.5.6-bin/conf/zoo.cfg

Dubbo学习

修改存储目录:dataDir=/usr/local/zooKeeper/zkdata

2、启动ZooKeeper

cd /usr/local/zooKeeper/apache-zooKeeper-3.5.6-bin/bin/
#启动
./zkServer.sh  start

Dubbo学习

看到上图表示ZooKeeper成功启动

3、查看ZooKeeper状态

./zkServer.sh status

zookeeper启动成功。standalone代表zk没有搭建集群,现在是单节点

Dubbo学习

zookeeper没有启动

Dubbo学习

4、开放端口

firewall-cmd --zone=public --add-port=2181/tcp --permanent
firewall-cmd --reload

Dubbo快速入门

Dubbo学习

dubbo-service模块

Dubbo学习

UserService类

package com.Aaron.service.impl;

import org.apache.dubbo.config.annotation.Service;
import com.Aaron.service.UserService;

/**
 * @Author: AlaskaBoo
 * @Date: 2022-09-01 19:47
 **/
//@Service 将该类的对象创建出来,放到Spring的Ioc容器中bean定义
@Service//将这个类提供的方法《服务)对外发布。将访问的地址ip,端口,路径注册到注册中心中
public class UserServiceImpl implements UserService {
    @Override
    public String sayHello() {
        return "Hello Dubbo~~~~";
    }
}

resource

spring包applicationContext.xml


log4j

DEBUG < INFO < WARN < ERROR < FATAL
Global logging configuration
log4j.rootLogger=info, stdout,file
My logging configuration...

#log4j.logger.com.tocersoft.school=DEBUG
#log4j.logger.net.sf.hibernate.cache=debug
## Console output...

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p %d %C: %m%n

log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=../logs/iask.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss}  %l  %m%n

web.xml


        contextConfigLocation
        classpath*:spring/applicationContext.xml

        org.springframework.web.context.ContextLoaderListener

pom依赖


    4.0.0

    com.Aaron
    dubbo-service
    1.0-SNAPSHOT
    war

        8
        8
        UTF-8
        5.1.9.RELEASE
        2.7.4.1
        4.0.0

            javax.servlet
            javax.servlet-api
            3.1.0
            provided

            org.springframework
            spring-context
            ${spring.version}

            org.springframework
            spring-webmvc
            ${spring.version}

            org.slf4j
            slf4j-api
            1.7.21

            org.slf4j
            slf4j-log4j12
            1.7.21

            org.apache.dubbo
            dubbo
            ${dubbo.version}

            org.apache.curator
            curator-framework
            ${zookeeper.version}

            org.apache.curator
            curator-recipes
            ${zookeeper.version}

            com.Aaron
            dubbo-interface
            1.0-SNAPSHOT

                org.apache.tomcat.maven
                tomcat7-maven-plugin
                2.2

                    9000
                    /

dubbo-web模块

Dubbo学习

UserController

package com.Aaron.controller;

import org.apache.dubbo.config.annotation.Reference;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.Aaron.service.UserService;

/**
 * @Author: AlaskaBoo
 * @Date: 2022-09-01 20:01
 **/
@RestController
@RequestMapping("/user")
public class UserController {
    /**
     * 远程注入
     *
     * @Reference
     * 1.从zookeeper注册中心获取userService的访问url
     * 2.进行远程调用RPC
     * 3.将结果封装为一个代理对象。给变量赋值
     */
    @Reference
    private UserService userService;

    @RequestMapping("/sayHello")
    public String sayHello() {
        return userService.sayHello();
    }
}

resouce

spring包springmvc.xml


log4j

DEBUG < INFO < WARN < ERROR < FATAL
Global logging configuration
log4j.rootLogger=info, stdout,file
My logging configuration...

#log4j.logger.com.tocersoft.school=DEBUG
#log4j.logger.net.sf.hibernate.cache=debug
## Console output...

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p %d %C: %m%n

log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=../logs/iask.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss}  %l  %m%n

web.xml


        springmvc
        org.springframework.web.servlet.DispatcherServlet

            contextConfigLocation
            classpath:spring/springmvc.xml

        springmvc
        *.do

pom.xml


    4.0.0

    com.Aaron
    dubbo-web
    1.0-SNAPSHOT
    war

        8
        8
        UTF-8
        5.1.9.RELEASE
        2.7.4.1
        4.0.0

            javax.servlet
            javax.servlet-api
            3.1.0
            provided

            org.springframework
            spring-context
            ${spring.version}

            org.springframework
            spring-webmvc
            ${spring.version}

            org.slf4j
            slf4j-api
            1.7.21

            org.slf4j
            slf4j-log4j12
            1.7.21

            org.apache.dubbo
            dubbo
            ${dubbo.version}

            org.apache.curator
            curator-framework
            ${zookeeper.version}

            org.apache.curator
            curator-recipes
            ${zookeeper.version}

            com.Aaron
            dubbo-interface
            1.0-SNAPSHOT

                org.apache.tomcat.maven
                tomcat7-maven-plugin
                2.2

                    8000
                    /

dubbo-interface

Dubbo学习

UserService

package com.Aaron.service;

/**
 * @Author: AlaskaBoo
 * @Date: 2022-09-01 19:45
 **/
public interface UserService {
    public String sayHello();
}

启动结果

Dubbo学习

Dubbo高级特性

一、dubbo-admin

Dubbo学习

二、dubbo-admin安装

1、环境准备

dubbo-admin 是一个前后端分离的项目。前端使用vue,后端使用springboot,安装 dubbo-admin 其实就是部署该项目。我们将dubbo-admin安装到开发环境上。要保证开发环境有jdk,maven,nodejs

安装node (如果当前机器已经安装请忽略)

因为前端工程是用vue开发的,所以需要安装node.js,node.js中自带了npm,后面我们会通过npm启动

下载地址

https://nodejs.org/en/

Dubbo学习

2、下载 Dubbo-Admin

进入github,搜索dubbo-admin

https://github.com/apache/dubbo-admin

下载:

Dubbo学习

3、把下载的zip包解压到指定文件夹(解压到那个文件夹随意)

Dubbo学习

4、修改配置文件

解压后我们进入…\dubbo-admin-develop\dubbo-admin-server\src\main\resources目录,找到 application.properties 配置文件 进行配置修改

Dubbo学习

修改zookeeper地址

Dubbo学习
centers in dubbo2.7
admin.registry.address=zookeeper://192.168.121.128:2181
admin.config-center=zookeeper://192.168.121.128:2181
admin.metadata-report.address=zookeeper://192.168.121.128:2181

admin.registry.address注册中心
admin.config-center 配置中心
admin.metadata-report.address元数据中心

5、打包项目

在 dubbo-admin-develop 目录执行打包命令

建议在cmd中执行,先换淘宝镜像

npm config set registry https://registry.npm.taobao.org

Dubbo学习
mvn  clean package
mvn clean package -Dmaven.test.skip=true

Dubbo学习

6、启动后端

切换到目录

dubbo-Admin-develop\dubbo-admin-distribution\target>

执行下面的命令启动 dubbo-admin,dubbo-admin后台由SpringBoot构建。

java -jar .\dubbo-admin-0.1.jar

Dubbo学习

7、前台后端

dubbo-admin-ui 目录下执行命令

npm run dev
npm run serve(我安装的16.11.1的node.js)

8、访问

浏览器输入。用户名密码都是root

http://localhost:8081/

Dubbo学习

三、dubbo-admin简单使用

Dubbo学习

注意:Dubbo Admin【服务Mock】【服务统计】将在后续版本发布….

在上面的步骤中,我们已经进入了Dubbo-Admin的主界面,在【快速入门】章节中,我们定义了服务生产者、和服务消费者,下面我们从Dubbo-Admin管理界面找到这个两个服务

1、点击服务查询

2、查询结果

Dubbo学习

A:输入的查询条件com.Aaron.service.UserService

B:搜索类型,主要分为【按服务名】【按IP地址】【按应用】三种类型查询

C:搜索结果

3.1.4 dubo-admin查看详情

我们查看com.Aaron.service.UserService (服务提供者)的具体详细信息,包含【元数据信息】

1)点击详情

Dubbo学习

从【详情】界面查看,主要分为3个区域

A区域:主要包含服务端 基础信息比如服务名称、应用名称等

B区域:主要包含了生产者、消费者一些基本信息

C区域:是元数据信息,注意看上面的图,元数据信息是空的

我们需要打开我们的生产者配置文件加入下面配置


重新启动生产者,再次打开Dubbo-Admin

这样我们的元数据信息就出来了

Dubbo学习

四、常用高级配置

1、序列化

Dubbo学习

Dubbo学习

在pojo中实体加Serializable

package com.Aaron.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
 * @Author: AlaskaBoo
 * @Date: 2022-09-02 17:12
 * 注意!!!

 * 将来所有的pojo类都需要实现注意!!!

 * 将来所有的pojo类都需要实现Serializable接口接口
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
    private int id;
    private String username;
    private String password;
}

interface中继承依赖

Dubbo学习

2、地址缓存

Dubbo学习

3、超时与重试(设置超时时间)

Dubbo学习

Dubbo学习

Dubbo学习

重试

Dubbo学习

4、多版本

Dubbo学习

Dubbo学习

Dubbo学习

5、负载均衡

Dubbo学习

Dubbo学习

Dubbo学习

Dubbo学习

Dubbo学习

Dubbo学习

Dubbo学习

6、容错机制

Dubbo学习

7、服务降级

Dubbo学习

Dubbo学习

搭建Zookeeper集群

1.1 搭建要求

真实的集群是需要部署在不同的服务器上的,但是在我们测试时同时启动很多个虚拟机内存会吃不消,所以我们通常会搭建 伪集群,也就是把所有的服务都搭建在一台虚拟机上,用端口进行区分。

我们这里要求搭建一个三个节点的Zookeeper集群(伪集群)。

1.2 准备工作

重新部署一台虚拟机作为我们搭建集群的测试服务器。

(1)安装JDK 【此步骤省略】。

(2)Zookeeper压缩包上传到服务器
(3)将Zookeeper解压 ,建立/usr/local/zookeeper-cluster目录,将解压后的Zookeeper复制到以下三个目录

/usr/local/zookeeper-cluster/zookeeper-1

/usr/local/zookeeper-cluster/zookeeper-2

/usr/local/zookeeper-cluster/zookeeper-3

[root@localhost ~]# mkdir /usr/local/zookeeper-cluster
[root@localhost ~]# cp -r  apache-zookeeper-3.5.6-bin /usr/local/zookeeper-cluster/zookeeper-1
[root@localhost ~]# cp -r  apache-zookeeper-3.5.6-bin /usr/local/zookeeper-cluster/zookeeper-2
[root@localhost ~]# cp -r  apache-zookeeper-3.5.6-bin /usr/local/zookeeper-cluster/zookeeper-3

(4)创建data目录 ,并且将 conf下zoo_sample.cfg 文件改名为 zoo.cfg

mkdir /usr/local/zookeeper-cluster/zookeeper-1/data
mkdir /usr/local/zookeeper-cluster/zookeeper-2/data
mkdir /usr/local/zookeeper-cluster/zookeeper-3/data

mv  /usr/local/zookeeper-cluster/zookeeper-1/conf/zoo_sample.cfg  /usr/local/zookeeper-cluster/zookeeper-1/conf/zoo.cfg
mv  /usr/local/zookeeper-cluster/zookeeper-2/conf/zoo_sample.cfg  /usr/local/zookeeper-cluster/zookeeper-2/conf/zoo.cfg
mv  /usr/local/zookeeper-cluster/zookeeper-3/conf/zoo_sample.cfg  /usr/local/zookeeper-cluster/zookeeper-3/conf/zoo.cfg

(5) 配置每一个Zookeeper 的dataDir 和 clientPort 分别为2181 2182 2183

修改/usr/local/zookeeper-cluster/zookeeper-1/conf/zoo.cfg

vim /usr/local/zookeeper-cluster/zookeeper-1/conf/zoo.cfg

clientPort=2181
dataDir=/usr/local/zookeeper-cluster/zookeeper-1/data

修改/usr/local/zookeeper-cluster/zookeeper-2/conf/zoo.cfg

vim /usr/local/zookeeper-cluster/zookeeper-2/conf/zoo.cfg

clientPort=2182
dataDir=/usr/local/zookeeper-cluster/zookeeper-2/data

修改/usr/local/zookeeper-cluster/zookeeper-3/conf/zoo.cfg

vim /usr/local/zookeeper-cluster/zookeeper-3/conf/zoo.cfg

clientPort=2183
dataDir=/usr/local/zookeeper-cluster/zookeeper-3/data

1.3 配置集群

(1)在每个zookeeper的 data 目录下创建一个 myid 文件,内容分别是1、2、3 。这个文件就是记录每个服务器的ID

echo 1 >/usr/local/zookeeper-cluster/zookeeper-1/data/myid
echo 2 >/usr/local/zookeeper-cluster/zookeeper-2/data/myid
echo 3 >/usr/local/zookeeper-cluster/zookeeper-3/data/myid

(2)在每一个zookeeper 的 zoo.cfg配置客户端访问端口(clientPort)和集群服务器IP列表。

集群服务器IP列表如下

vim /usr/local/zookeeper-cluster/zookeeper-1/conf/zoo.cfg
vim /usr/local/zookeeper-cluster/zookeeper-2/conf/zoo.cfg
vim /usr/local/zookeeper-cluster/zookeeper-3/conf/zoo.cfg

server.1=192.168.149.135:2881:3881
server.2=192.168.149.135:2882:3882
server.3=192.168.149.135:2883:3883

解释:server.服务器ID=服务器IP地址:服务器之间通信端口:服务器之间投票选举端口

1.4 启动集群

启动集群就是分别启动每个实例。

/usr/local/zookeeper-cluster/zookeeper-1/bin/zkServer.sh start
/usr/local/zookeeper-cluster/zookeeper-2/bin/zkServer.sh start
/usr/local/zookeeper-cluster/zookeeper-3/bin/zkServer.sh start

Dubbo学习

启动后我们查询一下每个实例的运行状态

/usr/local/zookeeper-cluster/zookeeper-1/bin/zkServer.sh status
/usr/local/zookeeper-cluster/zookeeper-2/bin/zkServer.sh status
/usr/local/zookeeper-cluster/zookeeper-3/bin/zkServer.sh status

先查询第一个服务

Dubbo学习

Mode为follower表示是 跟随者(从)

再查询第二个服务Mod 为leader表示是 领导者(主)

Dubbo学习

查询第三个为跟随者(从)

Dubbo学习

1.5 模拟集群异常

(1)首先我们先测试如果是从服务器挂掉,会怎么样

把3号服务器停掉,观察1号和2号,发现状态并没有变化

/usr/local/zookeeper-cluster/zookeeper-3/bin/zkServer.sh stop

/usr/local/zookeeper-cluster/zookeeper-1/bin/zkServer.sh status
/usr/local/zookeeper-cluster/zookeeper-2/bin/zkServer.sh status

Dubbo学习

由此得出结论,3个节点的集群,从服务器挂掉,集群正常

(2)我们再把1号服务器(从服务器)也停掉,查看2号(主服务器)的状态,发现已经停止运行了。

/usr/local/zookeeper-cluster/zookeeper-1/bin/zkServer.sh stop

/usr/local/zookeeper-cluster/zookeeper-2/bin/zkServer.sh status

Dubbo学习

由此得出结论,3个节点的集群,2个从服务器都挂掉,主服务器也无法运行。因为可运行的机器没有超过集群总数量的半数。

(3)我们再次把1号服务器启动起来,发现2号服务器又开始正常工作了。而且依然是领导者。

/usr/local/zookeeper-cluster/zookeeper-1/bin/zkServer.sh start

/usr/local/zookeeper-cluster/zookeeper-2/bin/zkServer.sh status

Dubbo学习

(4)我们把3号服务器也启动起来,把2号服务器停掉,停掉后观察1号和3号的状态。

/usr/local/zookeeper-cluster/zookeeper-3/bin/zkServer.sh start
/usr/local/zookeeper-cluster/zookeeper-2/bin/zkServer.sh stop

/usr/local/zookeeper-cluster/zookeeper-1/bin/zkServer.sh status
/usr/local/zookeeper-cluster/zookeeper-3/bin/zkServer.sh status

Dubbo学习

发现新的leader产生了~

由此我们得出结论,当集群中的主服务器挂了,集群中的其他服务器会自动进行选举状态,然后产生新得leader

(5)我们再次测试,当我们把2号服务器重新启动起来启动后,会发生什么?2号服务器会再次成为新的领导吗?我们看结果

/usr/local/zookeeper-cluster/zookeeper-2/bin/zkServer.sh start

/usr/local/zookeeper-cluster/zookeeper-2/bin/zkServer.sh status
/usr/local/zookeeper-cluster/zookeeper-3/bin/zkServer.sh status

Dubbo学习

我们会发现,2号服务器启动后依然是跟随者(从服务器),3号服务器依然是领导者(主服务器),没有撼动3号服务器的领导地位。

由此我们得出结论,当领导者产生后,再次有新服务器加入集群,不会影响到现任领导者。

Original: https://www.cnblogs.com/Alaskaboo/p/16651731.html
Author: Alaskaboo
Title: Dubbo学习

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/586490/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Spring Cloud Alibaba 最新版发布!

    大家好,我是栈长。 时隔大半年多,Spring Cloud Alibaba 2021.x 终于发布最新版本了,感谢这位粉丝的通知: 最新版本为 2021.0.4.0,上一个版本还是…

    Java 2023年6月15日
    070
  • 熊大同学的面试回忆录(2.5年开发经验)

    今天去看牙医,他问我年级轻轻牙齿怎么磨损这么严重?我说,没有点赞的这些年,我都是咬着牙过来的。 以下为读者面试后的分享,部分回答笔者做了一些补充整理,希望对你有帮助。(两年左右开发…

    Java 2023年5月29日
    058
  • Jedis管道操作

    Jedis管道操作 当我们有10000条数据要存储到redis中,使用原始方式存: @Test public void tenThousandTest(){ Jedis jedis…

    Java 2023年6月8日
    054
  • Java日志框架:logback详解

    为什么使用logback 记得前几年工作的时候,公司使用的日志框架还是log4j,大约从16年中到现在,不管是我参与的别人已经搭建好的项目还是我自己主导的项目,日志框架基本都换成了…

    Java 2023年5月29日
    063
  • Netty源码分析之ChannelPipeline(四)—出站事件的传播

    上篇文章中我们梳理了ChannelPipeline中入站事件的传播,这篇文章中我们看下出站事件的传播,也就是ChannelOutboundHandler接口的实现。 1、出站事件的…

    Java 2023年6月9日
    066
  • 删除重复值的结点

    删除重复值的结点 问题重述: 给定一个无序单链表的头节点head,删除其中值重复出现的结点 问题分析: 这道题要删除重复值的结点,我们可以想到哈希表,因为哈希表是无序不重复的,我们…

    Java 2023年6月7日
    047
  • Cron表达式(七子表达式)

    秒 分 时 日 月 周 年 可用的值 0~59 0~59 0~23 1~31 1~12(JAN-DEC) 1~7(SUN-SAT) 1970~2099 可用的通配符 , &#821…

    Java 2023年6月8日
    057
  • [转]OpenMP中几个容易混淆的函数(线程数量/线程ID/线程最大数)以及并行区域线程数量的确定

    说明:这部分内容比较基础,主要是分析几个容易混淆的OpenMP函数,加以理解。 (1)并行区域数量的确定: 在这里,先回顾一下OpenMP的parallel并行区域线程数量的确定,…

    Java 2023年5月29日
    061
  • SpringCloud Alibaba Nacos 服务治理中心

    一、什么是Nacos? 二、Nacos能干吗? 三、Nacos关键特性 四、Nacos中的基本概念 五、如何安装部署Nacos? 六、Nacos数据持久化 一、什么是Nacos? …

    Java 2023年6月5日
    065
  • Java基础语法(三)

    Java基础语法(三) 不积跬步,无以至千里;不积小流,无以成江海。 ——荀子《劝学》 Java基础语法(三) – 十六、方法 十七、命令行传参(扩展) 十八、可变参数…

    Java 2023年6月9日
    076
  • 并查集快速查找,快速合并

    并查集基础 一、概念及其介绍 并查集是一种树型的数据结构,用于处理一些不相交集合的合并及查询问题。 并查集的思想是用一个数组表示了整片森林(parent),树的根节点唯一标识了一个…

    Java 2023年6月5日
    060
  • MinIO简介和java Api的使用

    MinIO是一个对象存储服务,非常轻量,也提供了多种语言的api,可以非常方便使用。 存储桶 minio中的bucket桶 MinIO将存储空间分为多个部分,称为bucket桶,文…

    Java 2023年6月6日
    077
  • HIT软构博客3–javaI/O(FileReader、BufferedReader) 学习在Lab1中使用的java I/O类

    通过 Java I/O API 在 Java 中执行文件处理。 在 Java 中,自动为我们创建了 3 个流。所有这些流都与控制台相连。 1) System.out:标准输出流 2…

    Java 2023年6月5日
    0102
  • 加深对AQS原理的理解示例一:实现一个独占锁

    基于AQS语法自己定义的独占锁 只是一个简单的版本,非常粗糙,只为了加深对AQS原理理解。但还有一些列问题有待解决,比如锁的重入,锁不允许被其他线程中断等! /** *@Desc …

    Java 2023年6月15日
    065
  • Android 快速点击的处理

    为了对付拥有麒麟臂的测试人员或者用户对我们的按钮等控件展开惨无人道的快速啄击。厮以为可以用如下方法: 1 setEnabled 大法;在用户点击发生后调用setEnable(fal…

    Java 2023年6月9日
    050
  • Kotlin协程解析系列(上):协程调度与挂起

    vivo 互联网客户端团队- Ruan Wen 本文是Kotlin协程解析系列文章的开篇,主要介绍Kotlin协程的创建、协程调度与协程挂起相关的内容 一、协程引入 Kotlin …

    Java 2023年6月15日
    074
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球