1. 程式人生 > >7_1_Redis實現贊踩功能

7_1_Redis實現贊踩功能

hold reat sco aps mes esp oid 更新點 user

一、實現需求

1. 登錄賬號以後,在首頁home.html內可以點贊或者取消贊,只能點贊一次,點贊以後就不可再點贊;

取消贊以後為0.

2 點開news以後也可以點贊或者取消贊。

技術分享

技術分享

二.具體實現

1 util包下寫一個類似DAO的組件,組件類包括Jedis初始化,獲取Jedis,Jedis的獲取get,set,獲取集合大小等操作。

技術分享
package com.nowcoder.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; /** * Created by Administrator on 2017/5/1. */ @Service public class JedisAdapter implements InitializingBean { private static final Logger logger = LoggerFactory.getLogger(JedisAdapter.class
); private Jedis jedis = null; private JedisPool jedisPool = null; @Override public void afterPropertiesSet() throws Exception { //初始化 jedisPool = new JedisPool("localhost", 6379); } //獲取一個Jedis private Jedis getJedis(){ try{ jedis = jedisPool.getResource(); }
catch (Exception e){ logger.error("獲取jedis失敗!" + e.getMessage()); }finally { if(jedis != null){ jedis.close(); } } return jedis; } /** * 獲取Redis中集合中某個key值 * @param key * @return */ public String get(String key){ Jedis jedis = null; try { jedis = jedisPool.getResource(); return jedis.get(key); }catch (Exception e){ logger.error("Jedis get發生異常 " + e.getMessage()); return null; }finally { if(jedis != null){ jedis.close(); } } } /** * 給Redis中Set集合中某個key值設值 * @param key * @param value */ public void set(String key, String value){ Jedis jedis = null; try { jedis = jedisPool.getResource(); jedis.set(key, value); }catch (Exception e){ logger.error("Jedis set 異常" + e.getMessage()); }finally { if(jedis != null){ jedis.close(); } } } /** * 向Redis中Set集合添加值:點贊 * @return */ public long sadd(String key, String value){ Jedis jedis = null; try{ jedis = jedisPool.getResource(); return jedis.sadd(key, value); }catch (Exception e){ logger.error("Jedis sadd 異常 :" + e.getMessage()); return 0; }finally { if (jedis != null){ jedis.close(); } } } /** * 移除:取消點贊 * @param key * @param value * @return */ public long srem(String key, String value){ Jedis jedis = null; try{ jedis = jedisPool.getResource(); return jedis.srem(key, value); }catch (Exception e){ logger.error("Jedis srem 異常:" + e.getMessage()); return 0; }finally { if (jedis != null){ jedis.close(); } } } /** *p判斷key,value是否是集合中值 * @param key * @param value * @return */ public boolean sismember(String key, String value){ Jedis jedis = null; try{ jedis = jedisPool.getResource(); return jedis.sismember(key, value); }catch (Exception e){ logger.error("Jedis sismember 異常:" + e.getMessage()); return false; }finally { if (jedis != null){ try{ jedis.close(); }catch (Exception e){ logger.error("Jedis關閉異常" + e.getMessage()); } } } } /** * 獲取集合大小 * @param key * @return */ public long scard(String key){ Jedis jedis = null; try{ jedis = jedisPool.getResource(); return jedis.scard(key); }catch (Exception e){ logger.error("Jedis scard 異常:" + e.getMessage()); return 0; }finally { if (jedis != null){ jedis.close(); } } } }
View Code

2 util包下寫一個util工具類,實現點贊生成鍵key的值。

技術分享
package com.nowcoder.util;

import org.springframework.stereotype.Service;

/**
 * Created by Administrator on 2017/5/1.
 */
public class RedisKeyUtil {

    private static String SPLIT = ":";
    private static String BIZ_LIKE = "LIKE";
    private static String BIZ_DISLIKE = "DISLIKE";

    /**
     * 產生key:如在newsId為2上的咨詢點贊後會產生key: LIKE:ENTITY_NEWS:2
     * @param entityId
     * @param entityType
     * @return
     */
    public static String getLikeKey(int entityId, int entityType){
        return BIZ_LIKE + SPLIT + String.valueOf(entityType) + SPLIT + String.valueOf(entityId);
    }
    /**
     * 取消贊:如在newsId為2上的資訊取消點贊後會產生key: DISLIKE:ENTITY_NEWS:2
     * @param entityId
     * @param entityType
     * @return
     */
    public static String getDisLikeKey(int entityId, int entityType){
        return BIZ_DISLIKE + SPLIT + String.valueOf(entityType) + SPLIT + String.valueOf(entityId);
    }









}
View Code

3 Service包下寫上一個判斷點贊還是反對的方法,當點贊後將當前點贊用戶id存入likeKey集合中,同時從disLikeKey中移除此id:

技術分享
package com.nowcoder.service;

import com.nowcoder.util.JedisAdapter;
import com.nowcoder.util.RedisKeyUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * Created by Administrator on 2017/5/1.
 */
@Service
public class LikeService {

    @Autowired
    JedisAdapter jedisAdapter;

    /**
     * 判斷是點贊還是點反對
     * @param userId
     * @param entityType
     * @param entityId
     * @return
     */
    public int getLikeStatus(int userId, int entityType, int entityId) {
        //根據當前用戶的userid分別生成一個likeKey 和 disLikeKey,再分別判斷這兩個值是否在對應的Like集合中和disLikeKey集合中
        //比如如果在likeKey集合中,就返回一個1,否則返回-1
        String likeKey = RedisKeyUtil.getLikeKey(entityId, entityType);
        //判斷值為userId 的用戶是否在key為listKey 的集合中
        if(jedisAdapter.sismember(likeKey, String.valueOf(userId))){
            return 1;
        }
        String disLikeKey = RedisKeyUtil.getDisLikeKey(entityId, entityType);
        return jedisAdapter.sismember(disLikeKey, String.valueOf(userId)) ? -1: 0;
    }

    /**
     * 點贊:即當前用戶點贊後,被點贊用戶的like集合中就會加上一個該點贊的用戶信息
     * @param userId
     * @param entityType
     * @param entityId
     * @return
     */
    public long like(int userId, int entityType, int entityId){
        //在當前news上點贊後獲取key:   LIKE:ENTITY_NEWS:2
       String likeKey = RedisKeyUtil.getLikeKey(entityId, entityType);
       //在喜歡集合中添加當前操作用戶的userId(即當前用戶點贊後,被點贊用戶的like集合中就會加上一個點贊的用戶信息)
       jedisAdapter.sadd(likeKey, String.valueOf(userId));

       String disLikeKey = RedisKeyUtil.getDisLikeKey(entityId, entityType);
       jedisAdapter.srem(disLikeKey, String.valueOf(userId));

       //返回點贊數量
        return jedisAdapter.scard(likeKey);
    }

    /**
     * 反對 :即當前用戶點反對後,被點反對用戶的like集合中就會加上一個該點反對的用戶信息
     * @param userId
     * @param entityType
     * @param entityId
     * @return
     */
    public long disLike(int userId, int entityType, int entityId){

        //誰點擊反對,誰就出現在key為dislikeKey的Set集合中
        String disLikeKey = RedisKeyUtil.getDisLikeKey(entityId, entityType);
        jedisAdapter.sadd(disLikeKey, String.valueOf(userId));

        //從贊中刪除
        String likeKey = RedisKeyUtil.getLikeKey(entityId, entityType);
        jedisAdapter.srem(likeKey, String.valueOf(userId));

        return jedisAdapter.scard(likeKey);
    }













}
View Code

4 Controller: 調用LikeService,將當前用戶id存入Redis的LikeKey集合中,並更新News表中 的like_count數量;對應的dislike也是一樣。

技術分享
package com.nowcoder.controller;

import com.nowcoder.model.EntityType;
import com.nowcoder.model.HostHolder;
import com.nowcoder.model.News;
import com.nowcoder.service.LikeService;
import com.nowcoder.service.NewsService;
import com.nowcoder.util.ToutiaoUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * Created by Administrator on 2017/5/1.
 */
@Controller
public class LikeController {

    @Autowired
    LikeService likeService;
    @Autowired
    NewsService newsService;
    @Autowired
    HostHolder hostHolder;

    @RequestMapping(path = {"/like"}, method = {RequestMethod.GET, RequestMethod.POST})
    @ResponseBody
    public String like(@RequestParam("newsId") int newsId){
        //在newsId 的資訊上加入當前用戶
        long likeCount = likeService.like(hostHolder.getUser().getId(), EntityType.ENTITY_NEWS, newsId);

        //更新點贊數
        //News news = newsService.getById(newsId);
        newsService.updateLikeCount(newsId, (int)likeCount);

        return ToutiaoUtil.getJSONString(0, String.valueOf(likeCount));
    }

    @RequestMapping(path = {"/dislike"}, method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public String disLike(@RequestParam("newsId") int newsId){

        //點擊反對:調用disLike,將當前點擊反對的用戶id從key為dislikeKey的集合中移除
        long likeCount = likeService.disLike(hostHolder.getUser().getId(), EntityType.ENTITY_NEWS, newsId);
        if(likeCount <= 0){
            likeCount = 0;
        }

        //更新喜歡數
        newsService.updateLikeCount(newsId, (int)likeCount);
        return ToutiaoUtil.getJSONString(0, String.valueOf(likeCount));
    }


}
View Code

5. NewsService:

  public int updateLikeCount(int newsId, int likeCount){
        return newsDao.updateLikeCount(newsId, likeCount);
    }

NewsDao:

   @Update({"update", TABLE_NAME, "set like_count=#{likeCount} where id=#{newsId}"})
    int updateLikeCount(@Param("newsId") int newsId, @Param("likeCount") int likeCount);

6. 同時HomeController中首頁獲取News上的點贊時,要加入判斷。如果是未登錄,點贊數全部為0;登錄後就獲取點贊的狀態判斷是點贊還是反對。

 if (localUserId != 0) {
                vo.set("like", likeService.getLikeStatus(localUserId, EntityType.ENTITY_NEWS, news.getId()));
            } else {
                vo.set("like", 0);
            }

技術分享

7. NewsController中的獲取News詳情頁也要加入這樣的判斷:

技術分享

7_1_Redis實現贊踩功能