java實現(xiàn)點贊功能
本文實例為大家分享了java實現(xiàn)點贊功能的具體代碼,供大家參考,具體內(nèi)容如下
實現(xiàn)思路:
將點贊的數(shù)據(jù)先保存到redis中,然后定時同步到數(shù)據(jù)庫
第一步:
在redis中創(chuàng)建二個hash 用于存儲 用戶點贊記錄及記錄點贊數(shù)
MAP_USER_LIKED :用戶點贊的記錄 key:記錄id::用戶id value:1
MAP_USER_LIKED_COUNT:記錄點贊數(shù) key: 記錄id value:數(shù)量



第二步:
創(chuàng)建枚舉類
@Getter
public enum LikeStatusEnum {
? ? LIKE(1,"點贊"),
? ? UNLIKE(0,"取消點贊/未點贊");
? ? 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;
? ? }
}第三步:
將實現(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;
? ? }
? ? /**
? ? ?* 點贊、取消點贊
? ? ?*
? ? ?* @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中刪除一條點贊數(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);
? ? }
? ? /**
? ? ?* 該記錄 點贊加1
? ? ?*
? ? ?* @param recordId
? ? ?*/
? ? @Override
? ? public void incrementLikedCount(String recordId) {
? ? ? ? redisTemplate.opsForHash().increment(RedisHashEnum.MAP_USER_LIKED_COUNT,recordId,1);
? ? }
? ? /**
? ? ?* 譔記錄 點贊減1
? ? ?*
? ? ?* @param recordId
? ? ?*/
? ? @Override
? ? public void decrementLikeCount(String recordId) {
? ? ? ? redisTemplate.opsForHash().increment(RedisHashEnum.MAP_USER_LIKED_COUNT,recordId,-1);
? ? }
}第四步提供接口:
?/**
? ? ?* 進行點贊、取消點贊
? ? ?*
? ? ?* @param vo
? ? ?*/
? ? @Override
? ? public Result addKudos(KudosVo vo) {
? ? ? ? if(vo == null){
? ? ? ? ? ? return Result.error(ResponseMessage.PARAMERROR);
? ? ? ? }
? ? ? ? if("1".equals(vo.getStatus())){
? ? ? ? ? ? // 點贊
? ? ? ? ? ? postRedisService.saveLikeRedis(vo.getRecordId(),vo.getUserId(), LikeStatusEnum.LIKE.getCode());
? ? ? ? ? ? // 記錄+1
? ? ? ? ? ? postRedisService.incrementLikedCount(vo.getRecordId());
? ? ? ? }else if("0".equals(vo.getStatus())){
? ? ? ? ? ? // 取消點贊 更新狀態(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);
? ? }最后定時將redis 中的數(shù)據(jù)同步到數(shù)據(jù)庫
?/**每 5 分鐘執(zhí)行一次
? ? ?* 將點贊人員同步到庫中
? ? ?* */
// ? ?@Transactional(rollbackFor =Exception.class)
? ? @Scheduled(cron = "0 */5 * * * ?")
? ? public void transLikdedFromRedis()throws IOException{
? ? ? ? List<RedisLikedUserDTO> dtoList = getLikedUserFromRedis();
? ? ? ? dtoList.stream().forEach(x->{
? ? ? ? ? ? // 通過記錄及人員id 查詢 該 人員是否點贊
? ? ? ? ? ? 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);
? ? ? ? ? ? // 點贊
? ? ? ? ? ? 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())){
? ? ? ? ? ? ? ? ? ? ? ? // 沒有點贊人員
? ? ? ? ? ? ? ? ? ? ? ? workCircleRecord.setWorkKudosUserIds(x.getUserId());
? ? ? ? ? ? ? ? ? ? ? ? SysUser user = sysUserMapper.selectById(x.getUserId());
? ? ? ? ? ? ? ? ? ? ? ? if(user !=null){
? ? ? ? ? ? ? ? ? ? ? ? ? ? workCircleRecord.setWorkKudosUser(user.getRealname());
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? }else {
? ? ? ? ? ? ? ? ? ? ? ? // 有點贊人員
? ? ? ? ? ? ? ? ? ? ? ? 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())) {
? ? ? ? ? ? ? ? // 有記錄 并取消點贊
? ? ? ? ? ? ? ? // 根據(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){
? ? ? ? ? ? ? ? ? ? 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);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? });
? ? }/**獲取 所有點贊的人員
? ? ?* */
? ? public List<RedisLikedUserDTO> getLikedUserFromRedis() throws IOException{
? ? ? ? List<RedisLikedUserDTO> dtoList = new ArrayList<>();
? ? ? ? // 通過游標獲取所有鍵值對
? ? ? ? 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í)行一次
? ? ?* 將點贊數(shù)同步到庫中
? ? ?* */
? ? @Transactional(rollbackFor =Exception.class)
? ? @Scheduled(cron = "0 */5 * * * ?")
? ? public void transLikedCountFromRedis() throws IOException{
? ? ? ? // 獲取所有的點贊數(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);
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? });
? ? ? ? ? ? ? ? });
? ? ? ? ? ? }
? ? ? ? }
? ? }/** 取出所有的點贊數(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();
? ? ? ? ? ? // 獲取 點贊數(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;
? ? }以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
詳解關(guān)于mybatis-plus中Service和Mapper的分析
這篇文章主要介紹了詳解關(guān)于mybatis-plus中Service和Mapper的分析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09
Java創(chuàng)建多線程局域網(wǎng)聊天室實例
這篇文章主要介紹了Java創(chuàng)建多線程局域網(wǎng)聊天室實例,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下2021-07-07
java控制臺實現(xiàn)學(xué)生信息管理系統(tǒng)
這篇文章主要為大家詳細介紹了java控制臺實現(xiàn)學(xué)生信息管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-02-02
詳解SpringBoot集成Redis來實現(xiàn)緩存技術(shù)方案
本篇文章主要介紹了詳解SpringBoot集成Redis來實現(xiàn)緩存技術(shù)方案,具有一定的參考價值,有興趣的可以了解一下2017-06-06
Spring AOP方法內(nèi)部調(diào)用不生效的解決方案
最近有個需求,統(tǒng)計某個方法的調(diào)用次數(shù),開始使用 Spring AOP 實現(xiàn),后來發(fā)現(xiàn)當方法被內(nèi)部調(diào)用時,切面邏輯將不會生效,所以本文就給大家介紹了Spring AOP方法內(nèi)部調(diào)用不生效的解決方案,需要的朋友可以參考下2025-01-01
基于Java實現(xiàn)中文分詞系統(tǒng)的示例代碼
這篇文章主要為大家詳細介紹了如何利用Java語言實現(xiàn)一個簡易的中文分詞系統(tǒng),文中的示例代碼講解詳細,感興趣的小伙伴可以嘗試一下2022-07-07

