java 消息队列服务_ActiveMQ 消息队列服务

1 ActiveMQ简介

1.1 ActiveMQ是什么

ActiveMQ是一个消息队列应用服务器(推送服务器)。支持JMS规范。

1.1.1 JMS概述

全称:Java Message Service ,即为Java消息服务,是一套java消息服务的API标准。(标准即接口)

实现了JMS标准的系统,称之为JMS Provider。

1.1.2 消息队列

1.1.2.1 概念

消息队列是在消息的传输过程中保存消息的容器,提供一种不同进程或者同一进程不同线程直接通讯的方式。

Producer:消息生产者,负责产生和发送消息到Broker;

Broker:消息处理中心。负责消息存储、确认、重试等,一般其中会包含多个queue;

Consumer:消息消费者,负责从Broker中获取消息,并进行相应处理;

1.1.2.2 常见消息队列应用

(1)、ActiveMQ

ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线。ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现。

(2)、RabbitMQ

RabbitMQ是一个在AMQP基础上完成的,可复用的企业消息系统。他遵循Mozilla Public License开源协议。开发语言为Erlang。

(3)、RocketMQ

由阿里巴巴定义开发的一套消息队列应用服务。

1.2 ActiveMQ能做什么

(1)实现两个不同应用(程序)之间的消息通讯。

(2)实现同一个应用,不同模块之间的消息通讯。(确保数据发送的稳定性)

1.3 ActiveMQ下载

ActiveMQ下载地址:http://activemq.apache.org/download-archives.html

--可供下载的历史版本

--说明:

ActiveMQ 5.10.x以上版本必须使用JDK1.8才能正常使用。

ActiveMQ 5.9.x及以下版本使用JDK1.7即可正常使用。

119a654e0501e3c65e1582d601c6fcb1.png

--根据操作系统,选择下载版本。(本教程下载Linux版本)

d0e0437ac1517c299878054aabd057e1.png

1.4 ActiveMQ主要特点

(1)支持多语言、多协议客户端。语言: Java,C,C++,C#,Ruby,Perl,Python,PHP。应用协议:OpenWire,Stomp REST,WS Notification,XMPP,AMQP

(2)对Spring的支持,ActiveMQ可以很容易整合到Spring的系统里面去。

(3)支持高可用、高性能的集群模式。

2 入门示例

2.1 需求

使用ActiveMQ实现消息队列模型。

2.2 配置步骤说明

(1)搭建ActiveMQ消息服务器。

(2)创建一个java项目。

(3)创建消息生产者,发送消息。

(4)创建消息消费者,接收消息。

2.3 第一部分:搭建ActiveMQ消息服务器

2.3.1 第一步:下载、上传至Linux

--说明:确保已经安装了jdk

ecf96740435b903143219647dc5b2955.png

2.3.2 第二步:安装到/usr/local/activemq目录

(1)解压到/usr/local目录下

[root@node07192 ~]# tar -zxvf apache-activemq-5.9.0-bin.tar.gz -C /usr/local

(2)修改名称为activemq

[root@node07192 ~]# cd /usr/local/

[root@node07192 local]# mv apache-activemq-5.9.0/ activemq

2.3.3 第三步:启动ActiveMQ服务器

--说明:ActiveMQ是免安装软件,解压即可启动服务。

[root@node07192 local]# cd activemq/bin

[root@node07192 bin]# ./activemq start

--查看ActiveMQ启动状态

[root@node07192 bin]# ./activemq status

a254cc9d2424bb497887f5237367c480.png

2.3.4 第四步:浏览器访问ActiveMQ管理界面

2.3.4.1 Step1:查看ActiveMQ管理界面的服务端口。在/conf/jetty.xml中

--访问管理控制台的服务端口,默认为:8161

[root@node07192 bin]# cd ../conf

[root@node07192 conf]# vim jetty.xml

66abcae999438a3fc495ac492fdfe7b0.png

2.3.4.2 Step2:查看ActiveMQ用户、密码。在/conf/users.properties中:

--默认的用户名、密码均为amdin

[root@node07192 conf]# vim users.properties

44bc687d9e43463a47b34b3baa404d0c.png

2.3.4.3 Step3:访问ActiveMQ管理控制台。地址:http://ip:8161/

--注意:防火墙是没有配置该服务的端口的。

因此,要访问该服务,必须在防火墙中配置。

(1)修改防火墙,开放8161端口

[root@node07192 conf]# vim /etc/sysconfig/iptables

ae9d5d47131c654cc355fcc8d14ae7b9.png

(2)重启防火墙

[root@node07192 conf]# service iptables restart

(3)登录管理控制台

--登陆,用户名、密码均为admin

2d51775271bd4ffe707c95ed00e62847.png

--控制台主界面

4a3ba627a890ef833f2a9b2116e85594.png

--搭建ActiveMQ服务器成功!!!

2.4 第二部分:创建java项目,导入jar包

--导包说明:

ActiveMQ的解压包中,提供了运行ActiveMQ的所有jar。

e19e212de7d0cc0535d66abc49069aae.png

--创建项目

c7c900b7b6256548af6dbaed41c823ad.png

2.5 第三部分:创建消息生成者,发送消息

--说明:ActiveMQ是实现了JMS规范的。在实现消息服务的时候,必须基于API接口规范。

2.5.1 JMS常用的API说明

下述API都是接口类型,定义在javax.jms包中,是JMS标准接口定义。ActiveMQ完全实现这一套api标准。

2.5.1.1 ConnectionFactory

链接工厂, 用于创建链接的工厂类型。

2.5.1.2 Connection

链接,用于建立访问ActiveMQ连接的类型,由链接工厂创建。

2.5.1.3 Session

会话, 一次持久有效、有状态的访问,由链接创建。

2.5.1.4 Destination  &  Queue & Topic

目的地, 即本次访问ActiveMQ消息队列的地址,由Session会话创建。

(1)interfaceQueue extends Destination

(2)Queue:队列模型,只有一个消费者。消息一旦被消费,默认删除。

(3)Topic:主题订阅中的消息,会发送给所有的消费者同时处理。

2.5.1.5 Message

消息,在消息传递过程中数据载体对象,是所有消息【文本消息TextMessage,对象消息ObjectMessage等】具体类型的顶级接口,可以通过会话创建或通过会话从ActiveMQ服务中获取。

2.5.1.6 MessageProducer

消息生成者, 在一次有效会话中,用于发送消息给ActiveMQ服务的工具,由Session会话创建。

2.5.1.7 MessageCustomer

消息消费者【消息订阅者,消息处理者】, 在一次有效会话中,用于ActiveMQ服务中获取消息的工具,由Session会话创建。

我们定义的消息生产者和消费者,都是基于上面API实现的。

2.5.2 第一步:创建MyProducer类,定义sendMessage方法

package cn.gzsxt.mq.producer;

import javax.jms.Connection;

import javax.jms.ConnectionFactory;

import javax.jms.Destination;

import javax.jms.JMSException;

import javax.jms.Message;

import javax.jms.MessageProducer;

import javax.jms.Session;

import org.apache.activemq.ActiveMQConnectionFactory;

public class MyProducer {

// 定义链接工厂

ConnectionFactory connectionFactory = null;

// 定义链接

Connection connection = null;

// 定义会话

Session session = null;

// 定义目的地

Destination destination = null;

// 定义消息生成者

MessageProducer producer = null;

// 定义消息

Message message = null;

public void sendToMQ(){

try{

/*

* 创建链接工厂

* ActiveMQConnectionFactory - 由ActiveMQ实现的ConnectionFactory接口实现类.

* 构造方法: public ActiveMQConnectionFactory(String userName, String password, String brokerURL)

*  userName - 访问ActiveMQ服务的用户名,用户名可以通过jetty-realm.properties配置文件配置.

*  password - 访问ActiveMQ服务的密码,密码可以通过jetty-realm.properties配置文件配置.

*  brokerURL - 访问ActiveMQ服务的路径地址.路径结构为-协议名://主机地址:端口号

*      此链接基于TCP/IP协议.

*/

connectionFactory = new ActiveMQConnectionFactory("admin", "admin", "tcp://192.168.23.13:61616");

// 创建链接对象

connection = connectionFactory.createConnection();

// 启动链接

connection.start();

/*

* 创建会话对象

* 方法- connection.createSession(boolean transacted,int acknowledgeMode);

*  transacted - 是否使用事务,可选值为true|false

*      true - 使用事务,当设置此变量值,则acknowledgeMode参数无效,建议传递的acknowledgeMode参数值为

*          Session.SESSION_TRANSACTED

*      false - 不使用事务,设置此变量值,则acknowledgeMode参数必须设置.

*  acknowledgeMode - 消息确认机制,可选值为:

*      Session.AUTO_ACKNOWLEDGE - 自动确认消息机制

*      Session.CLIENT_ACKNOWLEDGE - 客户端确认消息机制

*      Session.DUPS_OK_ACKNOWLEDGE - 有副本的客户端确认消息机制

*/

session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

// 创建目的地,目的地命名即队列命名,消息消费者需要通过此命名访问对应的队列

destination = session.createQueue("test-mq");

// 创建消息生成者,创建的消息生成者与某目的地对应,即方法参数目的地.

producer = session.createProducer(destination);

// 创建消息对象,创建一个文本消息,此消息对象中保存要传递的文本数据.

message = session.createTextMessage("hello,activeme");

// 发送消息

producer.send(message);

System.out.println("消息发送成功!");

}catch(Exception e){

e.printStackTrace();

System.out.println("访问ActiveMQ服务发生错误!!");

}finally{

try {

// 回收消息发送者资源

if(null != producer)

producer.close();

} catch (JMSException e) {

e.printStackTrace();

}

try {

// 回收会话资源

if(null != session)

session.close();

} catch (JMSException e) {

e.printStackTrace();

}

try {

// 回收链接资源

if(null != connection)

connection.close();

} catch (JMSException e) {

e.printStackTrace();

}

}

}

}

2.5.3 第二步:创建一个测试类MessageTest

--添加junit类库,快捷键ctrl+1

package cn.gzsxt.mq.test;

import org.junit.Test;

import cn.gzsxt.mq.producer.MyProducer;

public class MessageTest {

@Test

public void sendToMQ(){

MyProducer producer = new MyProducer();

producer.sendToMQ();

}

}

2.5.4 第三步:测试

(1)设置防火墙,配置61616端口。注意修改之后重启防火墙。

(2)测试结果:

--查看控制台

e2b4b41fda4c13a59933b8dca7ad7388.png

--查看ActiveMQ管理控制界面

5a0c146fc2b9377e8afa994a45563be7.png

--消息发送成功!!!

2.6 第四部分:创建消息消费者,消费消息

2.6.1 第一步:创建MyConsumer类

package cn.gzsxt.mq.consumer;

import javax.jms.Connection;

import javax.jms.ConnectionFactory;

import javax.jms.Destination;

import javax.jms.JMSException;

import javax.jms.Message;

import javax.jms.MessageConsumer;

import javax.jms.Session;

import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnectionFactory;

/**

* @ClassName:MyConsumer

* @Description: 消息消费者代码

*/

public class MyConsumer {

// 定义链接工厂

ConnectionFactory connectionFactory = null;

// 定义链接

Connection connection = null;

// 定义会话

Session session = null;

// 定义目的地

Destination destination = null;

// 定义消息消费者

MessageConsumer consumer = null;

// 定义消息

Message message = null;

public void recieveFromMQ(){

try{

/*

* 创建链接工厂

* ActiveMQConnectionFactory - 由ActiveMQ实现的ConnectionFactory接口实现类.

* 构造方法: public ActiveMQConnectionFactory(String userName, String password, String brokerURL)

*  userName - 访问ActiveMQ服务的用户名,用户名可以通过jetty-realm.properties配置文件配置.

*  password - 访问ActiveMQ服务的密码,密码可以通过jetty-realm.properties配置文件配置.

*  brokerURL - 访问ActiveMQ服务的路径地址.路径结构为-协议名://主机地址:端口号

*      此链接基于TCP/IP协议.

*/

connectionFactory = new ActiveMQConnectionFactory("admin", "admin", "tcp://192.168.23.13:61616");

// 创建链接对象

connection = connectionFactory.createConnection();

// 启动链接

connection.start();

/*

* 创建会话对象

* 方法- connection.createSession(boolean transacted,int acknowledgeMode);

*  transacted - 是否使用事务,可选值为true|false

*      true - 使用事务,当设置此变量值,则acknowledgeMode参数无效,建议传递的acknowledgeMode参数值为

*          Session.SESSION_TRANSACTED

*      false - 不使用事务,设置此变量值,则acknowledgeMode参数必须设置.

*  acknowledgeMode - 消息确认机制,可选值为:

*      Session.AUTO_ACKNOWLEDGE - 自动确认消息机制

*      Session.CLIENT_ACKNOWLEDGE - 客户端确认消息机制

*      Session.DUPS_OK_ACKNOWLEDGE - 有副本的客户端确认消息机制

*/

session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

// 创建目的地,目的地命名即队列命名,消息消费者需要通过此命名访问对应的队列

destination = session.createQueue("test-mq");

// 创建消息消费者,创建的消息消费者与某目的地对应,即方法参数目的地.

consumer = session.createConsumer(destination);

// 从ActiveMQ服务中获取消息

message = consumer.receive();

TextMessage tMsg = (TextMessage) message;

System.out.println("从MQ中获取的消息是:"+tMsg.getText());

}catch(Exception e){

e.printStackTrace();

System.out.println("访问ActiveMQ服务发生错误!!");

}finally{

try {

// 回收消息消费者资源

if(null != consumer)

consumer.close();

} catch (JMSException e) {

e.printStackTrace();

}

try {

// 回收会话资源

if(null != session)

session.close();

} catch (JMSException e) {

e.printStackTrace();

}

try {

// 回收链接资源

if(null != connection)

connection.close();

} catch (JMSException e) {

e.printStackTrace();

}

}

}

}

2.6.2 第二步:修改测试类MessageTest,新增测试方法

@Test

public void recieveFromMQ(){

MyConsumer consumer = new MyConsumer();

consumer.recieveFromMQ();

}

2.6.3 第三步:测试

--查看Eclipse控制台

9b560cdbf902aa843f3a8c02bb643210.png

--查看ActiveMQ管理控制界面

e56b65fa7952fda22600cf3ea690957e.png

--消息被消费了,测试成功!!!

3 ActiveMQ监听器

问题:在前面的示例中,我们发现消费者每次只能消费一条消息。当队列中有多条消息的时候,我们需要多次运行消费者,才能消费完这些消息。很麻烦!!!!如何解决这个问题呢?我们希望一次将所有的消息全部接收。

答:使用ActiveMQ监听器来监听队列,持续消费消息。

3.1 配置步骤说明

(1)创建一个监听器对象。

(2)修改消费者代码,加载监听器。

3.2 配置步骤

3.2.1 第一步:创建监听器MyListener类

--说明:自定义监听器需要实现MessageListener接口

package cn.gzsxt.mq.listener;

import javax.jms.JMSException;

import javax.jms.Message;

import javax.jms.MessageListener;

import javax.jms.TextMessage;

public class MyListener implements MessageListener{

@Override

public void onMessage(Message message) {

if(null!=message){

TextMessage tMsg = (TextMessage) message;

try {

System.out.println("从MQ中获取的消息是:"+tMsg.getText());

} catch (JMSException e) {

e.printStackTrace();

}

}

}

}

3.2.2 第二步:修改MyConsumer代码,加载监听器

--说明:监听器需要持续加载,因此消费程序不能结束。

这里我们使用输入流阻塞消费线程结束。(实际开发中,使用web项目加载)

package cn.gzsxt.mq.consumer;

import javax.jms.Connection;

import javax.jms.ConnectionFactory;

import javax.jms.Destination;

import javax.jms.JMSException;

import javax.jms.Message;

import javax.jms.MessageConsumer;

import javax.jms.Session;

import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnectionFactory;

import cn.gzsxt.mq.listener.MyListener;

/**

* @ClassName:MyConsumer

* @Description: 消息消费者代码

*/

public class MyConsumer {

// 定义链接工厂

ConnectionFactory connectionFactory = null;

// 定义链接

Connection connection = null;

// 定义会话

Session session = null;

// 定义目的地

Destination destination = null;

// 定义消息消费者

MessageConsumer consumer = null;

// 定义消息

Message message = null;

public Message recieveFromMQ(){

try{

/*

* 创建链接工厂

* ActiveMQConnectionFactory - 由ActiveMQ实现的ConnectionFactory接口实现类.

* 构造方法: public ActiveMQConnectionFactory(String userName, String password, String brokerURL)

*  userName - 访问ActiveMQ服务的用户名,用户名可以通过jetty-realm.properties配置文件配置.

*  password - 访问ActiveMQ服务的密码,密码可以通过jetty-realm.properties配置文件配置.

*  brokerURL - 访问ActiveMQ服务的路径地址.路径结构为-协议名://主机地址:端口号

*      此链接基于TCP/IP协议.

*/

connectionFactory = new ActiveMQConnectionFactory("admin", "admin", "tcp://192.168.23.13:61616");

// 创建链接对象

connection = connectionFactory.createConnection();

// 启动链接

connection.start();

/*

* 创建会话对象

* 方法- connection.createSession(boolean transacted,int acknowledgeMode);

*  transacted - 是否使用事务,可选值为true|false

*      true - 使用事务,当设置此变量值,则acknowledgeMode参数无效,建议传递的acknowledgeMode参数值为

*          Session.SESSION_TRANSACTED

*      false - 不使用事务,设置此变量值,则acknowledgeMode参数必须设置.

*  acknowledgeMode - 消息确认机制,可选值为:

*      Session.AUTO_ACKNOWLEDGE - 自动确认消息机制

*      Session.CLIENT_ACKNOWLEDGE - 客户端确认消息机制

*      Session.DUPS_OK_ACKNOWLEDGE - 有副本的客户端确认消息机制

*/

session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

// 创建目的地,目的地命名即队列命名,消息消费者需要通过此命名访问对应的队列

destination = session.createQueue("test-mq");

// 创建消息消费者,创建的消息消费者与某目的地对应,即方法参数目的地.

consumer = session.createConsumer(destination);

// // 从ActiveMQ服务中获取消息

// message = consumer.receive();

//

// TextMessage tMsg = (TextMessage) message;

//

// System.out.println("从MQ中获取的消息是:"+tMsg.getText());

//加载监听器

consumer.setMessageListener(newMyListener());

//监听器需要持续加载,这里我们使用输入流阻塞当前线程结束。

System.in.read();

}catch(Exception e){

e.printStackTrace();

System.out.println("访问ActiveMQ服务发生错误!!");

}finally{

try {

// 回收消息消费者资源

if(null != consumer)

consumer.close();

} catch (JMSException e) {

e.printStackTrace();

}

try {

// 回收会话资源

if(null != session)

session.close();

} catch (JMSException e) {

e.printStackTrace();

}

try {

// 回收链接资源

if(null != connection)

connection.close();

} catch (JMSException e) {

e.printStackTrace();

}

}

return message;

}

}

3.3 测试

(1)多次运行生产者,发送多条消息到队列中。

6fab4d4173ac147d7a71078500602e6e.png

(2)运行消费者。观察结果

--查看Eclipse控制台,一次消费了3条消息

dd8a7ecd949f2cae2f6ec7b653a9f90f.png

--查看ActiveMQ管理控制界面,所有消息都被消费了!

3af905ced01f9bfd3f5702c6e2f928e5.png

--测试成功!!!

4 ActiveMQ消息服务模式

问题:在入门示例中,只能向一个消费者发送消息。但是有一些场景,需求有多个消费者都能接收到消息,比如:美团APP每天的消息推送。该如何实现呢?

答:ActiveMQ是通过不同的服务模式来解决这个问题的。

所以,要搞清楚这个问题,必须知道ActiveMQ有哪些应用模式。

4.1 PTP模式(point to point)

--消息模型

724883f21259e11677ed23cbab68a67c.png

消息生产者生产消息发送到queue中,然后消息消费者从queue中取出并且消费消息。

消息被消费以后,queue中不再有存储,所以消息消费者不可能消费到已经被消费的消息。

Queue支持存在多个消费者,但是对一个消息而言,只会有一个消费者可以消费、其它的则不能消费此消息了。

当消费者不存在时,消息会一直保存,直到有消费消费

我们的入门示例,就是采用的这种PTP服务模式。

4.2 TOPIC(主题订阅模式)

--消息模型

d4f0bf460f663ac924e4146d6e43d172.png

消息生产者(发布)将消息发布到topic中,同时有多个消息消费者(订阅)消费该消息。

和点对点方式不同,发布到topic的消息会被所有订阅者消费。

当生产者发布消息,不管是否有消费者。都不会保存消息

所以,主题订阅模式下,一定要先有消息的消费者(订阅者),后有消息的生产者(发布者)。

我们前面已经实现了PTP模式,下面我们来实现TOPIC模式。

5 Topic模式实现

5.1 配置步骤说明

发表于 2019-08-01 00:00

阅读 ( 411 )

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

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

相关文章

第一个C语言编译器是怎样编写的?

点击上方蓝字关注我,了解更多咨询以我们嵌入式开发中经常使用的C语言为例,我们来介绍一下第一个C语言编译器的来源。还是让我们回顾一下C语言历史:1970年Tomphson和Ritchie在BCPL(一种解释型语言)的基础上开发了B语言&…

C语言fgets()函数:以字符串形式读取文件

点击上方蓝字关注我&#xff0c;了解更多咨询C语言 fgets() 函数从文本文件中读取一个字符串&#xff0c;并将其保存到内存变量中。fgets() 函数位于 <stdio.h> 头文件中&#xff0c;其使用格式如下&#xff1a;fgets(字符串指针,字符个数n,文件指针);格式说明&#xff1…

摆脱冷气_摆脱匿名类

摆脱冷气我真的很喜欢编写和阅读lambda表达式-它们简洁&#xff0c;富于表现力和时尚&#xff08;来吧&#xff0c;这样就没关系了&#xff01;&#xff09;。 将此与匿名类进行比较。 这就是为什么我喜欢摆脱它们&#xff01; 在过去的几个月里&#xff0c;这种认识慢慢地实现…

深入了解C语言

点击上方蓝字关注我&#xff0c;了解更多咨询c语言在编程语言中是偏底层的语言&#xff0c;像JavaScript&#xff0c;以及java。都是在c语言的基础上编译出来的。像操作系统&#xff1a;unix &#xff0c;linux &#xff0c;windows都是依靠c语言开发出来的&#xff0c;使用c语…

C语言函数注意点有哪些?

点击上方蓝字关注我&#xff0c;了解更多咨询构成C程序的基本单位是函数 C语言程序是由函数构成的&#xff0c;不存在过程。函数名代表该函数的入口地址C语言函数可以嵌套调用&#xff0c;例如&#xff1a;fun(fun(x)) &#xff1b;于C语言中&#xff0c;子程序的…

C语言中的逻辑值

点击上方蓝字关注我&#xff0c;了解更多咨询C语言中的逻辑值1.C语言中的逻辑值2.逻辑运算符的运算规律3.逻辑值的举例说明一&#xff0e;C语言中的逻辑值逻辑值即逻辑运算操作的结果。在C语言中&#xff0c;逻辑运算包括关系运算与逻辑运算。关系运算包括大于(>),小于(<…

java page size_java ducument.pagesize.a2打印时用a4可以吗

展开全部概述Document是itext的基础&#xff0c;你可以添加文档数据(用户阅读62616964757a686964616fe58685e5aeb931333339666161的信息)和元数据(pdf内部使用的信息)。在创建document对象时&#xff0c;你可以定义page size&#xff0c;page color and page margins。构造函数…

C/C++语言重要语法之输入输出

点击上方蓝字关注我&#xff0c;了解更多咨询C语言是一种编译式的、通用的、大小写敏感的编程语言&#xff0c;完全支持面向对象开发。基本的输入输出cin和cout在C语言中&#xff0c;标准的键盘输入和屏幕输出功能分别使用scanf()和printf()两个函数实现。在C语言中&#xff0c…

mysql int number_Oracle/MySQL decimal/int/number 转字符串

有时客户需要流水数据&#xff0c;当导出为excel的时候&#xff0c;客户编号等很长数字的栏位&#xff0c;被excel变成科学记数法&#xff0c;无法正常查看。因此&#xff0c;需要将Oracle/MySQL中的decimal/int 转 varchar&#xff0c;这样在excel中就可以放心查看了。Oracle的…

C语言的“递归函数”这么难理解,为什么不丢弃它呢?

点击上方蓝字关注我&#xff0c;了解更多咨询变量就是在程序运行期间其值可以变化的量。每个变量都属于一种类型&#xff0c;每种类型都定义了变量的格式和行为。因此&#xff0c;一个变量应该有属于自己的名称&#xff0c;并且在内存中占有存储空间&#xff0c;其中&#xff0…

apache lucene_Apache Lucene的结构

apache lucene无可估量的高贵的Apache软件基金会&#xff08;Apache Software Foundation&#xff09;产生了许多巨大的产品&#xff08;Ant&#xff0c;CouchDB&#xff0c;Hadoop&#xff0c;JMeter&#xff0c;Maven&#xff0c;OpenOffice&#xff0c;Subversion等&#xf…

mysql 排序 过滤_【MYSQL】-3 排序与过滤

上周加入数据蛙二期培训&#xff0c;结束了孤独战斗的现状。断断续续自学了3个月(当然看了各种视频和各种书&#xff0c;一把辛酸泪。。。)&#xff0c;现在选择报班&#xff0c;主要还是觉得一个靠谱的组织和团队&#xff0c;可以极大缓解我学习过程中不时闪现的焦虑和无助&am…

构造函数 构造代码块_构造函数必须没有代码

构造函数 构造代码块构造函数中应完成多少工作&#xff1f; 在构造函数内部进行一些计算然后封装结果似乎是合理的。 这样&#xff0c;当对象方法需要结果时&#xff0c;我们将准备好它们。 听起来是个好方法&#xff1f; 不&#xff0c;这不对。 这是一个坏主意&#xff0c;原…

C语言按位逻辑运算符总结-与、或、非、异或

点击上方蓝字关注我&#xff0c;了解更多咨询C中有按位逻辑运算符&#xff1a;按位取反、按位与、按位或、按位异或。这4个运算符可以用于整型&#xff0c;包括char类型。按位操作针对每一个位进行操作&#xff0c;不影响左右两边的位。4个运算符的作用总结如下&#xff1a;一、…

C语言的本质——位运算

点击上方蓝字关注我&#xff0c;了解更多咨询位运算是指按二进制进行的运算。在系统软件中&#xff0c;常常需要处理二进制位的问题。C语言提供了6个位操作运算符。这些运算符只能用于整型操作数&#xff0c;即只能用于带符号或无符号的char,short,int与long类型。C语言提供的位…

Java创新型模式_java设计模式--创建型模式(一)

2016-04-24 10:10:34创建型模式&#xff1a;工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式注意&#xff1a;工厂模式可以分为三类&#xff1a; 1)简单工厂模式(Simple Factory) 2)工厂方法模式(Factory Method) 3)抽象工厂模式(Abstract Factory)这三种模式从上…

原来这就是C语言的基本结构—循环结构?!

点击上方蓝字关注我&#xff0c;了解更多咨询今天我们就着重说说循环结构。循环结构分为三种&#xff0c;分别是for、while、dowhile;我们首先说第一种&#xff1a;for循环..他的代码格式为&#xff1a;for(判断的数值初始化;判断条件;改变判断数值大小){循环语句块&#xff1b…

java count 在哪一类里_java 5线程中 Semaphore信号灯,CyclicBarrier类,CountDownLatch计数器以及Exchanger类使用...

先来讲解一下Semaphore信号灯的作用:可以维护当前访问自身的线程个数&#xff0c;并提供了同步机制&#xff0c;使用semaphore可以控制同时访问资源的线程个数例如&#xff0c;实现一个文件允许的并发访问数。请看下面的演示代码:1 public classSemaphoreTest2 {3 public stati…

C/C++入门易错点及常用小技巧

点击上方蓝字关注我&#xff0c;了解更多咨询C语言诞生至今已有30多个年头了&#xff0c;主要集中在需要运行效率比较高的行业&#xff0c;比如现在的游戏开发以及高效服务器等等。C学习难度比其它语言都要高&#xff0c;这是不可否认的&#xff0c;其学习难度主要在于它的复杂…

quasar_Quasar和Akka –比较

quasaractor模型是用于容错和高度可扩展系统的设计模式。 角色是独立的工作程序模块&#xff0c;它们仅通过消息传递与其他角色进行通信&#xff0c;可以与其他角色隔离而失败&#xff0c;但是可以监视其他角色的故障并在发生这种情况时采取一些恢复措施。 角色是简单&#xff…