Vertx入门学习(含代码)

article/2025/8/21 5:55:12

Vertx入门学习

  • 一、Vertx是什么?
  • 二、Vertx基本概念
  • 三、Vertx能干什么?
  • 四、Vertx的技术体系
  • 五、快速体验:搭建一个简单的Vertx项目并输出Hello World
  • 六、单元测试
  • 总结

一、Vertx是什么?

github: https://github.com/vert-x3
官网:http://vertx.io/

Vert.x诞生于2011年,当时叫node.x,不过后来因为某些原因改名为Vert.x,目前官网最新版本是4.4.0,官网上介绍Vert.x是一个用于在JVM上构建高效应用程序的工具包,是JVM上的Reative开发套件。说白了,Vert.x就是一堆的jar包,提供了一系列的编程API接口,通过这些API可以实现异步编程。
Vert.x目前是我见过功能最强大、对第三方库依赖最少的Java框架,是一个异步无阻塞的网络框架,其参照物是node.js,基本上node.js能干的事情,Vert.x都能干,它只依赖Netty4以及Jacskon,Vert.x利用Netty4的EventLoop来做单线程的事件循环,所以跑在Vert.x上的业务不能做CPU密集型的运算,这样会导致整个线程被阻塞,另外如果你需要建立分布式的Vert.x,则再依赖HazelCast这个分布式框架即可,注意Vert.x3必须基于Java8。由于基于JVM,所以Vert.x可以用其他语言来实现你的业务。
异步编程怎么理解呢?对于写过ajax的人来说,不难理解,$.ajax方法并不会阻塞,而是直接向下执行,等到远程服务器响应之后,才会回调success方法,那么这时候success方法才会执行。ajax下面的代码不会等到success方法执行完毕之后再执行,这就是所谓的异步。如下:

console.log("1");
$.ajax({"url" : "/hello","type" : "post","dataType" : "json","success" : function(val) {console.log("2");}
});
console.log("3");

浏览器会先输出1,在hello方法没有相应之前不会输出2,但是会先输出3,等接口响应success之后会输出2,这就是异步,异步编程是Vert.x的一大特性,也是Vert.x的核心,Vert.x可以开发Web应用,但Vert.x不仅仅是一个Web开发框架,他更像Spring,是一个技术栈(Vert.x生态可以查看https://github.com/vert-x3/vertx-awesome),或者说是一个Vert.x生态体系。在这个体系中,Vert.x只是提供了Web开发的能力。下面对Vertx和Spring做一个对比:

项目SpringVertx
核心框架spring-corevertx-core
Web开发spring-webmvcvertx-web
jdbc框架spring-jdbcvertx-jdbc-client
redisspring-data-redisvertx-redis-client
微服务spring-cloudvertx-hazelcast

可以说,很多spring能做的事情,Vertx也都能实现。那么既然如此,Spring如此强大,社区如此活跃,为何还会有Vertx呢?他们之前区别的核心点就只有一个:Spring的操作是同步的,Vertx的操作是异步的。异步带来了更高的性能,但同时也带来了编码和调试的复杂度,但不得不说异步可能是未来的一个趋势,至少在Java实现高性能服务器上的一个趋势。
在Java领域,做Web开发我们一般有很多的选择,比如使用原生的Servlet,比如使用SpringMVC,再比如使用Struts等等总之你有很多的选择。在国内,目前来讲,SpringMVC作为Spring体系下的Web层架构,是深受企业青睐的,绝大部分的企业可能都在使用SpringMVC,而对于我们今天要说的Vert.x这个Web层框架,却很少有人知道,但它却是仅次于SpringMVC,排名第二的一个Web层框架。
Vert.x是基于事件的,提供一个事件驱动编程模型,使用Vert.x作为服务器时,程序员只要编写事件处理器event handler即可,当TCP socket有数据时,event handler理解被创建调用,另外它还可以在以下几种情况激活: ‘当事件总线Event Bus接受到消息时,’ ‘当接收到HTTP消息时,’ 当一个连接断开时’,’ ‘当计时器超时时.’
作为服务层处理逻辑这一层基本上对应的传统Java里的领域模型处理层,各种Service调用以及对数据层的调用,差不多是一个承上启下的一层,传统的模型里,这一层基本上都是同步调用,即使有异步调用,也是与业务逻辑分离的异步,如果全异步会导致业务逻辑碎乱,代码很难描述清楚,到这里你会发现Vert.x其实不太好融合到业务性很强的服务层里,其主要原因如下
1、自身是异步体系,不适合描述顺序逻辑性强的业务。
2、由于异步的问题,访问数据层也必须是异步,导致业务模型进一步碎片化。

二、Vertx基本概念

我们学习一个新东西,都要去了解理解它的基本概念,学习Vert.x也是如此。那么Vert.x又有哪些基本概念呢?

  • Verticle:Vert.x的执行单元,即程序的入口,它可以用JS、Ruby、Java等多语言来编写,每个语言可能实现的方式不一样,比如Java需要继承一个AbstractVerticle抽象类。在同一个Vert.x实例中可以同时执行多个Verticle,一个应用可能由多个Verticle组成,它们被部署到不同的网络节点上,彼此之间通过在Vert.x的事件总线(event bus)上交换信息来通信。
  • Module:Vert.x应用由一个或者多个modules来实现,一个module由多个verticles来实现,所以可以把module理解为Java package,里面可能是特定业务的实现或者公共的服务实现(那些可以重用的服务),Vert.x编写好的module可以发布到maven的仓库里,以zip包装成二进制格式,或者发布到vert.x module 注册中心,实际上这种以模块方式的开发,支撑着整个Vert.x生态系统。
  • Event Loops:事件循环,是由Vert.x启动的事件处理线程,也是Vert.x项目对外开放的入口,Vert.x由此接收请求事件,一个Vert.x由一个或者多个事件循环线程组成,线程最大数为主机有效的CPU核数。处理函数是handler接口,用来处理事件。
  • Event Loop verticle:事件的业务处理线程,存在于Event Loop中,用于处理非阻塞短任务。
  • Event bus:是Vert.x的核心,在集群中容器之间的通信,各个Verticle之间的通信也都是经过Event bus来实现的,所以Event bus存在堵塞的可能。
  • Shared Data(共享数据):消息通过bus可以在各个Vert.x实例直接传输,但是如果多个Verticle在一个Vert.x实例内,是可以避免进行消息传输的,比如单个JVM内,你不会通过两个socket互相在两个Java对象之间传输消息的,这是同样的道理,但是因为实例隔离,因为actor模型,所以对象数据如果要传输到handler里必须通过消息传输。Shared Data是Vert.x提供的一个简单共享map和set,用来解决各个Verticle之间的数据共享的,数据被存储到一个不可变的数据结构里,各个实例可以直接通过此API获取数据。
  • Worker Verticle(阻塞处理):事件处理之外肯定会发生长时间数据处理请求,比如处理一个图片上传,然后转存到磁盘等,此时就需要事件的业务处理线程用来处理长时间阻塞任务,worker verticle就是这个阻塞处理线程,是一种阻塞式的方法,但是无法做到并发水平扩展,在Verticle类型中有一种特别的verticle叫做worker,与标准的verticle不同的是它采用的是vert.x内部的另外一种线程池叫做worker pool,而不是使用event loop ,worker verticle不会并行的执行handler,而是阻塞式的,等前一个handler处理完了才会执行后面的请求,这种的适合CPU密集型的,标准的verticle适合IO密集型的。vert.x为了支持标准的和阻塞的worker verticle提供了一种混合线程模型,你可以根据自己的需求按需选择合适的线程模型。
    纯文字的,可能没什么概念,下面我们来看一下Vertx的框架图,加深印象,便于理解:
    在这里插入图片描述

三、Vertx能干什么?

一句话总结:Java能做的,Vert.x都能做。咱这里主要列出来Vert.x擅长做什么?

  • Web开发,Vert.x封装了Web开发常用的组件,支持路由、Session管理、模板等,可以非常方便的进行Web开发。不需要容器!不需要容器!不需要容器!
  • TCP/UDP开发,Vert.x底层基于Netty,提供了丰富的IO类库,支持多种网络应用开发。不需要处理底层细节(如拆包和粘包),注重业务代码编写。
  • 提供对WebSocket的支持,可以做网络聊天室,动态推送等。
  • Event Bus(事件总线)是Vert.x的神经系统,通过Event Bus可以实现分布式消息,远程方法调用等等。正是因为Event Bus的存在,Vert.x可以非常便捷的开发微服务应用。
  • 支持主流的数据和消息的访问redis mongodb rabbitmq kafka 等。
  • 分布式锁,分布式计数器,分布式map的支持。

四、Vertx的技术体系

上面也提到了,Vert.x和Spring一样,也有着完善的生态,具体可以查看https://github.com/vert-x3/vertx-awesome 我们可以看到,每一块内容都提供了多种的实现,有官方支持的版本还有社区版本。下面我们具体介绍下技术体系中官方支持的版本。

  • 核心模块。Vert.x核心模块包含一些基础的功能,如HTTP,TCP,文件系统访问,EventBus、WebSocket、延时与重复执行、缓存等其他基础的功能,你可以在你自己的应用程序中直接使用。可以通过vertx-core模块引用即可。
  • web模块。Vert.x Web是一个工具集,虽然核心模块提供了HTTP的支持,但是要开发复杂的Web应用,还需要路由、Session、请求数据读取、Rest支持等等还需要Web模块,这里提供了上述的这些功能的API,便于开发,除了对Web服务的开发以外,还提供了对Web客户端请求的支持,通过vertx-web-client即可方便的访问HTTP服务。有朋友可能会有疑惑,我明明可以使用JDK提供的URL来请求HTTP服务啊,使用Vert.x一定要注意,Vert.x是一个异步框架,请求HTTP服务是一个耗时操作,所有的耗时,都会阻塞Event Bus,导致整体性能被拖垮,因此,对于请求Web服务,一定要使用Vert.x提供的vertx-web-client模块。
  • 数据访问模块:Vert.x提供了对关系型数据库、NoSQL、消息中间件的支持,传统的客户端因为是阻塞的,会严重影响系统的性能,因此Vert.x提供了对以上客户端的异步支持。具体支持的数据访问如下:MongoDB client,JDBC client,SQL common,Redis client,MySQL/PostgreSQLclient。
  • Reactive响应式编程:复杂的异步操作会导致异步回调地狱的产生,看下面的代码,这是我在Vert.x提供的例子中找到的,我们不去管这段代码干了啥,只是看后面的}就很惊讶了,如果操作更为复杂一些,会嵌套的层次更多,通过reactive可以最小化的简化异步回调地狱。
// create a test table
execute(conn.result(), "create table test(id int primary key, name varchar(255))", create -> {// start a transactionstartTx(conn.result(), beginTrans -> {// insert some test dataexecute(conn.result(), "insert into test values(1, 'Hello')", insert -> {// commit datarollbackTx(conn.result(), rollbackTrans -> {// query some dataquery(conn.result(), "select count(*) from test", rs -> {for (JsonArray line : rs.getResults()) {System.out.println(line.encode());}// and close the connectionconn.result().close(done -> {if (done.failed()) {throw new RuntimeException(done.cause());}});});});});});
});

再看一个使用Reactive2构建的多步操作的代码,paramCheckStep,insertPayDtlStep,requestStep等等都是异步方法,但这里就很好的处理了异步回调的问题,不再有那么多层的大括号,代码结构也geng

public void scanPay(JsonObject data, Handler<AsyncResult<JsonObject>> resultHandler) {paramCheckStep(data) // 参数校验.flatMap(this::insertPayDtlStep) // 插入流水.flatMap(x -> requestStep(x, config)) // 请求上游.flatMap(this::cleanStep) //参数清理.subscribe(ok -> {logger.info("成功结束");resultHandler.handle(Future.succeededFuture(ok));},err -> {logger.error("正在结束", err);resultHandler.handle(Future.failedFuture(err));});
}
  • 整合其他模块
    • 邮件客户端。Vert.x提供了一简单STMP邮件客户端,所以你可以在应用程序中发送电子邮件。
    • STOMP客户端与服务端。Vert.x提供了STOMP协议的实现包括客户端与服务端。
    • Consul Client。consul是google开源的一个使用go语言开发的服务发现、配置管理中心服务。内置了服务注册与发现框 架、分布一致性协议实现、健康检查、Key/Value存储、多数据中心方案。
    • RabbitMQ Client Kafka Client。消息队里的客户端支持。
    • JCA适配器。Vert.x提供了Java连接器架构适配器,这允许同任意JavaEE应用服务器进行互操作。
  • 认证与授权:Vert.x提供了简单API用于在应用中提供认证和授权。
    • Auth common 通用的认证API,可以通过重写AuthProvider类来实现自己的认证。
    • JDBC auth 后台为JDBC的认证实现。
    • JWT auth 用JSON Web tokens认证实现。
    • Shiro auth 使用Apache Shiro认证实现。
    • MongoDB auth MongoDB认证实现。
    • OAuth 2 Oauth2协义认证实现。
    • htdigest auth 这个是新增一种认证的支持
  • 微服务:Vert.x提供多个组件构建基于微服务的应用程序。比如服务发现(Vert.x Service Discovery)、断路器(Vert.x Circuit Breaker)、配置中心(Vert.x Config)等。

五、快速体验:搭建一个简单的Vertx项目并输出Hello World

首先新建一个Maven项目,然后在pom.xml中加入相关的依赖和插件,如下:

<?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>org.example</groupId><artifactId>vertxone</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><vertx.version>4.0.0</vertx.version><main.class>org.example.Main</main.class></properties><dependencies><dependency><groupId>io.vertx</groupId><artifactId>vertx-core</artifactId><version>${vertx.version}</version></dependency></dependencies><build><plugins><plugin><artifactId>maven-compiler-plugin</artifactId><version>3.3</version><configuration><source>1.8</source><target>1.8</target></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-shade-plugin</artifactId><version>3.2.4</version><executions><execution><phase>package</phase><goals><goal>shade</goal></goals><configuration><transformers><transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"><manifestEntries><Main-Class>${main.class}</Main-Class></manifestEntries></transformer></transformers><artifactSet/><outputFile>${project.build.directory}/${project.artifactId}-${project.version}-prod.jar</outputFile></configuration></execution></executions></plugin></plugins></build>
</project>

跟其它Maven项目一样,我们首先定义了项目的GroupId,ArtifactId以及版本号,随后我们定义了两个属性,分别是:vertx.version,也就是Vert.x的版本号,此处我们使用最新的Vert.x版本,也就是4.4.0;以及main.class,也就是我们要使用的包含有main函数的主类。之后我们引入了两个Maven插件,分别是maven-compiler-plugin和maven-shade-plugin,前者用来将.java的源文件编译成.class的字节码文件,后者可将编译后的.class字节码文件打包成可执行的jar文件,俗称fat-jar。
然后我们在src/main/java/org/example目录下新建两个java文件,分别是Main.java和MyFirstVerticle.java,代码如下:

Main.java

package org.example;import io.vertx.core.Vertx;/*** @author dxm* @description* @ClassName* @date 2023-03-14 15:19*/
public class Main {public static void main(String[] args) {Vertx vertx = Vertx.vertx();vertx.deployVerticle(MyFirstVerticle.class.getName());}
}

MyFirstVerticle.java

package org.example;import io.vertx.core.AbstractVerticle;/*** @author dxm* @description* @ClassName* @date 2023-03-14 15:25*/
public class MyFirstVerticle extends AbstractVerticle {public void start() {vertx.createHttpServer().requestHandler(req -> {req.response().putHeader("content-type", "text/plain").end("Hello World222!");}).listen(8080);}
}

然后用Maven的mvn package命令打包,随后在src的同级目录下会出现target目录,进入之后,会出现vertxone-1.0-SNAPSHOT.jar和vertxone-1.0-SNAPSHOT-prod.jar两个jar文件,后者是可执行文件,在有图形界面的操作系统中,您可双击执行或者用以下命令:java -jar vertxone-1.0-SNAPSHOT-prod.jar执行,然后打开浏览器,在浏览器的地址栏中输入:http://localhost:8080/ 便可看到熟悉的Hello World!啦。
在这里插入图片描述
我们也可以使用Launcher来替代Main类,这也是官方推荐的方式,在pom.xml中加入main.verticle属性,并将该属性值设置为maven-shade-plugin插件的manifestEntries的Main-Verticle对应的值,最后修改main.class为io.vertx.core.Launcher,修改后的pom.xml如下:

<?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>org.example</groupId><artifactId>vertxone</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><vertx.version>4.0.0</vertx.version><main.class>io.vertx.core.Launcher</main.class><main.verticle>org.example.MainVerticle</main.verticle></properties><dependencies><dependency><groupId>io.vertx</groupId><artifactId>vertx-core</artifactId><version>${vertx.version}</version></dependency></dependencies><build><plugins><plugin><artifactId>maven-compiler-plugin</artifactId><version>3.3</version><configuration><source>1.8</source><target>1.8</target></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-shade-plugin</artifactId><version>3.2.4</version><executions><execution><phase>package</phase><goals><goal>shade</goal></goals><configuration><transformers><transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"><manifestEntries><Main-Class>${main.class}</Main-Class><Main-Verticle>${main.verticle}</Main-Verticle></manifestEntries></transformer></transformers><artifactSet/><outputFile>${project.build.directory}/${project.artifactId}-${project.version}-prod.jar</outputFile></configuration></execution></executions></plugin></plugins></build></project>

然后在src/main/java/org/example目录下新增MainVerticle.java文件,代码如下:

package org.example;import io.vertx.core.AbstractVerticle;/*** @author dxm* @description* @ClassName* @date 2023-03-14 3:48 PM*/
public class MainVerticle extends AbstractVerticle {public void start() throws Exception {vertx.deployVerticle(MyFirstVerticle.class.getName());}
}

然后重新打包后执行,便可再次看到Hello World!。

六、单元测试

下面我们将会介绍测试部分,首先引入两个新的测试依赖,修改后的pom.xml如下:

<?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>org.example</groupId><artifactId>vertxone</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><vertx.version>4.0.0</vertx.version><main.class>io.vertx.core.Launcher</main.class><main.verticle>org.example.MainVerticle</main.verticle></properties><dependencies><dependency><groupId>io.vertx</groupId><artifactId>vertx-core</artifactId><version>${vertx.version}</version></dependency><dependency><groupId>io.vertx</groupId><artifactId>vertx-unit</artifactId><version>${vertx.version}</version><scope>test</scope></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope></dependency></dependencies><build><plugins><plugin><artifactId>maven-compiler-plugin</artifactId><version>3.3</version><configuration><source>1.8</source><target>1.8</target></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-shade-plugin</artifactId><version>3.2.4</version><executions><execution><phase>package</phase><goals><goal>shade</goal></goals><configuration><transformers><transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"><manifestEntries><Main-Class>${main.class}</Main-Class><Main-Verticle>${main.verticle}</Main-Verticle></manifestEntries></transformer><!--多语言支持在打包时需加入以下转换器--><transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"><resource>META-INF/services/io.vertx.core.spi.VerticleFactory</resource></transformer></transformers><artifactSet/><outputFile>${project.build.directory}/${project.artifactId}-${project.version}-prod.jar</outputFile></configuration></execution></executions></plugin></plugins></build>
</project>

随后在src/test/java/org/example目录下新增MyFirstVerticleTest.java文件:

package org.example;
import io.vertx.core.Vertx;
import io.vertx.ext.unit.Async;
import io.vertx.ext.unit.TestContext;
import io.vertx.ext.unit.junit.VertxUnitRunner;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;/*** @author dxm* @description* @ClassName* @date 2023-03-14 3:56 PM*/
@RunWith(VertxUnitRunner.class)
public class MyFirstVerticleTest {private Vertx vertx;@Beforepublic void setUp(TestContext context){vertx = Vertx.vertx();vertx.deployVerticle(MyFirstVerticle.class.getName(), context.asyncAssertSuccess());}@Afterpublic void tearDown(TestContext context) {vertx.close(context.asyncAssertSuccess());}@Testpublic void testApplication(TestContext context) {final Async async = context.async();vertx.createHttpClient().getNow(8080, "localhost", "/", response -> {response.handler(body -> {context.assertTrue(body.toString().contains("Hello"));async.complete();});});}
}

执行该测试案例便可得到期望的结果,有兴趣的可以练习一下。

总结

最后呢,我想说咱程序员不能只会一种语言,开发框架也不能只知道Spring,也得去了解学习接触一些其他的框架,拓展自己的知识面,在后面解决问题的时候,你就会发现,书到用时方恨少,所以还是要在日常进行不断的积累和总结,然后在适当的场景下选择合适的技术选型来解决问题,适合自己的才是最好的,最后给大家布置一个作业,就是结合自己现在的项目结构分层写一下增删改查的接口,感兴趣的你,赶紧去试试吧。


http://chatgpt.dhexx.cn/article/fSng31YJ.shtml

相关文章

Vert.x(vertx) 简明介绍

摘要 Vert.x最大的特点就在于异步&#xff08;底层基于Netty&#xff09;&#xff0c;通过事件循环&#xff08;EventLoop&#xff09;来调起存储在异步任务队列&#xff08;CallBackQueue&#xff09;中的任务&#xff0c;大大降低了传统阻塞模型中线程对于操作系统的开销。因…

Vertx学习一:这玩意是到底是个啥

Vertx&#xff0c;融合Java、Ruby、Python等语言的高性能架构&#xff0c;架构师必读 原文链接&#xff1a; http://www.360doc.com/content/18/0203/14/39530679_727432611.shtml 目录&#xff1a; 一、Vert.x简介 二、Vert.x原理解析 三、Vert牛刀小试 四、Vert应用实践 五…

【java】vertx从入门到放弃——入门(四)Codec

什么是Codec&#xff1f;概念这个玩意我是真不想说&#xff0c;毕竟我没有找到具体的概念&#xff0c;我自己大致的理解就是&#xff0c;用EventBus传输类的时候&#xff0c;对这个类进行序列化和反序列化的东西&#xff0c;因为vertx使用json进行传输&#xff0c;所以这个玩意…

Android thinker

国家虽安&#xff0c;忘战必危&#xff0c; Android虽爽&#xff0c;不学则忙&#xff0c;老夫纵横江湖数十载&#xff0c;深谙世事之难料&#xff0c;顾。。 ok&#xff0c;ok 不装比了&#xff0c;进入正题&#xff0c;今天要讲的是Android 热修之 thinker。 在研究这个之前…

ESP32-CAM AI THINKER 引脚排列:GPIO 用法说明

ESP32-CAM 是一款开发板,带有一个 ESP32-S 芯片、一个 OV2640 摄像头、microSD 卡插槽和几个用于连接外设的 GPIO。在本指南中,我们将介绍 ESP32-CAM GPIO 以及如何使用它们。 引脚排列图 下图显示了 ESP32-CAM AI-Thinker 的引脚排列图。 电路原理示意图 下图显示了 ESP…

Thinkpad 各系列简介

ThinkPad 各系列简介 如果提到商务笔记本&#xff0c;大家一定会想到凭借坚固和可靠的特性在业界享有很高声誉ThinkPad笔记本电脑&#xff0c;以及ThinkPad那经典的键盘红点设计和纯黑低调的外表。 在这里我就简单介绍一下ThinkPad的各系列产品。 Thinkpad名称来历 “ThinkP…

python thinker canvas create_arc 使用详解

版权声明&#xff1a;本文为博主原创文章&#xff0c;遵循 CC 4.0 BY-SA 版权协议&#xff0c;转载请附上原文出处链接和本声明。 本文链接&#xff1a;https://blog.csdn.net/A757291228/article/details/106739556 ———————————————— 版权声明&#xff1a;本文…

二、让界面动起来,Python基于thinker实现的简单的俄罗斯方块小游戏

文章目录 界面动起来定时刷新页面移动俄罗斯方块 界面动起来 **功能&#xff1a;**如何让方块「动起来」? 分析过程&#xff1a; 要想让方块动起来&#xff0c;需要实现以下两点&#xff1a; 定时刷新页面移动页面内部的俄罗斯方块 定时刷新页面 实现定时刷新页面&#xff…

三、生成随机方块,Python基于thinker实现的简单的俄罗斯方块小游戏

文章目录 生成第一步&#xff1a;随机生成方块对象第二步&#xff1a;修改游戏运行方法 固定第一步&#xff1a;记录固定的方块第二步&#xff1a;修改check_move方法 左右移动第一步&#xff1a;左右移动方块第二步&#xff1a;绑定键盘 旋转第一步&#xff1a;添加旋转方法第…

【G-thinker】G-thinker部分源码解析

一、main 子图匹配程序run.cpp中主要使用到worker.h和comper.h分别对应线程和进程单位&#xff0c;接下来我们从main函数入手解析源码 从主函数可以看到&#xff0c;子图匹配程序中GMatchWorker继承了worker&#xff0c;主函数声明了workerparams并且传入了路径和线程参数&am…

python用thinker库制作一个进制转换器(可打包exe)

进制类型分为&#xff1a; 二进制 字母B表示 八进制 字母O表示 十进制 字母D表示 十六机制 字母H表示 进制转换之间很麻烦&#xff0c;还得计算&#xff0c;如果可以做一个进制转换器多nice&#xff0c;其实也不难&#xff0c;就利用一个tkinter库就能制作&#xff0c;废话不多…

Thinker Board 2开发板上使用奥比中光 astra 深度相机

Thinker Board 2 国产开发板 arm架构 上使用奥比中光 astra 深度相机 准备工作 1、下载astraSDK 选择linux_arm 下载 https://developer.orbbec.com.cn/download.html?id53 2、下载openNI https://dl.orbbec3d.com/dist/openni2/OpenNI_2.3.0.66.zip 开始安装 1、安装fre…

think

我167&#xff0c;97斤&#xff0c;胸d&#xff0c;腰很细&#xff0c;反手轻松摸肚脐那种&#xff0c;骨架小&#xff0c;总结就是身高刚好人瘦胸大屁股大腿细腰细肤白。走路腰杆能挺到天上&#xff0c;气质挺好。漂亮女生太多了&#xff0c;想取胜只能从气质下手了。脸呢&…

Python基于thinker实现的简单的俄罗斯方块小游戏源代码:一、搭建界面

文章目录 一、搭建界面搭建基础窗体第一步&#xff1a;创建画板大小第二步&#xff1a;在画板上作画 绘制俄罗斯方块第一步&#xff1a;绘制o形俄罗斯方块第二步&#xff1a;绘制其他形状方块 记录俄罗斯方块小游戏的游戏思路和过程 一、搭建界面 **目标&#xff1a;**搭建基础…

thinker board s debian系统安装配置

thinker board s debian系统安装配置 好多年前买了一块thinker board s&#xff0c;装安卓系统来用&#xff0c;结果经常性卡死不知道为啥&#xff0c;可能是供电问题&#xff0c;也可能是系统bug&#xff0c;之后就吃灰不怎么用了&#xff0c;最近想装一个计算服务器&#xff…

python利用thinker制作多页面切换的桌面应用实例教程

本篇文章主要讲解&#xff0c;python利用thinker制作多页面的桌面实例教程。可以在一个主界面中相互进行切换和设置相关的表单信息&#xff0c;布局等方法 代码片段的实际效果 视频演示&#xff1a; python使用thinker制作多窗口代码片段实例效果 gif动态图&#xff1a; 构建…

模型思维-THE MODEL THINKER

序言这本书是怎样写成的 Part1为什么需要模型思维 01做一个多模型思考者 使用模型来思考能够带给你的&#xff0c;远远不仅仅是工作绩效的提高。它还会使你成为一个更优秀的人&#xff0c;让你拥有更强的思考能力。你将更擅长评估层出不穷的经济事件和政治事件&#xff0c;更能…

展示一下用thinker做小软件的UI

有一个大坑给大家分享一下。ttk.Treeview可以改变列宽&#xff0c;却不能改变某一行的行高&#xff08;可以改变整体的行高&#xff09;&#xff0c;其实就是Treeview没有自动换行功能&#xff0c;很痛苦&#xff0c;很折磨&#xff0c;......我一度放弃thinker&#xff0c;因为…

Python Thinker GUI的组件的简单总结

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、Label二、Button三、Entry四、Text五、CheckButton六、RadioButton七、Menu八、Canvas九、Scale 前言 例如&#xff1a;随之前学过Java的基础&#xff0c;…

Thinker 使用详解

文章目录 Tinker基本介绍它主要包含以下几部分&#xff1a;为什么使用 Tinker Tinker 执行原理及流程简单的使用 Tinker1,在项目的gradle.properties 中添加2,在项目的 gradle中添加&#xff1a;3,在 app 中的 gradle 中添加&#xff1a;4,接着进行初始化&#xff0c;新建一个类…