ActiveMQ入门到精通3-ActibeMQ API详解

三、ActiveMQ API讲解

我们写一个简单的Hello World实例,让大家感受下ActiveMQ,需要完成发送者和接受者两部分代码的编写。

(1)建立ConnectionFactory工厂对象,需要填入用户名、密码以及要连接的地址,均使用默认即可,默认端口为:tcp://10.0.31.144:61616

(2)通过ConnectionFactory工厂对象创建一个Connection链接,并且调用ConnectionFactory的start方法开启链接,Connection默认是关闭的。

(3)通过Connection对象创建session会话,用于接收消息,参数配置1:是否启用事务,蚕食配置2:签收模式,一般我们设置为自动签收。

签收模式有三种:

Session.AUTO_ACKNOWLEDGE 当客户端从receive或onMessage成功返回时,Session自动签收客户端的这条消息的收条。

Session.CLIENT_ACKNOWLEDGE 客户端通过调用消息(Message)的acknowledge方法签收消息,在这种情况下,签收发生在Session层面:签收一个已消费的消息,会自动的签收这个Session所有已消费的消息的收条。

Session.DUPS_OK_ACKNOWLEDGE 此选项指示Session不必确保对传送消息的签收,他可能引起消息的重复,但是降低了Session的开销,所以之后客户端能容忍接收重复消息时,才可以使用。

(4)通过session创建Destination对象,指的是一个客户端用来指定生产的消息目标或消息来源的对象。在PTP模式中,Destination被称作Queue队列,在Pub/Sub模式中Destination被称作topic主题。在程序中可以使用多个Queue或topic。

(5)我们需要通过session对象创建消息的发送和接受对象MessageProducer和MessageCustomer.

(6)我们可以使用MessageProducer的setDeliverryMode方法设置持久化特性和费持久化特性(DeliverryMode)。

(7)我们使用JMS规范的TextMessage形式创建数据(通过Session对象),并用MessageProducer的send方法发送数据或MessageCustomer的receive方法接收数据。

(8)最后不要忘记关闭Connection链接。

1 工程搭建Maven依赖

<dependency>
  <groupId>org.apache.activemq</groupId>
  <artifactId>activemq-all</artifactId>
  <version>5.11.1</version>
</dependency>

2 消息发送者

Sender.java


public class Sender {
    public static void main(String[] args) throws Exception{
        //(1)建立ConnectionFactory工厂对象,需要填入用户名、密码以及要连接的地址,均使用默认即可,默认端口为:tcp://10.0.31.144:61616
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("chen","chen123","tcp://10.0.31.144:61616");
        //(2)通过ConnectionFactory工厂对象创建一个Connection链接,并且调用ConnectionFactory的start方法开启链接,Connection默认是关闭的。
        Connection connection = connectionFactory.createConnection();
        connection.start();
        //(3)通过Connection对象创建session会话,用于接收消息,参数配置1:是否启用事务,蚕食配置2:签收模式,一般我们设置为自动签收。
        Session session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
        //(4)通过session创建Destination对象,指的是一个客户端用来指定生产的消息目标或消息来源的对象。在PTP模式中,Destination被称作Queue队列,在Pub/Sub模式中Destination被称作topic主题。在程序中可以使用多个Queue或topic。
        Destination destination = session.createQueue("helloworld");//创建一个queue的消息目标
        //(5)我们需要通过session对象创建消息的发送和接受对象MessageProducer和MessageCustomer.
        MessageProducer messageProducer = session.createProducer(destination);
        //(6)我们可以使用MessageProducer的setDeliverryMode方法设置持久化特性和费持久化特性(DeliverryMode)。
        messageProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT); //非持久化,下次再开启mq时,数据就不存在了
        //(7)我们使用JMS规范的TextMessage形式创建数据(通过Session对象),并用MessageProducer的sen发送数据或MessageCustomer的receive方法接收数据。
        for(int i=1;i<=10;i++){
            TextMessage textMessage = session.createTextMessage("我是消息内容"+i);
            messageProducer.send(textMessage);
        }
        //(8)最后不要忘记关闭Connection链接。
        if(null != connection){
            connection.close();
        }
    }
}

运行后观察MQ服务器:

3 消息接受者

Client.java


public class Client {
    public static void main(String[] args) throws Exception{
        //(1)建立ConnectionFactory工厂对象,需要填入用户名、密码以及要连接的地址,均使用默认即可,默认端口为:tcp://10.0.31.144:61616
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("chen","chen123","tcp://10.0.31.144:61616");
        //(2)通过ConnectionFactory工厂对象创建一个Connection链接,并且调用ConnectionFactory的start方法开启链接,Connection默认是关闭的。
        Connection connection = connectionFactory.createConnection();
        connection.start();
        //(3)通过Connection对象创建session会话,用于接收消息,参数配置1:是否启用事务,蚕食配置2:签收模式,一般我们设置为自动签收。
        Session session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
        //(4)通过session创建Destination对象,指的是一个客户端用来指定生产的消息目标或消息来源的对象。在PTP模式中,Destination被称作Queue队列,在Pub/Sub模式中Destination被称作topic主题。在程序中可以使用多个Queue或topic。
        Destination destination = session.createQueue("helloworld");//创建一个queue的消息目标
        //(5)我们需要通过session对象创建消息的发送和接受对象MessageProducer和MessageCustomer.
        MessageConsumer messageConsumer = session.createConsumer(destination);
        //(7)我们使用JMS规范的TextMessage形式创建数据(通过Session对象),并用MessageProducer的sen发送数据或MessageCustomer的receive方法接收数据。
        while (true){
            TextMessage msg = (TextMessage) messageConsumer.receive();
            if(null == msg) break;
            System.out.println("客户端收到消息:"+msg.getText());
        }
        //(8)最后不要忘记关闭Connection链接。
        if(null != connection){
            connection.close();
        }
    }
}

运行观察控制台输出:


客户端收到消息:我是消息内容1
客户端收到消息:我是消息内容2
客户端收到消息:我是消息内容3
客户端收到消息:我是消息内容4
客户端收到消息:我是消息内容5
客户端收到消息:我是消息内容6
客户端收到消息:我是消息内容7
客户端收到消息:我是消息内容8
客户端收到消息:我是消息内容9
客户端收到消息:我是消息内容10

观察Mq服务器:

解释:有一个消费端,消费了hellworld 10条消息

​4 消息优先级

MessageProducer的send方法提供了多个参数配置,

send(Destination,Message,int deliveryMode,int priority,long timeToLive):

deliveryMode:传送模式,PERSISTENT(默认)和NON_PERSISTENT,如果容忍消息丢失,可以使用NON_PERSISTENT。

priority:消息优先级,从0-9十个级别,0-4是普通消息,5-9是加急消息,默认是4。

timeToLive:消息过期时间,默认情况下消息永不过期。

要使用ActiveMQ的消息优先级,

首先,在activemq.xml中配置

<policyEntry queue=">" producerFlowControl="false" prioritizedMessages="true" useCache="false" expireMessagesPeriod="0" queuePrefetch="1" />

其次,因为每个消息都是长时间的操作,一定要等消息里的命令完全执行完毕后,再向ActiveMQ发送ACK,这样就可以保证所有的消息都是按照优先级来消费的。

5 消息的同步和异步接收

消息的同步接收是指:客户端主动去接收消息,客户端课采用MessageConsume的receive方法去接收下一个消息。

消息的异步接收是指:当消息到达MQ服务器时,MQ服务器主动通知客户端,客户点通过注册一个实现MessageListener接口的对象到MessageConsumer。MessageListener只有一个必须实现的方法:onMessage,它只接受一个参数Message。在为每个发送到Destination的消息实现onMessage时,调用该方法。

示例:参考下一节消息过滤的内容。

6 消息过滤

MessageConsumer是一个由Session创建的对象,用来从Destination接收消息。


session.createConsumer(Destination destination);
session.createConsumer(Destination destination,String messageSelector);
session.createConsumer(Destination destination,String messageSelector,boolean noLocal);
session.createDurableSubscriber(Topic topic,String name);
session.createDurableSubscriber(Topic topic,String name,boolean noLocal);

​其中messageSelector为消息选择器,noLocal标志默认为false,设置为true时,限制消费者只能接受和自己相同连接(connection)所发布的消息,此标志只适用于topic主题模式,不适用于queue队列模式;name标识订阅topic主题所对应的订阅名称,持久订阅时需要设置此参数。

举例:


    public final String SELECTOR = "JMS_TYPE='value'";

该选择器检查了传入消息的“JMS_TYPE”属性,并确定了这个属性的值是否等于“value”。如果相等,则消息被消费,如果不相等,那么消息会被忽略。

代码示例:

消息发送者:Sender.java


public class Sender {
    private ConnectionFactory connectionFactory;
    private Connection connection;
    private Session session;
    private MessageProducer messageProducer;

    public Sender() {
        try{
            this.connectionFactory = new ActiveMQConnectionFactory("chen",
                                                "chen123",
                                                "tcp://10.0.31.144:61616");
            this.connection = this.connectionFactory.createConnection();
            this.connection.start();
            this.session = this.connection.createSession(Boolean.FALSE,Session.AUTO_ACKNOWLEDGE);
            this.messageProducer=this.session.createProducer(null);
        }catch (JMSException e){
            e.printStackTrace();
        }
    }


    public void send() {
        try{
            Destination destination = this.session.createQueue("first");

            MapMessage msg1 = this.session.createMapMessage();
            msg1.setString("name","Jack");
            msg1.setString("address","Bei Jing");
            msg1.setIntProperty("age",23);
            msg1.setStringProperty("sex","m");


            MapMessage msg2 = this.session.createMapMessage();
            msg2.setString("name","rose");
            msg2.setString("address","Nan Jing");
            msg2.setIntProperty("age",22);
            msg2.setStringProperty("sex","f");

            MapMessage msg3 = this.session.createMapMessage();
            msg3.setString("name","Tom");
            msg3.setString("address","Tian Jin");
            msg3.setIntProperty("age",23);
            msg3.setStringProperty("sex","m");

            MapMessage msg4 = this.session.createMapMessage();
            msg4.setString("name","Lily");
            msg4.setString("address","Qing dao");
            msg4.setIntProperty("age",21);
            msg4.setStringProperty("sex","f");

            this.messageProducer.send(destination,msg1,DeliveryMode.NON_PERSISTENT,1,1000*60*60);
            this.messageProducer.send(destination,msg2,DeliveryMode.NON_PERSISTENT,3,1000*60*60);
            this.messageProducer.send(destination,msg3,DeliveryMode.NON_PERSISTENT,5,1000*60*60);
            this.messageProducer.send(destination,msg4,DeliveryMode.NON_PERSISTENT,7,1000*60*60);

            this.connection.close();
        }catch (JMSException e){
            e.printStackTrace();
        }
    }

  
    public static void main(String[] args) {
        Sender sender = new Sender();
        sender.send();
    }

}

运行send()方法向mq服务器发送4条数据;

消息接收者:Client.java

public class Client {
    //使用selector的属性,必须是由setXXXProperty()方法定义的属性.
    public final String SELECTOR_1 = "name LIKE 'T%'";//无效
    public final String SELECTOR_2 = "age >= 22";
    public final String SELECTOR_3 = "sex='f'";

    private ConnectionFactory connectionFactory;
    private Connection connection;
    private Session session;
    private Destination destination;
    private MessageConsumer messageConsumer;


    public Client() {
        try{
            this.connectionFactory = new ActiveMQConnectionFactory("chen",
                    "chen123",
                    "tcp://10.0.31.144:61616");
            this.connection = this.connectionFactory.createConnection();
            this.connection.start();
            this.session = this.connection.createSession(Boolean.FALSE,Session.AUTO_ACKNOWLEDGE);
            //定义destination
            this.destination=this.session.createQueue("first");
            //创建消费者的时候发生了变化
            this.messageConsumer=this.session.createConsumer(this.destination,SELECTOR_2);
        }catch (JMSException e){
            e.printStackTrace();
        }
    }

    public void receiver(){
        try{
            this.messageConsumer.setMessageListener(new Listener());
        }catch (JMSException e){
            e.printStackTrace();
        }
    }


    public static void main(String[] args) {
        Client c = new Client();
        c.receiver();
    }

}

其中Listener.java:

public class Listener implements MessageListener{

    public void onMessage(Message message) {
        try {

            if(message instanceof MapMessage){
                MapMessage msg = (MapMessage) message;
                System.out.println(msg.toString());
                System.out.println(msg.getString("name"));
                System.out.println(msg.getString("address"));
                System.out.println(msg.getInt("age"));
                System.out.println(msg.getString("sex"));

            }else{
                System.out.println("消息源类型错误!");
            }
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }
}

运行client.receive()方法,观察输出结果:


ActiveMQMapMessage {commandId = 5, responseRequired = false, messageId = ID:localhost-51630-1508748356821-1:1:1:1:1, originalDestination = null, originalTransactionId = null, producerId = ID:localhost-51630-1508748356821-1:1:1:1, destination = queue://first, transactionId = null, expiration = 1508751957013, timestamp = 1508748357013, arrival = 0, brokerInTime = 1508748322576, brokerOutTime = 1508748334499, correlationId = null, replyTo = null, persistent = false, type = null, priority = 1, groupID = null, groupSequence = 0, targetConsumerId = null, compressed = false, userID = null, content = org.apache.activemq.util.ByteSequence@6fecb8f3, marshalledProperties = org.apache.activemq.util.ByteSequence@5a725e7, dataStructure = null, redeliveryCounter = 0, size = 0, properties = {age=23, sex=m}, readOnlyProperties = true, readOnlyBody = true, droppable = false, jmsXGroupFirstForConsumer = false} ActiveMQMapMessage{ theTable = {} }
Jack
Bei Jing
23
m
ActiveMQMapMessage {commandId = 6, responseRequired = false, messageId = ID:localhost-51630-1508748356821-1:1:1:1:2, originalDestination = null, originalTransactionId = null, producerId = ID:localhost-51630-1508748356821-1:1:1:1, destination = queue://first, transactionId = null, expiration = 1508751957014, timestamp = 1508748357014, arrival = 0, brokerInTime = 1508748322578, brokerOutTime = 1508748334505, correlationId = null, replyTo = null, persistent = false, type = null, priority = 3, groupID = null, groupSequence = 0, targetConsumerId = null, compressed = false, userID = null, content = org.apache.activemq.util.ByteSequence@2e6bf465, marshalledProperties = org.apache.activemq.util.ByteSequence@39220730, dataStructure = null, redeliveryCounter = 0, size = 0, properties = {age=22, sex=f}, readOnlyProperties = true, readOnlyBody = true, droppable = false, jmsXGroupFirstForConsumer = false} ActiveMQMapMessage{ theTable = {} }
rose
Nan Jing
22
f
ActiveMQMapMessage {commandId = 7, responseRequired = false, messageId = ID:localhost-51630-1508748356821-1:1:1:1:3, originalDestination = null, originalTransactionId = null, producerId = ID:localhost-51630-1508748356821-1:1:1:1, destination = queue://first, transactionId = null, expiration = 1508751957015, timestamp = 1508748357015, arrival = 0, brokerInTime = 1508748322578, brokerOutTime = 1508748334505, correlationId = null, replyTo = null, persistent = false, type = null, priority = 5, groupID = null, groupSequence = 0, targetConsumerId = null, compressed = false, userID = null, content = org.apache.activemq.util.ByteSequence@70f0263d, marshalledProperties = org.apache.activemq.util.ByteSequence@5bfb2303, dataStructure = null, redeliveryCounter = 0, size = 0, properties = {age=23, sex=m}, readOnlyProperties = true, readOnlyBody = true, droppable = false, jmsXGroupFirstForConsumer = false} ActiveMQMapMessage{ theTable = {} }
Tom
Tian Jin
23
m

7 Pub/Sub模式

发布订阅模式有点类似于我们日常生活中订阅报纸。每年到年尾的时候,邮局就会发一本报纸集合让我们来选择订阅哪一个,在这个表里头列了所有出版发行的报纸,那么对于我们每一个订阅者来说,我们可以选择一份或者多份报纸。比如北京日报、潇湘晨报等。那么这些个我们订阅的报纸就相当于发布订阅模式里的topic。有很多个人订阅报纸,也有人可能订阅了和我相同的报纸。那么在这里相当于我们在同一个topic里面注册了。对于一份报纸发行来说,它和所有的订阅者就构成了一个1对多的关系,这种关系如下所示:

代码样例:

消息发布者Sender.java

public class Sender {
    private ConnectionFactory connectionFactory;
    private Connection connection;
    private Session session;
    private MessageProducer messageProducer;

    public Sender() {
        try{
            this.connectionFactory = new ActiveMQConnectionFactory("chen",
                                                "chen123",
                                                "tcp://10.0.31.144:61616");
            this.connection = this.connectionFactory.createConnection();
            this.connection.start();
            this.session = this.connection.createSession(Boolean.FALSE,Session.AUTO_ACKNOWLEDGE);
            this.messageProducer=this.session.createProducer(null);
        }catch (JMSException e){
            e.printStackTrace();
        }
    }


    public void sendMessage() {
        try{
            Destination destination = this.session.createTopic("topic");

            TextMessage msg1 = this.session.createTextMessage("消息1");
            TextMessage msg2 = this.session.createTextMessage("消息2");
            TextMessage msg3 = this.session.createTextMessage("消息3");
            this.messageProducer.send(destination,msg1);
            this.messageProducer.send(destination,msg2);
            this.messageProducer.send(destination,msg3);

            this.connection.close();
        }catch (JMSException e){
            e.printStackTrace();
        }
    }


    public static void main(String[] args) {
        Sender sender = new Sender();
        sender.sendMessage();
    }
}

运行main方法查看Mq服务器上的内容:

消息订阅者:(创建多个Client,同时运行)

public class Client {

    private ConnectionFactory connectionFactory;
    private Connection connection;
    private Session session;
    private Destination destination;
    private MessageConsumer messageConsumer;


    public Client() {
        try{
            this.connectionFactory = new ActiveMQConnectionFactory("chen",
                    "chen123",
                    "tcp://10.0.31.144:61616");
            this.connection = this.connectionFactory.createConnection();
            this.connection.start();
            this.session = this.connection.createSession(Boolean.FALSE,Session.AUTO_ACKNOWLEDGE);
            //定义destination
            this.destination=this.session.createTopic("topic");
            //创建消费者的时候发生了变化
            this.messageConsumer=this.session.createConsumer(this.destination);
        }catch (JMSException e){
            e.printStackTrace();
        }
    }

    public void receiver(){
        try{
            this.messageConsumer.setMessageListener(new Listener());
        }catch (JMSException e){
            e.printStackTrace();
        }
    }


    public static void main(String[] args) {
        Client c = new Client();
        c.receiver();
    }
}
public class Listener implements MessageListener{

    public void onMessage(Message message) {
        try {

            if(message instanceof TextMessage){
                TextMessage msg = (TextMessage) message;
                System.out.println(msg.toString());
                System.out.println(msg.getText());
            }else{
                System.out.println("消息源类型错误!");
            }
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值