用户行为数据可视化
8.1 构建javaweb系统查询用户行为
8.1.2 搭建并部署javaweb项目
tomcat的安装与配置
进入网址:https://tomcat.apache.org/download-90.cgi,选择图示版本
解压至windows本地文件夹即可
idea构建javaweb项目
在Idea中打开书中配套代码
点编辑配置
点配置,选择自己的文件夹
添加部署
添加完成将下述路径改成/newsWeb
将web.xml文件改成如下内容:
启动tomcat
pom.xml文件的json-lib库改成:
<dependency><groupId>net.sf.json-lib</groupId><artifactId>json-lib</artifactId><version>2.4</version><classifier>jdk15</classifier></dependency>
启动之后:
访问网址如下:
http://localhost:8080/newsWeb/TestServlet
如图
8.1.3 用户行为查询代码开发
修改配置文件
修改my.properties
修改web.xml文件
8.2 用户行为数据展示与分析
javaweb项目配置与打包
把my.properties改成:
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.datasource.size=5
jdbc.url=jdbc:mysql://192.168.255.139:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
jdbc.user=hive
jdbc.password=hive
JDBCHelper.java改成:
//第一步:加载驱动/*static{try {ConfigurationManager.getProperty(Constants.JDBC_DRIVER);Class.forName("com.mysql.jdbc.Driver");} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}}*/static {try {// 直接用配置文件里的值,适配 8.xClass.forName(ConfigurationManager.getProperty(Constants.JDBC_DRIVER));} catch (ClassNotFoundException e) {e.printStackTrace();}}
web.xml改成:
<!DOCTYPE web-app PUBLIC"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN""http://java.sun.com/dtd/web-app_2_3.dtd" ><web-app><display-name>newsWeb</display-name><servlet><servlet-name>NewsSvlt</servlet-name><servlet-class>com.djt.servlet.NewsSvlt</servlet-class></servlet><servlet-mapping><servlet-name>NewsSvlt</servlet-name><url-pattern>/news</url-pattern></servlet-mapping><welcome-file-list><welcome-file>jsp/news.jsp</welcome-file></welcome-file-list>
</web-app>
在webapp下新建目录jsp,在此下新建文件news.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%String path = request.getContextPath();String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>新闻大屏展示</title><!-- 引入 ECharts 和 jQuery --><script src="<%=path%>/js/echarts.min.js"></script><script src="<%=path%>/js/jquery-3.2.1.js"></script>
</head>
<body>
<div id="loading" style="text-align:center;padding:50px;font-size:18px;color:#666;">正在加载新闻数据...
</div>
<div id="content" style="display:none;"><div id="main" style="width:700px;height:420px;float:left;"></div><div id="sum" style="width:730px;height:420px;float:left;"></div><div id="period" style="width:1430px;height:250px;float:left;"></div>
</div></body><script type="text/javascript">var myChart, myChart_sum, myChart_period;function initCharts() {myChart = echarts.init(document.getElementById('main'));myChart_sum = echarts.init(document.getElementById('sum'));myChart_period = echarts.init(document.getElementById('period'));}$(document).ready(function(){// 初始化图表initCharts();// 加载数据initNewsNum();// 每10秒刷新一次(减少频率避免过多请求)setInterval(function() {initNewsNum();}, 10000);});function initNewsNum(){var action = "<%=path%>/news"; // 调用后端 Servlet$.ajax({url: action,type: 'GET',dataType: 'json',timeout: 10000,success: function(data) {console.log('接收到数据:', data);if (data.error) {console.error('服务器返回错误:', data.error);return;}// 隐藏加载提示,显示内容$('#loading').hide();$('#content').show();newsRank(data);newsSum(data.newssum);periodRank(data);},error: function(xhr, status, error) {console.error('AJAX请求失败:', status, error);console.error('响应内容:', xhr.responseText);// 隐藏加载提示,显示错误信息$('#loading').html('<div style="color:red;font-size:16px;">数据加载失败,请检查数据库连接<br/>错误信息: ' + error + '</div>');// 可选:显示空的图表$('#content').show();var emptyData = {name: [],newscount: [],logtime: [],periodcount: [],newssum: 0};newsRank(emptyData);newsSum(emptyData.newssum);periodRank(emptyData);}});}// 新闻浏览量排行function newsRank(json){var option = {backgroundColor: '#ffffff',title: {text: '新闻话题浏览量【实时】排行',subtext: '数据来自搜狗',textStyle: { fontWeight: 'normal', color: '#408829' }},tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },legend: { data: ['浏览量'] },grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true },xAxis: { type: 'value', boundaryGap: [0, 0.01] },yAxis: { type: 'category', data: json.name },series: [{name: '浏览量',type: 'bar',label: { normal: { show: true, position: 'insideRight' } },itemStyle:{ normal:{color:'#f47209'} },data: json.newscount}]};myChart.setOption(option);}// 新闻话题曝光总量function newsSum(data){var option = {backgroundColor: '#fbfbfb',title: { text: '新闻话题曝光量【实时】统计', subtext: '数据来自搜狗' },tooltip: { formatter: "{a} <br/>{b} : {c}%" },toolbox: { feature: { restore: {}, saveAsImage: {} } },series: [{name: '业务指标',type: 'gauge',max: 50000,detail: { formatter:'{value}个话题' },data: [{value: 0, name: '话题曝光量'}]}]};option.series[0].data[0].value = data;myChart_sum.setOption(option, true);}// 时段新闻浏览量排行function periodRank(json){var option = {backgroundColor: '#ffffff',color: ['#00FFFF'],tooltip : { trigger: 'axis', axisPointer : { type : 'shadow' } },grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true },xAxis : [{ type : 'category', data : json.logtime, axisTick: { alignWithLabel: true } }],yAxis : [{ type : 'value' }],series : [{name:'新闻话题曝光量',type:'bar',barWidth: '60%',data: json.periodcount}]};myChart_period.setOption(option, true);}
</script>
</body>
</html>
把打包好的拷贝到tomcat的webapps目录下:
启动数据库
确认hadoop01的数据库启动,并在tomcat里把表清空
启动
来到tomcat的bin目录下,双击start.bat
访问 http://localhost:8080/newsWeb/
此时没数据所以显示空白
8.2.2 项目整体联调
1️⃣ 启动 MySQL 服务
因为 Flink 处理结果要落到 MySQL 的 newscount
和 periodcount
表里,所以必须先启动数据库。
-
在
hadoop01
节点执行:service mysql start
或
systemctl start mysqld
-
验证:
mysql -uroot -p mysql> show databases;
确保有 test
数据库,以及表 newscount
、periodcount
已创建。
2️⃣ 启动 Zookeeper 服务
Kafka 依赖 Zookeeper 协调。
-
在
hadoop01/hadoop02/hadoop03
各节点执行:cd /home/hadoop/app/zookeeper/bin ./zkServer.sh start
-
验证:
./zkServer.sh status
确保有一个是
leader
,其他是follower
。
3️⃣ 启动 Kafka 集群
Flink DataStream 会消费 Kafka 的日志流。
-
在各节点执行:
cd /home/hadoop/app/kafka/bin ./kafka-server-start.sh -daemon ../config/server.properties
-
验证:
jps | grep Kafka
4️⃣ 启动 Flink 实时应用
书里用的例子是 KafkaFlinkMySQL
,把 Kafka 数据实时处理后写入 MySQL。
- 在 IDEA 里找到
KafkaFlinkMySQL.java
- 右键 →
Run 'KafkaFlinkMySQL.main()'
- Flink 应用会本地运行,消费 Kafka 日志,计算新闻浏览量 → 写入 MySQL。
5️⃣ 启动 Flume 聚合节点
Flume 负责把采集到的日志推送到 Kafka。
-
在
hadoop02
、hadoop03
上执行:cd /home/hadoop/app/flume ./bin/flume-ng agent -n a1 -c conf -f conf/flume-conf-aggregator.conf -Dflume.root.logger=INFO,console
6️⃣ 启动 Flume 采集节点
-
在
hadoop01
上执行:cd /home/hadoop/app/flume ./bin/flume-ng agent -n a1 -c conf -f conf/flume-conf-collector.conf -Dflume.root.logger=INFO,console
这一步会把日志源源不断地推送到聚合节点,再写到 Kafka。
7️⃣ 模拟产生数据
-
在
hadoop01
上执行:cd /home/hadoop/shell/bin ./sogoulogs.sh
8️⃣ 查看 MySQL 结果
最终效果
-
Flume → Kafka → Flink → MySQL → Java Web 大屏
-
打开大屏地址:
http://localhost:8080/newsWeb/
页面会通过
NewsSvlt
查询 MySQL → 返回 JSON → ECharts 实时展示统计结果。
访问http://localhost:8080/newsWeb/