1.pom.xm
org.apache.rocketmq
rocketmq-client
4.3.0
2.spring-mvc-mq.consumer.xml(消费者配置)
3.spring-mvc-mq.producer.xml(生成者配置)
4.MQEntity(消息父类)
package com.nobuy.entity.mq;
import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.persistence.Entity;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
/**
* @author Administrator
*
*/
public class MQEntity implements java.io.Serializable{
private static final long serialVersionUID = -2551495105702956945L;
private Map extObj = new LinkedHashMap();
private String mqId ;
private String mqKey;
/**
* 添加附加字段
* @param key
* @param value
*/
public void addExt(String key , Object value){
extObj.put(key, value);
}
/**
* 获取附加字段
* @param key
*/
public void getExt(String key ){
extObj.get(key);
}
public String getMqId() {
return mqId;
}
public void setMqId(String mqId) {
this.mqId = mqId;
}
public String getMqKey() {
return mqKey;
}
public void setMqKey(String mqKey) {
this.mqKey = mqKey;
}
@Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
@Override
public boolean equals(Object obj) {
return EqualsBuilder.reflectionEquals(this, obj);
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this);
}
}
5.LoanRequest.java(测试消费对象)
package com.nobuy.entity.mq;
import java.math.BigDecimal;
import java.util.Date;
import javax.persistence.Entity;
import com.nobuy.entity.mq.MQEntity;
/**
*
* @author Administrator
*/
public class LoanRequest extends MQEntity{
private static final long serialVersionUID = 5339647958993664240L;
/** 贷款申请编号,前段生存的唯一编号 */
private String applyNo;
/** 额度编号 */
private String creditNo;
/**贷款人员工号 */
private String employeeNo;
/** 贷款金额 */
private BigDecimal payamt;
/**还款方式
* 0:多次还本、分次付息
1:分次还本、分次付息
2:等额本金
**/
private String repayMode;
/**还款期限 1个月、3个月、6个月、9个月、12个月、15个月、18个月、24个月;
* 1,3, 6
* */
private String oprTerm;
/**用途*/
private String lendPurpose;
//申请日期
private Date applyDate;
//贷款卡号
private String loanCardNo;
//开户行
private String bankName;
//联行行号
private String bankCode ;
public String getBankName() {
return bankName;
}
public void setBankName(String bankName) {
this.bankName = bankName;
}
public String getBankCode() {
return bankCode;
}
public void setBankCode(String bankCode) {
this.bankCode = bankCode;
}
public String getEmployeeNo() {
return employeeNo;
}
public void setEmployeeNo(String employeeNo) {
this.employeeNo = employeeNo;
}
public BigDecimal getPayamt() {
return payamt;
}
public void setPayamt(BigDecimal payamt) {
this.payamt = payamt;
}
public String getRepayMode() {
return repayMode;
}
public void setRepayMode(String repayMode) {
this.repayMode = repayMode;
}
public String getOprTerm() {
return oprTerm;
}
public void setOprTerm(String oprTerm) {
this.oprTerm = oprTerm;
}
public String getLendPurpose() {
return lendPurpose;
}
public void setLendPurpose(String lendPurpose) {
this.lendPurpose = lendPurpose;
}
public String getLoanCardNo() {
return loanCardNo;
}
public void setLoanCardNo(String loanCardNo) {
this.loanCardNo = loanCardNo;
}
public String getApplyNo() {
return applyNo;
}
public void setApplyNo(String applyNo) {
this.applyNo = applyNo;
}
public String getCreditNo() {
return creditNo;
}
public void setCreditNo(String creditNo) {
this.creditNo = creditNo;
}
public Date getApplyDate() {
return applyDate;
}
public void setApplyDate(Date applyDate) {
this.applyDate = applyDate;
}
}
6.IConsumer(消费端接口)
package com.nobuy.service.mq;
import org.apache.rocketmq.common.message.MessageExt;
public interface IConsumer {
/**
* 消费端解析消息
* @param msg
*/
void handlerMessage( MessageExt msg );
}
7.IProducer(生产者接口)
package com.nobuy.service.mq;
import org.apache.rocketmq.client.producer.SendCallback;
import com.nobuy.entity.mq.MQEntity;
/**
* mq消息生产者
* @author Administrator
*
*/
public interface IProducer {
/**
* 同步发送MQ
* @param topic
* @param entity
*/
public void send(String topic, MQEntity entity);
/**
* 发送MQ,提供回调函数,超时时间默认3s
* @param topic
* @param entity
* @param sendCallback
*/
public void send( String topic, MQEntity entity, SendCallback sendCallback );
/**
* 单向发送MQ,不等待服务器回应且没有回调函数触发,适用于某些耗时非常短,但对可靠性要求并不高的场景,例如日志收集。
* @param topic
* @param entity
*/
public void sendOneway(String topic, MQEntity entity);
}
8.RocketMqProducerImpl(生成者接口实现)
package com.nobuy.service.impl.mq;
import java.text.MessageFormat;
import java.util.UUID;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.common.message.Message;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;
import com.nobuy.entity.mq.MQEntity;
import com.nobuy.service.mq.IProducer;
import com.nobuy.utils.mq.SerializableUtil;
import net.sf.json.JSONObject;
public class RocketMqProducerImpl implements IProducer, InitializingBean{
private static Logger logger = LoggerFactory.getLogger(RocketMqProducerImpl.class);
private String namesrvAddr;
private String producerGroup;
private Boolean retryAnotherBrokerWhenNotStoreOK;
private DefaultMQProducer producer;
/**
* spring 容器初始化所有属性后调用此方法
*/
public void afterPropertiesSet() throws Exception {
producer = new DefaultMQProducer();
producer.setProducerGroup( this.producerGroup );
producer.setNamesrvAddr( this.namesrvAddr );
producer.setRetryAnotherBrokerWhenNotStoreOK( this.retryAnotherBrokerWhenNotStoreOK );
// producer.setVipChannelEnabled(false);
/*
* Producer对象在使用之前必须要调用start初始化,初始化一次即可
* 注意:切记不可以在每次发送消息时,都调用start方法
*/
producer.start();
logger.info( "[{}:{}] start successd!",producerGroup,namesrvAddr );
}
/**
* 销毁
*/
public void destroy() throws Exception {
if (producer != null) {
logger.info("producer: [{}:{}] end ",producerGroup,namesrvAddr);
producer.shutdown();
}
}
public void send(String topic, MQEntity entity) {
String keys = UUID.randomUUID().toString();
entity.setMqKey(keys);
String tags = entity.getClass().getName();
// logger.info("业务:{},tags:{},keys:{},entity:{}",topic, tags, keys, entity);
String smsContent = MessageFormat.format("业务:{0},tags:{1},keys:{2},entity:{3}",topic,tags,keys,JSONObject.fromObject(entity).toString());
logger.info(smsContent);
Message msg = new Message(topic, tags, keys,
SerializableUtil.toByte(entity));
try {
producer.send(msg);
} catch (Exception e) {
logger.error(keys.concat(":发送消息失败"), e);
throw new RuntimeException("发送消息失败",e);
}
}
public void send(String topic, MQEntity entity, SendCallback sendCallback) {
String keys = UUID.randomUUID().toString();
entity.setMqKey(keys);
String tags = entity.getClass().getName();
// logger.info("业务:{},tags:{},keys:{},entity:{}",topic, tags, keys, entity);
String smsContent = MessageFormat.format("业务:{0},tags:{1},keys:{2},entity:{3}",topic,tags,keys,JSONObject.fromObject(entity).toString());
logger.info(smsContent);
Message msg = new Message(topic, tags, keys,
SerializableUtil.toByte(entity));
try {
producer.send(msg, sendCallback);
} catch (Exception e) {
logger.error(keys.concat(":发送消息失败"), e);
throw new RuntimeException("发送消息失败",e);
}
}
public void sendOneway(String topic, MQEntity entity) {
String keys = UUID.randomUUID().toString();
entity.setMqKey(keys);
String tags = entity.getClass().getName();
String smsContent = MessageFormat.format("业务:{0},tags:{1},keys:{2},entity:{3}",topic,tags,keys,JSONObject.fromObject(entity).toString());
logger.info(smsContent);
Message msg = new Message(topic, tags, keys,
SerializableUtil.toByte(entity));
try {
producer.sendOneway(msg);
} catch (Exception e) {
logger.error(keys.concat(":发送消息失败"), e);
throw new RuntimeException("发送消息失败",e);
}
}
public void setNamesrvAddr(String namesrvAddr) {
this.namesrvAddr = namesrvAddr;
}
public void setProducerGroup(String producerGroup) {
this.producerGroup = producerGroup;
}
public void setProducer(DefaultMQProducer producer) {
this.producer = producer;
}
public void setRetryAnotherBrokerWhenNotStoreOK(
Boolean retryAnotherBrokerWhenNotStoreOK) {
this.retryAnotherBrokerWhenNotStoreOK = retryAnotherBrokerWhenNotStoreOK;
}
}
9.AbstractConsumer(消费者父类)
package com.nobuy.service.impl.mq;
import org.apache.rocketmq.common.message.MessageExt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import com.nobuy.entity.mq.MQEntity;
import com.nobuy.service.mq.IConsumer;
import com.nobuy.utils.mq.SerializableUtil;
public abstract class AbstractConsumer implements IConsumer {
protected Logger logger = LoggerFactory.getLogger(AbstractConsumer.class);
private String classTypeName;
public void handlerMessage(MessageExt msg) {
try {
MQEntity entity = doStart(msg);
execute(entity);
doEnd(entity);
} catch (Exception e) {
logger.error("处理mq消息异常。",e);
}
}
/**
* 解析mq消息前置处理
* @param msg
* @param entity
* @throws ClassNotFoundException
*/
protected MQEntity doStart(MessageExt msg) throws ClassNotFoundException {
Class extends MQEntity> clazz = (Class extends MQEntity>) Class.forName(classTypeName);
return SerializableUtil.parse(msg.getBody(), clazz);
}
/**
* 解析mq消息后置处理
* @param entity
*/
protected void doEnd(MQEntity entity) {
}
/**
* 解析mq消息 MessageExt
* @param entity
*/
public abstract void execute(MQEntity entity);
public void setClassTypeName(String classTypeName) {
this.classTypeName = classTypeName;
}
}
12.RocketMqConsumerImpl(消费者)
package com.nobuy.service.impl.mq;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.client.consumer.listener.MessageListenerOrderly;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.protocol.heartbeat.MessageModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
public class RocketMqConsumerImpl implements InitializingBean {
private static final Logger logger = LoggerFactory.getLogger(RocketMqConsumerImpl.class);
private DefaultMQPushConsumer consumer;
private String namesrvAddr;
private String consumerGroup;
private String messageModel;
private String messageListener;
private Map handlermap = new HashMap();
private void initializingMessageSelector() throws InterruptedException, MQClientException {
consumer = new DefaultMQPushConsumer();
if( this.consumerGroup != null && this.consumerGroup.trim().length() > 0 ) {
consumer.setConsumerGroup( this.consumerGroup );
logger.debug( "set consumer group " + this.consumerGroup );
}
consumer.setNamesrvAddr( this.namesrvAddr );
consumer.setConsumeMessageBatchMaxSize( 1 );
logger.debug( "set consumer name server address " + this.namesrvAddr );
logger.debug( "set consumer message batch max size " + 1 );
if( "BROADCASTING".equals( messageModel ) ) {
consumer.setMessageModel( MessageModel.BROADCASTING );
logger.debug( "set consumer message model BROADCASTING" );
} else {
if( "CLUSTERING".equals( messageModel ) ) {
consumer.setMessageModel( MessageModel.CLUSTERING );
logger.debug( "set consumer message model CLUSTERING" );
} else {
logger.debug( "set consumer message model should be BROADCASTING or CLUSTERING" );
throw new RuntimeException( "set consumer message model should be BROADCASTING or CLUSTERING" );
}
}
/**
* 订阅指定topic下所有消息
* 注意:一个consumer对象可以订阅多个topic
*/
if( handlermap != null && !handlermap.isEmpty() ) {
for( String topic : handlermap.keySet() ) {
consumer.subscribe( topic, "*" );
logger.debug( "consumer subscribe topic " + topic + " *" );
}
} else {
logger.debug( "you should provide at least one message handler." );
throw new RuntimeException( "you should provide at least one message handler." );
}
/**
* 设置Consumer第一次启动是从队列头部开始消费还是队列尾部开始消费
* 如果非第一次启动,那么按照上次消费的位置继续消费
*/
consumer.setConsumeFromWhere( ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET );
if( "CONCURRENTLY".equals( messageListener ) ) {
consumer.registerMessageListener( new MessageListenerConcurrently() {
/**
* 默认msgs里只有一条消息,可以通过设置consumeMessageBatchMaxSize参数来批量接收消息
*/
public ConsumeConcurrentlyStatus consumeMessage( final List msgs, final ConsumeConcurrentlyContext context ) {
try {
if( msgs != null && !msgs.isEmpty() ) {
for( MessageExt msg : msgs ) {
logger.debug( String.format( "start consum message: message:id:%s topic:%s tags:%s ", msg.getMsgId(), msg.getTopic(), msg.getTags()) );
AbstractConsumer handler = handlermap.get( msg.getTopic() );
if( handler != null ) {
handler.handlerMessage( msg );
}
logger.debug( String.format( "consume message success! message:id:%s topic:%s tags:%s ", msg.getMsgId(), msg.getTopic(), msg.getTags()) );
}
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
} catch( Exception e ) {
logger.error( "consume message error!", e );
return ConsumeConcurrentlyStatus.RECONSUME_LATER;
}
}
} );
} else
if( "ORDERLY".equals( messageListener ) ) {
consumer.registerMessageListener( new MessageListenerOrderly() {
/**
* 默认msgs里只有一条消息,可以通过设置consumeMessageBatchMaxSize参数来批量接收消息
*/
public ConsumeOrderlyStatus consumeMessage( final List msgs, final ConsumeOrderlyContext context ) {
try {
if( msgs != null && !msgs.isEmpty() ) {
for( MessageExt msg : msgs ) {
logger.debug( String.format( "start consum message: message:id:%s topic:%s tags:%s message:%s", msg.getMsgId(), msg.getTopic(), msg.getTags(), new String( msg.getBody() ) ) );
AbstractConsumer handler = handlermap.get( msg.getTopic() );
if( handler != null ) {
handler.handlerMessage( msg );
}
logger.debug( String.format( "consume message success! message:id:%s topic:%s tags:%s message:%s", msg.getMsgId(), msg.getTopic(), msg.getTags(), new String( msg.getBody() ) ) );
}
}
return ConsumeOrderlyStatus.SUCCESS;
} catch( Exception e ) {
logger.error( "consume message error!", e );
return ConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT;
}
}
} );
}
/**
* Consumer对象在使用之前必须要调用start初始化,初始化一次即可
*/
consumer.start();
logger.debug( "consumer start successd!" );
}
public void afterPropertiesSet() throws Exception {
initializingMessageSelector();
}
public void destroy() throws Exception {
if (consumer != null) {
consumer.shutdown();
logger.debug( "consumer shutdown!" );
}
}
public void setNamesrvAddr( String namesrvAddr ) {
this.namesrvAddr = namesrvAddr;
}
public void setConsumerGroup( String consumerGroup ) {
this.consumerGroup = consumerGroup;
}
public void setMessageModel( String messageModel ) {
this.messageModel = messageModel;
}
public void setMessageListener( String messageListener ) {
this.messageListener = messageListener;
}
public void setHandlermap( Map handlermap ) {
this.handlermap = handlermap;
}
}
13.LoanRequestConsumer(消费者实现)
package com.nobuy.service.impl.mq;
import com.nobuy.entity.mq.MQEntity;
public class LoanRequestConsumer extends AbstractConsumer {
@Override
public void execute(MQEntity entity) {
System.out.println("LoanRequestConsumer 消费消息");
System.out.println(entity.toString());
}
}
14SerializableUtil(工具类)
package com.nobuy.utils.mq;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
/**
* java的序列化和反序列化
*
* @author Administrator
*/
public class SerializableUtil {
@SuppressWarnings("unchecked")
public static T parse(byte[] rec, Class classType) {
ByteArrayInputStream arrayInputStream = null;
ObjectInputStream objectInputStream = null;
try {
arrayInputStream = new ByteArrayInputStream(rec);
objectInputStream = new ObjectInputStream(arrayInputStream);
T t = (T) objectInputStream.readObject();
return t;
} catch (Exception e) {
e.printStackTrace();
}finally{
closeQuietly(arrayInputStream);
closeQuietly(objectInputStream);
}
return null;
}
public static byte[] toByte(Object obj) {
ByteArrayOutputStream arrayOutputStream = null;
ObjectOutputStream objectOutputStream = null;
try {
arrayOutputStream = new ByteArrayOutputStream();
objectOutputStream = new ObjectOutputStream(arrayOutputStream);
objectOutputStream.writeObject(obj);
objectOutputStream.flush();
byte[] rtn = arrayOutputStream.toByteArray();
return rtn;
} catch (IOException e) {
e.printStackTrace();
} finally {
closeQuietly(objectOutputStream);
closeQuietly(arrayOutputStream);
}
return null;
}
public static void closeQuietly(InputStream in){
if(in!=null){
try {
in.close();
} catch (Exception e) {
}
}
}
public static void closeQuietly(OutputStream out){
if(out!=null){
try {
out.close();
} catch (Exception e) {
}
}
}
}
15.ProducerTest(生成者test)
package com.nobuy.mq;
import java.math.BigDecimal;
import java.util.Date;
import org.jeecgframework.core.util.ApplicationContextUtil;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import com.nobuy.entity.mq.LoanRequest;
import com.nobuy.service.mq.IProducer;
import com.nobuy.service.pay.PayServiceI;
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = {"classpath*:spring*.xml"})
public class ProducerTest {
@Autowired
private IProducer producer;
@Test
public void testSendMq() {
LoanRequest loanRequest= new LoanRequest();
loanRequest.setApplyNo("loan00005432231");
loanRequest.setCreditNo("credit0000001");
loanRequest.setEmployeeNo("test1");
loanRequest.setLendPurpose("test1");
loanRequest.setLoanCardNo("362226197403220017");
loanRequest.setBankCode(null);
loanRequest.setBankName(null);
loanRequest.setOprTerm("12");
loanRequest.setPayamt(new BigDecimal(100000));
loanRequest.setRepayMode("0"); //0 1 2
loanRequest.setApplyDate(new Date());
producer.send("loanRequest", loanRequest);
}
}
转载后稍加修改
出自:https://www.cnblogs.com/yun965861480/p/7384915.html