热点文章定时计算
需求:为每个频道缓存热度较高的30条文章优先展示
断文章热度较高的标准是什么?文章:阅读,点赞,评论,收藏
package com.heima.article.service.impl; import com.alibaba.fastjson.JSON; import com.heima.apis.wemedia.IWemediaClient; import com.heima.article.mapper.ApArticleMapper; import com.heima.article.service.HotArticleService; import com.heima.common.constants.ArticleConstants; import com.heima.common.redis.CacheService; import com.heima.model.article.pojos.ApArticle; import com.heima.model.article.vos.HotArticleVo; import com.heima.model.common.dtos.ResponseResult; import com.heima.model.wemedia.pojos.WmChannel; import lombok.extern.slf4j.Slf4j; import org.joda.time.DateTime; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.DateTimeException; import java.util.ArrayList; import java.util.Comparator; import java.util.Date; import java.util.List; import java.util.stream.Collectors; @Service @Slf4j @Transactional public class HotArticleServiceImpl implements HotArticleService { @Autowired private ApArticleMapper apArticleMapper; @Autowired private IWemediaClient wemediaClient; @Autowired private CacheService cacheService; /** * 计算热点文章 */ @Override public void computeHotArticle() { //1、查询前5天的文章数据 Date dateParam = DateTime.now().minusDays(5).toDate(); List<ApArticle> apArticleList = apArticleMapper.findArticleListByLast5days(dateParam); //2、计算文章的分值 List<HotArticleVo> hotArticleVoList = ocomputeHotArticle(apArticleList); //3、为每个频道缓存30条分值较高的文章 cacheTagToRedis(hotArticleVoList); } /** * 为每个频道缓存30条分值较高的文章 * @param hotArticleVoList */ private void cacheTagToRedis(List<HotArticleVo> hotArticleVoList) { //每个频道缓存30条分值较高的文章 ResponseResult responseResult = wemediaClient.getChannels(); if(responseResult.getCode().equals(200)){ String channelJSon = JSON.toJSONString(responseResult.getData()); List<WmChannel> wmChannels = JSON.parseArray(channelJSon, WmChannel.class); //检索每个频道文章 if(wmChannels != null && wmChannels.size() > 0){ for (WmChannel wmChannel : wmChannels) { List<HotArticleVo> hotArticleVos = hotArticleVoList.stream().filter(x -> x.getChannelId().equals(wmChannel.getId())).collect(Collectors.toList()); //给文章进行排序,取30条较高的分值存入Reid是, key:频道id, value:30条分值较高的文章 sortArticleCache(hotArticleVos, ArticleConstants.HOT_ARTICLE_FIRST_PAGE + wmChannel.getId()); } } } //设置推荐数据 sortArticleCache(hotArticleVoList, ArticleConstants.HOT_ARTICLE_FIRST_PAGE + ArticleConstants.DEFAULT_TAG); } /** * 给文章进行排序,取30条较高的分值存入Reid是, key:频道id, value:30条分值较高的文章 * @param hotArticleVos * @param key */ private void sortArticleCache(List<HotArticleVo> hotArticleVos, String key) { hotArticleVos = hotArticleVos.stream().sorted(Comparator.comparing(HotArticleVo::getScore).reversed()).collect(Collectors.toList()); if (hotArticleVos.size() > 30) { hotArticleVos = hotArticleVos.subList(0, 30); } cacheService.set(key, JSON.toJSONString(hotArticleVos)); } /** * 计算文章分值 * @param apArticleList * @return */ private List<HotArticleVo> ocomputeHotArticle(List<ApArticle> apArticleList) { List<HotArticleVo> hotArticleVoList = new ArrayList<>(); if(apArticleList != null && apArticleList.size() > 0){ for (ApArticle apArticle : apArticleList) { HotArticleVo hotArticleVo = new HotArticleVo(); BeanUtils.copyProperties(apArticle, hotArticleVo); Integer score = computeScore(apArticle); hotArticleVo.setScore(score); hotArticleVoList.add(hotArticleVo); } } return hotArticleVoList; } /** * 计算某个文章具体分数 * @param apArticle * @return */ private Integer computeScore(ApArticle apArticle) { Integer score = 0; if(apArticle.getLikes() != null){ score += apArticle.getLikes() * ArticleConstants.HOT_ARTICLE_LIKE_WEIGHT; } if(apArticle.getViews() != null){ score += apArticle.getViews(); } if(apArticle.getComment() != null){ score += apArticle.getComment() * ArticleConstants.HOT_ARTICLE_COMMENT_WEIGHT; } if(apArticle.getCollection() != null){ score += apArticle.getCollection() * ArticleConstants.HOT_ARTICLE_COLLECTION_WEIGHT; } return score; } }