spring中实现远程监听

本文介绍了一种基于RMI协议的远程监听机制,用于缓存集群中的节点间同步更新缓存状态。通过动态查询活动节点并发布事件,确保各节点能够实时监听到缓存变动。
近期项目需要集群,缓存集群是自己实现的,需要在缓存发生变动后,需要发生消息给各个节点更新缓存。所以就做了个远程监听功能。远程监听用rmi协议,事件发布前都动态查询出活动的节点,事件发布后会被活动节点上的listener监听到。上代码
1.定义event和listener
public class  BaseEvent  extends EventObject {


private static final long serialVersionUID = 1L;


/** System time when the event happened */
private final long timestamp;


public BaseEvent(Object source) {
super(source);
this.timestamp = System.currentTimeMillis();

}

/**
* Return the system time in milliseconds when the event happened.
*/
public final long getTimestamp() {
return this.timestamp;
}
}


public interface EventLisenter<T extends BaseEvent>{

/**
* 事件处理
* @param baseEvent
*/
void onEvent(T t);
}

2、定义远程监听配置

public class RemoteLisenter{

private Class eventClass;

private Class serviceInterface;

private String serviceName;

private String registryPort;

public Class getServiceInterface() {
return serviceInterface;
}

public void setServiceInterface(Class serviceInterface) {
this.serviceInterface = serviceInterface;
}

public String getServiceName() {
return serviceName;
}

public void setServiceName(String serviceName) {
this.serviceName = serviceName;
}


监听管理类,用于事件注册,更新远程监听,发布事件

public class RemoteLisenterConfig {

private List<RemoteLisenter> remoteLisenters =new ArrayList<RemoteLisenter>();


public List<RemoteLisenter> getRemoteLisenters() {
return remoteLisenters;
}


public void setRemoteLisenters(List<RemoteLisenter> remoteLisenters) {
this.remoteLisenters = remoteLisenters;
}

}



@Service
public class ListennerManagement {


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


@Autowired
private HeartbeatService heartbeatService;


@Autowired
RemoteLisenterConfig remoteLisenterConfig;





/**
* 本地监听
*/
private Map<String, List<EventLisenter>> localListeners = new LinkedHashMap<String, List<EventLisenter>>();

/**
* 远程监听
*/
private Map<String, List<EventLisenter>> remoteListeners = new LinkedHashMap<String, List<EventLisenter>>();



/**
* 扫瞄所有bean,进行队本地事件进行事件监听
*
* @throws Exception
*/
@SuppressWarnings("rawtypes")
public void registryListener(ApplicationContext ctx) throws Exception {
// 取得容器中所有监听
Map<String, EventLisenter> beans = ctx
.getBeansOfType(EventLisenter.class);
if (beans == null || beans.size() == 0) {
return;
}
Collection<EventLisenter> list = beans.values();
for (EventLisenter listener : list) {
Class listenercls = AopTargetUtils.getTarget(listener).getClass();
Class eventCls = GenericTypeResolver.resolveTypeArgument(
listenercls, EventLisenter.class);

try {
if (localListeners.containsKey(eventCls.getName())) {
localListeners.get(eventCls.getName()).add(listener);
} else {
List<EventLisenter> l = new ArrayList<EventLisenter>();
l.add(listener);
localListeners.put(eventCls.getName(), l);
}
} catch (Exception e) {
throw new Exception("初始化事件监听器时出错:", e);
}
}

}


private void refreshRemoteListeners(){
//查询出集群服务器的IP(此处从数据库配置中查询)
List<String> ipList=heartbeatService.getAliveHostsExcludeSelf();
List<RemoteLisenter> RemoteLisenterList=remoteLisenterConfig.getRemoteLisenters();
remoteListeners = new LinkedHashMap<String, List<EventLisenter>>();
if(RemoteLisenterList!=null){
for (RemoteLisenter remoteLisenter : RemoteLisenterList) {

String eventClsName=remoteLisenter.getEventClass().getName();
Class listenerCls=remoteLisenter.getServiceInterface();
String port=remoteLisenter.getRegistryPort();
String serviceName=remoteLisenter.getServiceName();
if(ipList!=null){
for (String ip : ipList) {
EhCacheService ehCacheService=null;
EventLisenter listener = buildRemotListener(listenerCls, port,serviceName, ip);

if(listener!=null){
if (remoteListeners.containsKey(eventClsName)) {
remoteListeners.get(eventClsName).add(listener);
} else {
List<EventLisenter> l = new ArrayList<EventLisenter>();
l.add(listener);
remoteListeners.put(eventClsName, l);
}
}
}
}

}



}
}


private EventLisenter buildRemotListener(Class listenerCls, String port,
String serviceName, String ip) {

try {
RmiProxyFactoryBean rmiProxyFactoryBean = new RmiProxyFactoryBean();
rmiProxyFactoryBean.setServiceInterface(listenerCls);
rmiProxyFactoryBean.setServiceUrl("rmi://"+ip+":"+port+"/"+serviceName);
rmiProxyFactoryBean.afterPropertiesSet();

if (rmiProxyFactoryBean.getObject() instanceof EventLisenter) {
EventLisenter listener=(EventLisenter)rmiProxyFactoryBean.getObject();
return listener;
}else{
return null;
}
} catch (Exception e) {
logger.error("获取远程监听bean错误[listenerClass="+listenerCls+";port="+port+";ip="+ip+";serviceName="+serviceName+"]", e);
return null;
}





}


/**
* 发布事件
*
* @throws Exception
*/
@SuppressWarnings("rawtypes")
public void publishEvent(BaseEvent event) {
//本地监控
List<EventLisenter> localList = localListeners.get(event.getClass().getName());
if (localList != null) {
for (EventLisenter listener : localList) {
try {
listener.onEvent(event);
} catch (Exception e) {
logger.error(e.getMessage());
}
}
}

//远程监控
Class eventClass=event.getClass();
if(needRemoteListenre(eventClass)){
//刷新远程监听者
refreshRemoteListeners();

List<EventLisenter> remoteList = remoteListeners.get(event.getClass().getName());
if (remoteList != null) {
for (EventLisenter listener : remoteList) {
try {
listener.onEvent(event);
} catch (Exception e) {
logger.error(e.getMessage());
}
}
}
}
}


/**
* 判断本事件是否需要远程监听
* @param eventClass
* @return
*/
private boolean needRemoteListenre(Class eventClass) {

List<RemoteLisenter> RemoteLisenterList=remoteLisenterConfig.getRemoteLisenters();
if(RemoteLisenterList!=null){
for (RemoteLisenter remoteLisenter : RemoteLisenterList) {
Class eventCls=remoteLisenter.getEventClass();
if(eventCls.equals(eventCls))
return true;
}
}
return false;

}


public Map<String, List<EventLisenter>> getLocalListeners() {
return localListeners;
}


public Map<String, List<EventLisenter>> getRemoteListeners() {
return remoteListeners;
}



配置文件

<!-- 配置远程监听配置对象 -->
<bean id="remoteLisenterConfig" class="com.ejintai.cbs_policy_registry.base.event.RemoteLisenterConfig">
<property name="remoteLisenters">
<list>
<bean id="remoteLisenter1" class="com.ejintai.cbs_policy_registry.base.event.RemoteLisenter">
<property name="eventClass" value="com.ejintai.cbs_policy_registry.base.event.biz.EhCacheUpdateEvent" />
<property name="serviceName" value="ehCacheUpdateEventListener" />
<property name="serviceInterface" value="com.ejintai.cbs_policy_registry.base.event.EventLisenter"/>
<property name="registryPort" value="${rmi.port}"/>
</bean>
</list>
</property>
</bean>

<bean id="remoteEhCacheUpdateEventListener" class="org.springframework.remoting.rmi.RmiServiceExporter" >
<property name="serviceName" value="ehCacheUpdateEventListener" />
<property name="service" ref="ehCacheUpdateEventListener"/>
<property name="serviceInterface" value="com.ejintai.cbs_policy_registry.base.event.EventLisenter"/>
<property name="registryPort" value="${rmi.port}"/>
</bean>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值