SpringBoot 아 이 템 좋아요 기능 구현

앞 뒤 분리 프로젝트 C 중고 거래 플랫폼 애플 릿
SpringBoot-물품 소장 기능 실현
SpringBoot----댓 글 답장 기능 실현(데이터베이스 디자인)
SpringBoot---파일(그림)업로드 및 표시(다운로드)
칭찬 하 다
이 기능 은 저 에 게 많은 시간 을 들 였 습 니 다.간단하게 실현 하 는 것 이 간단 합 니 다.바로+C 입 니 다.그런데 이런'좋아요'는 고주파 요청 이 라 고 생각 합 니 다.그리고 검색 할 때 저 는 redis 를 사용 하여 캐 시 를 하 는 것 같 습 니 다.b.역 에서 도 동 영상 이 나 왔 는데 똑 같 아 요.
효과:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
기능:
먼저 데 이 터 를 되 돌려 달라 고 요청 하지만,먼저 데 이 터 를 redis 에 저장 한 다음,spring boot 정시 작업 을 사용 하여 일정 시간 마다 데 이 터 를 my sql 에 저장 합 니 다.이렇게 하면 redis 가 끊 긴 후에 데이터 가 손실 되 는 것 을 방지 할 수 있다.
데이터베이스 디자인:
在这里插入图片描述
MySQL 은 표 한 장과 다른 표 몇 장의 필드 를 사 용 했 습 니 다.하 나 는 좋아요 메 시 지 를 저장 하 는 것 입 니 다.바로 누가 누 르 고 누가 언제 누 르 는 지 를 누 르 는 것 입 니 다.필드 에 좋아요 수 를 저장 합 니 다.물품 정보 표 입 니 다.댓 글 표 이런 거.
-
在这里插入图片描述
redis,hash 데이터 구 조 를 사용 합 니 다.redisliked 좋아요 데 이 터 를 저장,redisliked_count 는 좋아요 수 데 이 터 를 저장 합 니 다.
설명:“1:: ::1 ”이것 은 저장 방식 입 니 다.앞의 1 은 obid 가 바로'좋아요'아 이 템 이나 댓 글 id 입 니 다.문자열 은 위 챗 openid 모든 사용자 의 유일한 id 이 고 뒤의 1 은 유형 으로'좋아요'를 누 르 는 것 이 아 이 템 인지 메 인 댓 글 인지 구분 합 니 다."\"0\""이 데 이 터 는'좋아요'를 누 른 상태 이 고,1 은'좋아요'를 누 르 면'좋아요'를 취소 합 니 다."1::1"이 앞 에 있 는 1 은'obid'가 아 이 템 이나 서브,메 인 댓 글 id'이 고,뒤 에는 어떤 유형 이 차이 나 는 지 알 수 있 습 니 다.“0”바로 좋아요 수 입 니 다.
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述  
배경 코드:
전단 에 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;

    /**
     *        redis
     *    +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);
    }
	
	//  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;

    /**
     *      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");
    }

    /**
     *     ,    
     * @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);
    }

    /**
     *   ,   ++
     * @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);
        //          
//        if(likedMapper.selectByObjIdAndOpenid(objId,openid,Integer.valueOf(type)).getLikeStatus()==0){
//            redisTemplate.opsForHash().increment(RedisKeyUtils.MAP_KEY_USER_LIKED_COUNT, key, 1);
//        }

        //      
        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             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     
    @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     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;

    /**
     *                
     */
    @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);
            }
        }
    }

    /**
     *             
     */
    @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 {
    //         key
    public static final String MAP_KEY_USER_LIKED = "redis_liked";
    //          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();
    }

}
정시 작업 설정 클래스

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)  //         
                .withIntervalInHours(2)  //        
                .repeatForever();
        return TriggerBuilder.newTrigger().forJob(quartzDetail())
                .withIdentity(LIKE_TASK_IDENTITY)
                .withSchedule(scheduleBuilder)
                .build();
    }
}
정시 작업 도구 클래스

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              
        likedService.transLikedFromRedisToDB();
        likedService.transLikedCountFromRedisToDB();

    }
}
참고:
springboot 은 어떻게 좋아요 기능 을 실현 합 니까? 좋아요 기능 의 실현 및 Springboot 타이머 의 응용
그리고 많 습 니 다.첫 페이지 에서 찾 아 낸 것 은 거의 다 봤 습 니 다.처음으로 진심 을 다 하 는 것 은..........................................
f12 csdn 에 가서 좋아요 를 누 르 면 글 의 좋아요 가 약간 좋아요 로 돌아 오 는 것 을 발견 할 수 있 습 니 다.댓 글 좋아요 누 르 면 없어 요.
在这里插入图片描述
在这里插入图片描述
삐걱삐걱 하면 못 알 아 보 겠 어!!!
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
스프링 부 트 아 이 템 좋아요 기능 구현 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 관련 스프링 부 트 좋아요 내용 은 저희 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 도 많은 응원 부 탁 드 리 겠 습 니 다!

좋은 웹페이지 즐겨찾기