1.配置文件
applicationContext-mq.xml
<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:rabbit="http://www.springframework.org/schema/rabbit"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://dev.cdsf.com/schema/webmvc
http://dev.cdsf.com/schema/webmvc.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-4.1.xsd
http://www.springframework.org/schema/rabbit
http://www.springframework.org/schema/rabbit/spring-rabbit-1.7.xsd
http://drools.org/schema/drools-spring
http://drools.org/schema/drools-spring.xsd">
<rabbit:connection-factory id="connectionFactory" host="${mq.host}"
port="${mq.port}" username="${mq.user}" password="${mq.password}" virtual-host="${mq.virtualHost}"
channel-cache-size="50" connection-timeout="60000" requested-heartbeat="30"/>
<rabbit:admin connection-factory="connectionFactory"/>
<bean id="jsonMessageConverter" class="org.springframework.amqp.support.converter.JsonMessageConverter"></bean>
<bean id="simplemessageConverter" class="org.springframework.amqp.support.converter.SimpleMessageConverter"></bean>
<!--创建消息队列模板-->
<rabbit:template id="rabbitTemplateSimp" connection-factory="connectionFactory"
exchange="${mq.exchange}" message-converter="simplemessageConverter" />
<!--定义消息队列-->
<rabbit:queue name="${mq.server.queue}" durable="false" auto-delete="true" />
<!-- topic模式 -->
<rabbit:topic-exchange id="${mq.exchange}" name="${mq.exchange}" durable="false" auto-delete="true" >
<rabbit:bindings>
<rabbit:binding queue="${mq.server.queue}" pattern="${mq.server.queue}"></rabbit:binding>
</rabbit:bindings>
</rabbit:topic-exchange>
<!-- 消费者 -->
<bean id="meConsumer" class="com.client.mq.consumer.RmqConsumer"/>
<bean id="rmqProducer" class="com.client.mq.producer.RmqProducer"/>
<rabbit:listener-container connection-factory="connectionFactory">
<rabbit:listener ref="meConsumer" method="onMessage" queues="${mq.server.queue}"/>
</rabbit:listener-container>
</beans>
2.生产者
@Component
public class RmqProducer {
private final Logger logger = LoggerFactory.getLogger(RmqProducer.class);
@Autowired
private RabbitTemplate rabbitTemplateSimp;
private Base64.Encoder encoder = Base64.getEncoder();
/**
* 发送信息
*
* @param msg
*/
public void sendMessage(ResponsePackage request) {
try {
if (request != null) {
long uuid = request.getHeader().getUuid();
Map<ClientProtocolEnum, String> routingKeyMap = getRoutingKey(uuid);
// PC、Androidp平台使用AMQP协议
if (routingKeyMap.containsKey(ClientProtocolEnum.AMQP)) {
rabbitTemplateSimp.convertAndSend(Constants.EX_CHANGE, routingKeyMap.get(ClientProtocolEnum.AMQP),
request.getByteBuffer().array());
}
// WEBGL平台使用STOMP协议
if (routingKeyMap.containsKey(ClientProtocolEnum.STOMP)) {
rabbitTemplateSimp.convertAndSend(Constants.EX_CHANGE, routingKeyMap.get(ClientProtocolEnum.STOMP),
encoder.encode(request.getByteBuffer().array()));
}
routingKeyMap = null;
}
} catch (Exception e) {
logger.error("Producer send message fail:", e);
}
}
private Map<ClientProtocolEnum, String> getRoutingKey(long uuid) {
Map<ClientProtocolEnum, String> routingKeyMap = new HashMap<ClientProtocolEnum, String>();
if (uuid == ClientTypeEnum.ALL.getType()) {
routingKeyMap.put(ClientProtocolEnum.AMQP, Constants.ROUT_KEY_CLIENT);
routingKeyMap.put(ClientProtocolEnum.STOMP, Constants.ROUT_KEY_CLIENT_WEBGL);
}
if (uuid == ClientTypeEnum.RUNNER.getType()) {
routingKeyMap.put(ClientProtocolEnum.AMQP, Constants.ROUT_KEY_RUNNER);
routingKeyMap.put(ClientProtocolEnum.STOMP, Constants.ROUT_KEY_RUNNER_WEBGL);
}
if (uuid == ClientTypeEnum.EDITOR.getType()) {
routingKeyMap.put(ClientProtocolEnum.AMQP, Constants.ROUT_KEY_EDITOR);
routingKeyMap.put(ClientProtocolEnum.STOMP, Constants.ROUT_KEY_EDITOR_WEBGL);
}
if (routingKeyMap.size() == 0) {
String routingKey = Constants.ROUT_KEY_USER_PREFIX + uuid;
routingKeyMap.put(ClientProtocolCache.get(uuid), routingKey);
}
return routingKeyMap;
}
}
3.消费者
public class RmqConsumer implements MessageListener{
@Autowired
private ClientServiceFactory serviceFactory;
private final Logger logger = LoggerFactory.getLogger(RmqConsumer.class);
@Autowired
private TaskExecutor taskExecutor;
private Base64.Decoder decoder = Base64.getDecoder();
@Override
public void onMessage(Message message) {
try {
byte[] body = message.getBody();
if (message.getMessageProperties().getContentType() != null) {
String bodyStr = new String(body);
body = decoder.decode(bodyStr);
message = new Message(body, message.getMessageProperties());
}
Header header = transHeader(body);
handleMessage(header, message);
} catch (UnsupportedEncodingException e) {
logger.error(e.getMessage());
} catch (Exception e) {
logger.error(e.getMessage());
}
}
private void handleMessage(final Header header, final Message message){
int messageId = header.getMessageId();
final ClientService clientService = serviceFactory.getLogic(messageId);
if (clientService == null) {
logger.warn("rejected service message id:{}", messageId);
return;
}
ClientProtocolCache.put(header.getUuid(), message.getMessageProperties().getContentType() == null ? ClientProtocolEnum.AMQP : ClientProtocolEnum.STOMP);
logger.info("reveiced service message id:{}", messageId);
Thread thread = new Thread(){
public void run(){
clientService.execute(message, header);
}
};
StringBuffer threadName = new StringBuffer("Rabbitmq messageId :");
threadName.append(header.getSeqId());
threadName.append("_");
threadName.append(header.getMessageId());
thread.setName(threadName.toString());
taskExecutor.execute(thread);
}
/**
* 获取请求header
* @param body 请求体
* @return
* @throws IOException
*/
private Header transHeader(byte[] body) throws IOException{
ByteBuffer byteBuffer = ByteBuffer.wrap(body);
Header header = new Header();
header.clearHeader();
header.read(byteBuffer);
return header;
}
}
其中用到了Springmvc中的线程池TaskExecutor。