linux C++ 环境下的ActiveMQ学习

2023-05-16

ActiveMQ

1.概述

ActiveMQ 是Apache出品,最流行的、功能强大的即时通讯和集成模式的开源服务器。ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现。提供客户端支持跨语言和协议,带有易于在充分支持JMS 1.1和1.4使用J2EE企业集成模式和许多先进的功能。

2.特点

2.⒈ 多种语言和协议编写客户端。语言: Java,C,C++,C#,Ruby,Perl,Python,PHP。应用协议: OpenWire,Stomp REST,WS Notification,XMPP,AMQP

●完全支持JMS1.1和J2EE 1.4规范 (持久化,XA消息,事务)

●对Spring的支持,ActiveMQ可以很容易内嵌到使用Spring的系统里面去,而且也支持Spring2.0的特性

●通过了常见J2EE服务器(如 Geronimo,JBoss 4,GlassFish,WebLogic)的测试,其中通过JCA 1.5 resource adaptors的配置,可以让ActiveMQ可以自动的部署到任何兼容J2EE 1.4 商业服务器上

●支持多种传送协议:in-VM,TCP,SSL,NIO,UDP,JGroups,JXTA

●支持通过JDBC和journal提供高速的消息持久化

● 从设计上保证了高性能的集群,客户端-服务器,点对点

●支持Ajax

●支持与Axis的整合

●可以很容易的调用内嵌JMS provider,进行测试

3.安装测试

ActiveMQ服务安装

开发环境

windows64 PC

下载最新版本5.15.0release, 解压apache-activemq-5.15.0-bin.zip(或者apache-activemq-5.15.0-bin.tar.gz)目录如下:

+bin (windows下面的bat和unix/linux下面的sh)

+conf (activeMQ配置目录,包含最基本的activeMQ配置文件)

+data (默认是空的)

+docs (index,replease版本里面没有文档,-.-b不知道为啥不带)

+example (几个例子

+lib (activemMQ使用到的lib)

-apache-activemq-4.1-incubator.jar (ActiveMQ的binary)

-LICENSE.txt

-NOTICE.txt

-README.txt

-user-guide.html

你可以使用bin\win64\activemq.bat(activemq) 启动,如果一切顺利的话,你就会看见类似下面的信息:

但若出现如下类似信息

 

则查看或修改配置文件E:\apache-activemq-5.15.0\apache-activemq-5.15.0\conf\jetty中的host\port是否有误

服务已经启动。。。。。。。。。。。。。。。。。。。

我们可以web访问一下下 --------->192.168.8.107:8161

接着我们在一块开发板上安装c++实现的ActiveMQ客户端库ActiveMQ_cpp,可搜索下载

开发环境

RK3288(ubuntu)

安装步骤:

依赖安装

下载apr-1.6.3.tar    apr-iconv-1.2.2.tar  apr-util-1.6.1.tar  cppunit-1.12.1.tar 

分别解压默认安装进入目录执行./configure 执行 make && make install

下载activemq-cpp-library-3.9.4-src.tar

解压执行./configure  --with-apr=/usr/local/apr/ --with-cppunit=/usr/local/cppunit/ 

执行make && make install

一切准备就绪,则我们实现一个demo直接贴代码


#include <decaf/lang/Thread.h>
#include <decaf/lang/Runnable.h>
#include <decaf/util/concurrent/CountDownLatch.h>
#include <decaf/lang/Long.h>
#include <decaf/util/Date.h>
#include <activemq/core/ActiveMQConnectionFactory.h>
#include <activemq/util/Config.h>
#include <activemq/library/ActiveMQCPP.h>
#include <cms/Connection.h>
#include <cms/Session.h>
#include <cms/TextMessage.h>
#include <cms/BytesMessage.h>
#include <cms/MapMessage.h>
#include <cms/ExceptionListener.h>
#include <cms/MessageListener.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <memory>

using namespace activemq;
using namespace activemq::core;
using namespace decaf;
using namespace decaf::lang;
using namespace decaf::util;
using namespace decaf::util::concurrent;
using namespace cms;
using namespace std;


class SimpleProducer : public Runnable {
private:
    CountDownLatch latch;
    Connection* connection;
    Session* session;
    Destination* destination;
    MessageProducer* producer;
    bool useTopic;
    bool clientAck;
    unsigned int numMessages;
    std::string brokerURI;
    std::string destURI;

private:

    SimpleProducer( const SimpleProducer& );
    SimpleProducer& operator= ( const SimpleProducer& );

public:

    SimpleProducer( const std::string& brokerURI, unsigned int numMessages,
                    const std::string& destURI, bool useTopic = false, bool clientAck = false ) :
        latch(1),
        connection(NULL),
        session(NULL),
        destination(NULL),
        producer(NULL),
        useTopic(useTopic),
        clientAck(clientAck),
        numMessages(numMessages),
        brokerURI(brokerURI),
        destURI(destURI) {
    }

    virtual ~SimpleProducer(){
        cleanup();
    }

    void close() {
        this->cleanup();
    }

    void waitUntilReady() {
        latch.await();
    }
    virtual void run() {
        try {
            auto_ptr<ActiveMQConnectionFactory> connectionFactory(new ActiveMQConnectionFactory( brokerURI ) );

		   try{
                connection = connectionFactory->createConnection();
                connection->start();
            } catch( CMSException& e ) {
                e.printStackTrace();
                printf("%s..........\n",e.getStackTraceString());
                throw e;
            }

            if( clientAck )
			{
                session = connection->createSession( Session::CLIENT_ACKNOWLEDGE );
            } else
			{
                session = connection->createSession(Session::AUTO_ACKNOWLEDGE );
            }

            if( useTopic )
			{
                destination = session->createTopic( destURI );
            } else
			{
                destination = session->createQueue( destURI );
            }

            producer = session->createProducer( destination );
            producer->setDeliveryMode( DeliveryMode::PERSISTENT );

            string threadIdStr = Long::toString( Thread::currentThread()->getId() );
            string text = (string)"Hello world! from thread " + threadIdStr;
            while(1)
            {
                unsigned int ix=0;
            for(ix = 0 ; ix<numMessages; ++ix )
			{
                TextMessage* message = session->createTextMessage( text );
                message->setIntProperty( "Integer", ix );
                printf( "Sent message #%d from thread %s\n", ix+1, threadIdStr.c_str() );
                producer->send( message );
                delete message;
            }

        }
        }catch ( CMSException& e ) {
            printf("%s..........\n",e.getStackTraceString());
            e.printStackTrace();
        }
    }

private:

    void cleanup(){
        try{
            if( destination != NULL ) delete destination;
        }catch ( CMSException& e ) { e.printStackTrace(); }
        destination = NULL;

        try
		{
            if( producer != NULL ) delete producer;
        }catch ( CMSException& e ) { e.printStackTrace(); }
        producer = NULL;

        try{
            if( session != NULL ) session->close();
            if( connection != NULL ) connection->close();
        }catch ( CMSException& e ) { e.printStackTrace(); }

        try{
            if( session != NULL ) delete session;
        }catch ( CMSException& e ) { e.printStackTrace(); }
        session = NULL;

        try{
            if( connection != NULL ) delete connection;
        }catch ( CMSException& e ) { e.printStackTrace(); }
        connection = NULL;
    }
};
#if 1
int main(int argc , char* argv[])
{
    std::cout<<"init ActiveMQCPP library"<<std::endl;
    activemq::library::ActiveMQCPP::initializeLibrary();
    std::cout << "=====================================================\n";
    std::cout << "Starting produce message:" << std::endl;
    std::cout << "-----------------------------------------------------\n";

    std::string  brokerURI =("failover:(tcp://192.168.8.107:61616)");
    unsigned int numMessages = 10;
    std::string destURI = "ckjiaoc@.isstech.com";

    bool useTopics = true;
    bool clientAck = false;
    SimpleProducer producer( brokerURI, numMessages, destURI, useTopics ,clientAck);
    producer.run();
    //producer.close();

    std::cout << "-----------------------------------------------------\n";
    std::cout << "Finished test" << std::endl;
    std::cout << "=====================================================\n";
    producer.waitUntilReady();

    std::cout << "delete ActiveMQCPP library=====================================================\n";
    activemq::library::ActiveMQCPP::shutdownLibrary();
}
#endif
./Serverservice 
init ActiveMQCPP library
=====================================================
Starting produce message:
-----------------------------------------------------
Sent message #1 from thread -1225509283
Sent message #2 from thread -1225509283
Sent message #3 from thread -1225509283
Sent message #4 from thread -1225509283
Sent message #5 from thread -1225509283
Sent message #6 from thread -1225509283
Sent message #7 from thread -1225509283
Sent message #8 from thread -1225509283
Sent message #9 from thread -1225509283
Sent message #10 from thread -1225509283
Sent message #1 from thread -1225509283
Sent message #2 from thread -1225509283
Sent message #3 from thread -1225509283
Sent message #4 from thread -1225509283
Sent message #5 from thread -1225509283
Sent message #6 from thread -1225509283

这时你会发现ActiveMQ的服务端的主题里就有你刚才发送的信息。。。。

主题名字可自定义,489值所对应的内容表示入队消息MessagesEnqueued 489条,0 MessageDequeued出队消息为0条,表示,此主题没有被订阅,下面,我们再实现一个可消费的ActiveMQ demo

代码如下

#include <decaf/lang/Thread.h>
#include <decaf/lang/Runnable.h>
#include <decaf/util/concurrent/CountDownLatch.h>
#include <activemq/core/ActiveMQConnectionFactory.h>
#include <activemq/core/ActiveMQConnection.h>
#include <activemq/transport/DefaultTransportListener.h>
#include <activemq/library/ActiveMQCPP.h>
#include <decaf/lang/Integer.h>
#include <activemq/util/Config.h>
#include <decaf/util/Date.h>
#include <cms/Connection.h>
#include <cms/Session.h>
#include <cms/TextMessage.h>
#include <cms/BytesMessage.h>
#include <cms/MapMessage.h>
#include <cms/ExceptionListener.h>
#include <cms/MessageListener.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>

using namespace activemq;
using namespace activemq::core;
using namespace activemq::transport;
using namespace decaf::lang;
using namespace decaf::util;
using namespace decaf::util::concurrent;
using namespace cms;
using namespace std;


class SimpleAsyncConsumer : public ExceptionListener,
                            public MessageListener,
                            public DefaultTransportListener {
private:

    Connection* connection;
    Session* session;
    Destination* destination;
    MessageConsumer* consumer;
    bool useTopic ;
    std::string brokerURI;
    std::string destURI;
    bool clientAck;

private:

    SimpleAsyncConsumer( const SimpleAsyncConsumer& );
    SimpleAsyncConsumer& operator= ( const SimpleAsyncConsumer& );

public:

    SimpleAsyncConsumer( const std::string& brokerURI,
                         const std::string& destURI,
                         bool useTopic = false,
                         bool clientAck = false ) :
        connection(NULL),
        session(NULL),
        destination(NULL),
        consumer(NULL),
        useTopic(useTopic),
        brokerURI(brokerURI),
        destURI(destURI),
        clientAck(clientAck) {
    }

    virtual ~SimpleAsyncConsumer() {
        this->cleanup();
    }

    void close() {
        this->cleanup();
    }

    void runConsumer() {

        try {
            ActiveMQConnectionFactory* connectionFactory = new ActiveMQConnectionFactory( brokerURI );
            connection = connectionFactory->createConnection();
            delete connectionFactory;

            ActiveMQConnection* amqConnection = dynamic_cast<ActiveMQConnection*>( connection );
            if( amqConnection != NULL )
			{
                amqConnection->addTransportListener( this );
            }

            connection->start();
            connection->setExceptionListener(this);

            if( clientAck ) {
                session = connection->createSession( Session::CLIENT_ACKNOWLEDGE );
            } else {
                session = connection->createSession( Session::AUTO_ACKNOWLEDGE );
            }

            if( useTopic ) {
                destination = session->createTopic( destURI );
            } else {
                destination = session->createQueue( destURI );
            }

            consumer = session->createConsumer( destination );
            consumer->setMessageListener( this );

        } catch (CMSException& e) {
            e.printStackTrace();
        }
    }

    virtual void onMessage( const Message* message ) {
        static int count = 0;
        try
        {
            count++;
            const TextMessage* textMessage =
                dynamic_cast< const TextMessage* >( message );
            string text = "";

            if( textMessage != NULL ) {
                text = textMessage->getText();
            } else {
                text = "NOT A TEXTMESSAGE!";
            }

            if( clientAck ) {
                message->acknowledge();
            }

            printf( "Message #%d Received: %s\n", count, text.c_str() );
        } catch (CMSException& e) {
            e.printStackTrace();
        }
    }

    virtual void onException( const CMSException& ex AMQCPP_UNUSED ) {
        printf("CMS Exception occurred.  Shutting down client.\n");
        exit(1);
    }

    virtual void transportInterrupted() {
        std::cout << "The Connection's Transport has been Interrupted." << std::endl;
    }

    virtual void transportResumed() {
        std::cout << "The Connection's Transport has been Restored." << std::endl;
    }

private:

    void cleanup(){
        try{
            if( destination != NULL ) delete destination;
        }catch (CMSException& e) {}
        destination = NULL;

        try{
            if( consumer != NULL ) delete consumer;
        }catch (CMSException& e) {}
        consumer = NULL;

        try{
            if( session != NULL ) session->close();
            if( connection != NULL ) connection->close();
        }catch (CMSException& e) {}

        try{
            if( session != NULL ) delete session;
        }catch (CMSException& e) {}
        session = NULL;

        try{
            if( connection != NULL ) delete connection;
        }catch (CMSException& e) {}
        connection = NULL;
    }
};
#if 1
int main(int argc, char* argv[]) {
    std::cout<<"init ActiveMQCPP library"<<std::endl;
    activemq::library::ActiveMQCPP::initializeLibrary();

    std::cout << "=====================================================\n";
    std::cout << "Starting recieve message:" << std::endl;
    std::cout << "-----------------------------------------------------\n";

    std::string  brokerURI =("failover:(tcp://192.168.8.107:61616)");

    std::string destURI = "ckjiaoc@.isstech.com";
    bool useTopics = true;
    bool clientAck = false;
    SimpleAsyncConsumer consumer( brokerURI, destURI, useTopics, clientAck );
    consumer.runConsumer();
    std::cout << "Press 'q' to quit" << std::endl;
    while( std::cin.get() != 'q') {}
    consumer.close();

    std::cout << "-----------------------------------------------------\n";
    std::cout << "Finished with the example." << std::endl;
    std::cout << "=====================================================\n";

    activemq::library::ActiveMQCPP::shutdownLibrary();
}
#endif // 0

 

./Consumer 
init ActiveMQCPP library
=====================================================
Starting recieve message:
-----------------------------------------------------
The Connection's Transport has been Restored.
Press 'q' to quit
Message #1 Received: Hello world! from thread -1225255331
Message #2 Received: Hello world! from thread -1225255331
Message #3 Received: Hello world! from thread -1225255331
Message #4 Received: Hello world! from thread -1225255331
Message #5 Received: Hello world! from thread -1225255331
Message #6 Received: Hello world! from thread -1225255331
Message #7 Received: Hello world! from thread -1225255331
Message #8 Received: Hello world! from thread -1225255331
Message #9 Received: Hello world! from thread -1225255331
Message #10 Received: Hello world! from thread -1225255331
Message #11 Received: Hello world! from thread -1225255331
Message #12 Received: Hello world! from thread -1225255331

这时我们再看看ActiveMQ服务端会有什么变化

没错,结果表明,入队2254条信息,出队1136条信息

特别说明一下,ActiveMQ 的订阅消息模式

点对点

消息生产者生产消息发送到queue中,然后消息消费者从queue中取出并且消费消息。这里要注意: 
消息被消费以后,queue中不再有存储,所以消息消费者不可能消费到已经被消费的消息。 
Queue支持存在多个消费者,但是对一个消息而言,只会有一个消费者可以消费。 

发布/订阅 
消息生产者(发布)将消息发布到topic中,同时有多个消息消费者(订阅)消费该消息。和点对点方式不同,发布到topic的消息会被所有订阅者消费。发布订阅模式适用于1个消息生产者,多个消费者场景,首先启动消息订阅方,在消息发布方开始执行后,接收该消息进行处理。在ActiveMQ管理界面会动态跟进消息产生-消费(入队、出队)情况;以及生产者个数,消费者个数。

这两种模式主要区别或解决的问题就是发送到队列的消息能否重复消费(多订阅)

注意:ActiveMQ 内容还有很多,如消息持久化和非持久化处理,不同的应用场景,其消息模式也有所不同,值得大家去学习

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

linux C++ 环境下的ActiveMQ学习 的相关文章

  • ThingsBoard—自定义规则节点

    一般的功能 xff0c 可以使用现有的节点来完成 但如果有比较复杂 xff0c 或有自己特殊业务需求的 xff0c 可能就需要自定义了 按官方教程来基本就可以入门 xff0c 如果需要深入 xff0c 可以参考ThingsBoard自有节点
  • Thingsboard 报错 Cannot resolve symbol ‘TransportProtos‘

    本人idea 版本为 2021 1 xff0c 顺利编译 thingsboard 打开进行源码阅读时 xff0c 发现报 Cannot resolve symbol 39 TransportProtos 39 xff0c 如下图 xff1a
  • ThingsBoard 规则引擎-邮件通知

    之前我们已经学习了Thingsboard安装 设备接入 简单的数据可视化内容 xff0c 今天来继续学习下thingsboard其他特性 规则引擎 应用场景 ThingsBoard规则引擎是一个支持高度可定制复杂事件处理的框架 xff0c
  • ThingsBoard编译报错:Failure to find org.gradle:gradle-tooling-api:jar:6.3

    删除本地仓库未下载完成的缓存文件 xff08 删除像图片显示这样以 lastUpdated结尾的文件 xff09 执行mvn v确保maven命令可以正常执行执行下面命令 xff0c 将下载的jar安装到本地仓库 注意 xff1a 将 Df
  • Thingsboard3.4-OTA升级

    背景 在做设备端对接thingsboard平台得时候 xff0c 去研究设备端对接平台的过程中 xff0c 花了不少时间 xff0c 在此之前也没有找到相关的文档 xff0c 于是出于减少大家去研究的时间 xff0c 写了这篇博客 xff0
  • PyCharm更换pip源为国内源、模块安装、PyCharm依赖包导入导出教程

    一 更换pip为国内源 1 使用PyCharm创建一个工程 2 通过File gt Setting 选择解释器为本工程下的Python解释器 3 单击下图中添加 43 xff0c 4 单击下图中的 Manage Repositories 按
  • Pycharm没有找到manage repositories按钮解决方案

    问题描述 xff1a 不知道是因为版本原因还是其他 xff0c pycharm没有找到manage repositories按钮 xff0c 无法更改下载源 xff0c 导致安装库的速度会很慢 解决办法 xff1a 1 点击左下角的pyth
  • 通过改变JVM参数配置降低内存消耗

    有个项目 xff0c 其服务器端原本内存占用很大 xff0c 16G内存几乎都用光了 原先的JVM参数配置是这样的 xff1a Xms16384m Xmx16384m XX PermSize 61 64m XX MaxPermSize 61
  • NodeJS yarn 或 npm如何切换淘宝或国外镜像源

    一 查看当前的镜像源 npm config get registry 或 yarn config get registry 二 设置为淘宝镜像源 xff08 全局设置 xff09 npm config set registry https
  • Centos7 部署InfluxDB

    因为目前网络上关于InfluxDB的资料并不多 xff0c 所以这里建议多参考官网 官网 xff1a Home InfluxData 点击此处的Docs xff1a 这里选择 InfluxDB OSS xff1a 使用文档时根据需求选择查看
  • SpringBoot 集成 Emqx 发布/订阅数据

    最近项目中用到Emqx发布 订阅数据 xff0c 特此记录便于日后查阅 ThingsboardEmqxTransportApplication Copyright 2016 2023 The Thingsboard Authors lt p
  • Centos7部署Minio集群

    1 地址规划 minio1 span class token number 10 0 span 0 200 minio2 span class token number 10 0 span 0 201 minio3 span class t
  • Centos7 部署单机 Minio 对象存储服务

    MinIO 是一款基于 Go 语言发开的高性能 分布式的对象存储系统 xff0c 客户端支持 Java xff0c Net xff0c Python xff0c Javacript xff0c Golang语言 MinIO 的主要目标是作为
  • Netty源码解读

    Netty源码解读 Netty线程模型 1 定义了两组线程池BossGroup和WorkerGroup xff0c BossGroup专门负责接收客户端的连接 WorkerGroup专门负责网络的读写 2 BossGroup和WorkerG
  • Springboot Netty 实现自定义协议

    Netty是由JBOSS提供的一个java开源框架 xff0c 现为 Github上的独立项目 Netty提供异步的 事件驱动的网络应用程序框架和工具 xff0c 用以快速开发高性能 高可靠性的网络服务器和客户端程序 也就是说 xff0c
  • Netty 单机百万连接测试

    1 Netty框架简介 1 1 Netty简介 netty是jboss提供的一个java开源框架 xff0c netty提供异步的 事件驱动的网络应用程序框架和工具 xff0c 用以快速开发高性能 高可用性的网络服务器和客户端程序 也就是说
  • Grafana 可视化展示容器日志

    1 进入 dashboard 2 选择对应模板 3 选择相应的服务 4 关键词检索
  • 云服务的三种模式:SaaS、PaaS、IaaS

    云服务的三种模式 1 SaaS xff08 软件即服务 xff09 SaaS xff08 Software as a Service xff09 xff0c 即软件即服务 提供给消费者完整的软件解决方案 xff0c 你可以从软件服务商处以租
  • 三种方式实现Java生产者与消费者

    一 什么是生产者与消费者 生产者与消费者是java并发环境下常见的设计模式 xff0c 一个线程负责生产数据 xff0c 一个线程负责消费数据 xff0c 两个线程同时去操作这个变量 xff0c 但是这是两个相互互斥的操作 二 代码演示 1
  • XML解析为Document对象

    XML解析为Document对象 我们在上一篇Spring源码分析中有提到 xff0c Spring是将xml文件的InputStream转换为DOM树 xff0c 然后在将DOM树解析转换为BeanDefinition从而注册bean x

随机推荐

  • java生产者消费者模型

    前言 生产者和消费者问题是线程模型中的经典问题 xff1a 生产者和消费者在同一时间段内共用同一个存储空间 xff0c 生产者往存储空间中添加产品 xff0c 消费者从存储空间中取走产品 xff0c 当存储空间为空时 xff0c 消费者阻塞
  • 医疗保健领域的 7 个拯救生命的 AI 用例。从早期疾病检测到增强医疗决策再到更好的患者治疗效果——这就是人工智能技术如何改变医疗保健行业。

    目录 1 肺部疾病的 AI 辅助胸部 X 线分析 新冠肺炎 肺癌 2 黑色素瘤的皮肤科扫描 3 人工智能和机器学习的 CT 和 MRI 扫描分析 4 人工智能辅助乳腺癌检测 5 数字病理学的人工智能 6 使用自然语言处理实现医疗保健管理任务
  • poj3101——Astronomy(大数数学&gcd)

    Astronomy Time Limit 2000MS Memory Limit 65536KTotal Submissions 5932 Accepted 1337 Description There are n planets in t
  • E: Unable to correct problems, you have held broken packages

    E Unable to correct problems you have held broken packages 问题 xff1a apt install libmysqlclient dev Reading package lists
  • 【MySQL】mysqldump 数据库备份mysqldump: Got error: 1449: The user specified as a definer ('root'@'%') do......

    在Linux中使用corntab 定时备份MySQL数据库 xff0c 后期因考虑安全性问题 xff0c 删除掉了 root 64 用户 xff0c 发现环境上备份报错了 mysqldump Warning Using a password
  • Android 同个工程 复制后生成两个不同的apk

    需求 xff1a 同时运行两个完全相同工程 xff0c 我们会发现手机上面只有一个apk文件 xff1f 解决 xff1a 其实我们可以改变一个工程里面的build gradle中的applicationId 的值就可以了 等再次运行两个工
  • Linux下Centos7 安装 docker总结

    本片博客只介绍在linux系统上的安装方法 本文使用 CentOS 7 6 版本 1 root权限更新Yum包 xff08 linux命令不熟悉的同学本文建议使用root权限登陆安装docker xff0c 省去很多不必要麻烦 xff09
  • 完美解决KindEditor手机弹出框显示问题

    完美解决KindEditor手机弹出框显示问题 kindeditor是非常方便简单使用的富文本编辑器 xff0c 也很符合国人的习惯 xff0c 尤其是表情等应用 xff0c 但是kindedtor在手机上的显示也是一个比较头疼的问题 xf
  • Ubuntu 18.04 设置开机自启脚本

    一 背景 同伴在频繁更新系统环境 xff0c 需要经常使用reboot命令重启 xff0c 但每次重启后端Jar都会停止 xff0c 每次重启都需要手动启动Web后端Jar包 针对此种情况 xff0c 想到了采用开机自动启动Jar包的方法来
  • 本地打印机获取以及文件打印 java

    选择相应的文件进行打印 span class hljs comment 打印文件的选择 span JFileChooser fileChooser 61 span class hljs keyword new span JFileChoos
  • sqlite 句柄-sqlite 基础教程(3)

    要操纵一个数据库你就得有一个这个数据库的句柄 又碰到这个难以理解的词了 xff0c 不过确实还没得一个更好的词来替代它 其实你跟本不需要去在乎这个词叫什么 xff0c 你只要搞清楚他是一个什么玩意儿 就如同鞋子为什么叫鞋子 xff0c 仔细
  • Python justswap自动化交易

    因为平时要在justswap上做一些自动化交易 xff0c 网上资料很少 xff0c 看了justswapapi文档之后 xff0c 发现只需要调用合约的方式就可以了 遂共享出自己的代码 span class token keyword f
  • RabbitMq学习笔记(五)—— Topic

    ReceiveTopicOne 匹配规则 span class hljs number 1 span span class hljs comment 声明交换器和队列 span channel exchangeDeclare EXCHANG
  • ViewBinding - Jetpack 视图绑定委托封装及使用示例

    通过视图绑定功能 xff0c 您可以更轻松地编写可与视图交互的代码 在模块中启用视图绑定之后 xff0c 系统会为该模块中的每个 XML 布局文件生成一个绑定类 绑定类的实例包含对在相应布局中具有 ID 的所有视图的直接引用 在大多数情况下
  • LiveData 的生命周期 - viewLifecycleOwner / this

    在给定所有者的生命周期内将给定的观察者添加到观察者列表中 事件在主线程上调度 如果 LiveData 已经有数据集 xff0c 它将被传递给观察者 方法 xff1a observe LifecycleOwner Observer 使用示例
  • 设计模式——生产者消费者模式

    1 基本概括 2 主要介绍 2 1 概念 生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题 生产者和消费者彼此之间不直接通讯 xff0c 而通过阻塞队列来进行通讯 xff0c 所以生产者生产完数据之后不用等待消费者处理 xff
  • Arch linux安装deepin-wine和微信(wechat)

    一 保证有国内的镜像源 xff0c 不然下载很慢 xff0c 没有国内包的镜像源 xff0c 则软件列表会少很多国内的软件 如果没有国内镜像源 xff0c 请修改镜像源 sudo vim etc pacman d mirrorlist s
  • KVM虚拟化(一)

    一 KVM虚拟化架构 1 主流虚拟机架构 图中对比了几种主流虚拟化技术架构 xff1a ESXi Xen与KVM xff0c 其主要差别在与各组件 xff08 CPU 内存 磁盘与网络IO xff09 的虚拟化与调度管理实现组件有所不同 在
  • docker Centos 7 安装 xfce4 桌面 + x11vnc + novnc

    docker Centos 7 安装 xfce4 桌面 43 x11vnc 43 novnc 启动容器环境变量xfce4 桌面安装 启动 Xvfb安装 启动 xfce4 桌面 x11vnc安装 x11vnc启动 x11vnc novnc 上
  • linux C++ 环境下的ActiveMQ学习

    ActiveMQ 1 概述 ActiveMQ 是Apache出品 xff0c 最流行的 功能强大的即时通讯和集成模式的开源服务器 ActiveMQ 是一个完全支持JMS1 1和J2EE 1 4规范的 JMS Provider实现 提供客户端