Jms实战


<?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:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.0.xsd">

<!-- 加载DataChange的环境变量 -->
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location"
value="file:${appHome}/datachange.properties" /><!-- webserver环境和线上环境一定要设appHome,单元测试环境下appHome为null -->
<property name="ignoreResourceNotFound" value="true" />
<property name="ignoreUnresolvablePlaceholders" value="true" />
<property name="properties" ref="localDataChangeProperties" /><!-- 本地环境下使用此值 -->
</bean>

<bean name="localDataChangeProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location" value="classpath:configDefault/datachange.properties" />
</bean>

<!-- 导入默认的DataChange的发送者的配置 -->
<import resource="classpath:dataChangeConfigDefault/spring-dataChange-sender.xml" />

<context:component-scan base-package="com.xxxpiao.datachange" />
</beans>


<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<!-- 加载DataChange的环境变量 -->
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location"
value="file:${appHome}/dataChange-receiver.properties" /><!-- webserver环境和线上环境一定要设appHome,单元测试环境下appHome为null -->
<property name="ignoreResourceNotFound" value="true" />
<property name="ignoreUnresolvablePlaceholders" value="true" />
<property name="properties" ref="localDataChangeProperties" /><!--
本地环境下使用此值 -->
</bean>

<bean name="localDataChangeProperties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location"
value="classpath:/configDefault/dataChange-receiver.properties" />
</bean>

<bean name="betGameIssueOpenAwardFilter" class="com.xxx.datachange.common.domain.FilterConfig">
<property name="dataType" value="bet_game_issue"></property>
</bean>
<bean name="betIssueDataChangeListener"
class="com.xxx.betcart.server.datachange.BetIssueDataChangeListener" />
<bean name="changeHandleMapping"
class="com.xxx.datachange.client.domain.ChangeHandleMapping">
<property name="sender" value="coreservice"></property>
<property name="receiver" value="group-betcart"></property>
<property name="dataChangeListener" ref="betIssueDataChangeListener" />
<property name="filterConfigList">
<list>
<ref bean="betGameIssueOpenAwardFilter"></ref>
</list>
</property>
</bean>

<bean name="betPlanPackageFilter" class="com.xxx.datachange.common.domain.FilterConfig">
<property name="dataType" value="order"></property>
</bean>
<bean name="betPlanPackageDataChangeListener"
class="com.xxx.betcart.server.datachange.BetPlanPackageDataChangeListener" >
<property name="expertAccount" value="${dataChange.expertAccount}"/>
</bean>
<bean name="betPlanPackageChangeHandleMapping"
class="com.xxx.datachange.client.domain.ChangeHandleMapping">
<property name="sender" value="coreservice"></property>
<property name="receiver" value="group-betcart-planpackage"></property>
<property name="dataChangeListener" ref="betPlanPackageDataChangeListener" />
<property name="filterConfigList">
<list>
<ref bean="betPlanPackageFilter"></ref>
</list>
</property>
</bean>



<bean name="receiveManager" class="com.xxx.datachange.client.receive.ReceiveManager">
<property name="zkDataChangeRoot" value="/datachange/metaq" />
<property name="zkConnect" value="${dataChange.zkConnect}" />
<property name="changeHandleMappingList">
<list>
<ref bean="changeHandleMapping"/>
<ref bean="betPlanPackageChangeHandleMapping"/>
</list>
</property>

<!-- 只处理发送时间在这个日期之后的消息,这样可以防止新应用接收到很久以前的消息 -->
<property name="acceptMsgUpdateTimeAfterThis">
<bean factory-bean="dataChangeDateFormat" factory-method="parse">
<constructor-arg value="2014-05-06" />
</bean>
</property>
</bean>
<bean id="dataChangeDateFormat" class="java.text.SimpleDateFormat">
<constructor-arg value="yyyy-MM-dd" />
</bean>
</beans>


package com.xxxpiao.core.jms;

import java.io.Serializable;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.ObjectMessage;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;

import com.alibaba.fastjson.JSON;

/**
* 通用的消息发送类
* @project coreService
* @author wellpha.wu
* @date 2011-02-12
* Copyright (C) 2010-2012 www.2caipiao.com Inc. All rights reserved.
*/
public class MessageProducer {
protected JmsTemplate jmsTemplate;

/**
* 使用jmsTemplate的send/MessageCreator()发送ObjectMessage类型的消息
*/
public void sendMessage(final Serializable obj, Destination destination) {
jmsTemplate.send(destination, new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
ObjectMessage message = session.createObjectMessage();
message.setObject(obj);
return message;
}
});
}

public void sendTxtJSONMessage(final Serializable obj, Destination destination) {
jmsTemplate.send(destination, new MessageCreator() {
public Message createMessage(Session session) throws JMSException
{
TextMessage message = session.createTextMessage();
message.setText(JSON.toJSONString(obj));
return message;
}
});
}

public void sendTxtMessage(final String text, Destination destination) {
jmsTemplate.send(destination, new MessageCreator() {
public Message createMessage(Session session) throws JMSException
{
TextMessage message = session.createTextMessage();
message.setText(text);
return message;
}
});
}
public void setJmsTemplate(JmsTemplate jmsTemplate) {
this.jmsTemplate = jmsTemplate;
}

}




package com.xxxpiao.core.jms;

import javax.jms.Destination;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.xxx.datachange.domain.DataChangeDO;


public class DataChangePublisher extends MessageProducer
{
protected static final Logger logger = LoggerFactory.getLogger("data_change_log");
/** 消息队列 */
private Destination datachangeTopic;

public void setDatachangeTopic(Destination datachangeTopic) {
this.datachangeTopic = datachangeTopic;
}

public void senDataChangeMessage(final DataChangeDO dataChangeDO)
{
logger.info("datatypemessage--DataId:{},DataType:{},ChangeType:{}.",
new Object[]{dataChangeDO.getDataId(),dataChangeDO.getDataType(),dataChangeDO.getChangeType()});
super.sendTxtJSONMessage(dataChangeDO, datachangeTopic);
}
}




package com.xxxpiao.datachange.manager;

import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.annotation.PreDestroy;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import com.xxx.datachange.constant.ChagneTypeConstant;
import com.xxx.datachange.constant.ChangeFieldBitConstant;
import com.xxx.datachange.constant.DataType;
import com.xxx.datachange.domain.DataChangeDO;
import com.xxxpiao.common.entity.member.Member;
import com.xxxpiao.common.entity.member.MemberChargeLog;
import com.xxxpiao.core.jms.DataChangePublisher;

/**
* 专门用于发送JMS消息
*
*/
@Service
public class DataChangeManagerImpl
{
protected static transient final Logger logger = LoggerFactory.getLogger("data_change_log");

@Autowired
@Qualifier("dataChangePublisher")
private DataChangePublisher dataChangePublisher;

private final ExecutorService threadPool = Executors.newFixedThreadPool(10);

/**
* 生成可靠的UUID,从DataChange1.0 升级到2.0,需要为每个消息设置一个UUID来去重。
* 以后会删除,其它程序不能使用这个函数
* @author zhixuan.chen
* @date 2014年3月19日
* @return
*/
public static String generateUUID() {
return UUID.randomUUID().toString();
}

/**
* 产生投注消息,包括合买,追号等投注消息
* @param orderID
* @param planID
*/
public void createOrderPlanMessage(String uuid, long orderID,long planID,int orderType)
{
threadPool.execute(new CreateOrderTask(uuid, dataChangePublisher,orderID,planID,orderType));
}



/**
* 注册消息
* @param member
*/
public void createRegisterMessage(String uuid, Member member)
{
threadPool.execute(new CreateMemberTask(uuid, member,dataChangePublisher,ChagneTypeConstant.DATA_INSERT));
}

/**
* 注册消息
* @param member
*/
public void createRegisterMessage(String uuid, Member member,long type)
{
threadPool.execute(new CreateMemberTask(uuid, member,dataChangePublisher,ChagneTypeConstant.DATA_INSERT,type));
}

/**
* 实名认证消息
* @param member
*/
public void createRealNameMessage(String uuid, Member member)
{
threadPool.execute(new CreateMemberTask(uuid, member,dataChangePublisher,ChagneTypeConstant.DATA_MODIFY,ChangeFieldBitConstant.member_certNo));
}

/**
* 充值消息
* @param returnLog
*/
public void createChargeMessage(String uuid, MemberChargeLog returnLog)
{
threadPool.execute(new CreateChargeTask(uuid, returnLog,dataChangePublisher));
}

/**
* 设置大奖号码消息
* @param member
*/
public void createGetMoneyWayMessge(String uuid, Member member)
{
threadPool.execute(new CreateMemberTask(uuid, member,dataChangePublisher,ChagneTypeConstant.DATA_MODIFY,ChangeFieldBitConstant.member_get_money_phone));
}

/**
* 发送中奖消息
* @param planId
* @param memberId
*/
public void createDrawMessage(String uuid, long planId,long memberId)
{
threadPool.execute(new CreateDrawTask(uuid, planId,memberId,dataChangePublisher));
}

private static final class CreateChargeTask implements Runnable
{
private String uuid;
private MemberChargeLog returnLog = null;
private DataChangePublisher dataChangePublisher;

public CreateChargeTask(String uuid, MemberChargeLog returnLog,DataChangePublisher dataChangePublisher)
{
this.uuid = uuid;
this.returnLog = returnLog;
this.dataChangePublisher = dataChangePublisher;
}

@Override
public void run()
{
try
{

if(returnLog!=null)
{
logger.info("CreateChargeTask chargeid is {}",new Object[]{returnLog.getId()});
}
DataChangeDO dataChangeDO = new DataChangeDO();
dataChangeDO.setUuid(uuid);
dataChangeDO.setDataId(returnLog.getId());
dataChangeDO.setDataType(DataType.chargeLog);
dataChangeDO.setChangeType(ChagneTypeConstant.DATA_INSERT);
dataChangePublisher.senDataChangeMessage(dataChangeDO);
}
catch(Throwable e)
{
if(returnLog!=null)
{
logger.error("Run createChargeTas failed "+returnLog.getId(),e);
}else
{
logger.error("Run createChargeTas failed",e);
}

}
finally
{
this.returnLog = null;
this.dataChangePublisher = null;
}
}

}

private static final class CreateMemberTask implements Runnable
{
private String uuid;
private Member member = null;
private DataChangePublisher dataChangePublisher;
private byte optype;
private long type = -1;

public CreateMemberTask(String uuid, Member member,DataChangePublisher dataChangePublisher,byte optype)
{
this.uuid = uuid;
this.member = member;
this.optype = optype;
this.dataChangePublisher = dataChangePublisher;
}

public CreateMemberTask(String uuid, Member member,DataChangePublisher dataChangePublisher,byte optype,long type)
{
this.uuid = uuid;
this.member = member;
this.optype = optype;
this.type = type;
this.dataChangePublisher = dataChangePublisher;
}

@Override
public void run()
{
try
{
if(member!=null)
{
logger.info("CreateMemberTask memberid is {},optype is {},type {}",new Object[]{member.getId(),optype,type});
}
DataChangeDO dataChangeDO = new DataChangeDO();
dataChangeDO.setUuid(uuid);
dataChangeDO.setDataId(member.getId());
dataChangeDO.setDataType(DataType.member);
dataChangeDO.setChangeType(optype);
if(type!=-1)
{
dataChangeDO.setChangeFieldBit(type);
}
dataChangePublisher.senDataChangeMessage(dataChangeDO);
}
catch(Throwable e)
{
if(member!=null)
{
logger.error("Run CreateMemberTask failed "+member.getId(),e);
}else
{
logger.error("Run CreateMemberTask failed",e);
}
}
finally
{
this.member = null;
this.dataChangePublisher = null;
}
}

}


private static final class CreateOrderTask implements Runnable
{
private long orderID ;
private long planID ;
private int orderType = -1;
private long presentType = -1;
private DataChangePublisher dataChangePublisher;

/**
* 唯一的消息ID,目前是UUID,用于dataChange1.0升级2.0的改造。
* 其它程序不可乱用,以后会删掉!
* @author zhixuan.chen
* @date 2014-03-19
*/
private String uuid;

public CreateOrderTask(String uuid, DataChangePublisher dataChangePublisher,long orderID,long planID,int orderType)
{
this.uuid = uuid;
this.dataChangePublisher = dataChangePublisher;
this.orderID = orderID;
this.planID = planID;
this.orderType = orderType;
}

public CreateOrderTask(String uuid, DataChangePublisher dataChangePublisher,
long orderID, long planID, int orderType, int presentType) {
this.uuid = uuid;
this.dataChangePublisher = dataChangePublisher;
this.orderID = orderID;
this.planID = planID;
this.orderType = orderType;
this.presentType=presentType;
}

@Override
public void run()
{
try
{
logger.info("CreateOrderTask orderID is {},planID is {},ordertype {},presentType {}",new Object[]{orderID,planID,orderType,presentType});
DataChangeDO dataChangeDO = new DataChangeDO();
dataChangeDO.setUuid(uuid);
dataChangeDO.setDataId(orderID);
dataChangeDO.setRelateId(planID);
dataChangeDO.setChangeFieldBit(orderType);
//这个地方吧放在oldStatus1
dataChangeDO.setOldStatus1((int)presentType);
dataChangeDO.setDataType(DataType.order);
dataChangeDO.setChangeType(ChagneTypeConstant.DATA_INSERT);
dataChangePublisher.senDataChangeMessage(dataChangeDO);
}
catch(Throwable e)
{
logger.error("Run CreateOrderTask failed "+orderID,e);
}
finally
{
this.dataChangePublisher = null;
}
}
}

private static final class CreateDrawTask implements Runnable
{
private String uuid;
private long planId;
private long memberId;
private DataChangePublisher dataChangePublisher;

public CreateDrawTask(String uuid, long planId,long memberId,DataChangePublisher dataChangePublisher)
{
this.uuid = uuid;
this.planId=planId;
this.memberId=memberId;
this.dataChangePublisher = dataChangePublisher;
}

@Override
public void run()
{
try
{

logger.info("CreateDrawTask dataid is {},relateid is {}",new Object[]{planId,memberId});
DataChangeDO dataChangeDO = new DataChangeDO();
dataChangeDO.setUuid(uuid);
dataChangeDO.setDataId(planId);
dataChangeDO.setDataType(DataType.betPlan);
dataChangeDO.setChangeType(ChagneTypeConstant.DATA_MODIFY);
dataChangeDO.setRelateId(memberId);
dataChangePublisher.senDataChangeMessage(dataChangeDO);
}
catch(Throwable e)
{
logger.error("Run CreateDrawTask failed ,{},{}",new Object[]{planId,memberId});
}
finally
{
this.dataChangePublisher = null;
}
}

}

/**
* 产生登陆信息
* @param memberId
*/
public void createClientLoginMessage(String uuid, long memberId)
{
threadPool.execute(new CreateClientLoginTask(uuid, dataChangePublisher,memberId));
}


private static final class CreateClientLoginTask implements Runnable
{
private String uuid;
private long memberId;
private DataChangePublisher dataChangePublisher;

public CreateClientLoginTask(String uuid, DataChangePublisher dataChangePublisher,long memberId)
{
this.uuid = uuid;
this.memberId=memberId;
this.dataChangePublisher = dataChangePublisher;
}

@Override
public void run()
{
try
{

logger.info("CreateClientLoginTask dataid is {}",memberId);
DataChangeDO dataChangeDO = new DataChangeDO();
dataChangeDO.setUuid(uuid);
dataChangeDO.setDataId(memberId);
dataChangeDO.setDataType(DataType.member);
dataChangeDO.setChangeType(ChagneTypeConstant.DATA_MODIFY);
dataChangeDO.setChangeFieldBit(ChangeFieldBitConstant.member_last_login_time);
dataChangePublisher.senDataChangeMessage(dataChangeDO);
}
catch(Throwable e)
{
logger.error("Run CreateClientLoginTask failed ,{}",memberId);
}
finally
{
this.dataChangePublisher = null;
}
}

}

/**
* 当spring容器停止的时候销毁资源
*/
@PreDestroy
public void destroy()
{
threadPool.shutdownNow();
logger.debug("发消息服务线程池关闭");
}

// 增加代购消息发送给VIP系统添加财富值使用
public void createOrderPlanMessage(String uuid, long orderID,long planID,int orderType,int presentType) {
threadPool.execute(new CreateOrderTask(uuid, dataChangePublisher,orderID,planID,orderType,presentType));
}


}




package com.xxx.datachange.domain;

public class DataChangeDO implements java.io.Serializable
{

private static final long serialVersionUID = 608049506513890581L;

/**
* 唯一的消息ID,目前是UUID,用于dataChange1.0升级2.0的改造。
* 其它程序不可乱用,以后会删掉!
* @author zhixuan.chen
* @date 2014-03-19
*/
private String uuid;

/**
* 唯一的消息ID,目前是UUID,用于dataChange1.0升级2.0的改造。
* 其它程序不可乱用,以后会删掉!
* @author zhixuan.chen
* @date 2014年3月19日
* @return
*/
public String getUuid() {
return uuid;
}

/**
* 唯一的消息ID,目前是UUID,用于dataChange1.0升级2.0的改造。
* 其它程序不可乱用,以后会删掉!
* @author zhixuan.chen
* @date 2014年3月19日
* @param uuid
*/
public void setUuid(String uuid) {
this.uuid = uuid;
}

/**
* 数据记录ID,根据后面DATATYPE来判断,当
*/
private long dataId;

/**
* 数据变化类型, 1表示消息类型对应表示member,2表示消息类型对应表示bet_order表,3表示消息类型对应表示member_charge_log表
*/
private int dataType;

/**
* 1消息操作类型为插入,2消息操作类型为修改,3消息操作类型为设置提款号码
*/
private byte changeType;

/**
* 原始状态1,跟具体业务部门协商,暂时没有使用
*/
private int oldStatus1;

/**
* 原始状态2,跟具体业务部门协商,暂时没有使用
*/
private int oldStatus2;

/**
* 变化字段索引,跟具体业务部门协商,暂时没有使用
*/
private long changeFieldBit;

/**
* 与当前变化,关联ID。目前在投注消息中,DATAID是ORDERID,但是业务数据通过方案来查可能更快一下。给出了关联的方案主键为方案ID
*/
private long relateId;

public long getDataId() {
return dataId;
}

public void setDataId(long dataId) {
this.dataId = dataId;
}

public int getDataType() {
return dataType;
}

public void setDataType(int dataType) {
this.dataType = dataType;
}

public byte getChangeType() {
return changeType;
}

public void setChangeType(byte changeType) {
this.changeType = changeType;
}

public int getOldStatus1() {
return oldStatus1;
}

public void setOldStatus1(int oldStatus1) {
this.oldStatus1 = oldStatus1;
}

public int getOldStatus2() {
return oldStatus2;
}

public void setOldStatus2(int oldStatus2) {
this.oldStatus2 = oldStatus2;
}

public long getChangeFieldBit() {
return changeFieldBit;
}

public void setChangeFieldBit(long changeFieldBit) {
this.changeFieldBit = changeFieldBit;
}

public void addChangeFieldBit(long bit){
this.changeFieldBit |= bit;
}


public long getRelateId() {
return relateId;
}

public void setRelateId(long relateId) {
this.relateId = relateId;
}


}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值