7_1_Redis實現贊踩功能
阿新 • • 發佈:2017-05-07
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;View Codeimport 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(); } } } }
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實現贊踩功能