RocketMq注解形式实战——分布式微服务集成rocketmq
微服务集成rocketmq—注解形式实战
定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(MqAutoConfiguration.class)
public @interface EnableMq {
}
定义配置类注册Bean
@Data
public class MqProperties {
/**
* 生产者/消费者名称
*/
private String name;
/**
* ip
*/
private String host;
/**
* 端口
*/
private String port;
}
package cn.mq.config;
import cn.mq.service.MyMqCustomer;
import cn.mq.service.MyMqProducer;
import cn.mq.service.impl.MyMqProducerImpl;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.protocol.heartbeat.SubscriptionData;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import java.util.Map;
/**
* <p>
* 生产者\消费者
* </p>
*
*/
@ComponentScan("cn.mq")
@EnableAutoConfiguration
@AllArgsConstructor
@Slf4j
@Configuration
public class MqAutoConfiguration {
private final Environment environment;
@Bean
@ConfigurationProperties(prefix = "rocketmq")
public MqProperties getMqProperTies() {
return new MqProperties();
}
@Bean
@ConditionalOnBean(MqProperties.class)
public MyMqProducer myMqProducer(MqProperties mqProperties) throws MQClientException {
log.info("==============[[启动 【MQ】 消息生产者]]=============");
MyMqProducerImpl producer = new MyMqProducerImpl(environment.getProperty("spring.application.name", ""));
producer.setNamesrvAddr(mqProperties.getHost() + ":" + mqProperties.getPort());
producer.start();
log.info("==============[[【MQ】 消息生产者启动成功]]=============");
String namesrvAddr = producer.getNamesrvAddr();
log.info("==============[[【producer----NamesrvAddr】 NamesrvAddr]]=============,NamesrvAddr={}",namesrvAddr);
return producer;
}
@Bean
@ConditionalOnBean({MqProperties.class, MyMqCustomer.class})
public DefaultMQPushConsumer defaultMqPushConsumer(MqProperties mqProperties, MyMqCustomer mqCustomer) throws MQClientException {
log.info("==============[[启动注册 【MQ】 消息消费者]]=============");
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(environment.getProperty("spring.application.name", ""));
consumer.setNamesrvAddr(mqProperties.getHost() + ":" + mqProperties.getPort());
mqCustomer.subscribe(consumer);
Map<String, SubscriptionData> sub = consumer.getDefaultMQPushConsumerImpl().getSubscriptionInner();
sub.forEach((k, v) -> log.info("==============订阅topic【{}】, 子tags【{}】=============", k, v.getSubString()));
mqCustomer.registerMessageListener(consumer);
consumer.start();
log.info("==============[[【MQ】 消息消费者注册成功]]=============");
String namesrvAddr = consumer.getNamesrvAddr();
log.info("==============[[【consumer----NamesrvAddr】 NamesrvAddr]]=============,NamesrvAddr={}",namesrvAddr);
return consumer;
}
}
生产者
package cn.mq.service;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.apache.rocketmq.client.producer.MQProducer;
import java.io.UnsupportedEncodingException;
public interface MyMqProducer extends MQProducer {
void sendImPushMsg(Integer targetUserId, Object msgType, Long dataId, String msg) throws JsonProcessingException, UnsupportedEncodingException;
}
package cn.mq.service.impl;
import cn.mq.service.MyMqProducer;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.common.RemotingHelper;
import org.springframework.beans.factory.annotation.Autowired;
import java.io.UnsupportedEncodingException;
@Slf4j
@AllArgsConstructor
public class MyMqProducerImpl extends DefaultMQProducer implements MyMqProducer {
@Autowired
private ObjectMapper objectMapper;
public MyMqProducerImpl(String producerGroup) {
super(producerGroup);
}
@Override
public void sendImPushMsg(Integer targetUserId, Object msgType, Long dataId, String msg) throws JsonProcessingException, UnsupportedEncodingException {
JSONObject json = new JSONObject();
json.put("creator", "zs");
json.put("userId", targetUserId);
json.put("type", JSONObject.toJSON(msgType));
json.put("id", dataId);
json.put("msg", msg);
Message message = new Message("test-topic", null,
objectMapper.writeValueAsString(json).getBytes(RemotingHelper.DEFAULT_CHARSET));
SendResult sendResult = null;
try {
sendResult = this.send(message);
} catch (Exception e) {
e.printStackTrace();
}
log.info("IM推送消息[msgType:{}]发送MQ结果:{}", JSONObject.toJSON(msgType), sendResult.getSendStatus());
if (sendResult.getSendStatus() != SendStatus.SEND_OK) {
log.error("IM推送消息发送MQ失败,消息:{}", json.toJSONString());
}
}
}
生产者使用示例
package cn.rc100.oa.service.impl;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.common.RemotingHelper;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
/**
* <p>
* 审核消息队列服务
* </p>
*
*/
@Slf4j
@Service
@AllArgsConstructor
public class AuditMqServiceImpl implements AuditMqService {
private final MyMqProducer myMqProducer;
private final ObjectMapper objectMapper;
@Override
public void sendAuditResult(Audit audit, Object obj) {
if (ObjectUtil.isNull(obj)) {
obj = audit;
}
try {
Message msg = new Message(MqTopicConstants.OA_AUDIT_RESULT, audit.getType().toString(),
objectMapper.writeValueAsString(obj).getBytes(RemotingHelper.DEFAULT_CHARSET));
SendResult sendResult = myMqProducer.send(msg);
log.info("审核消息发送结果:{}", sendResult.getSendStatus());
} catch (Exception e) {
log.error("审核消息发送失败,审核Id:{},审核内容:{}", audit.getId(), audit.getContent());
e.printStackTrace();
throw new RuntimeException(e);
}
}
/**
* <p>
* 推送消息发送到mq
* </p>
*
* @param targetUserId 目标用户id
* @param type 推送消息类型
* @param dataId 数据Id 用于数据跳转
* @param msg 消息
* @return void
* @author xxx
* @since ----
*/
@Async
public void sendToMq(Integer targetUserId, BaseMsgType type, Integer dataId, String msg) {
try {
JSONObject json = new JSONObject();
json.put("creator", SecurityUtils.getUser() == null ? 1 : SecurityUtils.getUser().getId());
json.put("userId", targetUserId);
json.put("type", objectMapper.writeValueAsString(type));
json.put("id", dataId);
json.put("appKey", CommonConstants.EPLUS_APPKEY);
json.put("msg", msg);
Message message = new Message(MqTopicConstants.MSG_PUSH, null,
objectMapper.writeValueAsString(json).getBytes(RemotingHelper.DEFAULT_CHARSET));
SendResult sendResult = myMqProducer.send(message);
log.info("OA推送消息[key:{},des:{}]发送MQ结果:{}", type.getKey(), type.getDes(), sendResult.getSendStatus());
} catch (Exception e) {
log.error("OA推送消息发送MQ失败,类型:{},类型描述:{}", type.getKey(), type.getDes());
e.printStackTrace();
}
}
@Async
@Override
public void sendResultPushMsg(Audit audit, String reason) {
String msg = StrUtil.format("您的{}审核已被{}", audit.getContent(), audit.getAuditStatus().getDescribe());
if (audit.getAuditStatus() != OaAuditStatusEnum.PASSED && StrUtil.isNotBlank(reason)) {
msg += StrUtil.LF + "原因:" + reason;
}
this.sendToMq(audit.getCreateUser(), OaMsg.create().audit().notification(), audit.getId(), msg);
}
@Async
@Override
public void sendAuditPushMsg(Audit audit, String auditUsers, boolean isUrge) {
String str = "{}有一个{}审核需要您审批,请及时处理";
if (isUrge) {
str = "{}有一个{}审核急需您审批,请尽快处理";
}
String msg = StrUtil.format(str, audit.getCreateUserName(), audit.getContent());
StrUtil.splitTrim(auditUsers, ",").stream()
.filter(StrUtil::isNotBlank)
.map(Integer::valueOf)
.forEach(id -> this.sendToMq(id, OaMsg.create().audit().toDo(), audit.getId(), msg));
}
@Async
@Override
public void sendAuditCopyPushMsg(Audit audit, Integer userId) {
String msg = StrUtil.format("您有一个{}的{}审核抄送,请知悉", audit.getCreateUserName(), audit.getContent());
this.sendToMq(userId, OaMsg.create().copy().notification(), audit.getId(), msg);
}
}
消费者
package cn.mq.service;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.exception.MQClientException;
/**
* <p>
* 消费者实例接口
* </p>
*
*/
public interface Consumer {
/**
* <p>
* 消费监听
* </p>
*
*/
void listener(DefaultMQPushConsumer consumer) throws MQClientException;
}
消费者使用
接口方式
package cn.mq.service;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.exception.MQClientException;
public interface MyMqCustomer {
void subscribe(DefaultMQPushConsumer consumer) throws MQClientException;
void registerMessageListener(DefaultMQPushConsumer consumer);
}
接口方式-其它微服务使用示例
package com.example.rock.mq;
import cn.mq.service.MyMqCustomer;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.message.MessageExt;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class rockMqCustomer implements MyMqCustomer {
@Override
public void subscribe(DefaultMQPushConsumer consumer) throws MQClientException {
consumer.subscribe("test-topic", "rock");
}
@Override
public void registerMessageListener(DefaultMQPushConsumer consumer) {
consumer.registerMessageListener((MessageListenerConcurrently) (msg, content) -> {
log.info("消息接收成功");
try {
for (MessageExt m : msg) {
//log.info(m.getTopic()+":"+new String(m.getBody()));
if("test-topic".equals(m.getTopic())){
System.out.println("消费成功");
}
}
}catch (Exception e){
return ConsumeConcurrentlyStatus.RECONSUME_LATER;
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
});
}
}
抽象类方式
package cn.mq.service;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.common.message.MessageExt;
public interface SimpleConsumer {
String getConsumerName();
void subscribe(DefaultMQPushConsumer consumer);
void consume(MessageExt msg);
}
package cn.mq;
import cn.hutool.core.util.StrUtil;
import cn.mq.config.MqProperties;
import cn.mq.service.Consumer;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.env.Environment;
/**
* <p>
* 消费者基类,用于多消费者实例
* </p>
*/
@AllArgsConstructor
public abstract class BaseConsumer implements InitializingBean {
private final Environment environment;
private final MqProperties mqProperties;
/**
* <p>
* 多消费者注册
* </p>
*/
protected abstract void register();
/**
* <p>
* 新消费者
* </p>
*
*/
@SneakyThrows
protected void newConsumer(String consumerGroup, Consumer consumer) {
if (StrUtil.isBlank(consumerGroup)) {
consumerGroup = environment.getProperty("spring.application.name", "")
.replace("lx-", "")
.replace("-biz", "");
}
DefaultMQPushConsumer dc = new DefaultMQPushConsumer(consumerGroup);
dc.setNamesrvAddr(mqProperties.getHost() + ":" + mqProperties.getPort());
consumer.listener(dc);
dc.start();
}
@Override
public void afterPropertiesSet() {
register();
}
}
package cn.mq;
import cn.mq.config.MqProperties;
import cn.mq.service.SimpleConsumer;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.springframework.core.env.Environment;
/**
* <p>
* 简单消费者
* </p>
*
*/
@Slf4j
public abstract class BaseSimpleConsumer extends BaseConsumer implements SimpleConsumer {
public BaseSimpleConsumer(Environment environment, MqProperties mqProperties) {
super(environment, mqProperties);
}
@Override
public String getConsumerName() {
return null;
}
@Override
protected void register() {
newConsumer(this.getConsumerName(), consumer -> {
this.subscribe(consumer);
consumer.registerMessageListener((MessageListenerConcurrently)(msgs, context) -> {
try {
msgs.forEach(m -> {
try {
log.info("收到MQ消息,Topic:{},Tags:{},Msg:{}", m.getTopic(), m.getTags(),
JSONObject.toJSON(new String(m.getBody())));
} catch (Exception e) {
return;
}
this.consume(m);
});
} catch (Exception e) {
e.printStackTrace();
return ConsumeConcurrentlyStatus.RECONSUME_LATER;
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
});
});
}
}
抽象类方式-其它服务使用示例
package cn.rc100.newhouse.mq;
import cn.mq.service.dto.DeptIdChangeDto;
import cn.mq.service.core.util.JacksonUtils;
import cn.mq.BaseSimpleConsumer;
import cn.mq.config.EplusMqProperties;
import cn.mq.constant.MqTopicConstants;
import lombok.SneakyThrows;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.protocol.heartbeat.MessageModel;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
/**
* <p>
* mq消费者
* </p>
*
*/
@Component
public class MqNbCustomer extends BaseSimpleConsumer {
private final OperationLogService operationLogService;
private final UserDeptService userDeptService;
private final RebateService rebateService;
public MqNbCustomer(Environment environment, EplusMqProperties eplusMqProperties, OperationLogService operationLogService,
UserDeptService userDeptService, RebateService rebateService) {
super(environment, eplusMqProperties);
this.operationLogService = operationLogService;
this.userDeptService = userDeptService;
this.rebateService = rebateService;
}
@SneakyThrows
@Override
public void subscribe(DefaultMQPushConsumer consumer) {
consumer.setMessageModel(MessageModel.BROADCASTING);
consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
consumer.subscribe(MqTopicConstants.DEPT_TRANSFER, "*");
consumer.subscribe(MqTopicConstants.USER_DEPT_TRANSFER, "*");
consumer.subscribe(MqTopicConstants.OA_AUDIT_RESULT, "34 || 35 || 36 || 38 || 39");
}
@Override
public void consume(MessageExt msg) {
// 部门调动
if (MqTopicConstants.DEPT_TRANSFER.equals(msg.getTopic())) {
DeptIdChangeDto changeDto = JacksonUtils.toBean(msg.getBody(), DeptIdChangeDto.class);
operationLogService.deptTransfer(changeDto);
} else if (MqTopicConstants.USER_DEPT_TRANSFER.equals(msg.getTopic())) {
DeptIdChangeDto changeDto = JacksonUtils.toBean(msg.getBody(), DeptIdChangeDto.class);
userDeptService.userDeptTransfer(changeDto);
} else if (MqTopicConstants.OA_AUDIT_RESULT.equals(msg.getTopic())) {
AuditResultVo result = JacksonUtils.toBean(msg.getBody(), AuditResultVo.class);
rebateService.auditRebate(result);
}
}
}
服务启动类
添加自定义注解@EnableMq
package com.example.rock;
import cn.mq.annotation.EnableMq;
import cn.swagger.annotation.EnableSwagger;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@EnableMq
@EnableXxlJob
@EnableSwagger
@SpringCloudApplication
public class RockApplication {
public static void main(String[] args) {
SpringApplication.run(RockApplication.class, args);
}
}
本文来自博客园,作者:随风笔记,转载请注明原文链接:https://www.cnblogs.com/sfbj/p/15919635.html

浙公网安备 33010602011771号