使用Java代碼實現(xiàn)Redis和數(shù)據(jù)庫數(shù)據(jù)同步
這里我用到了Redis當(dāng)中的發(fā)布訂閱模式實現(xiàn)(JAVA代碼實現(xiàn))
先看圖示
下面為代碼實現(xiàn)
首先將RedisMessageListenerContainer交給Spring管理.
@Configuration public class redisConfig { @Autowired RedisConnectionFactory redisConnectionFactory; @Autowired @Qualifier("carServiceDb") private CarService carService;//操作數(shù)據(jù)庫 @Bean public RedisMessageListenerContainer listenerContainer(){ //創(chuàng)建一個Redis消息監(jiān)聽器容器對象 RedisMessageListenerContainer listenerContainer = new RedisMessageListenerContainer(); //設(shè)置Redis連接工廠對象 listenerContainer.setConnectionFactory(redisConnectionFactory); //向監(jiān)聽器容器中添加一個監(jiān)聽器,該監(jiān)聽器的主題為INSERTED listenerContainer.addMessageListener(new MessageListener() { @Override public 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())); //向監(jiān)聽器容器中添加一個監(jiān)聽器,該監(jiān)聽器的主題為UPDATED listenerContainer.addMessageListener(new MessageListener() { @Override public 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())); //向監(jiān)聽器容器中添加一個監(jiān)聽器,該監(jiān)聽器的主題為DELETED listenerContainer.addMessageListener(new MessageListener() { @Override public 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();就是發(fā)送消息的,其中參數(shù)1是發(fā)送消息的名稱,參數(shù)2是發(fā)送消息的內(nèi)容
@Service("carService") @Slf4j public class CarServiceImpl extends ServiceImpl<CarMapper, Car> implements CarService { //購物車hash的Key public static final String CAR_KEY = "carKey"; //hash購物車中field的前綴 public static final String USER_CAR_HASH_FIELD_PREFIX = "car::"; @Resource private StringRedisTemplate stringRedisTemplate; /** * 這里存儲的時候采用Redis當(dāng)中的hash存儲 * * @param car */ @Override @Synchronized public void addCar(Car car) { //這里存儲的時候采用Redis當(dāng)中的hash存儲 HashOperations<String, String, String> opsForHash = stringRedisTemplate.opsForHash(); //這里field為CAR_HASH_FIELD String userCarKey = USER_CAR_HASH_FIELD_PREFIX + car.getUserId(); //Map<String,Car> 鍵(存儲bookId) 值存儲購物車某一個商品的信息 Map<String, Car> CarMap = null; boolean flag = true; //獲得Redis中以存儲的當(dāng)前用戶的購物車信息 if (opsForHash.hasKey(CAR_KEY, userCarKey)) { //存在當(dāng)前用戶的購物車信息,那么獲取原有的數(shù)據(jù) String carMapJson = opsForHash.get(CAR_KEY, userCarKey); CarMap = JSONObject.parseObject(carMapJson, new TypeReference<Map<String, Car>>() { }); //檢測當(dāng)前購物車信息中是否包含新添加上的商品,如果包含則更新數(shù)量,如果不包含才新增 if (CarMap.containsKey(car.getBookId())) { //獲取原先商品的數(shù)量 Integer BeforeNumber = CarMap.get(car.getBookId()).getNumber(); log.info("BeforeNumber==============>{}", BeforeNumber); Integer nowNumber = car.getNumber(); //前端傳過來現(xiàn)在的 log.info("nowNumber==============>{}", nowNumber); CarMap.get(car.getBookId()).setNumber(BeforeNumber + nowNumber); flag = false; //存在商品 //修改 //包含才新增 圖書的數(shù)量 在原有的基礎(chǔ)上新增圖書的數(shù)量 } else { //新增 //如果不包含當(dāng)前商品信息 那么直接將商品添加到購物車信息當(dāng)中 CarMap.put(car.getBookId(), car); } } else { /* 新增 * * 當(dāng)前的用戶的購物車信息不存在 * 首先把其添加的商品首先存儲到CarMap中 * */ CarMap = new HashMap<>(); CarMap.put(car.getBookId(), car); } //最后將其存入redis當(dāng)中 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()))); } } @Override public Collection<Car> getCarList(String userId) { //這里存儲的時候采用Redis當(dāng)中的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(); } @Override public void updataCount(String bookId, int number, String userId) { //這里存儲的時候采用Redis當(dāng)中的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當(dāng)中 opsForHash.put(CAR_KEY, userCarKey, JSONObject.toJSONString(CarMap)); stringRedisTemplate.convertAndSend(ChannelEnum.UPDATED.name(), JSONObject.toJSONString(CarMap.get(car.getBookId()))); } @Override public 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中獲取用戶對應(yīng)的購物車數(shù)據(jù) String carJsonStr = forHash.get(CAR_KEY, userCarKey); //修改指定商品的數(shù)量 Map<String,Car> carMap = JSONObject.parseObject(carJsonStr, new TypeReference<Map<String,Car>>() { }); for(String bookId : bookIds){ carMap.remove(bookId); } //將修改后的數(shù)據(jù)重新添加到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();就是發(fā)送消息的,其中參數(shù)1是發(fā)送消息的名稱,參數(shù)2是發(fā)送消息的內(nèi)容
第一段代碼中的這個就是監(jiān)聽到后接收到的消息,其中參數(shù)1{當(dāng)中的onMessage方法的參數(shù)1Message為發(fā)送消息的內(nèi)容,參數(shù)2pattern是發(fā)送消息的名稱} 參數(shù)2為監(jiān)聽指定的消息名稱(這個要和stringRedisTemplate.convertAndSend()中參數(shù)1的要保持一致)
listenerContainer.addMessageListener(new MessageListener() { @Override public void onMessage(Message message, byte[] pattern) { } }, new ChannelTopic(ChannelEnum.INSERTED.name()));
以上就是使用Java代碼實現(xiàn)Redis和數(shù)據(jù)庫數(shù)據(jù)同步的詳細(xì)內(nèi)容,更多關(guān)于Java Redis和數(shù)據(jù)庫同步的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
SpringBoot實現(xiàn)自定義配置文件提示的方法
這篇文章主要介紹了SpringBoot實現(xiàn)自定義配置文件提示的方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-03-03SpringBoot實現(xiàn)HTTP調(diào)用的七種方式總結(jié)
小編在工作中,遇到一些需要調(diào)用三方接口的任務(wù),就需要用到 HTTP 調(diào)用工具,這里,我總結(jié)了一下 實現(xiàn) HTTP 調(diào)用的方式,共有 7 種(后續(xù)會繼續(xù)新增),需要的朋友可以參考下2023-09-09在RabbitMQ中實現(xiàn)Work queues工作隊列模式
這篇文章主要介紹了如何在RabbitMQ中實現(xiàn)Work queues模式,代碼詳細(xì),解釋清晰,可以幫助大家更好理解java,對這方面感興趣的朋友可以參考下2021-04-04Spring?Security實現(xiàn)接口放通的方法詳解
在用Spring?Security項目開發(fā)中,有時候需要放通某一個接口時,我們需要在配置中把接口地址配置上,這樣做有時候顯得麻煩。本文將通過一個注解的方式快速實現(xiàn)接口放通,感興趣的可以了解一下2022-05-05SpringCloud的網(wǎng)關(guān)Zuul和Gateway詳解
SpringCloudZuul和SpringCloudGateway都是用于構(gòu)建微服務(wù)架構(gòu)中的API網(wǎng)關(guān)的組件,但SpringCloudGateway在性能、功能特性和生態(tài)支持等方面有一些優(yōu)勢,因此推薦使用SpringCloudGateway作為首選2025-02-02