信创产品TongLinkQ安装及springboot2整合使用

安装

参考1
参考2

上传

上传到/home/tlq目录下

解压,将license.dat拷贝到TLQ8中

创建用户

复制代码
sudo useradd tlq 新建用户
sudo passwd tlq 设置密码
su tlq (在tql用户下操作)

设置环境变量

复制代码
 cd /home/tlq/TLQ8/
 cat ./setp >> ~/.bash_profile

生效
source ~/.bash_profile

查看
env|grep TLQ

启动

复制代码
tlq        #启动TongLink/Q
tlq  -cstop   #  停止 TongLink/Q 
tlq  -cabort   #强制停止服务

springboot2集成

解压后的目录中存在sample示例代码

集成代码

消息发送

j 复制代码
package com.justai.icp.sms.config;

import com.tongtech.tmqi.QueueConnectionFactory;

import javax.jms.*;

public class QueueSenderNoJNDI {

  public static void main(String[] args) {
    //==发送消息的目的队列
    String queName = "lq";
    //==连接工厂类
    QueueConnectionFactory queueConnectionFactory = null;
    //==连接类
    QueueConnection queueConnection = null;
    //==会话类
    QueueSession queueSession = null;
    //==打开的队列
    Queue queue = null;
    //==生产者
    QueueSender queueSender = null;

    try {
      //==创建连接工厂对象,并设置服务器地址信息,如果应用和TLQ服务端不在同一台机器上,请使用实际的服务端IP和Port替代下方的127.0.0.1和10024
      queueConnectionFactory = new QueueConnectionFactory();
      queueConnectionFactory.setProperty("tmqiAddressList", "tlkq://10.10.12.85:10024");
      //==创建Connection和Session
      queueConnection = queueConnectionFactory.createQueueConnection();
      queueSession = queueConnection.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
      //==打开TLQ 队列和创建QueueSender
      queue = queueSession.createQueue(queName);
      queueSender = queueSession.createSender(queue);
      //==启动连接
      queueConnection.start();

      //==生成一个TEXT类型消息
      MapMessage mapMessage = queueSession.createMapMessage();
      System.out.println("发送消息...");
      mapMessage.setString("type","sms");
      mapMessage.setString("msg","哈哈哈");
      queueSender.send(mapMessage);
      System.out.println("发送完成...");

    } catch (Exception jmse) {
      System.out.println("Exception oxxurred :" + jmse);
      jmse.printStackTrace();
    } finally {
      try {
        if (queueSession != null) {
          //==关闭会话
          queueSession.close();
        }
        if (queueConnection != null) {
          //==关闭连接
          queueConnection.close();
        }
      } catch (Exception e) {
        System.out.println("退出时发生错误。");
        e.printStackTrace();
      }
    }
  }
}

消息接收

j 复制代码
package com.justai.icp.sms.config;

import com.tongtech.jms.FileMessage;
import com.tongtech.tmqi.QueueConnectionFactory;

import javax.jms.*;

public class QueueReceiverNoJNDI {
	public static void main(String[] args) {
    //==发送消息的目的队列
    String queName = "lq";
    //==连接工厂类
    QueueConnectionFactory queueConnectionFactory = null;
    //==连接类
    QueueConnection queueConnection = null;
    //==会话类
    QueueSession queueSession = null;
    //==打开的队列
    Queue queue = null;
    //==消费者
    QueueReceiver queueReceiver = null;

    try {
      //==创建连接工厂对象,并设置服务器地址信息,如果应用和TLQ服务端不在同一台机器上,请使用实际的服务端IP和Port替代下方的127.0.0.1和10024
      queueConnectionFactory = new QueueConnectionFactory();
      queueConnectionFactory.setProperty("tmqiAddressList", "tlkq://10.10.12.85:10024");
      //==创建Connection和Session
      queueConnection = queueConnectionFactory.createQueueConnection();
      queueSession = queueConnection.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
      //==打开TLQ 队列和创建QueueReceiver
      queue = queueSession.createQueue(queName);
      queueReceiver = queueSession.createReceiver(queue);
      //==启动连接
      queueConnection.start();

      //==接收消息,参数为超时时间,单位毫秒,如果不填写时间,则receive会无限期等待,直到接收到消息
      Message message = queueReceiver.receive(2000);
      
      //==判断接收到的消息的类型,并输出内容
      if (message != null) {
        if (message instanceof TextMessage) {
          TextMessage textMessage = (TextMessage)message;
          System.out.println("收到一条Text消息:" + textMessage.getText());
        } else if (message instanceof MapMessage) {
          System.out.println("收到一条Map消息");
        } else if (message instanceof StreamMessage) {
          System.out.println("收到一条Text消息");
        } else if (message instanceof BytesMessage) {
          System.out.println("收到一条Bytes消息");
        } else if (message instanceof ObjectMessage) {
          System.out.println("收到一条Object消息");
        } else if (message instanceof FileMessage) {
          System.out.println("收到一条文件消息");
        }
      } else {
        System.out.println("没有收到消息");
      }
    } catch (Exception jmse) {
      System.out.println("Exception oxxurred :" + jmse.toString());
      jmse.printStackTrace();
    } finally {
      try {
        if (queueSession != null) {
          //==关闭会话
          queueSession.close();
        }
        if (queueConnection != null) {
          //==关闭连接
          queueConnection.close();
        }
      } catch (Exception e) {
        System.out.println("退出时发生错误。");
        e.printStackTrace();
      }
    }
  }
}

消息异步接收

j 复制代码
package com.justai.icp.sms.config;

import com.tongtech.jms.FileMessage;

import javax.jms.*;
import java.util.Properties;


public class QueueReceiverAsynNewJNDI {
    public static final String tcf = "tongtech.jms.jndi.JmsContextFactory";/* initial context factory*/
   
    public static final String remoteURL = "tlq://10.10.12.85:10024";
    public static final String remoteFactory = "RemoteConnectionFactory";
	
	public static void main(String[] args) {
  
		ConnectionFactory testConnFactory = null;
		Connection myConn = null;
		Session mySession = null;
		Queue testQueue = null;
		MessageConsumer testConsumer = null;
		try {
            //==设置TLQ JMS连接工厂
			Properties pro = new Properties();
			pro.put("java.naming.factory.initial", tcf);
            //==设置JNDI服务器URL,如果本应用程序例子和JNDI服务器不在一起,请用JNDI服务器IP地址取代127.0.0.1;
            //==同时要修改服务端配置tlqjndi.conf中RemoteConnectionFactory的tmqiAddressList修改为JMS服务器IP
			pro.setProperty("java.naming.provider.url", remoteURL);

            //==查找TLQ JMS连接工厂和消息队列
			javax.naming.Context ctx = new javax.naming.InitialContext(pro);
			//查找指定名称的连接工厂信息,RemoteConnectionFactory对应的是TLQ服务节点tlqjndi.conf中[JndiSystem]->[Factory]->FactoryName配置项
			testConnFactory = (ConnectionFactory) ctx.lookup(remoteFactory);
			//查找指定的JNDI队列名称,this.pQueName对应的是TLQ服务节点tlqjndi.conf中[JndiSystem]->[JndiQueue]->JndiQueueName配置项
            testQueue = (Queue) ctx.lookup("MyQueue");
            //==创建Connection,此时并不能立即开始收发消息,必须调用start启动连接,Connection是线程安全的
			myConn = testConnFactory.createConnection();
            //创建会话,此会话非线程安全,所以一个会话只能用在一个线程中
			mySession = myConn.createSession(false, Session.AUTO_ACKNOWLEDGE);
            //==打开TLQ 队列和创建消费者
			testConsumer = mySession.createConsumer(testQueue);
            //==创建并设置监听器
			MessageRec receiver = new MessageRec();
			testConsumer.setMessageListener(receiver);
			//==启动连接
            myConn.start();
			synchronized (receiver) {
				receiver.wait();
			}
			
		} catch (Exception jmse) {
			System.out.println("Exception oxxurred :" + jmse.toString());
			jmse.printStackTrace();
		} finally {
			try {
				if (mySession != null) {
                    //==关闭会话
					mySession.close();
				}
				if (myConn != null) {
                    //==关闭连接
					myConn.close();
				}
			} catch (Exception e) {
				System.out.println("退出时发生错误。");
				e.printStackTrace();
			}
		}
	}

}	

//==监听器类,重写了onMessage方法,在onMessage方法中实现业务处理
class MessageRec implements javax.jms.MessageListener{

	public void onMessage(Message message) {
		try{
                //==判断接收到的消息的类型,并输出内容
				if(message instanceof TextMessage){
					TextMessage textMessage = (TextMessage)message;
					System.out.println("收到一条Text消息:"+textMessage.getText());
				}else if(message instanceof MapMessage ){
					MapMessage mapMessage = (MapMessage)message;
					System.out.println("收到一条Map消息"+mapMessage.getString("type"));
				}else if(message instanceof StreamMessage ){
					System.out.println("收到一条Text消息");
				}else if(message instanceof BytesMessage ){
					System.out.println("收到一条Bytes消息");
				}else if(message instanceof ObjectMessage ){
					System.out.println("收到一条Object消息");
				}else if(message instanceof FileMessage ){
					System.out.println("收到一条File消息");
				}
//				synchronized (this) {
//					notify();
//				}
		}catch(Exception jmse){
			System.out.println("Exception oxxurred :" + jmse.toString());
			jmse.printStackTrace();
		}
		
	}
}

springboot2异步监听

j 复制代码
package com.justai.icp.sms.consumer;

import com.alibaba.fastjson.JSON;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.justai.icp.common.core.domain.R;
import com.justai.icp.common.domain.system.domain.SysMessageUser;
import com.justai.icp.common.domain.system.domain.SysUser;
import com.justai.icp.common.redis.service.RedisService;
import com.justai.icp.feign.remote.system.RemoteUserService;
import com.justai.icp.sms.dto.SysMsgDto;
import com.justai.icp.sms.enums.MessageStatusEnum;
import com.justai.icp.sms.service.IMessageDataService;
import com.justai.icp.sms.utils.CMSSmsUtil;
import com.tongtech.jms.FileMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.jms.*;
import java.io.IOException;
import java.time.Duration;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.ThreadFactory;
import java.util.stream.Collectors;

import static com.justai.icp.common.domain.system.enums.MessageTypeEnum.*;

@Slf4j
@Component
public class MsgConsumer {
    private final ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("thread-call-runner-%d").build();

    @Autowired
    private IMessageDataService messageDataService;

    @Autowired
    private RedisService redisService;

    @Autowired
    private RemoteUserService remoteUserService;

    @Value("${tlq.remoteServer}")
    private String tlqRemoteServer;
    private static final String TCF = "tongtech.jms.jndi.JmsContextFactory";
    private static final String REMOTE_URL = "tlq://";
    private static final String REMOTE_FACTORY = "RemoteConnectionFactory";
    private static final String QUEUE_NAME = "MyQueue";

    private Connection connection;
    com.tongtech.tmqi.QueueConnectionFactory queueConnectionFactory = null;
    //==连接类
    QueueConnection queueConnection = null;
    //==会话类
    QueueSession queueSession = null;
    //==打开的队列
    Queue queue = null;
    //==消费者
    QueueReceiver queueReceiver = null;
    /**
     * 容器启动后自动执行
     */
    @PostConstruct
    public void startListener() {
        try {
            queueConnectionFactory = new com.tongtech.tmqi.QueueConnectionFactory();
            queueConnectionFactory.setProperty("tmqiAddressList", "tlkq://10.10.12.85:10024");
            //==创建Connection和Session
            queueConnection = queueConnectionFactory.createQueueConnection();
            queueSession = queueConnection.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
            Queue queue = queueSession.createQueue("lq");

            connection = queueConnectionFactory.createConnection();
            Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            MessageConsumer consumer = session.createConsumer(queue);

            // 注册监听
            consumer.setMessageListener(new MessageListenerImpl());

            connection.start();
            log.info("TongLinkQ 消息监听器已启动,监听队列:{}", QUEUE_NAME);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("启动 TongLinkQ 监听器失败", e);
        }
    }

    /**
     * 容器关闭时释放连接
     */
    @PreDestroy
    public void stop() {
        try {
            if (connection != null) {
                connection.close();
                log.info("TongLinkQ 连接已关闭");
            }
        } catch (JMSException e) {
            log.error("关闭 TongLinkQ 连接异常", e);
        }
    }

    /**
     * 真正的消息处理类
     */
    private class MessageListenerImpl implements MessageListener {
        @Override
        public void onMessage(Message message) {
            try {
                if (message instanceof TextMessage) {
                    log.info("收到 Text 消息: {}", ((TextMessage) message).getText());
                } else if (message instanceof MapMessage) {
                    String type = ((MapMessage) message).getString("type");
                    String msg = ((MapMessage) message).getString("msg");
                    String msgId = ((MapMessage) message).getString("msgId");
                    log.info("收到 Map 消息: {}", msg);
                    dealMsg(type,msg);
                } else if (message instanceof FileMessage) {
                    log.info("收到 File 消息");
                } else {
                    log.info("收到其他类型消息: {}", message.getClass().getSimpleName());
                }
            } catch (JMSException e) {
                log.error("处理消息异常", e);
            }
        }
    }

    private void dealMsg(String type,String msg)
    {
        if (type.equals(String.valueOf(INTERNAL)))
        {

        }else if (type.equals(String.valueOf(MAIL)))
        {

        }else if (type.equals(String.valueOf(SMS)))
        {
            dealSmsMsgForYC(msg);
        }else {

        }
    }

    public void dealSmsMsgForYC(String msg)
    {
        System.out.println("deal sms msg");
        log.info("deal sms msg");
        try {
            SysMsgDto msgDto = JSON.parseObject(msg, SysMsgDto.class);

            String redisKey = "msglock:" + msgDto.getId();
            //幂等性处理,避免重复消费
            Boolean lock = redisService.redisTemplate.opsForValue().setIfAbsent(redisKey, Duration.ofSeconds(300));
            if (Boolean.TRUE.equals(lock))
            {
                System.out.println("进入分布式锁");
                try
                {
                    //获取消息状态 (推送状态:1未处理;2已推送;3已入队;4已完成;5异常)
                    int pushStatus = messageDataService.getMsgPushStatus(msgDto.getId());

                    System.out.println("判断状态"+pushStatus);
                    if (pushStatus != MessageStatusEnum.COMPLETED.getStatus())
                    {
                        //获取消息-用户
                        List<SysMessageUser> messageUsers = getSysMessageUsers(msgDto);

                        //获取用户信息列表
                        R<List<SysUser>> listR = remoteUserService.getUserListByIds(new HashSet<>(msgDto.getReceiveUser()));
                        System.out.println(JSON.toJSONString(listR));
                        log.info("get user list:{}",JSON.toJSONString(listR));
                        if (listR.isSuccess())
                        {
                            List<SysUser> userList = listR.getData();
                            //收集邮箱列表
                            List<String> phoneList = userList.parallelStream().map(SysUser::getPhonenumber).collect(Collectors.toList());
                            //发送邮件
                            for (String phone : phoneList)
                            {
                                String content = msgDto.getMessageData();
                                // 发送短信
                                int result = 0;
                                try
                                {
                                    result = CMSSmsUtil.sendBatchMessage(phone, content);
                                } catch (IOException e)
                                {
                                    throw new RuntimeException(e);
                                }
                                // 根据短信发送状态返回参数
                                if( result == 1 ){
                                    System.out.println("手机号码" +phone + "短信发送成功!");
                                    log.info("手机号码" +phone + "短信发送成功!");
                                } else {
                                    System.out.println("手机号码" +phone + "短信发送失败!");
                                    log.error("手机号码" +phone + "短信发送失败,请稍后再试!");
                                }
                            }
                        }
                        System.out.println("发送完成");
                        //保存
                        messageDataService.saveMsgUserBatch(messageUsers);
                        //修改消息状态
                        messageDataService.updateMsgStatus(String.valueOf(msgDto.getId()),MessageStatusEnum.COMPLETED);

                    }
                }catch (Exception e)
                {
                    log.error(e.getMessage());
                    e.printStackTrace();
                }finally
                {
                    //释放锁
                    redisService.deleteObject(redisKey);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            //手动应答
            log.error("邮件发送失败:" + e.getMessage());
        }
    }

    /**
     * 收集数据
     * @param msgDto 消息对象
     * @return 消息用户集合
     */
    private List<SysMessageUser> getSysMessageUsers(SysMsgDto msgDto)
    {
        List<String> receiveUserList = msgDto.getReceiveUser();
        //收集要发送的用户信息
        List<SysMessageUser> messageUsers = new ArrayList<>();
        for (String receiveUserId : receiveUserList)
        {
            SysMessageUser messageUser = new SysMessageUser();
            messageUser.setMessageId(msgDto.getId());
            messageUser.setUserId(receiveUserId);
            messageUser.setMsgType(msgDto.getMessageType());
            messageUser.setStatus("1");
            messageUsers.add(messageUser);
        }
        return messageUsers;
    }
}
相关推荐
孟婆来包棒棒糖~25 分钟前
泛型与反射
java·反射·javase·泛型
A尘埃30 分钟前
Spring Event 企业级应用
java·spring·event
YuTaoShao3 小时前
【LeetCode 热题 100】139. 单词拆分——(解法一)记忆化搜索
java·算法·leetcode·职场和发展
Best_Liu~3 小时前
策略模式 vs 适配器模式
java·spring boot·适配器模式·策略模式
direction__3 小时前
Java Main无法初始化主类的原因与解决方法(VsCode工具)
java·vscode
帧栈4 小时前
开发避坑指南(29):微信昵称特殊字符存储异常修复方案
java·mysql
每天的每一天4 小时前
面试可能问到的问题思考-Redis
java
青云交4 小时前
Java 大视界 -- Java 大数据在智能安防人脸识别系统中的活体检测与防伪技术应用
java·大数据·生成对抗网络·人脸识别·智能安防·防伪技术·活体测试
我崽不熬夜5 小时前
Java中基本的输入输出(I/O)操作:你知道如何处理文件吗?
java·后端·java ee