序:
MQ的优势就不做介绍了可以自行百度,前篇写了springboot集成本地搭建的rabbitmq组建,但是项目最后部署打算还是直接使用阿里云的AMQP,阿里云AMQP是直接可以兼容rabbitmq并且在集成的时候 rabbitmq 是通过用户密码等配置做集成而阿里云先调用阿里动态生产的密钥做链接更加安全后台也更完善。
- POM:
在POM中引入
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.5.0</version>
</dependency>
<dependency>
<groupId>com.alibaba.mq-amqp</groupId>
<artifactId>mq-amqp-client</artifactId>
<version>1.0.5</version>
</dependency>
- 阿里密钥类:
import com.alibaba.mq.amqp.utils.UserUtils;
import com.rabbitmq.client.impl.CredentialsProvider;
import org.apache.commons.lang3.StringUtils;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
/**
* 阿里云 UserName、Password 生成类(动态变化)
*/
public class AliyunCredentialsProvider implements CredentialsProvider {
/**
* Access Key ID.
*/
private final String accessKeyId;
/**
* Access Key Secret.
*/
private final String accessKeySecret;
/**
* security temp token. (optional)
*/
private final String securityToken;
/**
* 实例 id(从阿里云 AMQP 版控制台获取)
*/
private final String instanceId;
public AliyunCredentialsProvider(final String accessKeyId, final String accessKeySecret,
final String instanceId) {
this(accessKeyId, accessKeySecret, null, instanceId);
}
public AliyunCredentialsProvider(final String accessKeyId, final String accessKeySecret,
final String securityToken, final String instanceId) {
this.accessKeyId = accessKeyId;
this.accessKeySecret = accessKeySecret;
this.securityToken = securityToken;
this.instanceId = instanceId;
}
@Override
public String getUsername() {
if(StringUtils.isNotEmpty(securityToken)) {
return UserUtils.getUserName(accessKeyId, instanceId, securityToken);
} else {
return UserUtils.getUserName(accessKeyId, instanceId);
}
}
@Override
public String getPassword() {
try {
return UserUtils.getPassord(accessKeySecret);
} catch (InvalidKeyException e) {
//todo
} catch (NoSuchAlgorithmException e) {
//todo
}
return null;
}
}
- 生产者:
import com.rabbitmq.client.*;
import com.yibaijin.yibaijin.service.sender.service.MessageSenderService;
import com.yibaijin.yibaijin.service.util.ConfigUtil;
import com.yibaijin.yibaijin.service.util.JsonTool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.concurrent.TimeoutException;
public void MqSender(String uuid,HashMap<String,String> message) throws IOException, TimeoutException
{
ConnectionFactory factory = new ConnectionFactory();
// 设置接入点,到控制台概览页面上查看获取
factory.setHost("×××××.aliyuncs.com");
factory.setCredentialsProvider(new AliyunCredentialsProvider("×××××", "×××××", "amqp-cn-×××××"));
factory.setAutomaticRecoveryEnabled(true);
factory.setNetworkRecoveryInterval(5000);
// 设置 Vhost 名称,请确保已在控制台上创建完成
factory.setVirtualHost();
// 默认端口,非加密端口 5672,加密端口 5671
factory.setPort(5672);
//基于网络环境合理设置超时时间
factory.setConnectionTimeout(30 * 1000);
factory.setHandshakeTimeout(30 * 1000);
factory.setShutdownTimeout(0);
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
AMQP.BasicProperties props = new AMQP.BasicProperties.Builder().messageId(uuid).build();
channel.basicPublish("×××××", "×××××", true, props,
message.toString().getBytes(StandardCharsets.UTF_8));
connection.close();
}
- 消费者:
public static void aaa() throws IOException, TimeoutException, NoSuchAlgorithmException, InvalidKeyException {
long timestamp = System.currentTimeMillis();
ConnectionFactory factory = new ConnectionFactory();
// 设置接入点,到控制台概览页面上查看获取
factory.setHost("×××××.aliyuncs.com");
// ${instanceId} 为实例 ID,从阿里云 AMQP 版控制台获取
// ${AccessKey} 阿里云身份验证,在阿里云服务器管理控制台创建
// ${SecretKey} 阿里云身份验证,在阿里云服务器管理控制台创建
//一定要这个才能自动恢复
factory.setCredentialsProvider(new AliyunCredentialsProvider("×××××", "×××××", "×××××"));
factory.setAutomaticRecoveryEnabled(true);
factory.setNetworkRecoveryInterval(5000);
// 设置 Vhost 名称,请确保已在控制台上创建完成
factory.setVirtualHost();
// 固定端口
factory.setPort(5672);
factory.setConnectionTimeout(300 * 1000);
factory.setHandshakeTimeout(300 * 1000);
factory.setShutdownTimeout(0);
Connection connection = factory.newConnection();
final Channel channel = connection.createChannel();
// 创建 ${ExchangeName},该 Exchange 必须在控制台上已存在,并且 Exchange 的类型与控制台上的类型一致
// AMQP.Exchange.DeclareOk exchangeDeclareOk = channel.exchangeDeclare("exchangeTest", "direct", true, false, false, null);
// 创建 ${QueueName} ,该 Queue 必须在控制台上已存在
// AMQP.Queue.DeclareOk queueDeclareOk = channel.queueDeclare("queue_one_key1", false, false, false, new HashMap<String, Object>());
// Queue 与 Exchange 进行绑定,并确认绑定的 BindingKeyTest
// AMQP.Queue.BindOk bindOk = channel.queueBind("queue_one_key1", "exchangeTest", "N4yk063g");
// 开始消费消息
channel.basicConsume("×××××", false, "×××××", new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope,
AMQP.BasicProperties properties, byte[] body)
throws IOException {
//接收到的消息,进行业务逻辑处理
System.out.println("Received: " + new String(body, "UTF-8") + ", deliveryTag: " + envelope.getDeliveryTag() + ", messageId: " + properties.getMessageId());
process(body); //自己处理逻辑方法
System.out.println("Received: " + new String(body, "UTF-8") + ", deliveryTag: " + envelope.getDeliveryTag() + ", messageId: " + properties.getMessageId());
channel.basicAck(envelope.getDeliveryTag(), false);
}
});
- 启动类:
重点是启动类,阿里给的demo都是main方法启动所以消费者这部分写成了静态类方便在项目启动的时候一起启动监控MQ的变化;
public class ServiceBootWebApplication {
public static void main(String[] args) {
System.setProperty("mail.mime.charset","UTF-8");
System.setProperty("mail.mime.splitlongparameters", "false");
SpringApplication.run(ServiceBootWebApplication.class, args);
try {
Receiver.aaa();
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
}
- 备注:
正常我们都有多个环境,每个环境都独立买一套阿里MQ太浪费,解决办法是通过
根据不同环境加载不同的vhost
完全个人实践。。。。。