实现Redis和数据库数据同步问题(JAVA代码实现)

这里我用到了Redis当中的发布订阅模式实现(JAVA代码实现)

先看图示 

        

下面为代码实现

首先将RedisMessageListenerContainer交给Spring管理.

@Configuration
public class redisConfig {@AutowiredRedisConnectionFactory redisConnectionFactory;@Autowired@Qualifier("carServiceDb")private CarService carService;//操作数据库@Beanpublic RedisMessageListenerContainer listenerContainer(){//创建一个Redis消息监听器容器对象RedisMessageListenerContainer listenerContainer = new RedisMessageListenerContainer();//设置Redis连接工厂对象listenerContainer.setConnectionFactory(redisConnectionFactory);//向监听器容器中添加一个监听器,该监听器的主题为INSERTEDlistenerContainer.addMessageListener(new MessageListener() {@Overridepublic void onMessage(Message message, byte[] pattern) {System.out.println("*************insert*************");String carJsonStr = new String(message.getBody());Car car = JSONObject.parseObject(carJsonStr, Car.class);carService.addCar(car);System.out.println(new String(message.getBody()));System.out.println(new String(pattern));System.out.println("*************insert*************");}}, new ChannelTopic(ChannelEnum.INSERTED.name()));//向监听器容器中添加一个监听器,该监听器的主题为UPDATEDlistenerContainer.addMessageListener(new MessageListener() {@Overridepublic void onMessage(Message message, byte[] pattern) {System.out.println("*************UPDATED*************");String carJsonStr = new String(message.getBody());Car car = JSONObject.parseObject(carJsonStr, Car.class);carService.updataCount(car.getBookId(),car.getNumber(),car.getUserId());System.out.println(new String(message.getBody()));System.out.println(new String(pattern));System.out.println("*************UPDATED*************");}}, new ChannelTopic(ChannelEnum.UPDATED.name()));//向监听器容器中添加一个监听器,该监听器的主题为DELETEDlistenerContainer.addMessageListener(new MessageListener() {@Overridepublic void onMessage(Message message, byte[] pattern) {System.out.println("*************DELETED*************");System.out.println(new String(message.getBody()));System.out.println(new String(pattern));List<String[]> strings = JSONArray.parseArray(new String(message.getBody()), String[].class);String[] bookIds = strings.get(0);String userId = strings.get(1)[0];carService.delCar(bookIds,userId);System.out.println("----------------------");System.out.println(Arrays.toString(bookIds));System.out.println(userId);System.out.println("--------delete--------");System.out.println("*************DELETED*************");}}, new ChannelTopic(ChannelEnum.DELETED.name()));return listenerContainer;}
}

          下面代码中的 stringRedisTemplate.convertAndSend();就是发送消息的,其中参数1是发送消息的名称,参数2是发送消息的内容

@Service("carService")
@Slf4j
public class CarServiceImpl extends ServiceImpl<CarMapper, Car> implements CarService {//购物车hash的Keypublic static final String CAR_KEY = "carKey";//hash购物车中field的前缀public static final String USER_CAR_HASH_FIELD_PREFIX = "car::";@Resourceprivate StringRedisTemplate stringRedisTemplate;/*** 这里存储的时候采用Redis当中的hash存储** @param car*/@Override@Synchronizedpublic void addCar(Car car) {//这里存储的时候采用Redis当中的hash存储HashOperations<String, String, String> opsForHash = stringRedisTemplate.opsForHash();//这里field为CAR_HASH_FIELDString userCarKey = USER_CAR_HASH_FIELD_PREFIX + car.getUserId();//Map<String,Car>  键(存储bookId)  值存储购物车某一个商品的信息Map<String, Car> CarMap = null;boolean flag = true;//获得Redis中以存储的当前用户的购物车信息if (opsForHash.hasKey(CAR_KEY, userCarKey)) {//存在当前用户的购物车信息,那么获取原有的数据String carMapJson = opsForHash.get(CAR_KEY, userCarKey);CarMap = JSONObject.parseObject(carMapJson, new TypeReference<Map<String, Car>>() {});//检测当前购物车信息中是否包含新添加上的商品,如果包含则更新数量,如果不包含才新增if (CarMap.containsKey(car.getBookId())) {//获取原先商品的数量Integer BeforeNumber = CarMap.get(car.getBookId()).getNumber();log.info("BeforeNumber==============>{}", BeforeNumber);Integer nowNumber = car.getNumber(); //前端传过来现在的log.info("nowNumber==============>{}", nowNumber);CarMap.get(car.getBookId()).setNumber(BeforeNumber + nowNumber);flag = false; //存在商品//修改//包含才新增 图书的数量 在原有的基础上新增图书的数量} else {//新增//如果不包含当前商品信息 那么直接将商品添加到购物车信息当中CarMap.put(car.getBookId(), car);}} else {/*   新增** 当前的用户的购物车信息不存在*       首先把其添加的商品首先存储到CarMap中* */CarMap = new HashMap<>();CarMap.put(car.getBookId(), car);}//最后将其存入redis当中opsForHash.put(CAR_KEY, userCarKey, JSONObject.toJSONString(CarMap));if (flag){//新增stringRedisTemplate.convertAndSend(ChannelEnum.INSERTED.name(), JSONObject.toJSONString(CarMap.get(car.getBookId())));}else {//修改stringRedisTemplate.convertAndSend(ChannelEnum.UPDATED.name(), JSONObject.toJSONString(CarMap.get(car.getBookId())));}}@Overridepublic Collection<Car> getCarList(String userId) {//这里存储的时候采用Redis当中的hash存储HashOperations<String, String, String> opsForHash = stringRedisTemplate.opsForHash();String userCarKey = USER_CAR_HASH_FIELD_PREFIX + userId;String jsonStr = opsForHash.get(CAR_KEY, userCarKey);Map<String,Car> CarMap = JSONObject.parseObject(jsonStr, Map.class);return CarMap.values();}@Overridepublic void updataCount(String bookId, int number, String userId) {//这里存储的时候采用Redis当中的hash存储HashOperations<String, String, String> opsForHash = stringRedisTemplate.opsForHash();String userCarKey = USER_CAR_HASH_FIELD_PREFIX + userId;String jsonStr = opsForHash.get(CAR_KEY, userCarKey);Map<String,Car> CarMap = JSONObject.parseObject(jsonStr, new TypeReference<Map<String, Car>>() {});if (!CarMap.containsKey(bookId)){ //不包含return;}Car car = CarMap.get(bookId);car.setNumber(number);//最后将其存入redis当中opsForHash.put(CAR_KEY, userCarKey, JSONObject.toJSONString(CarMap));stringRedisTemplate.convertAndSend(ChannelEnum.UPDATED.name(), JSONObject.toJSONString(CarMap.get(car.getBookId())));}@Overridepublic void delCar(String[] bookIds, String userId) {//获得操作RedisHash的对象HashOperations<String, String, String> forHash = stringRedisTemplate.opsForHash();String userCarKey = USER_CAR_HASH_FIELD_PREFIX+userId;List<String[]> list = new ArrayList<>();//从redis中获取用户对应的购物车数据String carJsonStr = forHash.get(CAR_KEY, userCarKey);//修改指定商品的数量Map<String,Car> carMap = JSONObject.parseObject(carJsonStr, new TypeReference<Map<String,Car>>() {});for(String bookId : bookIds){carMap.remove(bookId);}//将修改后的数据重新添加到redis中forHash.put(CAR_KEY,userCarKey,JSONObject.toJSONString(carMap));list.add(bookIds);list.add(new String[]{userId});stringRedisTemplate.convertAndSend(ChannelEnum.DELETED.name(), JSONObject.toJSONString(list));}
}

上述的两段代码中

第二段代码中stringRedisTemplate.convertAndSend();就是发送消息的,其中参数1是发送消息的名称,参数2是发送消息的内容

第一段代码中的这个就是监听到后接收到的消息,其中参数1{当中的onMessage方法的参数1Message为发送消息的内容,参数2pattern是发送消息的名称}    参数2为监听指定的消息名称(这个要和stringRedisTemplate.convertAndSend()中参数1的要保持一致)

listenerContainer.addMessageListener(new MessageListener() {@Overridepublic void onMessage(Message message, byte[] pattern) {}}, new ChannelTopic(ChannelEnum.INSERTED.name()));

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

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

相关文章

Linux线程:线程分离

目录 一、什么是线程分离 1.1pthread_detach 1.2pthread线程库存在的意义 1.3__thread线程的局部存储 1.4系统调用clone 一、什么是线程分离 1.1pthread_detach 默认情况下&#xff0c;新创建的线程是joinable的&#xff0c;线程退出后&#xff0c;需要对其进行pthread_joi…

数据标准的制定落地

目录 什么是数据标准 基本定义 目的 数据标准体系分类 从内容层面分类 从管理视角分类 从面向的对象分类 从数据结构的角度分类 数据标准价值 业务价值 技术价值 管理价值 数据标准和数据治理的关系 数据标准在数据治理各项任务中的作用 数据标准与主数据 数据…

车联网安全入门——ICSim模拟器使用

文章目录 车联网安全入门——ISCim模拟器使用介绍主要特点&#xff1a;使用场景&#xff1a; 安装使用捕获can流量candumpcansnifferwiresharkSavvyCAN主要特点&#xff1a;使用场景&#xff1a; 重放can报文cansendSavvyCAN 总结 车联网安全入门——ISCim模拟器使用 &#x1…

LabVIEW步进电机的串口控制方法与实现

本文介绍了在LabVIEW环境中通过串口控制步进电机的方法&#xff0c;涵盖了基本的串口通信原理、硬件连接步骤、LabVIEW编程实现以及注意事项。通过这些方法&#xff0c;用户可以实现对步进电机的精确控制&#xff0c;适用于各种自动化和运动控制应用场景。 步进电机与串口通信…

【刷题(15】普通数组

一 普通数组基础 首先&#xff0c;我们根据下图先了解一下什么是前缀和。 既然我们明白了前缀和是怎么回事&#xff0c;那我们就来看一下我们该怎么输入 先给出答案&#xff0c;然后再给出分析。 答案&#xff1a; for (int i 1; i < n; i ){cin >> a[i];s[i] s…

Pytest框架中用例用例执行常用参数介绍

pytest 支持通过命令行参数来定制测试运行的方式。以下是一些常用的 pytest 执行参数介绍。 学习目录 -q 或 --quiet: 安静模式&#xff0c;只显示进度和摘要 -s : 选项允许在测试的输出中捕获 stdout 和 stderr。 -v : 选项会使 pytest 的输出更加详细。 -k &#xff1a;…

DIYP对接骆驼后台IPTV管理,退出菜单中显示用户名已经网络信息,MAC,剩余天数,套餐名称等

演示&#xff1a;https://url03.ctfile.com/f/1779803-1042599473-4dc000?p8976 (访问密码: 8976) 后台加上EPG&#xff0c;增加一些播放源的动态端口替换。 前台app上&#xff0c;退出菜单中显示用户名已经网络信息&#xff0c;MAC&#xff0c;剩余天数&#xff0c;套餐名称…

QT之常用控件

一个图形化界面当然需要有各种各样的控件&#xff0c;QT也不例外&#xff0c;在QT designer中就有提供各种各样的控件&#xff0c;用以开发图形化界面。 而想使用好一个QT控件&#xff0c;就需要了解这些控件。 QWidget 在QT中&#xff0c;所有控件都继承自 QWidget 类&…

中间件模版引擎

文章目录 中间件1.自定义中间件1&#xff09;全局2&#xff09;局部中间件 2.内置中间件(静态资源目录&#xff09; Art-template1.模板语法1&#xff09;输出2&#xff09;原文输出3&#xff09;条件判断4&#xff09;循环5&#xff09;子模版6&#xff09;模版继承7&#xff…

git远程仓库限额的解决方法——大文件瘦身

Git作为世界上最优秀的分布式版本控制工具&#xff0c;也是优秀的文件管理工具&#xff0c;它赋予了项目成员对项目进行远程协同开发能力&#xff0c;因此受到越来越多的行业从业人员的喜爱。很多优秀的项目管理平台&#xff0c;比如国内的Gitee&#xff0c;国外的Github&#…

Django表单革命:打造安全、高效、用户友好的Web应用

Django表单处理&#xff0c;听起来是不是有点枯燥&#xff1f;别急&#xff0c;阿佑将带你领略Django表单的艺术之美。我们将以轻松幽默的语言&#xff0c;一步步引导你从表单的创建到管理&#xff0c;再到验证和自定义&#xff0c;让你在不知不觉中掌握Django表单的精髓。文章…

SpringMVC:转发和重定向

1. 请求转发和重定向简介 参考该链接第9点 2. forward 返回下一个资源路径&#xff0c;请求转发固定格式&#xff1a;return "forward:资源路径"如 return "forward:/b" 此时为一次请求返回逻辑视图名称 返回逻辑视图不指定方式时都会默认使用请求转发in…

留给“端侧大模型”的时间不多了

端侧大模型&#xff08;Edge AI models&#xff09;&#xff0c;也就是只在设备本地&#xff08;如智能手机、IoT设备、嵌入式系统等&#xff09;运行的大模型&#xff0c;过去一两年来非常流行。 具体表现在&#xff0c;终端设备厂商&#xff0c;如苹果、荣耀、小米、OV等&…

【操作与配置】VS2017与MFC环境配置

【操作与配置】VS2017与MFC环境配置 概述 Visual Studio 是一款强大且多功能的集成开发环境&#xff08;IDE&#xff09;&#xff0c;适用于软件开发人员和团队。使用此应用程序&#xff0c;您可以构建和调试现代Web应用程序&#xff0c;并利用扩展帮助探索几乎任何编程语言。…

重学java 55. 集合 Set接口

我救自己万万次&#xff0c;铮铮劲草&#xff0c;绝不动摇 —— 24.6.2 一、Set集合介绍 Set和Map密切相关的 Map的遍历需要先变成单列集合&#xff0c;只能变成set集合 二、HashSet集合的介绍和使用 1.概述 HashSet是Set接口的实现类 2.特点 a、元素唯一 b、元素无序 c、无索引…

devicemotion 或者 deviceorientation在window.addEventListener 事件中不生效,没有输出内容

问题&#xff1a;devicemotion 或者 deviceorientation 在window.addEventListener 事件中不生效&#xff0c;没有输出内容 原因&#xff1a; 1、必须在Https协议下才可使用 2、必须用户手动点击click事件中调用 &#xff0c;进行权限申请 源码&#xff1a; <!DOCTYPE h…

Docker 部署 mysql 服务

linux用法 Container&#xff08;容器&#xff09;集合成 Services&#xff08;服务&#xff09; 交互集合成 Stack&#xff08;堆栈&#xff09;卸载可能存在的旧版本 sudo apt-get update使apt可以通过HTTPS使用存储库&#xff08;repository&#xff09; sudo apt-get ins…

961操作系统知识总结

部分图片可能无法显示&#xff0c;参考这里&#xff1a;https://zhuanlan.zhihu.com/p/701247894 961操作系统知识总结 一 操作系统概述 1. 操作系统的基本概念 重要操作系统类型&#xff1a;批处理操作系统(批量处理作业&#xff0c;单道批处理/多道批处理系统&#xff0c;用…

7. MySQL 视图、索引

文章目录 【 1. 视图 View 】1.1 视图原理1.2 创建视图 CREATE VIEW1.2.1 创建基于单表的视图1.2.2 创建基于多表的视图 1.3 查看视图1.3.1 查看视图的内容1.3.2 查看视图的详细信息 1.4 修改视图 ALTER VIEW1.4.1 修改视图内容1.4.2 修改视图名称 1.5 删除视图 DORP VIEW 【 2…

使用python下载股票数据至sqlite数据库

代码下载地址&#xff1a; https://download.csdn.net/download/weixin_44600457/89389489