...
|
...
|
@@ -6,12 +6,15 @@ import com.sunyo.wlpt.message.bus.service.exception.CustomExceptionType; |
|
|
import com.sunyo.wlpt.message.bus.service.response.ResultJson;
|
|
|
import com.sunyo.wlpt.message.bus.service.utils.AESUtils;
|
|
|
import com.sunyo.wlpt.message.bus.service.utils.IdUtils;
|
|
|
import io.netty.util.internal.StringUtil;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
|
|
import org.springframework.stereotype.Component;
|
|
|
|
|
|
import java.io.IOException;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.List;
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
import java.util.concurrent.TimeoutException;
|
|
|
|
...
|
...
|
@@ -74,59 +77,6 @@ public class DirectUtils { |
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* DirectExchange的 消息消费者
|
|
|
*
|
|
|
* @throws IOException IO异常
|
|
|
* @throws TimeoutException 超时异常
|
|
|
*/
|
|
|
public void directConsumer(XmlData xmlData) throws IOException, TimeoutException
|
|
|
{
|
|
|
// 1、创建ConnectionFactory
|
|
|
Connection connection = getConnection(xmlData.getServerIp(), xmlData.getServerPort(),
|
|
|
xmlData.getVirtualHostName(), xmlData.getSuperUsername(), xmlData.getSuperPassword());
|
|
|
// 2、 通过Connection创建一个新的Channel
|
|
|
Channel channel = connection.createChannel();
|
|
|
// 3、设置绑定关系(队列、交换机名称、路由键名称)
|
|
|
// channel.queueBind(queueName, exchangeName, routingKeyName);
|
|
|
// 一次只接受一条未确认的消息
|
|
|
channel.basicQos(1);
|
|
|
// 4、开启监听Queue
|
|
|
DefaultConsumer consumer = new DefaultConsumer(channel) {
|
|
|
@Override
|
|
|
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException
|
|
|
{
|
|
|
try {
|
|
|
// 0、获取出全局唯一的 信息业务id(messageId)
|
|
|
String messageId = properties.getMessageId();
|
|
|
// 必须保证 messageId 不为空,避免空指针异常
|
|
|
if (redisTemplate.opsForValue().setIfAbsent(messageId, "0", 10, TimeUnit.MINUTES)) {
|
|
|
|
|
|
// 消费成功,将redis中的 messageId 对应的value修改为 1
|
|
|
redisTemplate.opsForValue().set(messageId, "1", 10, TimeUnit.MINUTES);
|
|
|
// 手动ack
|
|
|
channel.basicAck(envelope.getDeliveryTag(), false);
|
|
|
|
|
|
log.info("接收到消息:" + new String(body, "UTF-8"));
|
|
|
} else {
|
|
|
// 获取redis中的value,如果是1,就手动ack。如果是0,就什么也不做(是0代表着,正在被消费中)
|
|
|
if ("1".equalsIgnoreCase(redisTemplate.opsForValue().get(messageId))) {
|
|
|
// 手动ack
|
|
|
channel.basicAck(envelope.getDeliveryTag(), false);
|
|
|
}
|
|
|
}
|
|
|
} catch (Exception e) {
|
|
|
// 手动ack
|
|
|
channel.basicAck(envelope.getDeliveryTag(), false);
|
|
|
log.error("接收消息发送错误:" + e.getMessage());
|
|
|
}
|
|
|
}
|
|
|
};
|
|
|
// 消费消息
|
|
|
channel.basicConsume(xmlData.getQueueName(), false, consumer);
|
|
|
}
|
|
|
|
|
|
|
|
|
public ResultJson sendMessage(XmlData xmlData) throws IOException, TimeoutException
|
|
|
{
|
|
|
/**
|
...
|
...
|
@@ -194,6 +144,160 @@ public class DirectUtils { |
|
|
closeConnectionAndChanel(channel, connection);
|
|
|
return ResultJson.success(CustomExceptionType.MESSAGE_SUCCESS);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* byte字节数组 转 String
|
|
|
*
|
|
|
* @param byteArray 字节数组
|
|
|
* @return
|
|
|
*/
|
|
|
public static String byteArrayToStr(byte[] byteArray)
|
|
|
{
|
|
|
if (byteArray == null) {
|
|
|
return null;
|
|
|
}
|
|
|
String str = new String(byteArray);
|
|
|
return str;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* DirectExchange的 消息消费者(推模式)
|
|
|
*
|
|
|
* @throws IOException IO异常
|
|
|
* @throws TimeoutException 超时异常
|
|
|
*/
|
|
|
public List<String> directConsumerByPush(XmlData xmlData) throws IOException, TimeoutException
|
|
|
{
|
|
|
List<String> list = new ArrayList<>();
|
|
|
|
|
|
// 1、创建ConnectionFactory
|
|
|
Connection connection = getConnection(xmlData.getServerIp(), xmlData.getServerPort(),
|
|
|
xmlData.getVirtualHostName(), xmlData.getSuperUsername(), xmlData.getSuperPassword());
|
|
|
|
|
|
// 2、 通过Connection创建一个新的Channel
|
|
|
Channel channel = connection.createChannel();
|
|
|
|
|
|
// 一次只接受一条未确认的消息
|
|
|
channel.basicQos(1);
|
|
|
|
|
|
// 4、开启监听Queue
|
|
|
DefaultConsumer consumer = new DefaultConsumer(channel) {
|
|
|
@Override
|
|
|
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException
|
|
|
{
|
|
|
try {
|
|
|
// 0、获取出全局唯一的 信息业务id(messageId)
|
|
|
String messageId = properties.getMessageId();
|
|
|
|
|
|
// 必须保证 messageId 不为空,避免空指针异常
|
|
|
if (redisTemplate.opsForValue().setIfAbsent(messageId, "0", 10, TimeUnit.MINUTES)) {
|
|
|
|
|
|
// 消费成功,将redis中的 messageId 对应的value修改为 1
|
|
|
redisTemplate.opsForValue().set(messageId, "1", 1, TimeUnit.MINUTES);
|
|
|
// 手动ack
|
|
|
channel.basicAck(envelope.getDeliveryTag(), false);
|
|
|
log.info("接收到消息:" + new String(body, "UTF-8"));
|
|
|
String message = new String(body, "UTF-8");
|
|
|
list.add(message);
|
|
|
} else {
|
|
|
// 获取redis中的value,如果是1,就手动ack。如果是0,就什么也不做(是0代表着,正在被消费中)
|
|
|
if ("1".equalsIgnoreCase(redisTemplate.opsForValue().get(messageId))) {
|
|
|
// 手动ack
|
|
|
channel.basicAck(envelope.getDeliveryTag(), false);
|
|
|
}
|
|
|
}
|
|
|
} catch (Exception e) {
|
|
|
// 手动ack
|
|
|
channel.basicAck(envelope.getDeliveryTag(), false);
|
|
|
log.error("接收消息发送错误:" + e.getMessage());
|
|
|
}
|
|
|
}
|
|
|
};
|
|
|
// 消费消息
|
|
|
channel.basicConsume(xmlData.getQueueName(), false, consumer);
|
|
|
return list;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* DirectExchange的 消息消费者(拉模式)
|
|
|
*
|
|
|
* @throws IOException IO异常
|
|
|
* @throws TimeoutException 超时异常
|
|
|
*/
|
|
|
public ResultJson directConsumerByPull(XmlData xmlData) throws IOException, TimeoutException
|
|
|
{
|
|
|
List<String> list = new ArrayList<>();
|
|
|
|
|
|
Connection connection = getConnection(xmlData.getServerIp(), xmlData.getServerPort(), xmlData.getVirtualHostName(), xmlData.getSuperUsername(), xmlData.getSuperPassword());
|
|
|
Channel channel = connection.createChannel();
|
|
|
channel.basicQos(1);
|
|
|
|
|
|
GetResponse response = channel.basicGet(xmlData.getQueueName(), false);
|
|
|
if (response != null && response.getMessageCount() >= 0) {
|
|
|
String messageId = response.getProps().getMessageId();
|
|
|
if (redisTemplate.opsForValue().setIfAbsent(messageId, "0", 1, TimeUnit.MINUTES)) {
|
|
|
redisTemplate.opsForValue().set(messageId, "1", 1, TimeUnit.MINUTES);
|
|
|
String data = byteArrayToStr(response.getBody());
|
|
|
list.add(data);
|
|
|
channel.basicAck(response.getEnvelope().getDeliveryTag(), false);
|
|
|
} else {
|
|
|
if ("1".equalsIgnoreCase(redisTemplate.opsForValue().get(messageId))) {
|
|
|
channel.basicAck(response.getEnvelope().getDeliveryTag(), false);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
String message = list.get(0);
|
|
|
return StringUtil.isNullOrEmpty(message)
|
|
|
? ResultJson.error(CustomExceptionType.RECEIVE_SERVER_EXCEPTION)
|
|
|
: ResultJson.success(CustomExceptionType.RECEIVE_SUCCESS, message);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* DirectExchange的 消息消费者(拉模式、批量拉取)
|
|
|
*/
|
|
|
public ResultJson directConsumerByPullMore(XmlData xmlData, Integer count) throws IOException, TimeoutException
|
|
|
{
|
|
|
List<String> list = new ArrayList<>();
|
|
|
String serverIp = xmlData.getServerIp();
|
|
|
Integer serverPort = xmlData.getServerPort();
|
|
|
String virtualHostName = xmlData.getVirtualHostName();
|
|
|
String superUsername = xmlData.getSuperUsername();
|
|
|
String superPassword = xmlData.getSuperPassword();
|
|
|
|
|
|
Connection connection = getConnection(serverIp, serverPort, virtualHostName, superUsername, superPassword);
|
|
|
Channel channel = connection.createChannel();
|
|
|
channel.basicQos(1);
|
|
|
|
|
|
while (list.size() < count) {
|
|
|
GetResponse response = channel.basicGet(xmlData.getQueueName(), false);
|
|
|
if (response != null) {
|
|
|
if (response.getMessageCount() >= 0) {
|
|
|
String messageId = response.getProps().getMessageId();
|
|
|
if (redisTemplate.opsForValue().setIfAbsent(messageId, "0", 1, TimeUnit.MINUTES)) {
|
|
|
redisTemplate.opsForValue().set(messageId, "1", 1, TimeUnit.MINUTES);
|
|
|
String data = byteArrayToStr(response.getBody());
|
|
|
list.add(data);
|
|
|
channel.basicAck(response.getEnvelope().getDeliveryTag(), false);
|
|
|
} else {
|
|
|
if ("1".equalsIgnoreCase(redisTemplate.opsForValue().get(messageId))) {
|
|
|
channel.basicAck(response.getEnvelope().getDeliveryTag(), false);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
} else {
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
int size = list.size();
|
|
|
if (0 < size && size < count) {
|
|
|
return new ResultJson<>("20200", "接收消息,成功!但是,该队列内只有" + size + "条消息", list);
|
|
|
}
|
|
|
return size > 0
|
|
|
? ResultJson.success(CustomExceptionType.RECEIVE_SUCCESS, list)
|
|
|
: ResultJson.error(CustomExceptionType.RECEIVE_SERVER_EXCEPTION);
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
...
|
...
|
|