通过Docker启动Solace,并在Spring Boot通过JMS整合Solace

1 简介

Solace是一个强大的实时性的事件驱动消息队列。本文将介绍如何在Spring中使用,虽然代码使用的是Spring Boot,但并没有使用相关starter,跟Spring的整合一样,可通用。JMS是通过的消息处理框架,可以深入学习一下,不同的MQ在JMS的整合上都是类似的。

2 通过Docker启动Solace

有两种方式试用Solace,一种是通过Docker来启动,另一种是使用Cloud版本,但Cloud版本有试用期限,我们使用Docker来启动吧。

先下载镜像:

$ docker pull solace/solace-pubsub-standard:9.13.0.16

然后通过以下命令启动:

$ docker run -d -p 8080:8080 -p 55554:55555 -p 8008:8008 -p 1883:1883 -p 8000:8000 -p 5672:5672 -p 9000:9000 -p 2222:2222 --shm-size=2g --env username_admin_globalaccesslevel=admin --env username_admin_password=admin --name=solace solace/solace-pubsub-standard:9.13.0.16

这里端口改为55554,是因为Mac的原因。

然后便可以访问来登陆管理界面:http://localhost:8080/

用户名密码为:admin/admin

登陆后可以看到如下界面,Solace按VPN来管理队列,VPN有点像分组,比如某个业务线使用某个VPN。

我们在default的VPN上创建一个Queue,名为pkslow-queue

其它设置如下:

接着在该Queue上创建Topic:

创建完成后,我们可以直接测试一下:

可以Publish到Topic或Queue,也可以从其中一个Subscribe。

完成以上设置后,我们就可以在Spring Boot中整合了。

3 Spring Boot JMS整合Solace

3.1 发送消息

我们是通过JmsTemplate来发送消息的,而JmsTemplate需要连接到MQ,就需要一个ConnectionFactory,这个Factory是带着MQ的一些连接信息。配置代码如下:

@Configuration
public class SolacePubConfig {

    private final SolaceProperties solaceProperties;

    public SolacePubConfig(SolaceProperties solaceProperties) {
        this.solaceProperties = solaceProperties;
    }

    @Bean("connectionFactory")
    public ConnectionFactory connectionFactory() throws Exception {
        Properties env = new Properties();
        env.put(InitialContext.INITIAL_CONTEXT_FACTORY, "com.solacesystems.jndi.SolJNDIInitialContextFactory");
        env.put(InitialContext.PROVIDER_URL, solaceProperties.getBrokerUrl());
        env.put(SupportedProperty.SOLACE_JMS_VPN, solaceProperties.getVpn());
        env.put(InitialContext.SECURITY_PRINCIPAL, solaceProperties.getUsername());
        env.put(InitialContext.SECURITY_CREDENTIALS, solaceProperties.getPassword());
        return SolJmsUtility.createConnectionFactory(env);
    }

    @Bean
    public CachingConnectionFactory cachingConnectionFactory(ConnectionFactory connectionFactory) {
        CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory(connectionFactory);
        cachingConnectionFactory.setSessionCacheSize(10);
        return cachingConnectionFactory;
    }

    @Bean
    public JmsTemplate pubJmsTemplate(CachingConnectionFactory cachingConnectionFactory) {
        JmsTemplate jmsTemplate = new JmsTemplate(cachingConnectionFactory);
        jmsTemplate.setPubSubDomain(true);
        jmsTemplate.setExplicitQosEnabled(true);
        jmsTemplate.setDeliveryPersistent(true);
        jmsTemplate.setDefaultDestinationName(solaceProperties.getDefaultPubDestinationName());
        return jmsTemplate;
    }

}

生成JmsTemplate后,就可以引用并发送消息了:

@RestController
@RequestMapping("/solace")
public class SolaceTestController {
    private final JmsTemplate pubJmsTemplate;
    private final SolaceProperties solaceProperties;

    public SolaceTestController(JmsTemplate pubJmsTemplate, SolaceProperties solaceProperties) {
        this.pubJmsTemplate = pubJmsTemplate;
        this.solaceProperties = solaceProperties;
    }

    @GetMapping
    public String send() {
        pubJmsTemplate.send(solaceProperties.getDefaultPubDestinationName(), session -> session.createTextMessage("www.pkslow.com"));
        pubJmsTemplate.send(session -> session.createTextMessage("Larry Deng"));
        return "OK";
    }
}

用到的属性配置如下:

server.port=8083

pkslow.solace.brokerUrl=smf://127.0.0.1:55554
pkslow.solace.vpn=default
pkslow.solace.username=default
pkslow.solace.password=default
pkslow.solace.defaultPubDestinationName=pkslow-topic
pkslow.solace.defaultSubDestinationName=pkslow-queue
@Configuration
@ConfigurationProperties(prefix = "pkslow.solace")
@Setter
@Getter
public class SolaceProperties {
    private String brokerUrl;
    private String vpn;
    private String username;
    private String password;
    private String defaultPubDestinationName;
    private String defaultSubDestinationName;
}

3.2 接收消息

我们通过MessageListenerContainer来接收消息,MessageListenerContainer也需要一个ConnectionFactory,也有MQ的连接信息。还需要一个MessageListener,用来定义如何处理消息。我们的配置如下:

@Configuration
@Slf4j
public class SolaceSubConfig {
    private final SolaceProperties solaceProperties;

    public SolaceSubConfig(SolaceProperties solaceProperties) {
        this.solaceProperties = solaceProperties;
    }

    @Bean
    public SingleConnectionFactory singleConnectionFactory(@Qualifier("connectionFactory") ConnectionFactory targetConnectionFactory) {
        return new SingleConnectionFactory(targetConnectionFactory);
    }

    @Bean
    public MessageListener messageListener() {
        return message -> {
            try {
                log.info("Received message " + ((TextMessage) message).getText() + " on destination: " +
                        message.getJMSDestination().toString());
            } catch (JMSException ex) {
                throw new RuntimeException(ex);
            }
        };
    }


    @Bean
    public MessageListenerContainer messageListenerContainer(SingleConnectionFactory singleConnectionFactory, MessageListener messageListener) {
        DefaultMessageListenerContainer container = new DefaultMessageListenerContainer();
        container.setConnectionFactory(singleConnectionFactory);
        container.setDestinationName(solaceProperties.getDefaultSubDestinationName());
        container.setMessageListener(messageListener);

        return container;
    }
}

这里@Qualifier("connectionFactory") ConnectionFactory targetConnectionFactory复用了在SolacePubConfig创建的对象。

3.3 测试

发送GET请求就可以触发发送了:

GET http://localhost:8083/solace

我发了三次,结果日志如下:

4 代码

代码请看GitHub: http://github.com/LarryDpk/pkslow-samples


References:

Docker available image tags

Docker Solace Guide

Spring Solace

本文转载于网络 如有侵权请联系删除

相关文章

  • 游戏工业化?TA们该如何协作开发

    前言近一两年游戏工业化的话题时常被提起,当初在影视行业的时候也是如此。比如最近鬼猫猫写的游戏工业化系列就讲的十分不错今天我们来聊聊,跟游戏工业化也有关系的TA们该如何协作开发。我自己亲身经历过的一些实践心得,在我们开始正式内容之前,我想先讲下我以前待过的公司(影视视效)的TD们,是如何协作的。为了方便叙述,我们下文都简称我以前待过的公司(影视视效)为BM。本人正好也经历了BM从pipeline1.0到pipeline2.0的迭代过程。在2015年我刚加入BM的时候,那时候我们全球的代码还是通过SVN去同步的,然后北京这边会定期拉取SVN去获取代码更新,那时我们有6家分部的代码都在这个SVN上面,也没有什么分支的概念,导致经常代码冲突或者代码更新不及时出现生产被中断的现象。那时候全球的PipelineTD们彼此也没有什么交流,都是通过邮件。大概在2017的时候,我们全球pipeline有一次重大的更新,弃用了SVN转为使用GitLab去管理我们的代码,通过使用Rez去管理我们的软件包。为了方便沟通,我们部署了开源的即时通讯软件Rocket.Chat。全球所有的pipelineTD开始正式

  • Web网页自动化实战《3.在艺龙网中,根据城市+日期+关键词精准匹配了酒店》下篇

    目录一、代码思路二、唯一定位“目的地”1、文本定位2、层级定位三、总结1、代码2、遇到的坑手工测试是怎么点的,自动化测试就怎么点击。(截图讲解的技术知识是正确的。因为艺龙网站的页面元素有变动,所以你实操起来,看到的元素和截图上的会有区别。)一、代码思路想用代码实现以下操作:1.打开网址进入首页,点击目的地输入框,等弹框弹出来,选择热门城市里面的广州,点击。2.元素定位到入住日期输入框,清空入住日期输入框中的内容,输入日期,点击目的地使日期弹框关闭。3.元素定位到退房日期输入框,清空退房日期输入框中的内容,输入退房日期,点击目的地使日期弹框关闭。4.元素定位到关键词输入框,清空关键词输入框中的内容,输入关键词,点击目的地使弹框关闭。5.点击搜索。6.(这时已经跳转到下一个页面),在这个页面中点击某酒店名称。7.关闭所有页面。二、唯一定位“目的地”1、文本定位表达式://标签名[text()=文本内容]这个是固定语法。//dt[text()="目的地"]定位出来2个,鼠标悬浮在第一个的黄色部分上,发现目的地上覆盖着蓝色且提示dt.w60,说明这个是我想要的元素看第二个看

  • 数据结构(一)

    数据结构(一)發佈於 2019-02-22数据结构和算法是计算机软件相关专业的基础课程,要想从事编程工作,无论是否是科班出身,都不可能绕过这部分知识。 从本篇开始,我会详细的复习一遍数据结构以及算法。数据结构数据结构:是相互之间存在一种或多种特定关系的数据元素的集和。基本概念数据数据:是描述客观事物的符号,是计算机中可以操作的对象,是能被计算机识别,并输入给计算机处理的符号的集和。 数据包括:整型等数值类型,以及声音图片等非数值类型。数据元素数据元素:是组成数据的、有一定意义的基本单位,在计算机中通常作为整体处理。也被称为记录。数据项数据项:一个数据元素可以由若干个数据项组成。数据项是数据不可分割的最小单位。数据对象数据对象:性质相同的数据元素的集和,是数据的子集。逻辑结构和物理结构我们把数据结构划分为逻辑结构和物理结构。逻辑结构逻辑结构:是指数据对象中数据元素之间的相互关系。逻辑结构可分为以下四种:集合结构:集合结构中的数据元素除了同属于一个集合之外,他们之间没有其他关系线性结构:线性结构中的数据元素之间是一对一的关系树形结构:树形结构中的数据元素之间存在一种一对多的关系图形结构:图

  • 【STM32F429】第5章 RL-USB移植(MDK AC6)

    论坛原始地址(持续更新):http://www.armbbs.cn/forum.php?mod=viewthread&tid=99710 第5章RL-USB移植(MDKAC6)本章教程为大家讲解RL-USB协议栈的AC6编译器移植。5.1初学者重要提示5.2移植RL-USB整体说明5.3了解RL-USB模板框架设计5.4第1步,安装指定的MDK软件包5.5第2步,准备一个工程模板5.6第3步,添加RL-USB并配置5.7第4步,修改文件includes5.8第5步,添加两个应用文件5.9第6步,创建应用任务(重要,注意启动任务)5.10常见移植错误总结5.11使用的MicroUSB接口并注意跳线帽设置5.12实验例程5.13总结5.1初学者重要提示学习RL-USB移植前,务必保证已经熟练掌握了RTX5内核的移植,因为本章节的移植要用到RTX5移植的一些操作方法:http://www.armbbs.cn/forum.php?mod=viewthread&tid=93149。STM32H7使用MDKRTE环境添加RTX5和RL-USB,需要强制运行一次STM32CubeMX

  • 数组类型与数组指针的巧妙利用

    本例通过存取结构,慢慢引入了数组类型与指针的一些使用方法;其中六个小例子的测试内容和结果都是一样的.unitUnit1; interface uses Windows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms, Dialogs,StdCtrls; type TForm1=class(TForm) Button1:TButton; Button2:TButton; Button3:TButton; Button4:TButton; Button5:TButton; Button6:TButton; procedureButton1Click(Sender:TObject); procedureButton2Click(Sender:TObject); procedureButton3Click(Sender:TObject); procedureButton4Click(Sender:TObject); procedureButton5Click(Sender:TObject); procedureButt

  • 安装 TensorFlow安装 TensorFlow

    安装TensorFlow我们已在如下配置的64位笔记本电脑/台式机操作系统中构建并测试过TensorFlow:MacOSX10.11(ElCapitan)或更高版本Ubuntu16.04或更高版本Windows7或更高版本也许您能在其他笔记本电脑或台式机系统上安装TensorFlow,但我们只支持上述配置(且只会修复这些配置中的问题)。下列指南介绍了如何安装让您可以使用Python编写应用的TensorFlow版本:在Ubuntu上安装TensorFlow在macOS上安装TensorFlow在Windows上安装TensorFlow从源代码安装TensorFlowPythonTensorFlowAPI的许多方面都已从版本0.n升级为1.0。以下指南介绍了如何将旧版TensorFlow应用迁移到版本1.0:转换到TensorFlow1.0下列指南介绍了如何安装TensorFlow库以搭配其他编程语言使用。这些API的作用是在应用中部署TensorFlow模型,因此功能不像PythonAPI那么广泛。安装适用于Java的TensorFlow安装适用于C的TensorFlow安装适用于Go

  • 天下武功,唯'QUICK'不破,揭秘QUIC的五大特性及外网表现

    HTTP从上世纪90年代诞生起,就被约定为跑在TCP协议之上的应用层协议。而后虽然HTTP协议版本从0.9到2.0,上层协议不断优化,在享受TCP带来的有序可靠的数据服务同时,却也始终绕不开TCP协议的一些弊端。此时一种基于UDP的“快”协议,不但能可靠的向上层提供数据,还能更快的把这些数据交付上去,其更革命性的给出了提升互联网交互速度的新思路。QUIC简介QUIC(QuickUDPInternetConnections)是谷歌提出的一种传输协议,由于其建立在UDP之上,使得相对于TCP之上的SPDY、HTTP2等其他协议,QUIC的可定制和优化的空间更大.在UDP的上层,QUIC提供了可靠、有序、安全、而且更快速的传输服务.目前,在Chrome中有85%以上关于谷歌自有业务的请求响应都是通过QUIC承载,可以说QUIC已经经受住了真实复杂外网环境的考验。谷歌在介绍自家的QUIC协议时提到了几个关键特性:链接耗时更短拥塞控制更出色更好的多路复用前向纠错特性链接迁移特性可以看到QUIC的这五个特性关键字都在表达:我很快。下面会分重点的提到这五个特性及安全性保证。最后用数据说话,看看在腾讯

  • 动态规划之矩阵连乘

    给定n个矩阵{A1,A2,…,An},其中Ai与Ai+1是可乘的,i=1,2,…,n-1。如何确定计算矩阵连乘积的计算次序,使得依此次序计算矩阵连乘积需要的数乘次数最少。例如:  A1={30x35};A2={35x15};A3={15x5};A4={5x10};A5={10x20};A6={20x25};结果为:((A1(A2A3))((A4A5)A6)) 最小的乘次为15125。原问题为n个矩阵连乘,将原问题分解为子问题,即当n等于1,2,3.....时。n==1时,单一矩阵,不需要计算。最小乘次为0n==2时,根据n==1时的结果,遍历计算出每相邻两个矩阵的最小乘次n==3时,根据n==1和n==2时的结果,此时已经求出每相邻1个、2个矩阵的最小乘次,遍历计算出该相邻三个矩阵的最小乘次依次类推……当n==n时,根据n==1、2、……n-1时的结果,此时已经求出每相邻1个、2个、3个……n-1个矩阵的最小乘次,由此求出n==n时的最小乘次每当n增加1时,就利用已求出的子结构来求解此时的最优值。数学描述如下:设矩阵Ai的维数为Pi ×Pi+1。设A[i:j]为矩阵AiAi+1....

  • 建设DevOps统一运维监控平台,先从日志监控说起

    前言 随着Devops、云计算、微服务、容器等理念的逐步落地和大力发展,机器越来越多,应用越来越多,服务越来越微,应用运行基础环境越来多样化,容器、虚拟机、物理机不一而足。 面对动辄几百上千个虚拟机、容器,数十种要监控的对象,现有的监控系统还能否支撑的住?来自于容器、虚拟机、物理机的应用日志、系统服务日志如何采用同一套方案快速、完整的收集和检索?怎样的架构、技术方案才更适合如此庞大繁杂的监控需求呢?本文主要从以下几个方面来分享下笔者在日志监控方面的一些经验。目录一、DevOps浪潮下带来的监控挑战二、统一监控平台架构解析三、日志监控的技术栈四、日志监控经典方案ELK五、微服务+容器云背景下的日志监控实践Journald+fluentd+elasticsearch六、如何选择适合自己的日志监控方案?一、DevOps浪潮下带来的监控挑战现在Devops、云计算、微服务、容器等理念正在逐步落地和大力发展,机器越来越多,应用越来越多,服务越来越微,应用运行基础环境越来多样化,容器,监控面临的压力越来越大。挑战主要有: 监控源的多样化挑战 业务、应用、网络设备、存储设备、物理机、虚拟机、容器、

  • 【答疑解惑】失之毫厘谬以千里

    1、scanf使用陷阱如果scanf中%d是连着写的如“%d%d”,在输入数据时,数据之间不可以加逗号,只能是空格或tab键或者回车键“12”或“1(按tab)2”。若是“%d,%d”,则在输入数据时需要加“,”,如“1,2”。scanf没有精度控制,所以输入输出格式也是要注意。一个不留神,都不知道怎么错的。高手一针见血的指出格式错误。高手一看就知道好几处错误,学习一定要注意细节,概念谁都知道但没有仔细去研究,多实践很多小伙伴书上理论学的很棒,但是一旦动手敲代码错误百出,小白变小黑,捷径就是不断实践。2.如何学会使用函数函数的参数都是有用途的,应该传什么值才能得到正确的结果,说明一点,你想得到什么,你得提供给我需要的。给定的值(弧度)。返回-1至1之间的计算结果。 弧度与角度的关系为: 弧度=180/π角度 角度=π/180弧度其实这个程序距离成功运行只差那么一点点,在编程的过程中,对自己要保持信心,同时不要忽略细节。如果还是不明白建议好好看看C语言基础教程的函数章节。 如果在学习中遇到困惑可以加入下面的QQ群,也可以直接加编程导师微信号coderonline后续小编会持续的推出答疑释

  • Linux狂神说笔记[通俗易懂]

    大家好,又见面了,我是你们的朋友全栈君。 Linux在服务器端,很多大型项目都是部署在Linux服务器上利用VM+Centos7搭建本地Linux系统你可以使用man[命令]来查看各个命令的使用文档,如:mancp。概念 云服务器就是一个远程电脑Linux中一切皆文件 根目录/,所有的文件都挂载在这个节点下/bin:bin是Binary的缩写,这个目录存放着最经常使用的命令。 /boot:这里存放的是启动Linux时使用的一些核心文件,包括一些连接文件以及镜像文件。 /dev:dev是Device(设备)的缩写,存放的是Linux的外部设备,在Linux中访问设备的方式和访问文件的方式是相同的。 /etc:这个目录用来存放所有的系统管理所需要的配置文件和子目录。 /home:用户的主目录,在Linux中,每个用户都有一个自己的目录,一般该目录名是以用户的账号命名的。 /lib:这个目录里存放着系统最基本的动态连接共享库,其作用类似于Windows里的DLL文件。 /lost+found:这个目录一般情况下是空的,当系统非法关机后,这里就存放了一些文件。 /media:linux系统会自

  • 腾讯云腾讯云TI平台TIONE查看notebook生命周期脚本列表腾讯云TI平台TIONEAPI20191022

    1.接口描述接口请求域名:tione.tencentcloudapi.com。 查看notebook生命周期脚本列表 默认接口请求频率限制:20次/秒。 APIExplorer提供了在线调用、签名验证、SDK代码生成和快速检索接口等能力。您可查看每次调用的请求内容和返回结果以及自动生成SDK调用示例。 2.输入参数以下请求参数列表仅列出了接口请求参数和部分公共参数,完整公共参数列表见公共请求参数。 参数名称 必选 类型 描述 Action 是 String 公共参数,本接口取值:DescribeNotebookLifecycleScripts。 Version 是 String 公共参数,本接口取值:2019-10-22。 Region 是 String 公共参数,详见产品支持的地域列表。 Offset 否 Integer 偏移量,默认为0 Limit 否 Integer 返回数量,默认为20 Filters.N 否 ArrayofFilter 过滤条件。instance-name-String-是否必填:否-(过滤条件)按照名称过滤

  • Requst Servervariables

    Request.ServerVariables("Url") 返回服务器地址   Request.ServerVariables("Path_Info") 客户端提供的路径信息 Request.ServerVariables("Appl_Physical_Path") 与应用程序元数据库路径相应的物理路径 Request.ServerVariables("Path_Translated") 通过由虚拟至物理的映射后得到的路径 Request.ServerVariables("Script_Name") 执行脚本的名称 Request.ServerVariables("Query_String") 查询字符串內容 Request.ServerVariables("Http_Referer") 请求的字符串內容 Request.ServerVariables("Server_Port") 接受请求的服务器端口号 Request.ServerVariables("Remote_Addr") 发

  • spark 教程三 spark Map filter flatMap union distinct intersection操作

    RDD的创建 spark所有的操作都围绕着弹性分布式数据集(RDD)进行,这是一个有容错机制的并可以被并行操作的元素集合,具有只读、分区、容错、高效、无需物化、可以缓存、RDD依赖等特征 RDD的创建基础RDD 1.并行集合(ParallelizedCollections):接收一个已经存在的Scala集合,然后进行各种并行运算 varsc=newSparkContext(conf) varrdd=sc.parallelize(Array(2,4,9,3,5,7,8,1,6)); rdd.foreach(println) 复制   2.hadoop数据集(HadoopDatasets):在一个文件的每条记录上运行函数只要文件系统是HDFS,或者hadoop支持的任意存档存储系统即可 valfile=sc.textFile("hdfs://hostname:9090/path/somefile.txt") 复制  Map的操作 map(func)返回一个新的RDD,由每一个元素经过func后转换组成 //设置confmaster=local为本

  • java application.properties 密码加密

    main方法 publicstaticvoidmain(String[]args){ BasicTextEncryptortextEncryptor=newBasicTextEncryptor(); //加密所需的salt(盐) textEncryptor.setPassword("Yc@0!9IsC"); //要加密的数据(数据库的用户名或密码) Strings1=textEncryptor.encrypt("ftp21"); Strings2=textEncryptor.encrypt("Summer2018"); Strings3=textEncryptor.encrypt("Anfang@123!");// Strings4=textEncryptor.encrypt("admin123"); Strings5=textEncryptor.encrypt("cegs"); Strings6=textEncryptor.encrypt("ivms_thr"); Strings7=textEncryptor.encrypt("Anfang@123!");

  • JDBC的第一个程序

    JDBC的第一个程序 1、先建个数据库 2、把数据库和Java项目连上 1.建个数据库 数据库为:jdbcstudy 这个数据库jdbcstudy中有个表为:users             2.把数据库和Java项目连上 效果如下:   下面代码,可以作为连接数据库的代码模板,只需要改动标注的4个地方。   完整代码如下: packagecom.wang.lesson;​importjava.sql.*;​publicclassjdbcFirstDemo{  publicstaticvoidmain(String[]args)throwsClassNotFoundException,SQLException{    //step1:加载驱动,下面这行是固定写法    Class.forName("com.mysql.jdbc.Driver");//固定写法&nbs

  • Ranklib源码剖析--LambdaMart

    Ranklib是一套优秀的LearningtoRank领域的开源实现,其中有实现了MART,RankNet,RankBoost,LambdaMart,RandomForest等模型。其中由微软发布的LambdaMART是IR业内常用的LearningtoRank模型,本文主要介绍Ranklib中的LambdaMART模型的具体实现,用以帮助理解paper中阐述的方法。本文是基于version2.3版本的Ranklib来介绍的。 LambdaMart的基本原理详见之前的博客:http://www.cnblogs.com/bentuwuying/p/6690836.html。要知道LambdaMart是基于MART的,而MART又是由若干棵regressiontree组合而成的。所以,我们先来看看Ranklib中是如何实现regressiontree的,以及在给定trainingdatawithlabels的情况下,regressiontree是如何拟合的。 1.regressiontree regressiontree拟合给定trainingdata的步骤总结概括如下: Regress

  • 【Python画画】失败案例总结

    攻略一网站:https://blog.csdn.net/pipisorry/article/details/46564967 1.spy++找窗口句柄 2.游戏照片提取 3.俩图切成好多方块比较颜色直方图差异 4.标记不同 fromctypesimport*importos,timeimportpyautoguiaspagimportwin32conimportwin32guifromPILimportImageGrabfrom_testimporthuaHuafromPyQt5.QtWidgetsimportQApplicationimportsys#fromUtility.ColorsimportDEFAULT,REDfromnumpyimport*#--------------------------------------------------------------------defchannel_compare(cha_a,cha_b):#比较两个颜色通道差异值并返回sum_a=sum([i*vfori,vinenumerate(cha_a)])sum_b=sum([i*

  • EntityFramework动态组合多排序字段

      前言:在使用EF当中,肯定会遇到动态查询的需求,建立一个公共调用的动态组合表达式查询也是必不可少的,以下是建立动态组合多排序字段做个记录,供以后调用 1、建立一个结构,用于多个排序字段组合,这个结构体有两个字段,一个是需要排序的属性名,一个是是否是升序降序的判断 publicstructOrderModelField { publicstringpropertyName{get;set;} publicboolIsDESC{get;set;} }复制 组合方法 publicIList<T>GetAllEntity(Expression<Func<T,bool>>condition,intpageIndex,intpageSize,outlongtotal,paramsOrderModelField[]orderByExpression) { //条件过滤 varquery=this.QQYALIEntities.Set<T>().Where(condition); //创建表达式变量参数 varparameter=

  • MySQL日志篇,MySQL日志之binlog日志,binlog日志详解

      视频地址 https://www.bilibili.com/video/BV1oT4y1o7TW 一、描述 binlog二进制日志文件,这个文件记录了MySQL所有的DML操作。通过binlog日志我们可以做数据恢复,增量备份,主主复制和主从复制等等。 二、常用操作 2-1、docker里面无法使用vim、常用命令问题解决 https://blog.csdn.net/Tomwildboar/article/details/120710690 https://blog.csdn.net/KwaiSZ/article/details/106937983 2-2、开启binlog 查看是否开启binlog日志 showvariableslike'log_%'; 在 my.cnf 里面加上配置如下配置,重启mysql。 一般来说my.cnf在:/etc/mysql/my.cnf 或 /etc/my.cnf #binlog存储的位置 log-bin=/var/lib/mysql/mysql-bin #日志

  • 函数

    函数定义 具有一定功能的代码块的封装,提高代码的复用性,遵循高内聚,低耦合的思想。 函数声明 functionfn(){} 复制 函数表达式 1、命名函数表达式 vara=functionfn(){}) 复制 2、匿名函数表达式————一般称为函数表达式 varb=function(){} 复制 匿名函数与命名函数的区别是a.name与b.name的不同。 函数组成形式 函数名称 参数 形参与实参的个数可以不相等,形参比实参多,多余的形参为undefined,实参比形参多,多余的也放在arguments中。 1、形参 函数名.length为形参的个数 复制 2、实参 arguments.length为实参的个数 复制 实参具有arguments类数组,里面放置实参,实参多于形参,多余的实参也放在里面。 形参与实参是一一对应,相互映射的关系。 返回值 return结束函数的执行,并返回一个结果。函数执行完,执行的结果通过return返回出去,没有return或return后面没有值,则返回undefined。

相关推荐

推荐阅读