亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

SpringBoot實現(xiàn)物品點贊功能

 更新時間:2021年04月28日 11:07:36   作者:古墓派學(xué)子  
這篇文章主要介紹了SpringBoot物品點贊功能實現(xiàn),本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

前后端分離項目–二手交易平臺小程序

SpringBoot----物品收藏功能實現(xiàn)
SpringBoot----評論回復(fù)功能實現(xiàn)(數(shù)據(jù)庫設(shè)計)
SpringBoot----文件(圖片)上傳與顯示(下載)

點贊

這個功能耗費了我挺多時間,簡單實現(xiàn)很簡單,就++ – .但是還是感覺這種點贊是一個高頻率的請求,而且搜的時候我看都是使用redis做緩存。b站也搜到一個視頻來著,也是一樣的。

效果:

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

功能:

首先還是一個先發(fā)請求返回數(shù)據(jù),但是先數(shù)據(jù)存到了redis中,然后使用springboot定時任務(wù)每隔一定時間將數(shù)據(jù)存到mysql中。這樣可以防止redis掛掉之后數(shù)據(jù)丟失。

數(shù)據(jù)庫設(shè)計:

在這里插入圖片描述

MySQL使用了一張表和另外幾張表的一個字段,一張存放點贊信息,就是誰點贊了誰在啥時候。字段存放點贊數(shù)量。就是物品信息表。評論表這些。
-

在這里插入圖片描述

redis,使用的是hash數(shù)據(jù)結(jié)構(gòu),redis_liked存放點贊數(shù)據(jù),redis_liked_count存放點贊數(shù)量數(shù)據(jù)。

解釋 :

對于 “1::字符串::1 ” 這個是一種存放方式,前面1為objid就是被點贊物品或者評論id,字符串為微信openid每個用戶唯一id,后面1為類型區(qū)分點贊的是物品還是主評論,子評論。

對于 "\"0\"" 這個數(shù)據(jù)則是點贊的狀態(tài),1為點贊0為取消點贊對于"1::1"這個前面1是objid就是物品或者子、主評論id,后面則是區(qū)別是哪個類型。“0”就是點贊數(shù)量。

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述 

后臺代碼:

前端就發(fā)like或者取消unlike請求

package com.w.wx.controller;

import com.w.wx.domain.Msg;
import com.w.wx.service.impls.RedisServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RestController
@RequestMapping("/wx/liked")
public class LikedContro {

    @Autowired
    private RedisServiceImpl redisService;

    /**
     * 保存點贊數(shù)據(jù)到redis
     * 點贊數(shù)+1
     * 同一個不能點贊兩次
     * @param objId
     * @param openid
     * @param type
     * @return
     */
    @RequestMapping("like")
    public Msg saveLikedToRedis(Integer objId,String openid , String type){

        redisService.incrementLikedCount(objId, type, openid);

        redisService.saveLikedToRedis(objId,openid,type);

        int oneInfoCount = redisService.getOneInfoCount(objId, type);
        return Msg.success().add("count",oneInfoCount);
    }

    @RequestMapping("unlike")
    public  Msg decrementLikedCount(Integer objId,String openid,String type){
        redisService.decrementLikedCount(objId,type,openid);
        redisService.unlikeFromRedis(objId,openid,type);

        int oneInfoCount = redisService.getOneInfoCount(objId, type);
        return Msg.success().add("count",oneInfoCount);
    }
	
	//恢復(fù)redis
    @RequestMapping("restore")
    public Msg restoreRedisCountInfo(){
        redisService.savaInfoFromDb2Re(0);
        redisService.savaInfoFromDb2Re(1);
        redisService.savaInfoFromDb2Re(2);
        return Msg.success();
    }
}

操作redis代碼

package com.w.wx.service.impls;

import com.w.wx.mapper.LikedMapper;
import com.w.wx.domain.Liked;
import com.w.wx.service.ImagesService;
import com.w.wx.service.RedisService;
import com.w.wx.utils.RedisKeyUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class RedisServiceImpl implements RedisService {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private LikedServiceImpl likedService;
    @Autowired
    private ImagesService imagesService;

    /**
     * 保存數(shù)據(jù)到redis
     * @param objId
     * @param openid
     * @param type
     */
    @Override
    public void saveLikedToRedis(Integer objId, String openid,String type) {

        imagesService.addLikedNotice(objId, openid,type);
        String likedKey = RedisKeyUtils.getLikedKey("" + objId, openid,type);
        redisTemplate.opsForHash().put(RedisKeyUtils.MAP_KEY_USER_LIKED,likedKey, "1");
    }

    /**
     * 取消點贊
     * @param objId
     * @param openid
     * @param type
     */
    @Override
    public void unlikeFromRedis(Integer objId, String openid,String type) {
        String likedKey = RedisKeyUtils.getLikedKey("" + objId, openid,type);
        redisTemplate.opsForHash().put(RedisKeyUtils.MAP_KEY_USER_LIKED,likedKey, "0");
    }

    /**
     * 刪除數(shù)據(jù),沒有用到
     * @param objId
     * @param openid
     * @param type
     */
    @Override
    public void deleteFromRedis(Integer objId, String openid,String type) {
        String key = RedisKeyUtils.getLikedKey("" + objId, openid,type);
        redisTemplate.opsForHash().delete(RedisKeyUtils.MAP_KEY_USER_LIKED, key);
    }

    /**
     * 自增,點贊數(shù)++
     * @param objId
     * @param type
     * @param openid
     * @return
     */
    @Override
    public Long incrementLikedCount(Integer objId,String type, String openid) {
        String key = RedisKeyUtils.getLikedKey("" + objId,type);
        String likedKey = RedisKeyUtils.getLikedKey("" + objId, openid,type);
        //根據(jù)定時器時長有延遲
//        if(likedMapper.selectByObjIdAndOpenid(objId,openid,Integer.valueOf(type)).getLikeStatus()==0){
//            redisTemplate.opsForHash().increment(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT, key, 1);
//        }

        //防止重復(fù)點贊
        if("0".equals(redisTemplate.opsForHash().get(RedisKeyUtils.MAP_KEY_USER_LIKED,likedKey))
                || redisTemplate.opsForHash().get(RedisKeyUtils.MAP_KEY_USER_LIKED,likedKey) == null){

           return redisTemplate.opsForHash().increment(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT, key, 1);
        }

        return null;
    }

    @Override
    public void decrementLikedCount(Integer objId,String type, String openid) {
        String key = RedisKeyUtils.getLikedKey("" + objId,type);
        String likedKey = RedisKeyUtils.getLikedKey("" + objId, openid,type);
//        if(likedMapper.selectByObjIdAndOpenid(objId,openid,Integer.valueOf(type)).getLikeStatus()==1){
//            redisTemplate.opsForHash().increment(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT, key, -1);
//        }

        if("1".equals(redisTemplate.opsForHash().get(RedisKeyUtils.MAP_KEY_USER_LIKED,likedKey))){
            redisTemplate.opsForHash().increment(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT, key, -1);
        }
    }

    /**
     * 獲取redis中存放的點贊數(shù)據(jù)然后存放到mysql做持久化
     * @return
     */
    @Override
    public List<Liked> getLikedDataFromRedis() {
        Cursor<Map.Entry<Object, Object>> cursor = redisTemplate.opsForHash().scan(RedisKeyUtils.MAP_KEY_USER_LIKED, ScanOptions.NONE);
        List<Liked> list = new ArrayList<>();
        while (cursor.hasNext()){
            Map.Entry<Object, Object> entry = cursor.next();
            String key = (String) entry.getKey();

            String[] split = key.split("::");
            int status =  Integer.parseInt((String) entry.getValue());


            Liked like = new Liked();
            like.setObjId(Integer.valueOf(split[0]));
            like.setUserOpenid(split[1]);
            like.setType(Integer.valueOf(split[2]));
            like.setLikeStatus(status);

            list.add(like);

            //存到 list 后從 Redis 中刪除
           // redisTemplate.opsForHash().delete(RedisKeyUtils.MAP_KEY_USER_LIKED, key);
        }

        return list;
    }

    //獲取redis中點贊數(shù)量
    @Override
    public Cursor<Map.Entry<Object, Object>> getLikedCountFromRedis() {
        Cursor<Map.Entry<Object, Object>> cursor = redisTemplate.opsForHash().scan(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT, ScanOptions.NONE);
        //redisTemplate.opsForHash().delete(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT);
        return cursor;
    }

    @Override
    public int getOneInfoCount(Integer objId, String type) {
        String key = RedisKeyUtils.getLikedKey("" + objId,type);
        return (int)redisTemplate.opsForHash().get(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT,key);
    }

    public void saveCountInfo(Integer objId,Integer type,Integer count){
        String key = RedisKeyUtils.getLikedKey("" + objId,""+type);
        redisTemplate.opsForHash().put(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT,key,count);
    }

    //redis掛掉后通過mysql中數(shù)據(jù)恢復(fù)redis
    @Override
    public void savaInfoFromDb2Re(Integer type) {
        List<Map<String,Object>> likeds = likedService.selectLikedInfoByType(type);
        if (likeds.isEmpty()||likeds.equals("")){
            return;
        }

        Iterator<Map<String,Object>> it = likeds.listIterator();
        while(it.hasNext()){
            Map<String,Object> map = it.next();
            Integer objId =  (Integer) map.get("objId");
            Integer count =  Integer.parseInt(map.get("num_liked").toString());
            log.info("objId:"+objId+"count:"+count+"type:"+type);
            saveCountInfo(objId,type,count);
        }
    }
}

操作mysql代碼

package com.w.wx.service.impls;

import com.w.wx.mapper.CommentsInfoMapper;
import com.w.wx.mapper.CommentsReplyMapper;
import com.w.wx.mapper.GoodsMapper;
import com.w.wx.mapper.LikedMapper;
import com.w.wx.domain.CommentsInfo;
import com.w.wx.domain.Liked;
import com.w.wx.service.LikedService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.Cursor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.util.*;

@Service
@Slf4j

public class LikedServiceImpl implements LikedService {

    @Autowired
    private RedisServiceImpl redisService;
    @Autowired
    private LikedMapper likedMapper;
    @Autowired
    private CommentsInfoMapper commentsInfoMapper;
    @Autowired
    private CommentsReplyMapper commentsReplyMapper;
    @Autowired
    private GoodsMapper goodsMapper;

    /**
     * 將緩存中點贊記錄持久化到數(shù)據(jù)庫
     */
    @Override
    @Transactional
    public void transLikedFromRedisToDB() {
        List<Liked> likeds = redisService.getLikedDataFromRedis();

        for (Liked like : likeds) {
            Date date = new Date();
            Timestamp timestamp = new Timestamp(date.getTime());
            //首先判斷之前是否有
            Liked liked = likedMapper.selectByObjIdAndOpenid(like.getObjId(),like.getUserOpenid(),like.getType());
            if(liked==null ){
                //沒有則新增
                like.setCreateTime(timestamp);
                likedMapper.insert(like);
            }else{
                //有則更新
                 likedMapper.updateByPrimaryKey(liked.getLikeId(),like.getLikeStatus(),timestamp);
            }
        }
    }

    /**
     * 將點贊數(shù)量持久化到數(shù)據(jù)庫
     */
    @Override
    @Transactional
    public void transLikedCountFromRedisToDB() {
        Cursor<Map.Entry<Object, Object>> cursor = redisService.getLikedCountFromRedis();
        while (cursor.hasNext()){
            Map.Entry<Object, Object> map = cursor.next();
            String key = (String)map.getKey();
            //分離出objId和type
            String[] split = key.split("::");
            int type =Integer.parseInt(split[1]);
            int objId = Integer.parseInt(split[0]);
            int likeNum = (Integer) map.getValue();
            if ( type == 1){
                //為主評論
                commentsInfoMapper.updateByPrimaryKey(objId,likeNum);

            }else if(type == 2){
                //為子評論
                commentsReplyMapper.updateByPrimaryKey(objId,likeNum);
            }else{
                //為物品
                goodsMapper.updateGoodsLikeSum(objId,likeNum);
            }
        }
    }

    @Override
    public List<Map<String,Object>> selectLikedInfoByType(Integer type) {
        return likedMapper.selectLikedInfoByType(type);
    }
}

工具類

package com.w.wx.utils;

public class RedisKeyUtils {
    //保存用戶點贊數(shù)據(jù)的key
    public static final String MAP_KEY_USER_LIKED = "redis_liked";
    //保存用戶被點贊數(shù)量的key
    public static final String MAP_KEY_USER_LIKED_COUNT = "redis_liked_count";

    /**
     * 拼接被點贊的用戶id和點贊的人的id作為key。格式 222222::333333::1
     * @param likedUserId 被點贊的人id
     * @param likedPostId 點贊的人的id
     * @return
     */
    public static String getLikedKey(String likedUserId, String likedPostId,String type){
        StringBuilder builder = new StringBuilder();
        builder.append(likedUserId);
        builder.append("::");
        builder.append(likedPostId);
        builder.append("::");
        builder.append(type);
        return builder.toString();
    }

    public static String getLikedKey(String likedUserId,String type){
        StringBuilder builder = new StringBuilder();
        builder.append(likedUserId);
        builder.append("::");
        builder.append(type);
        return builder.toString();
    }

}

定時任務(wù)配置類

package com.w.wx.config;

import com.w.wx.utils.LikeTask;
import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
public class QuartzConfig {
    private static final String LIKE_TASK_IDENTITY = "LikeTaskQuartz";

    @Bean
    public JobDetail quartzDetail(){
        return JobBuilder.newJob(LikeTask.class).withIdentity(LIKE_TASK_IDENTITY).storeDurably().build();
    }

    @Bean
    public Trigger quartzTrigger(){
        SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
//                .withIntervalInSeconds(5)  //設(shè)置時間周期單位秒
                .withIntervalInHours(2)  //兩個小時執(zhí)行一次
                .repeatForever();
        return TriggerBuilder.newTrigger().forJob(quartzDetail())
                .withIdentity(LIKE_TASK_IDENTITY)
                .withSchedule(scheduleBuilder)
                .build();
    }
}

定時任務(wù)工具類

package com.w.wx.utils;

import com.w.wx.service.LikedService;
import com.w.wx.service.impls.LikedServiceImpl;
import lombok.extern.slf4j.Slf4j;

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;

import java.text.SimpleDateFormat;
import java.util.Date;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class LikeTask extends QuartzJobBean {
    @Autowired
    LikedServiceImpl likedService;

    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {

        log.info("LikeTask-------- {}", sdf.format(new Date()));

        //將 Redis 里的點贊信息同步到數(shù)據(jù)庫里
        likedService.transLikedFromRedisToDB();
        likedService.transLikedCountFromRedisToDB();

    }
}

參考:

springboot如何實現(xiàn)點贊功能
點贊功能的實現(xiàn)及Springboot定時器的應(yīng)用

還有好多,第一頁搜出來的基本都看過,第一次搞真心不會。。。
f12去看看csdn點贊,會發(fā)現(xiàn)點文章的贊會有點贊量的返回。點評論的贊就沒

在這里插入圖片描述
在這里插入圖片描述

嗶哩嗶哩就看不懂了?。?!

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

到此這篇關(guān)于SpringBoot物品點贊功能實現(xiàn)的文章就介紹到這了,更多相關(guān)SpringBoot點贊內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java中addMouseListener()方法的使用

    java中addMouseListener()方法的使用

    這篇文章主要介紹了java中addMouseListener()方法的使用,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • java 多態(tài)與抽象類詳解總結(jié)

    java 多態(tài)與抽象類詳解總結(jié)

    在面向?qū)ο蟮母拍钪?,所有的對象都是通過類來描繪的,但是反過來,并不是所有的類都是用來描繪對象的,如果一個類中沒有包含足夠的信息來描繪一個具體的對象,這樣的類就是抽象類,而多態(tài)是同一個行為具有多個不同表現(xiàn)形式或形態(tài)的能力
    2021-11-11
  • 在Java Spring框架中使用的設(shè)計模式有哪些

    在Java Spring框架中使用的設(shè)計模式有哪些

    面試中常會被問道Spring框架使用了哪些設(shè)計模式?關(guān)于這個問題本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-09-09
  • Java實現(xiàn)簡單的郵件發(fā)送功能

    Java實現(xiàn)簡單的郵件發(fā)送功能

    這篇文章主要為大家詳細(xì)介紹了Java實現(xiàn)簡單的郵件發(fā)送功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • Java將數(shù)字金額轉(zhuǎn)為大寫中文金額

    Java將數(shù)字金額轉(zhuǎn)為大寫中文金額

    這篇文章主要為大家詳細(xì)介紹了Java將數(shù)字金額轉(zhuǎn)為大寫中文金額,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-08-08
  • Java Listener監(jiān)聽器使用規(guī)范詳細(xì)介紹

    Java Listener監(jiān)聽器使用規(guī)范詳細(xì)介紹

    監(jiān)聽器是一個專門用于對其他對象身上發(fā)生的事件或狀態(tài)改變進行監(jiān)聽和相應(yīng)處理的對象,當(dāng)被監(jiān)視的對象發(fā)生情況時,立即采取相應(yīng)的行動。監(jiān)聽器其實就是一個實現(xiàn)特定接口的普通java程序,這個程序?qū)iT用于監(jiān)聽另一個java對象的方法調(diào)用或?qū)傩愿淖?/div> 2023-01-01
  • 淺談Java BitSet使用場景和代碼示例

    淺談Java BitSet使用場景和代碼示例

    這篇文章主要介紹了淺談Java BitSet使用場景和代碼示例,具有一定借鑒價值,需要的朋友可以參考下。
    2017-12-12
  • Spring的@Conditional詳解

    Spring的@Conditional詳解

    這篇文章主要介紹了Spring的@Conditional詳解,給想要注入Bean增加限制條件,只有滿足限制條件才會被構(gòu)造并注入到Spring的IOC容器中,通常和@Bean注解一起使用,需要的朋友可以參考下
    2024-01-01
  • Java的NIO之并發(fā)環(huán)境下非阻塞IO技術(shù)詳解

    Java的NIO之并發(fā)環(huán)境下非阻塞IO技術(shù)詳解

    這篇文章主要介紹了Java的NIO之并發(fā)環(huán)境下非阻塞IO技術(shù)詳解,Java NIO(New IO)是Java平臺提供的一種用于高效處理I/O操作的API,它引入了一組新的類和概念,以提供更好的性能和可擴展性,需要的朋友可以參考下
    2023-09-09
  • 在Eclipse IDE使用Gradle構(gòu)建應(yīng)用程序(圖文)

    在Eclipse IDE使用Gradle構(gòu)建應(yīng)用程序(圖文)

    這篇文章主要介紹了在Eclipse IDE使用Gradle構(gòu)建應(yīng)用程序(圖文),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-12-12

最新評論