学生提交材料清单
1.Spark 项目运行结果截图
2.Hive数据库查询截图
3.接口测试截图
4.数据可视化网页截图
5.分别导出Spark项目,前后端项目的Zip(压缩包)
注意:
1.所有截图请统一粘贴到一个 Word 文件中,命名为:
提交截图_姓名_班级.docx;2.最终考生提交内容打包为一个总压缩包,命名格式如下:
张三-大数据高23-1班-大数据实训.rar
一、Hive 环境启动
【题目要求】
启动 Hadoop 分布式文件系统(HDFS)与 YARN;
启动 Hive Metastore 与 HiveServer2 服务。
# 启动 Hadoop 文件系统
start-dfs.sh
start-yarn.sh
# 启动 Hive 服务
hive --service metastore &
hive --service hiveserver2 &
二、Hive 数据库与数据导入
【题目要求】
创建数据库
salesdb;创建表
salesinfo,包含订单信息与分类字段;从本地路径
/opt/exam_spark/sales_data.csv加载数据;查询前 3 行,验证导入是否成功。
【参考代码】
DROP DATABASE IF EXISTS salesdb CASCADE;
CREATE DATABASE IF NOT EXISTS salesdb;
USE salesdb;
CREATE TABLE IF NOT EXISTS salesinfo (
order_id STRING,
customer_id STRING,
product_id STRING,
sale_date DATE,
quantity INT,
unit_price INT,
payment_method STRING,
region STRING,
product_name STRING,
category STRING
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
STORED AS TEXTFILE
TBLPROPERTIES ("skip.header.line.count"="1");
LOAD DATA LOCAL INPATH '/opt/exam_spark/sales_data.csv' INTO TABLE salesinfo;
SELECT * FROM salesinfo LIMIT 3;
三、Spark SQL 分析前 6 热销商品
【题目要求】
创建
Spark项目SparkTask,并导入Pom.xml文件;创建 Scala 类
TopProductAnalysis.scala,路径为:src/main/scala/org/example/TopProductAnalysis.scala使用 Spark SQL 对 Hive 表 salesinfo 进行如下分析:
统计 Hive 表
salesinfo中 2021 年各商品的总销量和总销售额。输出字段:
product_name:商品名称;total_quantity:销量总数;total_sales:销售额(万元)查询结果按销售额降序排序,取前 6 名,通过
.show()展示,并保存到 Hive 表top_products_result。
【参考代码】
package org.example
import org.apache.spark.sql.SparkSession
object TopProductAnalysis {
def main(args: Array[String]): Unit = {
// 1. 设置 Hadoop 用户(防止权限问题)
System.setProperty("HADOOP_USER_NAME", "root")
// 2. 初始化 SparkSession,启用 Hive 支持
val spark = SparkSession.builder()
.appName("TopProductAnalysis")
.master("local[*]") // 或 yarn 模式
.enableHiveSupport()
.getOrCreate()
println("1. SparkSession 初始化完成,Hive 支持已开启")
// 3. 切换到 salesdb 数据库
spark.sql("USE salesdb")
// 4. 执行统计 SQL
println("2.正在统计 2021 年各商品的销量与销售额(Top 6)...")
val result = spark.sql(
"""
|SELECT
| product_name,
| SUM(quantity) AS total_quantity,
| ROUND(SUM(quantity * unit_price)/10000, 2) AS total_sales
|FROM salesinfo
|WHERE sale_date IS NOT NULL and year(sale_date)= 2021
|GROUP BY product_name
|ORDER BY total_sales DESC
|LIMIT 6
|""".stripMargin)
// 5. 展示结果
val count = result.count()
println(s"3.查询完成,前 6 名热销商品记录:")
result.show(truncate = false)
// 6. 写入 Hive 表
println("4.正在将结果写入 Hive 表:salesdb.top_products_result...")
result.write.mode("overwrite").saveAsTable("top_products_result")
println("5.写入成功,表名:salesdb.top_products_result")
// 7. 关闭 Spark
spark.stop()
println("6. 程序执行结束,SparkSession 已关闭。")
}
}
四、Spring Boot 接口开发 + Vue 可视化
4.1 后端接口开发
【题目要求】
创建
Spring Boot项目 ,名称为Backend,并导入Pom.xml文件;创建类
TopProductController,路径为:src/main/java/com/example/backend/controller/TopProductController.java使用 Spring Boot 创建接口
/top-products,请求方式为GET;在接口中通过 JDBC 查询 Hive 表
top_products_result;查询字段包括:
product_name,total_quantity,total_sales;将查询结果以 JSON 列表形式返回,每条记录包含上述字段键值对。
【参考代码】
package com.example.backend.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.sql.*;
import java.util.*;
@RestController // 声明该类是一个 REST 控制器,返回 JSON 格式数据
public class TopProductController {
@GetMapping("/top-products") // 定义一个 GET 接口,路径为 /top-products
public List<Map<String, Object>> getTopProducts() {
// 用于存放查询结果的列表(每个 Map 是一条产品数据)
List<Map<String, Object>> result = new ArrayList<>();
try {
// 1. 加载 Hive JDBC 驱动类(用于连接 Hive)
Class.forName("org.apache.hive.jdbc.HiveDriver");
// 2. 建立连接:连接 HiveServer2,指定数据库为 salesdb
Connection conn = DriverManager.getConnection(
"jdbc:hive2://master:10000/salesdb", "root", "123456");
// 3. 创建 SQL 执行对象
Statement stmt = conn.createStatement();
// 4. 执行 SQL 查询:从 top_products_result 表中获取产品名称、销量和销售额
ResultSet rs = stmt.executeQuery(
"SELECT product_name, total_quantity, total_sales FROM top_products_result");
// 5. 遍历结果集,将每一行转换为一个 Map,并加入结果列表中
while (rs.next()) {
Map<String, Object> map = new HashMap<>();
map.put("product_name", rs.getString("product_name")); // 产品名称
map.put("total_quantity", rs.getInt("total_quantity")); // 销量
map.put("total_sales", rs.getDouble("total_sales")); // 销售额
result.add(map); // 将这一条记录添加到结果集中
}
// 6. 释放资源
rs.close(); // 关闭结果集
stmt.close(); // 关闭执行对象
conn.close(); // 关闭连接
} catch (Exception e) {
// 如果出现异常,打印错误信息
e.printStackTrace();
}
// 7. 返回查询结果(自动转为 JSON)
return result;
}
}
4.2 Vue + ECharts 可视化
【题目要求】
创建
VUE项目 ,名称为Frontend;创建组件文件
components/TopProductChart.vue和主页面App.vue、配置代理文件vite.config.js;使用 Vue3 + ECharts 创建柱状图组件;
从接口
/api/top-products获取数据;显示 2021 年前 6 名热销商品的销售额(单位:万元)排行榜,并以柱状图形式展示。
【参考代码】
vite.config.js
// 引入 Vite 的配置函数和 Vue 插件
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// 默认导出配置对象
export default defineConfig({
// 注册插件:使用 Vue 插件支持 .vue 文件
plugins: [vue()],
// 本地开发服务器配置
server: {
port: 5173, // 本地开发服务器端口(默认也是 5173,可自定义)
// 配置代理:解决前端开发中跨域请求后端的问题
proxy: {
'/api': {
target: 'http://localhost:8080', // 后端服务器地址(Spring Boot 或其他服务)
changeOrigin: true, // 修改请求头中的 origin 字段,避免跨域
rewrite: path => path.replace(/^\/api/, '')
// 将请求路径中的 `/api` 前缀去掉,例如:
// 前端请求:/api/region-sales → 实际转发为:http://localhost:8080/region-sales
}
}
}
})
App.vue
<!-- 页面结构区域 -->
<template>
<div class="chart-wrapper">
<h1>数据可视化</h1>
<h2>大数据高23-1班 张三</h2>
<!-- 引入的图表组件,用于展示区域销售数据 -->
<TopProductChart />
</div>
</template>
<!-- 脚本逻辑区域 -->
<script setup>
// 引入封装好的区域图表组件
import TopProductChart from './components/TopProductChart.vue'
</script>
<!-- 页面样式区域 -->
<style>
/* 设置整个页面的背景色和默认字体样式 */
body {
background-color: #f0f2f5; /* 浅灰背景色 */
margin: 0;
padding: 20px;
font-family: "Microsoft YaHei", sans-serif;
}
/* 图表容器样式:限制最大宽度、居中显示 */
.chart-wrapper {
max-width: 1400px;
margin: 40px auto; /* 上下间距 40px,左右居中 */
font-family: sans-serif;
}
</style>
components/TopProductChart.vue
<template>
<!-- 图表容器,通过 ref="chartRef" 绑定 DOM 元素 -->
<div class="chart-container" ref="chartRef"></div>
</template>
<script setup>
// 引入 Vue 的响应式 API 和生命周期钩子
import { ref, onMounted } from 'vue'
// 引入 ECharts 图表库
import * as echarts from 'echarts'
// 引入 axios,用于向后端发送请求获取数据
import axios from 'axios'
// 绑定图表 DOM 元素
const chartRef = ref()
// 渲染图表函数(在页面加载后执行)
const renderChart = async () => {
// 1. 请求后端接口,获取热销商品数据
const res = await axios.get('/api/top-products')
const data = res.data
// 2. 构造横坐标数据:销售额(保留两位小数)
const xData = data.map(item => item.total_sales.toFixed(2))
// 3. 构造纵坐标数据:商品名称
const yData = data.map(item => item.product_name)
// 4. 初始化 ECharts 实例(绑定到 chartRef DOM)
const chart = echarts.init(chartRef.value)
// 5. 设置图表配置项
chart.setOption({
// 图表标题
title: {
text: '2021年前6热销商品销售额排行', // 主标题
subtext: '单位:万元', // 副标题
left: 'center' // 居中显示
},
// 提示框(鼠标悬停显示)
tooltip: {
trigger: 'axis', // 鼠标悬停在坐标轴触发提示
axisPointer: { type: 'shadow' }, // 阴影指示器
formatter: params => { // 自定义提示内容
const d = params[0]
return `${d.name}<br/>销售额:${d.value} 万元`
}
},
// 图表网格(用于设置图表和边框之间的间距)
grid: {
left: 120, // 左边预留空间(避免商品名称被遮挡)
right: 100, // 右边预留空间(避免标签文字被裁剪)
bottom: 40,
top: 80
},
// 横坐标配置(销售额)
xAxis: {
type: 'value', // 数值型坐标轴
name: '销售额(万元)', // 显示单位标签
axisLabel: { fontSize: 14 } // 标签字体大小
},
// 纵坐标配置(商品名称)
yAxis: {
type: 'category', // 类别型坐标轴
data: yData, // 商品名称数组
axisLabel: { fontSize: 14 } // 标签字体大小
},
// 数据系列(柱状图)
series: [
{
type: 'bar', // 图表类型为柱状图
data: xData, // 销售额数据
label: {
show: true, // 显示柱体右侧的数值标签
position: 'right',
formatter: '{c} 万' // 格式化为“数值 万”
},
itemStyle: {
color: '#2b6cb0' // 柱子颜色(深蓝)
}
}
]
})
}
// 在组件挂载后执行图表渲染
onMounted(() => renderChart())
</script>
<style scoped>
/* 图表容器样式 */
.chart-container {
width: 100%; /* 宽度占满父容器 */
max-width: 1000px; /* 最大不超过 1000px,防止太宽溢出 */
min-width: 700px; /* 最小保证图表基本显示完整 */
height: 500px; /* 固定高度 */
margin: 10px auto; /* 垂直外边距 + 水平居中 */
background: #fff; /* 白色背景 */
border-radius: 12px; /* 圆角边框 */
padding: 20px; /* 内边距 */
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.08); /* 轻微阴影,提升层次感 */
}
</style>
