(三)--JMS规范的落地产品

一. 是什么

1. JavaEE

是一套使用Java进行企业级应用开发的大家一致遵循的13个核心规范工业标准,JavaEE平台提供了一个几月组件的方法来加快设计, 开发,装配及部署企业应用程序.

1.JDBC(Java DataBase)数据库连接

2.JNDI(Java Naming and Directory Interface)Java的命名和目录接口

3. EJB (Enterprise JavaBean)

4. RMI(Remote Method Invoke)远程方法调用

5. Java IDL(Interface Description Language)/CORBA(Common Object Broker Architecture)接口定义语言/公用对象请求代理程序体系结构

6. JSP(Java Server Pages)

7. Servlet

8.XML(Extensible Markup Language) 可扩展白标记语言

9. JMS(Java Message  Service)Java消息服务

10. JTA(Java Transaction API) Java事务API

11. JTS(Java Transaction Service) Java 事务服务

12. JAF (JavaBean Activation Framework)

二. JMS

Java Message Service(Java消息服务时JavaEE中的一个技术)

1. 什么是Java消息服务

Java消息服务指的是两个应用程序之间进行异步通信的API, 它为标准消息协议和消息服务提供了一组通用接口,包括创建,发送,读取消息等,用于支持JAVA应用程序开发,在JavaEE中, 当两个应用程序使用JMS进行通信时,它们之间并不是直接相连的,而是通过一个共同的消息收发服务组件,关联起来以达到解耦/异步削峰的效果

2. JMS的组成结构和特点

在这里插入图片描述

2.1 JMS provider

实现JMS接口和规范的消息中间件,也就是我们的MQ服务器

2.2 JMS producer

消息生产者,创建和发送JMS消息的客户端应用

2.3 JMS consumer

消息消费者, 接收和处理JMS消息的客户端应用

2.4 JMS message

2.4.1 消息头

JMSDestination

  • 消息发送的目的地,主要是指Queue和Topic

JMSDeliveryMode

  • 持久模式和非持久模式.

一条持久性的消息: 应该被传送"一次仅仅一次", 这就意味着如果JMS提供者出现故障, 该消息不会丢失 . 它会在服务器恢复之后再次传递.

一条非持久的消息, 最多会传送一次, 这意味这服务器出现故障,该消息将永远丢失.

JMSExpiration

  • 可以设置消息在一定时间后过期, 默认是永不过期的.
  • 消息过期时间,等于Destination的send方法中的timeToLive值加上发送时刻的GMT时间值.
  • 如果timeToLive值等于零, 则JMSExpiration被设为零,表示该消息永不过期.
  • 如果发送后,在消息过期时间之后消息还没有被发送到目的地,则该消息被清除.
    在这里插入图片描述

JMSPriority

  • 消息优先级, 从0-9十个级别, 0到4是普通消息, 5-9是加急消息,
    JMS不要求MQ严格按照这十个优先级发送消息,但必须保证加急消息要先于普通消息到达,默认是4级.

JMSMessageID
唯一识别每个消息的标识由MQ生产
在这里插入图片描述

2.4.2 消息体
封装具体的消息数据 

5中消息体格式

  1. TextMessage 普通字符串消息,包含一个string
  2. MapMessage 一个Map类型的消息,key为String类型, 而值为Java基本类型
  3. BytesMessage 二进制数组消息,包含一个byte[]
  4. StreamMessage Java数据流消息,用标准流操作来顺序的填充和读取.
  5. ObjectMessage 对象消息,包含一个可序列化的Java对象

发送和接受的消息体类型必须一致对应
消息属性

  1. 如果需要除消息头字段以外的值, 那么可以使用消息属性
  2. 识别/去重/重点标注等操作非常有用的方法
  3. 是什么
    他们是以属性名和属性值对的形式制定的.可以将属性是为消息头得扩展,属性指定一些消息头没有包括的附加信息,比如可以在属性里指定消息选择器.
    消息的属性就像可以分配给一条消息的附加消息头一样. 它们允许开发者添加有关消息的不透明附加信息.
    它们还用于暴露消息选择器在消息过滤时使用的数据.
	TextMessage message= session.createTextMessage();
	message.setText(text);
	message.setStringProperty("username", "z3");//自定义属性

3. JMS的可靠性

1. PERSISTENT: 持久性
2. transaction:事务
3. Acknowledge: 签收

在这里插入图片描述
持久化消息
这是队列的默认传送方式,此模式保证这些消息只被传送一次成功使用一次,对于这些消息,可靠性是优先考虑的因素,

可靠性的另一个重要方面是确保持久性消息传达至目标后,消息服务在向消费者传送它们之前不会丢失这些信息.

持久化主题生产者

package PERSIST;

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;

/**
 * @author xianyiquan
 * @className
 * @create 2019-12-28 13:45
 */
public class JmsProduce_Topic_Persist {

    public static final String ACYIVEMQ_URL = "tcp://192.168.249.88:61616";
    public static final String TOPIC_NAME = "queue01-xianyiquan";
    
    public static void main(String[] args) throws JMSException {
        //1.创建连接工厂,按照给定的url地址,采用默认用户名和密码
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACYIVEMQ_URL);

        //2.通过连接工厂,获得connection并启动访问
        Connection connection = activeMQConnectionFactory.createConnection();
//        connection.start();

        //3.创建会话session
        //两个参数,第一个叫事务/第二个叫签收
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

        //4.创建目的地(具体是队列还是主题topic)
//        Destination destination = session.createQueue(QUEUE_NAME);
        Topic topic = session.createTopic(TOPIC_NAME);

        //5.创建消息的生产者
        MessageProducer producer = session.createProducer(topic);

		//持久化,默认是持久化的
        producer.setDeliveryMode(DeliveryMode.PERSISTENT);
        connection.start();
        //6. 通过使用producer生产3条消息发送到MQ队列里面
        for (int i = 1; i <= 3; i++) {
            //7. 创建消息,好比创建好的订单消息
            TextMessage textMessage = session.createTextMessage("TOPIC_NAME----" + i);//理解为一个字符串
            //8. 通过producer 发送给MQ
            producer.send(textMessage);
        }

        //关闭资源
        producer.close();
        session.close();
        connection.close();
        System.out.println("*************TOPIC_NAME消息发布到MQ完成");
    }

}

持久化主题消费者

package PERSIST;

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;
import java.io.IOException;

/**
 * @author xianyiquan
 * @className
 * @create 2019-12-28 14:34
 */
public class JmsConsumer_Topic_Persist {


    public static final String ACYIVEMQ_URL = "tcp://192.168.249.88:61616";
    public static final String TOPIC_NAME = "queue01-xianyiquan";

    public static void main(String[] args) throws JMSException, IOException {

        System.out.println("******** z3");
        //1.创建连接工厂,按照给定的url地址,采用默认用户名和密码
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACYIVEMQ_URL);

        //2.通过连接工厂,获得connection并启动访问
        Connection connection = activeMQConnectionFactory.createConnection();
        connection.setClientID("z3");

        //3.创建会话session
        //两个参数,第一个叫事务/第二个叫签收
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

        //4.创建目的地(具体是队列还是主题topic)
//        Destination destination = session.createQueue(QUEUE_NAME);
        Topic topic = session.createTopic(TOPIC_NAME);

        TopicSubscriber durableSubscriber = session.createDurableSubscriber(topic, "remark....");
        connection.start();

        Message message = durableSubscriber.receive();
        while ( null != message ){
            TextMessage textMessage = (TextMessage) message;
            System.out.println("*******收到的持久化topic: " + textMessage.getText());
            message = durableSubscriber.receive(1000L);
        }
        /**
         * 1. 一定要先运行一次消费者,等于向MQ注册,类似我订阅了这个主题.
         * 2. 然后再运行生产者发送消息,此时.
         * 3. 无论消费者是否在线,都会接收到,不在线的话,  下次连接的时候,会把没有接收过来的消息全都接收下来.
         */
        session.close();
        connection.close();
    }
}

在这里插入图片描述
事务生产者:

package TX;

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;

/**
 * @author xianyiquan
 * @className
 * @create 2019-12-28 13:45
 */
public class JmsProduce_TX {

    public static final String ACYIVEMQ_URL = "tcp://192.168.249.88:61616";
    public static final String TOPIC_NAME = "queue01-xianyiquan";
    
    public static void main(String[] args) throws JMSException {

        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACYIVEMQ_URL);
        Connection connection = activeMQConnectionFactory.createConnection();
        Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);//-----------------------------------
        Queue queue = session.createQueue(TOPIC_NAME);
        MessageProducer messageProducer = session.createProducer(queue);
        messageProducer.setDeliveryMode(DeliveryMode.PERSISTENT);
        connection.start();
        //6. 通过使用producer生产3条消息发送到MQ队列里面
        for (int i = 1; i <= 3; i++) {
            TextMessage textMessage = session.createTextMessage("tx msg----" + i);//理解为一个字符串
            //textMessage.acknowledge();
            messageProducer.send(textMessage);
        }
        //关闭资源
        messageProducer.close();
        session.commit();//--------------------------------------------------
        session.close();
        connection.close();
        System.out.println("*************tx消息发布到MQ完成");
        try {
            //ok session.commit;
        }catch (Exception e){
            e.printStackTrace();
            //error
            session.rollback();
        }finally {
        }
    }
}

事务消费者

package TX;

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;
import java.io.IOException;

/**
 * @author xianyiquan
 * @className
 * @create 2019-12-28 14:34
 */
public class JmsConsumer_TX {


    public static final String ACYIVEMQ_URL = "tcp://192.168.249.88:61616";
    public static final String QUEQU = "queue01";

    public static void main(String[] args) throws JMSException, IOException {

        System.out.println("******** z3");
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACYIVEMQ_URL);

        Connection connection = activeMQConnectionFactory.createConnection();

        Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);//-----------------------

        Queue queue = session.createQueue(QUEQU);

        MessageConsumer messageConsumer = session.createConsumer(queue);
        connection.start();

        while ( true ){
            TextMessage textMessage = (TextMessage)messageConsumer.receive(4000L);
            if(null != textMessage){
                System.out.println("******消费者收到消息: " + textMessage.getText());
            	//textMessage.acknowledge();
            } else {
                break;
            }
        }
        /**
         * 1. 一定要先运行一次消费者,等于向MQ注册,类似我订阅了这个主题.
         * 2. 然后再运行生产者发送消息,此时.
         * 3. 无论消费者是否在线,都会接收到,不在线的话,  下次连接的时候,会把没有接收过来的消息全都接收下来.
         */
        messageConsumer.close();
        session.commit();//--------------------------------------------------------------------------------------------
        session.close();
        connection.close();
    }
}

在这里插入图片描述

JMS的点对点总结

点对点模型是基于队列的, 生产者发消息到队列, 消费者从队列接收消息, 队列的存在使得消息的异步传输成为可能.和我们平时给朋友发送短信类似.

1: 如果在Session关闭时有部分消息已被收到但还没有被签收(acknowledge), 那当消费者下次连接到相同的队列时, 这些消息还会被再次拒收
2. 队列可以长久地保存消息直到消费者收到消息, 消费者不需要因为担心消息会丢失而时刻和队列保持激活的连接状态, 充分体现了异步传输模式的优势

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值