java實(shí)現(xiàn)點(diǎn)贊功能
本文實(shí)例為大家分享了java實(shí)現(xiàn)點(diǎn)贊功能的具體代碼,供大家參考,具體內(nèi)容如下
實(shí)現(xiàn)思路:
將點(diǎn)贊的數(shù)據(jù)先保存到redis中,然后定時(shí)同步到數(shù)據(jù)庫(kù)
第一步:
在redis中創(chuàng)建二個(gè)hash 用于存儲(chǔ) 用戶點(diǎn)贊記錄及記錄點(diǎn)贊數(shù)
MAP_USER_LIKED :用戶點(diǎn)贊的記錄 key:記錄id::用戶id value:1
MAP_USER_LIKED_COUNT:記錄點(diǎn)贊數(shù) key: 記錄id value:數(shù)量
第二步:
創(chuàng)建枚舉類
@Getter public enum LikeStatusEnum { ? ? LIKE(1,"點(diǎn)贊"), ? ? UNLIKE(0,"取消點(diǎn)贊/未點(diǎn)贊"); ? ? private Integer code; ? ? private String msg; ? ? LikeStatusEnum(Integer code,String msg){ ? ? ? ? this.code = code; ? ? ? ? this.msg = msg; ? ? } }
@Getter public enum RedisHashEnum { ? ? MAP_USER_LIKED("MAP_USER_LIKED"), ? ? MAP_USER_LIKED_COUNT("MAP_USER_LIKED_COUNT"); ? ? private String value; ? ? RedisHashEnum(String value){ ? ? ? ? this.value =value; ? ? } }
第三步:
將實(shí)現(xiàn)類寫好
@Service public class PostRedisServiceImpl implements PostRedisService { ? ? @Resource ? ? private RedisTemplate redisTemplate; ? ? @Autowired(required = false) ? ? public void ?setRedisTemplate(RedisTemplate redisTemplate){ ? ? ? ? RedisSerializer serializer = new StringRedisSerializer(); ? ? ? ? redisTemplate.setKeySerializer(serializer); ? ? ? ? redisTemplate.setValueSerializer(serializer); ? ? ? ? redisTemplate.setHashKeySerializer(serializer); ? ? ? ? redisTemplate.setHashValueSerializer(serializer); ? ? ? ? this.redisTemplate = redisTemplate; ? ? } ? ? /** ? ? ?* 點(diǎn)贊、取消點(diǎn)贊 ? ? ?* ? ? ?* @param recordId ? ? ?* @param userId ? ? ?*/ ? ? @Override ? ? public void saveLikeRedis(String recordId, String userId,Integer status) { ? ? ? ? String key =recordId+"::"+userId; ? ? ? ? redisTemplate.opsForHash().put(RedisHashEnum.MAP_USER_LIKED,key, status); ? ? } ? ? /** ? ? ?* 從Redis中刪除一條點(diǎn)贊數(shù) ? ? ?* ? ? ?* @param recordId ? ? ?* @param userId ? ? ?*/ ? ? @Override ? ? public void deleteLikeFromRedis(String recordId, String userId) { ? ? ? ? String key =recordId+"::"+userId; ? ? ? ? redisTemplate.opsForHash().delete(RedisHashEnum.MAP_USER_LIKED,key); ? ? } ? ? /** ? ? ?* 該記錄 點(diǎn)贊加1 ? ? ?* ? ? ?* @param recordId ? ? ?*/ ? ? @Override ? ? public void incrementLikedCount(String recordId) { ? ? ? ? redisTemplate.opsForHash().increment(RedisHashEnum.MAP_USER_LIKED_COUNT,recordId,1); ? ? } ? ? /** ? ? ?* 譔記錄 點(diǎn)贊減1 ? ? ?* ? ? ?* @param recordId ? ? ?*/ ? ? @Override ? ? public void decrementLikeCount(String recordId) { ? ? ? ? redisTemplate.opsForHash().increment(RedisHashEnum.MAP_USER_LIKED_COUNT,recordId,-1); ? ? } }
第四步提供接口:
?/** ? ? ?* 進(jìn)行點(diǎn)贊、取消點(diǎn)贊 ? ? ?* ? ? ?* @param vo ? ? ?*/ ? ? @Override ? ? public Result addKudos(KudosVo vo) { ? ? ? ? if(vo == null){ ? ? ? ? ? ? return Result.error(ResponseMessage.PARAMERROR); ? ? ? ? } ? ? ? ? if("1".equals(vo.getStatus())){ ? ? ? ? ? ? // 點(diǎn)贊 ? ? ? ? ? ? postRedisService.saveLikeRedis(vo.getRecordId(),vo.getUserId(), LikeStatusEnum.LIKE.getCode()); ? ? ? ? ? ? // 記錄+1 ? ? ? ? ? ? postRedisService.incrementLikedCount(vo.getRecordId()); ? ? ? ? }else if("0".equals(vo.getStatus())){ ? ? ? ? ? ? // 取消點(diǎn)贊 更新狀態(tài) ? ? ? ? ? ? postRedisService.saveLikeRedis(vo.getRecordId(),vo.getUserId(), LikeStatusEnum.UNLIKE.getCode()); // ? ? ? ? ? ?postRedisService.deleteLikeFromRedis(vo.getRecordId(),vo.getUserId()); ? ? ? ? ? ? // 記錄 -1 ? ? ? ? ? ? postRedisService.decrementLikeCount(vo.getRecordId()); ? ? ? ? } ? ? ? ? return Result.success(ResponseMessage.SUCCESS); ? ? }
最后定時(shí)將redis 中的數(shù)據(jù)同步到數(shù)據(jù)庫(kù)
?/**每 5 分鐘執(zhí)行一次 ? ? ?* 將點(diǎn)贊人員同步到庫(kù)中 ? ? ?* */ // ? ?@Transactional(rollbackFor =Exception.class) ? ? @Scheduled(cron = "0 */5 * * * ?") ? ? public void transLikdedFromRedis()throws IOException{ ? ? ? ? List<RedisLikedUserDTO> dtoList = getLikedUserFromRedis(); ? ? ? ? dtoList.stream().forEach(x->{ ? ? ? ? ? ? // 通過記錄及人員id 查詢 該 人員是否點(diǎn)贊 ? ? ? ? ? ? LambdaQueryWrapper<WorkCircleRecord> queryWrapper = new LambdaQueryWrapper<>(); ? ? ? ? ? ? queryWrapper.eq(WorkCircleRecord::getDeleteIf,true); ? ? ? ? ? ? queryWrapper.eq(WorkCircleRecord::getId,x.getRecordId()); ? ? ? ? ? ? queryWrapper.like(WorkCircleRecord::getWorkKudosUserIds,x.getUserId()); ? ? ? ? ? ? WorkCircleRecord record = workCircleRecordMapper.selectOne(queryWrapper); ? ? ? ? ? ? // 點(diǎn)贊 ? ? ? ? ? ? if(record == null&&"1".equals(x.getStatus())){ ? ? ? ? ? ? ? ? // 根據(jù)記錄id ?查詢 ? ? ? ? ? ? ? ? LambdaQueryWrapper<WorkCircleRecord> wrapper = new LambdaQueryWrapper<>(); ? ? ? ? ? ? ? ? wrapper.eq(WorkCircleRecord::getDeleteIf,true); ? ? ? ? ? ? ? ? wrapper.eq(WorkCircleRecord::getId,x.getRecordId()); ? ? ? ? ? ? ? ? WorkCircleRecord workCircleRecord = workCircleRecordMapper.selectOne(wrapper); ? ? ? ? ? ? ? ? if(workCircleRecord != null){ ? ? ? ? ? ? ? ? ? ? // 沒有此人員 添加 ? ? ? ? ? ? ? ? ? ? if(StringUtils.isBlank(workCircleRecord.getWorkKudosUserIds())){ ? ? ? ? ? ? ? ? ? ? ? ? // 沒有點(diǎn)贊人員 ? ? ? ? ? ? ? ? ? ? ? ? workCircleRecord.setWorkKudosUserIds(x.getUserId()); ? ? ? ? ? ? ? ? ? ? ? ? SysUser user = sysUserMapper.selectById(x.getUserId()); ? ? ? ? ? ? ? ? ? ? ? ? if(user !=null){ ? ? ? ? ? ? ? ? ? ? ? ? ? ? workCircleRecord.setWorkKudosUser(user.getRealname()); ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? }else { ? ? ? ? ? ? ? ? ? ? ? ? // 有點(diǎn)贊人員 ? ? ? ? ? ? ? ? ? ? ? ? String userIds = x.getUserId()+","+workCircleRecord.getWorkKudosUserIds(); ? ? ? ? ? ? ? ? ? ? ? ? workCircleRecord.setWorkKudosUserIds(userIds); ? ? ? ? ? ? ? ? ? ? ? ? SysUser user = sysUserMapper.selectById(x.getUserId()); ? ? ? ? ? ? ? ? ? ? ? ? String userNames = user.getRealname()+workCircleRecord.getWorkKudosUser(); ? ? ? ? ? ? ? ? ? ? ? ? workCircleRecord.setWorkKudosUser(userNames); ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? workCircleRecordMapper.updateById(workCircleRecord); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? }else if("0".equals(x.getStatus())) { ? ? ? ? ? ? ? ? // 有記錄 并取消點(diǎn)贊 ? ? ? ? ? ? ? ? // 根據(jù)記錄id ?查詢 ? ? ? ? ? ? ? ? LambdaQueryWrapper<WorkCircleRecord> wrapper = new LambdaQueryWrapper<>(); ? ? ? ? ? ? ? ? wrapper.eq(WorkCircleRecord::getDeleteIf,true); ? ? ? ? ? ? ? ? wrapper.eq(WorkCircleRecord::getId,x.getRecordId()); ? ? ? ? ? ? ? ? WorkCircleRecord workCircleRecord = workCircleRecordMapper.selectOne(wrapper); ? ? ? ? ? ? ? ? // 將此點(diǎn)贊人員去除 ? ? ? ? ? ? ? ? if(workCircleRecord !=null){ ? ? ? ? ? ? ? ? ? ? SysUser user = sysUserMapper.selectById(x.getUserId()); ? ? ? ? ? ? ? ? ? ? List<String> userIds = Arrays.asList(workCircleRecord.getWorkKudosUserIds().split(",")); ? ? ? ? ? ? ? ? ? ? List<String> userNames =Arrays.asList(workCircleRecord.getWorkKudosUser().split(",")); ? ? ? ? ? ? ? ? ? ? userIds.remove(x.getUserId()); ? ? ? ? ? ? ? ? ? ? userNames.remove(user.getRealname()); ? ? ? ? ? ? ? ? ? ? workCircleRecord.setWorkKudosUserIds(String.join(",",userIds)); ? ? ? ? ? ? ? ? ? ? workCircleRecord.setWorkKudosUser(String.join(",",userNames)); ? ? ? ? ? ? ? ? ? ? workCircleRecordMapper.updateById(workCircleRecord); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? }); ? ? }
/**獲取 所有點(diǎn)贊的人員 ? ? ?* */ ? ? public List<RedisLikedUserDTO> getLikedUserFromRedis() throws IOException{ ? ? ? ? List<RedisLikedUserDTO> dtoList = new ArrayList<>(); ? ? ? ? // 通過游標(biāo)獲取所有鍵值對(duì) ? ? ? ? Cursor<Map.Entry<Object,Object>> cursor = redisTemplate.opsForHash().scan(RedisHashEnum.MAP_USER_LIKED.getValue(),ScanOptions.NONE); ? ? ? ? while (cursor.hasNext()){ ? ? ? ? ? ? Map.Entry<Object,Object> map = cursor.next(); ? ? ? ? ? ? String key = map.getKey().toString(); ? ? ? ? ? ? String[] split = key.split("::"); ? ? ? ? ? ? RedisLikedUserDTO dto = new RedisLikedUserDTO(); ? ? ? ? ? ? dto.setRecordId(split[0]); ? ? ? ? ? ? dto.setUserId(split[1]); ? ? ? ? ? ? dto.setStatus(Integer.parseInt(map.getValue().toString())); ? ? ? ? ? ? dtoList.add(dto); ? ? ? ? ? ? // 將redis 中的記錄刪除 ? ? ? ? ? ? redisTemplate.opsForHash().delete(RedisHashEnum.MAP_USER_LIKED.getValue(),key); ? ? ? ? } ? ? ? ? cursor.close(); ? ? ? ? return dtoList; ? ? }
/**每 5 分鐘執(zhí)行一次 ? ? ?* 將點(diǎn)贊數(shù)同步到庫(kù)中 ? ? ?* */ ? ? @Transactional(rollbackFor =Exception.class) ? ? @Scheduled(cron = "0 */5 * * * ?") ? ? public void transLikedCountFromRedis() throws IOException{ ? ? ? ? // 獲取所有的點(diǎn)贊數(shù) ? ? ? ? List<RedisLikeCountDTO> dtoList = getLikedCountFromRedis(); ? ? ? ? // 獲取所有的記錄id ? ? ? ? List<String> recordIdList = dtoList.stream().map(x->x.getRecordId()).collect(Collectors.toList()); ? ? ? ? if(CollectionUtils.isNotEmpty(recordIdList)){ ? ? ? ? ? ? List<WorkCircleRecord> recordList = workCircleRecordMapper.selectBatchIds(recordIdList); ? ? ? ? ? ? if(CollectionUtils.isNotEmpty(recordList)){ ? ? ? ? ? ? ? ? // 通過id 匹配 ? ? ? ? ? ? ? ? dtoList.stream().forEach(x->{ ? ? ? ? ? ? ? ? ? ? recordList.stream().forEach(k->{ ? ? ? ? ? ? ? ? ? ? ? ? if(x.getRecordId().equals(k.getId())){ ? ? ? ? ? ? ? ? ? ? ? ? ? ? Integer num = x.getCount()+k.getWorkKudos(); ? ? ? ? ? ? ? ? ? ? ? ? ? ? if(num<0){ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? k.setWorkKudos(0); ? ? ? ? ? ? ? ? ? ? ? ? ? ? }else { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? k.setWorkKudos(num); ? ? ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? ? ? ? ? workCircleRecordMapper.updateById(k); ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? }); ? ? ? ? ? ? ? ? }); ? ? ? ? ? ? } ? ? ? ? } ? ? }
/** 取出所有的點(diǎn)贊數(shù) ? ? ?* */ ? ? public List<RedisLikeCountDTO> getLikedCountFromRedis() throws IOException { ? ? ? ? List<RedisLikeCountDTO> dtoList = new ArrayList<>(); ? ? ? ? Cursor<Map.Entry<Object,Object>> cursor= ?redisTemplate.opsForHash().scan(RedisHashEnum.MAP_USER_LIKED_COUNT, ScanOptions.NONE); ? ? ? ? while (cursor.hasNext()){ ? ? ? ? ? ? Map.Entry<Object,Object> map = cursor.next(); ? ? ? ? ? ? // 獲取 點(diǎn)贊數(shù) ? ? ? ? ? ? String key = map.getKey().toString(); ? ? ? ? ? ? RedisLikeCountDTO dto = new RedisLikeCountDTO(); ? ? ? ? ? ? dto.setRecordId(key); ? ? ? ? ? ? dto.setCount(Integer.parseInt(map.getValue().toString())); ? ? ? ? ? ? dtoList.add(dto); ? ? ? ? ? ? redisTemplate.opsForHash().delete(RedisHashEnum.MAP_USER_LIKED_COUNT,key); ? ? ? ? } ? ? ? ? cursor.close(); ? ? ? ? return dtoList; ? ? }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Java中數(shù)組復(fù)制的三種方式小結(jié)
在Java中,數(shù)組復(fù)制是一種常見的操作,它允許開發(fā)人員在不修改原始數(shù)組的情況下創(chuàng)建一個(gè)新的數(shù)組,本文就來介紹三種方法,具有一定的參考價(jià)值,感興趣的可以了解一下2024-02-02spring boot+vue 的前后端分離與合并方案實(shí)例詳解
這篇文章主要介紹了spring boot+vue 的前后端分離與合并方案實(shí)例詳解,需要的朋友可以參考下2017-11-11Java網(wǎng)絡(luò)編程教程之設(shè)置請(qǐng)求超時(shí)的方法
這篇文章主要給大家介紹了關(guān)于Java網(wǎng)絡(luò)編程教程之設(shè)置請(qǐng)求超時(shí)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-12-12Springboot實(shí)現(xiàn)異步任務(wù)線程池代碼實(shí)例
這篇文章主要介紹了Springboot實(shí)現(xiàn)異步任務(wù)線程池代碼實(shí)例,異步任務(wù)線程池是一種用于處理異步任務(wù)的機(jī)制,它可以提高程序的并發(fā)性能和響應(yīng)速度,通過將任務(wù)提交給線程池,線程池會(huì)自動(dòng)管理線程的創(chuàng)建和銷毀,從而避免了頻繁創(chuàng)建和銷毀線程的開銷,需要的朋友可以參考下2023-10-10通過實(shí)例學(xué)習(xí)JAVA對(duì)象轉(zhuǎn)成XML輸出
這篇文章主要介紹了通過實(shí)例學(xué)習(xí)JAVA對(duì)象轉(zhuǎn)成XML輸出,做流程圖的項(xiàng)目時(shí),新的流程定義為xml的,需要對(duì)xml與java對(duì)象進(jìn)行互轉(zhuǎn),下面我們來深入學(xué)習(xí),需要的朋友可以參考下2019-06-06Springboot集成Elasticsearch的步驟與相關(guān)功能
ElasticSearch是開源搜索平臺(tái)領(lǐng)域的一個(gè)新成員,?ElasticSearch是一個(gè)基于Lucene構(gòu)建的開源,分布式,RESTful搜索引擎,這篇文章主要給大家介紹了關(guān)于Springboot集成Elasticsearch的相關(guān)資料,需要的朋友可以參考下2021-12-12Mybatis實(shí)體類對(duì)象入?yún)⒉樵兊墓P記
這篇文章主要介紹了Mybatis實(shí)體類對(duì)象入?yún)⒉樵兊墓P記,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06SSM框架整合之Spring+SpringMVC+MyBatis實(shí)踐步驟
大家都知道Spring是一個(gè)輕量級(jí)的控制反轉(zhuǎn)(IoC)和面向切面(AOP)的容器框架,本文主要介紹三大框架的整合包含spring和mybatis的配置文件,還有spring-mvc的配置文件的詳細(xì)介紹,通過項(xiàng)目實(shí)踐步驟給大家詳細(xì)介紹,感興趣的朋友一起看看吧2021-06-06最新jsonwebtoken-jwt 0.12.3 基本使用小結(jié)
這篇文章主要介紹了最新jsonwebtoken-jwt 0.12.3 基本使用小結(jié),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-12-12