rabmitmq整合spring

来源:互联网 发布:网络语鸡肋是什么意思 编辑:程序博客网 时间:2024/06/05 22:44

之前讲了rabmitmq的控制台的相关配置,这些配置是再开发前必要的配置

下面讲讲真货,怎么运用到项目中,本章讲解的是spring整合rabmitmq,废话不多说了,直接上代码

1、首先创建连接池

<bean id="connectionFactory"
class="org.springframework.amqp.rabbit.connection.CachingConnectionFactory">
<property name="host" value="127.0.0.1" />
<property name="port" value="5672" />
<property name="username" value="test" />
<property name="password" value="test />
<property name="publisherConfirms" value="true" />
<property name="publisherReturns" value="false" />
</bean>


2、创建rabbitTemplate 消息模板类

<bean id="rabbitTemplate" class="org.springframework.amqp.rabbit.core.RabbitTemplate">
<constructor-arg ref="connectionFactory"/>
<property name="encoding" value="UTF-8"/>
<property name="channelTransacted" value="false"/>
</bean>

3、定义发送器

<bean id="mqSenderTest" class="com.test.MqSenderTest"> //class指向业务发送器
<property name="rabbitTemplate" ref="rabbitTemplate" />
<property name="queue" value="test.queue" />
<property name="exchange" value="test.queue" />
<property name="routingKey" value="test.queue" />
</bean>

4、定义消费者(如果需要消费消息就配置)

<!--定义queue -->
<rabbit:queue id="queueTest" name="test.queue" durable="true" auto-delete="false" exclusive="false" />


<!-- 定义direct exchange,绑定queue -->
<rabbit:direct-exchange id="exchangeTest" name="test.queue" durable="true" auto-delete="false">
<rabbit:bindings>
<rabbit:binding queue="queueTest" key="test.queue"></rabbit:binding>
</rabbit:bindings>
</rabbit:direct-exchange>

<!-- queue litener  观察 监听模式 当有消息到达时会通知监听在对应的队列上的监听对象-->
    <rabbit:listener-container connection-factory="connectionFactory">
             <rabbit:listener queues="queueTest" ref="mqConsumerTest"/>
    </rabbit:listener-container>

至此相关的配置就都ok了,接下来是实现定义发送器、消费者

5、每个发送器实现需求可能不同,所以定义抽象发送器,如果发送内容相同则不用定义抽象类,抽象类中的属性都是由上面spring注入的

public abstract class AbstractSenderTest {


protected Logger logger = LoggerFactory.getLogger(getClass());


public String exchange;


public String routingKey;


public String queue;


public RabbitTemplate rabbitTemplate;


public String getExchange() {
return exchange;
}


public void setExchange(String exchange) {
this.exchange = exchange;
}


public String getRoutingKey() {
return routingKey;
}


public void setRoutingKey(String routingKey) {
this.routingKey = routingKey;
}


public String getQueue() {
return queue;
}


public void setQueue(String queue) {
this.queue = queue;
}


public RabbitTemplate getRabbitTemplate() {
return rabbitTemplate;
}


public void setRabbitTemplate(RabbitTemplate rabbitTemplate) {
this.rabbitTemplate = rabbitTemplate;
}

public abstract void send(MqMessage mqMessage);

}

6、实现发送器抽象类,MqMessage是封装的发送模版,也可以发送json,如果是个类的话接收的时候就需要用这个类来接收了

public class MqSenderTest extends AbstractSenderTest {


public void send(MqMessage mqMessage) {
try {
rabbitTemplate.setQueue(queue);
rabbitTemplate.setExchange(exchange);
rabbitTemplate.setRoutingKey(routingKey);
rabbitTemplate.setChannelTransacted(false);
rabbitTemplate.setImmediate(true);
if (!rabbitTemplate.isConfirmListener()) {
rabbitTemplate.setConfirmCallback(new ConfirmCallback() {
@SuppressWarnings("static-access")
@Override
public void confirm(CorrelationData correlationData, boolean ack) {
if (!ack) {
mqMessage.addSendNum();
if (mqMessage.isAgainSend()) {
rabbitTemplate.convertAndSend(mqMessage);
} else {
logger.error("队列【" + queue + "】MQ消息连续发送" + mqMessage.MAX_SENDNUM + "次失败,报文:"
+ JSONUtils.toJson(mqMessage));
}
}
}
});
}
rabbitTemplate.convertAndSend(mqMessage);
} catch (Exception e) {
logger.error("队列【" + this.queue + "】MQ消息发送失败:" + e);
}


}


}

7、定义抽象消费者,实现MessageListener接口的onMessage方法,只要监听到有接收到消息就开始处理,如果处理失败则重试,fromMessage是处理接收来的消息格式进行相应转换,handle就是实际实现改抽象消费者处理的逻辑

public abstract class AbstractConsumerTest implements MessageListener {


    protected final Logger logger = LoggerFactory.getLogger(getClass());


    public static final String DEFAULT_CHARSET = "UTF-8";


    protected Object fromMessage(Message message) throws MessageConversionException {
        Object content = null;
        MessageProperties properties = message.getMessageProperties();
        if (properties != null) {
            String contentType = properties.getContentType();
            if (contentType != null && contentType.equals(MessageProperties.CONTENT_TYPE_TEXT_PLAIN)) {
                String encoding = properties.getContentEncoding();
                if (encoding == null) {
                    encoding = DEFAULT_CHARSET;
                }
                try {
                    content = new String(message.getBody(), encoding);
                } catch (UnsupportedEncodingException e) {
                    logger.error("", e);
                    throw new MessageConversionException("", e);
                }
            } else if (contentType != null &&
                    contentType.equals(MessageProperties.CONTENT_TYPE_SERIALIZED_OBJECT)) {
                content = SerializeUtils.deserialize(message.getBody());
            }else if (contentType != null &&
                    contentType.equals(MessageProperties.CONTENT_TYPE_JSON)) {
                try {
content = new String(message.getBody(),"utf-8");
} catch (UnsupportedEncodingException e) {
}
            }
        }
        if (content == null) {
            content = SerializeUtils.deserialize(message.getBody());
        }
        return content;
    }


    @Override
    public void onMessage(Message message) {
        boolean result = false;
        Object object = null;
        boolean tranSuccess = true;
        try{
        object = fromMessage(message);
        }catch(Exception e){
        logger.error("MQ接收消息转换出错");
        tranSuccess = false;
        }
        if (object == null) {
            result = true;
            if(tranSuccess){
            logger.error("接收到MQ消息 【空】报文");
            }
        } else if (object instanceof MqMessage) {
        try{
           MqMessage mqMessage = (MqMessage) object;
           logger.error("即将处理的MQ消息:" + JSONUtils.toJson(object));
           result = handle(mqMessage);
        }catch(Exception e){
        result = false;
        logger.error("【处理MQ消息异常】"+e);
        }
        }else if (object instanceof String) {
        try{
        MqMessage mqMessage = new MqMessage(object);
           logger.error("即将处理的MQ(JSON格式)消息:" + object);
           result = handle(mqMessage);
        }catch(Exception e){
        result = false;
        logger.error("【处理的MQ(JSON格式)异常:】",e);
        }
        }
        if (!result) {//消息未处理
            try {
                logger.error("接收后未处理的MQ消息报文:" + JSONUtils.toJson(object));
            } catch (Exception e) {
                logger.error("接收后未处理的MQ消息报文:" + object);
            }
        }
    }


    public abstract boolean handle(MqMessage mqMessage);
}

8、实现抽象消费者,@Service("mqConsumerTest")注册到spring容器中,上面的配置文件有引用这个

@Service("mqConsumerTest")
public class MqConsumerTest extends AbstractConsumerTest {


@Autowired
private MqCloudService mqCloudService;


private Logger logger = LoggerFactory.getLogger(MqCloudConsumer.class);


@Override
public boolean handle(MqMessage mqMessage) {
boolean flag = false;
...具体处理逻辑
return flag;
}
}


9、实现发送mq消息,场景:完成业务发送mq消息记录操作日志

@Service
public class MqLogServiceImpl implements MqLogService {

    @Autowired

    private MqSenderTest mqSenderTest;

    @Override
   
  public void send(){

...

...

...业务逻辑

mqSenderTest.send(new MqMessage());//具体发送什么消息就不写了

   }

}


至此spring整合mq的入门阶段就结束了...


原创粉丝点击