JavaWeb_LeadNews_Day10-Xxljob, Redis实现定时热文章

JavaWeb_LeadNews_Day10-Xxljob, Redis实现定时热文章

  • xxl-job概述
    • windows部署调度中心
    • docker部署调度中心
  • xxl-job入门案例
  • xxl-job分片广播
  • 热点文章定时计算
    • 思路分析
    • 具体实现
      • 热文章计算
      • 定时计算
  • 查询文章接口改造
  • 来源
  • Gitee

xxl-job概述

windows部署调度中心

  1. 运行 xxl-job\doc\db\tables_xxl_job.sql
  2. 修改 xxl-job-admin子模块下的application.properties
    spring.datasource.password=1234
    
  3. 启动 xxl-job-admin子模块下的启动程序
  4. 访问localhost:8080/xxl-job-admin, 账号: admin, 密码:123456

docker部署调度中心

  1. 创建mysql容器
docker run -p 3306:3306 --name mysql57 \
-v /opt/mysql/conf:/etc/mysql \
-v /opt/mysql/logs:/var/log/mysql \
-v /opt/mysql/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=root \
-d mysql:5.7.25
  1. 拉取镜像
docker pull xuxueli/xxl-job-admin:2.3.0
  1. 创建xxl-job-admin容器
docker run -e PARAMS="--spring.datasource.url=jdbc:mysql://192.168.174.133:3306/xxl_job?Unicode=true&characterEncoding=UTF-8 \
--spring.datasource.username=root \
--spring.datasource.password=root" \
-p 8888:8080 -v /tmp:/data/applogs \
--name xxl-job-admin -d xuxueli/xxl-job-admin:2.3.0

xxl-job入门案例

  1. 调度中心新建示例任务
  2. 依赖
    <dependency><groupId>com.xuxueli</groupId><artifactId>xxl-job-core</artifactId><version>2.3.0</version>
    </dependency>
    
  3. 配置
    application.yml
    server:port: 8881xxl:job:admin:addresses: http://192.168.174.133:8888/xxl-job-adminexecutor:appname: xxl-job-executor-sampleport: 9999
    
    XxlJobConfig.java
    @Configuration
    public class XxlJobConfig {private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class);@Value("${xxl.job.admin.addresses}")private String adminAddresses;@Value("${xxl.job.executor.appname}")private String appname;@Value("${xxl.job.executor.port}")private int port;@Beanpublic XxlJobSpringExecutor xxlJobExecutor() {logger.info(">>>>>>>>>>> xxl-job config init.");XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();xxlJobSpringExecutor.setAdminAddresses(adminAddresses);xxlJobSpringExecutor.setAppname(appname);xxlJobSpringExecutor.setPort(port);return xxlJobSpringExecutor;}/*** 针对多网卡、容器内部署等情况,可借助 "spring-cloud-commons" 提供的 "InetUtils" 组件灵活定制注册IP;**      1、引入依赖:*          <dependency>*             <groupId>org.springframework.cloud</groupId>*             <artifactId>spring-cloud-commons</artifactId>*             <version>${version}</version>*         </dependency>**      2、配置文件,或者容器启动变量*          spring.cloud.inetutils.preferred-networks: 'xxx.xxx.xxx.'**      3、获取IP*          String ip_ = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress();*/
    }
    
  4. 任务代码
    @Component
    public class HelloJob {@XxlJob("demoJobHandler")public void demoJobHandler(){XxlJobHelper.log("XXL-JOB, Hello World.");System.out.println("简单任务执行...");}}
    

xxl-job分片广播

  1. 创建分片执行器 xxl-job-sharding-sample
  2. 创建任务, 路由策略为分片广播
  3. 分片广播任务代码, 创建多个实例
    @XxlJob("shardingJobHandler")
    public void shardingJobHandler()
    {// 分片的参数int shardIndex = XxlJobHelper.getShardIndex(); // 实例在集群中的序号int shardTotal = XxlJobHelper.getShardTotal(); // 集群总量// 业务逻辑List<Integer> list = getList();for (Integer integer : list) {if(integer % shardTotal == shardIndex){System.out.println("当前分片: "+shardIndex+", 当前任务项: "+integer);}}
    }public List<Integer> getList()
    {List<Integer> list = new ArrayList<>();for (int i = 0; i < 10000; i++) {list.add(i);}return list;
    }
    

热点文章定时计算

思路分析

具体实现

热文章计算

@Slf4j
@Service
@Transactional
public class HotArticleServiceImpl implements HotArticleService {@Autowiredprivate ApArticleMapper apArticleMapper;/*** 计算热门文章*/@Overridepublic void computeHotArticle() {// 1. 查询前5天的文章数据Date dayParam = DateTime.now().minusDays(5).toDate();List<ApArticle> articleList = apArticleMapper.findArticleListByLast5days(dayParam);// 2. 计算文章的分值List<HotArticleVo> hotArticleVoList = getHotArticleVoList(articleList);// 3. 为每个频道缓存30条分值较高的文章cacheTagToRedis(hotArticleVoList);}@Autowiredprivate IWemediaClient wemediaClient;@Autowiredprivate CacheService cacheService;/*** 为每个频道缓存30条分值较高的文章* @param hotArticleVoList*/private void cacheTagToRedis(List<HotArticleVo> hotArticleVoList) {// 为每个频道缓存30条分值较高的文章ResponseResult responseResult = wemediaClient.getChannels();if(responseResult.getCode().equals(200)){String jsonString = JSON.toJSONString(responseResult.getData());List<WmChannel> wmChannelList = JSON.parseArray(jsonString, WmChannel.class);// 检索出每个频道的文章if(wmChannelList!=null){for (WmChannel wmChannel : wmChannelList) {List<HotArticleVo> hotArticleVos = hotArticleVoList.stream().filter(item ->item.getChannelId().equals(wmChannel.getId())).collect(Collectors.toList());// 给文章排序, 取30条分值较高的文章存入redis key: 频道id value: 30条分值较高的文章sortAndCache(hotArticleVos, ArticleConstants.HOT_ARTICLE_FIRST_PAGE + wmChannel.getId());}}}// 设置推荐数据// 给文章排序, 取30条分值较高的文章存入redis key: 频道id value: 30条分值较高的文章sortAndCache(hotArticleVoList, ArticleConstants.HOT_ARTICLE_FIRST_PAGE + ArticleConstants.DEFAULT_TAG);}/*** 排序并且缓存数据* @param hotArticleVos* @param key*/private void sortAndCache(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 articleList* @return*/private List<HotArticleVo> getHotArticleVoList(List<ApArticle> articleList) {List<HotArticleVo> articleVoList = new ArrayList<>();if(articleList!=null) {for (ApArticle apArticle : articleList) {HotArticleVo hotArticleVo = new HotArticleVo();BeanUtils.copyProperties(apArticle, hotArticleVo);Integer score = computeArticleScore(apArticle);hotArticleVo.setScore(score);articleVoList.add(hotArticleVo);}}return articleVoList;}/*** 计算文章分数* @param apArticle* @return*/private Integer computeArticleScore(ApArticle apArticle) {Integer score = 0;if(apArticle.getLikes() != null){score += ArticleConstants.HOT_ARTICLE_LIKE_WEIGHT*apArticle.getLikes();}if(apArticle.getComment() != null){score += ArticleConstants.HOT_ARTICLE_COMMENT_WEIGHT*apArticle.getComment();}if(apArticle.getCollection() != null){score += ArticleConstants.HOT_ARTICLE_COLLECTION_WEIGHT*apArticle.getCollection();}if(apArticle.getViews() != null){score += apArticle.getViews();}return score;}
}// ApArticleMapper.java
List<ApArticle> findArticleListByLast5days(@Param("dayParam") Date dayParam);// ApArticleMapper.xml
<select id="findArticleListByLast5days" resultType="com.heima.model.article.pojos.ApArticle">SELECTaa.*FROM`ap_article` aaLEFT JOIN ap_article_config aac ON aa.id = aac.article_id<where>and aac.is_delete != 1and aac.is_down != 1<if test="dayParam != null">and aa.publish_time <![CDATA[>=]]> #{dayParam}</if></where>
</select>

总结:

  1. ApArticleMapper.java中的形参必须添加@Param注解, 否则在ApArticleMapper.xml中会将dayParam解释为Date的属性然后报错.

定时计算

  1. 新建热文章计算执行器leadnews-hot-article-executor
  2. 新建定时任务
  3. 依赖和配置
  4. 任务代码
    @Component
    @Slf4j
    public class ComputeHotArticleJob {@Autowiredprivate HotArticleService hotArticleService;@XxlJob("computeHotArticleJob")public void handle(){log.info("热文章分值计算调度任务开始执行...");hotArticleService.computeHotArticle();log.info("热文章分值计算调度任务执行结束...");}}
    

查询文章接口改造

// article-Controller
public class ArticleHomeController {...public ResponseResult load(@RequestBody ArticleHomeDto articleHomeDto){// return apArticleService.load(articleHomeDto, ArticleConstants.LOADTYPE_LOAD_MORE);return apArticleService.load2(articleHomeDto, ArticleConstants.LOADTYPE_LOAD_MORE, true);}...
}// article-Service
public ResponseResult load2(ArticleHomeDto dto, Short type, boolean firstPage) {if(firstPage==true){String jsonString = cacheService.get(ArticleConstants.HOT_ARTICLE_FIRST_PAGE + dto.getTag());if(StringUtils.isNotBlank(jsonString)){List<HotArticleVo> hotArticleVoList = JSON.parseArray(jsonString, HotArticleVo.class);return ResponseResult.okResult(hotArticleVoList);}}return load(dto, type);
}

来源

黑马程序员. 黑马头条

Gitee

https://gitee.com/yu-ba-ba-ba/leadnews

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/117197.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

字节美团题库之重排链表

文章目录 题目详情题目分析完整实现Java代码总结 题目详情 注&#xff1a;面试真实遇到&#xff0c;对于面试遇到算法时要冷静分析 LCR 026 给定一个单链表 L 的头节点 head &#xff0c;单链表 L 表示为&#xff1a; L0 → L1 → … → Ln-1 → Ln 请将其重新排列后变为&am…

解决npm install报错: No module named gyp

今天运行一个以前vue项目&#xff0c;启动时报错如下&#xff1a; ERROR Failed to compile with 1 error上午10:19:33 error in ./src/App.vue?vue&typestyle&index0&langscss& Syntax Error: Error: Missing binding D:\javacode\Springboot-MiMall-RSA\V…

如何设计一个好的游戏剧情(Part 1:主题的设定)

提醒&#xff1a;此教程仅仅为作者的一些经验和感悟&#xff0c;非专业教程&#xff0c;若介意请前往网上搜集或者书本查阅相关资料&#xff01; 前言&#xff1a;游戏为什么要有剧情——游戏剧情的重要性 游戏剧情的重要性难以低估。一个精彩的剧情可以让玩家感受到强烈的情感…

mac帧 arp

1.分片 2.MSS max segment size 3.跨网络的本质 就是经历很多的子网或者局域网 4.将数据从A主机跨网络送到B主机的能力 IP和mac IP解决的是路径选择的问题 5.数据链路层 用于两个设备&#xff08;同一种数据链路节点&#xff09;之间进行传递 6.以太网ether 7.局域网通…

python 深度学习 解决遇到的报错问题3

目录 一、AttributeError: The vocab attribute was removed from KeyedVector in Gensim 4.0.0. 二、ImportError: cannot import name logsumexp 三、FutureWarning: Passing (type, 1) or 1type as a synonym of type is deprecated; in a future version of numpy, it w…

单调递增的数字【贪心算法】

单调递增的数字 当且仅当每个相邻位数上的数字 x 和 y 满足 x < y 时&#xff0c;我们称这个整数是单调递增的。 给定一个整数 n &#xff0c;返回 小于或等于 n 的最大数字&#xff0c;且数字呈 单调递增 。 public class Solution {public int monotoneIncreasingDigits…

Citespace、vosviewer、R语言的文献计量学 、SCI

文献计量学是指用数学和统计学的方法&#xff0c;定量地分析一切知识载体的交叉科学。它是集数学、统计学、文献学为一体&#xff0c;注重量化的综合性知识体系。特别是&#xff0c;信息可视化技术手段和方法的运用&#xff0c;可直观的展示主题的研究发展历程、研究现状、研究…

9.2作业

QT实现闹钟 widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include<QTimerEvent> #include<QDateTime> #include<QLineEdit> #include<QLabel> #include<QPushButton> #include <QTextToSpeech> QT_BEGIN_NAMES…

word导出为HTML格式教程,同时也导出图片

在写文档教程时&#xff0c;有时需要借鉴人家的专业文档内容&#xff0c;一般都是word格式文档。word直接复制里面的内容&#xff0c;帐帖到网站编辑器会有很多问题&#xff0c;需要二次清楚下格式才行&#xff0c;而且图片是没办法直接复制到编辑器内的。所以最方便的办法是将…

面试官:说一下 MyBatis 的一级缓存和二级缓存 ?

目录 1. MyBatis 的缓存机制 2. 为什么不默认开启 MyBatis 的二级缓存 3. MyBatis 如何开启二级缓存 1. MyBatis 的缓存机制 MyBayis 中包含两级缓存&#xff1a;一级缓存和二级缓存 1. 一级缓存是 SqlSession 级别的&#xff0c;是 MyBatis 自带的缓存功能&#xff0c;默认…

在CentOS7上使用Docker安装和部署RabbitMQ

&#x1f680; 1 拉取RabbitMQ Docker镜像 首先&#xff0c;使用Docker命令从Docker Hub拉取RabbitMQ官方镜像。打开终端并运行以下命令&#xff1a; docker pull rabbitmq&#x1f680; 2 创建RabbitMQ容器 一旦镜像下载完成&#xff0c;使用以下命令创建RabbitMQ容器&…

x86 汇编手册快速入门

本文翻译自&#xff1a;Guide to x86 Assembly 在阅读 Linux 源码之前&#xff0c;我们需要有一些 x86 汇编知识。本指南描述了 32 位 x86 汇编语言编程的基础知识&#xff0c;包括寄存器结构&#xff0c;数据表示&#xff0c;基本的操作指令&#xff08;包括数据传送指令、逻…

【leetcode 力扣刷题】数学题之数的开根号:二分查找

用二分查找牛顿迭代解决开根号 69. x的平方根367. 有效的完全平方数 69. x的平方根 题目链接&#xff1a;69. x的平方根 题目内容&#xff1a; 题意是要我们求一个数的算数平方根&#xff0c;但是不能使用内置函数&#xff0c;那么我们就暴力枚举。我们知道如果y>2的话&am…

PO设计模式是selenium自动化测试中最佳的设计模式之一

Page Object Model&#xff1a;PO设计模式是selenium自动化测试中最佳的设计模式之一&#xff0c;主要体现在对界面交互细节的封装&#xff0c;也就是在实际测试中只关注业务流程就OK了传统的设计中&#xff0c;在新增测试用例之后&#xff0c;代码会有以下几个问题&#xff1a…

经管博士科研基础【16】一元二次函数的解的公式

1. 一元二次函数的形式 2. 一元二次函数的图形与性质 一元二次函数的图像是一条抛物线&#xff0c;图像定点公式为(-b/2a,4ac-b*b/4a)&#xff0c;对称轴位直线x-b/2a。 3. 求根公式 形如ax*xb*xc0的一元二次方程&#xff0c;其求根公式为&#xff1a; 4. 韦达定理 如果x1和…

ScreenToGif-动图制作软件实用操作

ScreenToGif官网&#xff1a;ScreenToGif ⭕第一步&#xff1a;启动页面 ⭕第二步&#xff1a;选项 &#x1f95d;录像机-捕获频率选择手动-播放延迟1000ms(可以任意) ⭕第三步&#xff1a;录像机开始录屏 &#x1f95d;我们调整录屏的大小后&#xff0c;打开画图&#xff0c…

剪枝基础与实战(5): 剪枝代码详解

对模型进行剪枝,我们只对有参数的层进行剪枝,我们基于BatchNorm2d对通道重要度 γ \gamma γ参数进行稀释训练。对BatchNorm2d及它的前后层也需要进行剪枝。主要针对有参数的层:Conv2d、BatchNorm2d、Linear。但是我们不会对Pool2d 层进行剪枝,因为Pool2d只用来做下采样,没…

【进阶篇】MySQL分库分表详解

文章目录 0. 前言1. 垂直分库分表2. 水平分库分表 1. 理解过程及实现方案问题讨论衍生出分库分表策略借助成熟组件使用分库分表阶段完成后面临的问题1. 异地多活问题2. 数据迁移问题3. 分布式事务问题4. join查询的问题 分库分表的策略实现示例 2. 参考文档 0. 前言 假设有一个…

46、SpringBoot输入校验--JSR 303

★ Spring Boot的输入校验 springboot支持两种校验方式&#xff1a;1. Spring原生提供的 Validation&#xff0c;这种验证方式需要开发者手写验证代码&#xff0c;比较繁琐。就是普通的if判断2. 使用JSR 303的校验&#xff0c;这种验证方式只需使用注解、即可以声明式的方式进…

4G版本云音响设置教程阿里云平台版本

4G版本云音响设置教程介绍 第一章 介绍了在阿里云物联网平台生一个设备使用的三元素 第二章 转换阿里云三元素 为MQTT参数&#xff0c;并下载到设备中 第三章 阿里云物联网套件协议使用说明&#xff0c;如何发送数据至设备并播放 本文目录引导 目录 4G版本云音响设置教程介…