Hazelcast系列(十):Map(二)监听器和拦截器

系列文章

Hazelcast系列(一):初识hazelcast

Hazelcast系列(二):hazelcast集成(嵌入式)

Hazelcast系列(三):hazelcast集成(服务器/客户端)

Hazelcast系列(四):hazelcast管理中心

Hazelcast系列(五):Auto-Detection发现机制

Hazelcast系列(六):Multicast发现机制

Hazelcast系列(七):TCP-IP发现机制

Hazelcast系列(八):数据结构

Hazelcast系列(九):Map(一)加载和存储

Hazelcast系列(十):Map(二)监听器和拦截器

目录

        前言

        监听器

                监听器列表

                配置方式

        拦截器

                拦截器方法

                配置方式

        测试

                测试监听器

                测试拦截器

        其他


前言

通过 Hazelcast系列(九):Map(一)加载和存储 对 Map 从数据库中加载方式以及存储数据方式有个大概了解,续接上文,咱们继续对 Map 的其他方面进行探讨。

Map 内容相关文章:

Hazelcast系列(九):Map(一)主要探讨 Map 加载、存储以及配置

Hazelcast系列(十):Map(二)主要探讨 Map 监听器、拦截器

Hazelcast系列(十一):Map(三)主要探讨 Map 备份、过期和驱逐以及内存格式

接下来,咱们来认识一下 Map 的 监听器拦截器

监听器

监听器 Listener 可以帮助使用者监听不同的事件进行额外的数据操作,事件例如添加数据、删除数据、更新特定数据等等。

针对于 Map 而言,事件分为基于 Map级别 的事件和基于 条目(Entry)的事件。

Map级别事件是由于Map级别的操作触发的,例如:IMap.clear()、IMap.evictAll()。

条目级别事件是由于操作某个特定条目后触发的,例如:IMap.remove()、IMap.evict()。

监听器列表

以下是 Map 级别和基于 条目(Entry) 的事件的监听器:

监听器名称描述
EntryAddedListener将条目添加到地图时会收到通知
EntryEvictedListener当基于大小的驱逐,从Map中删除条目时,会收到通知
EntryExpiredListener当基于过期的驱逐,从Map中删除条目时,会收到通知
EntryLoadedListener当条目通过MapLoader实现的load加载时,会收到通知
EntryMergedListener当合并WAN复制的条目时,会收到通知
EntryRemovedListener当条目直接从map删除时,会收到通知
EntryUpdatedListener当条目被更新时,会收到通知
EventLostListener当事件丢失时,会收到通知
MapClearedListener当使用Map的clear方法移除所有条目时,会收到通知
MapEvictedListener当使用Map的evictAll方法删除所有条目时,会收到通知
MapPartitionLostListener当主分区和分区所有备份都丢失了特定Map数据的时候,会收到通知

配置方式

配置的监听器必须实现 MapListener相应子接口,例如 EntryAddedListener 或 MapClearedListener。

监听类
/*** Hazelcast监听器*/
public class HazelcastMapListener implements EntryAddedListener<Long, StudentPo>, EntryUpdatedListener<Long, StudentPo> {@Overridepublic void entryAdded(EntryEvent<Long, StudentPo> entryEvent) {//TODOLong key = entryEvent.getKey();System.out.println("监听到" + key + "添加");}@Overridepublic void entryUpdated(EntryEvent<Long, StudentPo> entryEvent) {Long key = entryEvent.getKey();System.out.println("监听到" + key + "更新");}
}
添加方式
  • 方式一

    • 说明:通过编程方式添加监听器
    • 示例
HazelcastInstance hz = Hazelcast.newHazelcastInstance();
IMap<String, String> map = hz.getMap("mapcache");
//不仅仅监听本节点的事件
map.addEntryListener(new HazelcastMapListener(), true);//仅仅监听本节点的事件
//map.addLocalEntryListener(new HazelcastMapListener());
  • 方式二

    • 说明:通过编程方式添加某个条件下的监听器
    • 示例
HazelcastInstance hz = Hazelcast.newHazelcastInstance();
IMap<String, String> map = hz.getMap("mapcache");
//不仅仅监听本节点的事件
map.addEntryListener( new HazelcastMapListener(), Predicates.equal("name","xiaozi") ,true );//仅仅监听本节点的事件
//map.addLocalEntryListener(new HazelcastMapListener(), Predicates.equal("name", "xiaozi"), true);
  • 方式三

    • 说明:通过配置方式添加监听器
    • 示例
hazelcast:map:mapcache:entry-listeners:- class-name: com.hazelcast.hazelcastspringbootdemo1.config.HazelcastMapListenerinclude-value: falselocal: false

        这里的配置参数同编程方式的方法参数都是一样的,编程方式有些方法只不过重载了。

        说明:class-name  监听器的全限定类名

                   include-value  是否包含特定值的监听

                   local  是否只监听本节点的事件

拦截器

与监听器不同,拦截器可以在 Map 操作完成之前更改对其执行的操作。使用监听器,你可以在方法完成并且内存中的映射已修改后执行操作。拦截器操作是同步的,允许你更改方法的行为、更改其值或完全取消它。

拦截器是服务端的功能。

Map 拦截器是链式的,因此多次添加相同的拦截器到同一个 Map 可能会导致重复的效果。当使用拦截器时,很容易发生这种情况。

当你以这种方式添加拦截器时,一定要实现 hashCode() 方法,以便为拦截器的每个实例返回相同的值。最好也实现 equals() 方法,因为这确保了可以可靠地删除 Map 拦截器。

IMap API 有两种向 Map 添加和删除拦截器的方法: addInterceptor removeInterceptor

拦截器方法

方法名描述
interceptGet用新值替换返回的 map.get() 值
afterGetmap.get() 操作完成后采取的操作
interceptPut将 map.put() 中的值替换为新值

afterPut

map.put() 完成后要采取的操作
interceptRemove

获取已删除的 Map 的 Entry

afterRemovemap.remove() 完成后要采取的操作

配置方式

配置的监听器必须实现 MapInterceptor 相应子接口

拦截器类
/*** hazelcast拦截器类*/
public class HazelcastMapInterceptor implements MapInterceptor {/*** 拦截get操作,可以返回其他值来替换原有值** @param o* @return*/@Overridepublic Object interceptGet(Object o) {return o;}/*** get操作执行完后被调用** @param o*/@Overridepublic void afterGet(Object o) {System.out.println("已获取的值" + o);}/*** 拦截put,返回的值会设置到map中** @param oldVal* @param newVal* @return*/@Overridepublic Object interceptPut(Object oldVal, Object newVal) {return newVal;}/*** put操作执行后被调用** @param o*/@Overridepublic void afterPut(Object o) {}/*** 拦截remove,返回被删除对象** @param o* @return*/@Overridepublic Object interceptRemove(Object o) {return o;}/*** remove操作执行后被调用** @param o*/@Overridepublic void afterRemove(Object o) {}/*** hashCode值,为每个实例返回相同的值** @return*/@Overridepublic int hashCode() {return 1956850123;}
}
添加方式
/*** hazelcast配置类*/
@Configuration
public class HazelcastServerConfig {/*** 配置类* @return*/@Beanpublic Config serverConfig() {ClasspathYamlConfig yamlConfig = new ClasspathYamlConfig("hazelcast.yaml");return yamlConfig;}/*** 实例对象* @param serverConfig* @return*/@Beanpublic HazelcastInstance hazelcastInstance(Config serverConfig) {HazelcastInstance hazelcastInstance = Hazelcast.newHazelcastInstance(serverConfig);IMap<Object, Object> map = hazelcastInstance.getMap(HazelcastConstants.HAZECAST_MAP_CACHE);map.addInterceptor(new HazelcastMapInterceptor());return hazelcastInstance;}
}

          暂未找到对应的yaml配置方式,所以采用编程的方式添加

         注意:多个节点添加拦截器一定要添加hashcode方法,避免同一个拦截器被多次加入

测试

同一份代码复制两份进行测试,开启不同的端口

测试监听器

  • 两个节点分别为 Node1 和 Node2,都采用方式三配置方式Node1 节点只监听本节点的事件,Node2 监听所有的事件
  • 向 Node2 添加数据

  •  Node2 收到事件, Node1 未收到事件(这里并不是往哪个节点添加,数据肯定就放到哪儿,注意,这里会根据 Hazelcast 分区负载存放

  • 接下来,向 Node1 添加多次添加数据数据(No从29-34),结果如下

  •  可以发现 Node2 收到所有的事件,Node2 符合预期,而 Node1 仅收到 No=34 的事件,这说明只有 No=34 这个 Key 的值在分区在 Node1 节点上,那么如何确认呢? 
  • 可以通过管理中心通过 Map 的 Key 获取,Value 的信息不但包含值,还有所在的节点地址,除此之外,可以通过自己编写 API 获取,这里采用第二种方式,编写 API 获取相关信息
  • 发送请求获取 Key 相关信息,结果如下

  • 192.168.119.1:5702 就是 Node1 节点的地址(这里 Node1 节点启动的时候会打印当前节点地址和端口,可作为依据),测试完成 

测试拦截器

环境同前面测试监听器一样

  • 通过 Node1 发起请求获取 No=34 的 Key 的信息

  • 结果如下,Node1 打印了信息,Node2 没有打印,前面我们也验证过,No=34 的数据存放在 Node1 上,所以正确

  •  通过 Node1 发起请求获取 No=28 的 Key 的信息

  

  • 结果如下,Node1 没打印拦截器信息,Node2 打印拦截器信息,No=28 的数据存放在 Node2 上,所以正确,测试完成 

其他

  • 对象序列化有多种方式,JAVA 自带的 Serializable 序列化效率是最低的
  • 监听器根据数据所在分区的所在节点触发事件,如果仅监听当前节点事件,通过当前节点操作数据,不一定就在当前节点触发事件(前提是有多个节点)
  • 拦截器最好重写 hashCode方法,避免同一个拦截器被多次使用
  • 拦截器生效的节点也就是 Key 所在的节点

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/286717.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

P51 各式各样的神奇的自注意力机制

计算量大 当input sequence 很长时&#xff0c;计算量特别大 self-atttention 至少一个大模型的一部分当input sequence 很长时&#xff0c;主要运算来自self - attention&#xff0c; 加快 self attention ,才能有明显的加快速度 变形 local attention 只计算左右两个位置…

八大在线PS工具,你不能错过的编辑利器

即时设计 即时设计是一款优秀的在线ps网页版替代工具&#xff0c;具有各种硬件设备的标准尺寸&#xff0c;可以直接在编辑器中创建不同设备(手机、平板电脑、电脑等)尺寸的画板。)并预览您的设计效果。 即时设计支持互动事件演示&#xff0c;丰富的过渡动画&#xff0c;各种渐…

python接口自动化测试--requests使用和基本方法封装

之前学习了使用jmeterant做接口测试&#xff0c;并实现了接口的批量维护管理(大概500多条用例)&#xff0c;对“接口”以及“接口测试”有了一个基础了解&#xff0c;最近找了一些用python做接口测试的资料&#xff0c;一方面为了学习下如何使用python进行接口测试(如何做出一个…

[每周一更]-(第29期):mac小白入手“MacBook Pro M2“各种问题指南

作为使用15年重度Windows用户&#xff0c;从2008年初中毕业接触电脑&#xff0c;到2012年上大学从事计算机相关学习工作&#xff0c;一直都是忠实的Windows使用者&#xff0c;使用的系统&#xff1a;Microsoft Windows XP、7、10、11, 体验到系统的兼容性和灵活的注册表使用&am…

dbeaver导出数据为excel格式

dbeaver导出excel 目前数据的可选择只有这几种 恰好没有我们需要的excel模式,而我们需要数据一般都需要excel的 所以我们可以通过以下步骤得到我们的excel格式的数据集: 1.直接选csv模式,至于csv有陌生的小伙伴可以理解:CSV&#xff08;Comma-Separated Values&#xff09;是…

机器学习之线性回归(Linear Regression)

概念 线性回归(Linear Regression)是机器学习中的一种基本的监督学习算法,用于建立输入变量(特征)与输出变量(目标)之间的线性关系。它假设输入变量与输出变量之间存在线性关系,并试图找到最佳拟合线来描述这种关系。 在简单线性回归中,只涉及两个变量:一个是自变量…

internet download manager 6.42怎么删除卸载,2024最新idm卸载不干净怎么解决

internet download manager 6.42简称为IDM&#xff0c;这是一款非常好用的下载软件&#xff0c;很多小伙伴都在使用。如果后续我们不再需要使用该软件&#xff0c;小伙伴们知道具体该如何将其卸载掉吗&#xff0c;其实卸载方法是非常简单的&#xff0c;只需要进行几个非常简单的…

基于paddlepaddle的FPS最远点采样

什么是FPS最远点采样&#xff1f; 最远点采样&#xff08;Farthest Point Sampling&#xff0c;FPS&#xff09;是一种常用的采样算法&#xff0c;主要用于点云数据&#xff08;如激光雷达点云数据、分子坐标等&#xff09;的采样。 为了方便解释&#xff0c;定义一下待采样点…

【Spring】11 EnvironmentAware 接口

文章目录 1. 简介2. 作用3. 使用3.1 创建并实现接口3.2 配置 Bean 信息3.3 创建启动类3.4 启动 4. 应用场景总结 Spring 框架为开发者提供了丰富的扩展点&#xff0c;其中之一就是 Bean 生命周期中的回调接口。本文将着重介绍一个与环境&#xff08;Environment&#xff09;相关…

JVM调优排错专题

JVM调优排错专题 1 打开MAT报错 1 打开MAT报错 下载了linux版本的 MAT 软件&#xff0c;1.15.0版本。 下载地址&#xff1a;https://eclipse.dev/mat/downloads.php 运行时报错了。 错误截图 报错日志 wittasus:/usr/develop/mat$ ./MemoryAnalyzer Unrecognized option:…

如何实现TAB切换时按钮变换样式

实现TAB切换时按钮变换样式的方法 当鼠标移动到TAB标签按钮时&#xff0c;按钮样式发生改变(红底白色加粗字体)&#xff0c;当点击按钮切换显示内容后&#xff0c;按钮样式发生改变(黄底黑色加粗字体) 选中按钮“作业批阅结果”&#xff0c;右键>>编辑按钮形状>>编…

黑盒测试中关键截图如何打点

黑盒测试中关键截图如何打点Android黑盒测试过程中如何进行有效的打点是我们经常遇到的问题&#xff0c;我们一般会在脚本内部进行数据打点&#xff0c;也可以使用其他进程录屏或截图。那我们如何选取合适的方式进行打点记录呢&#xff1f;下图是对常用打点方式的统计&#xff…