李翔-大数据技术

Big data technology!

《大数据综合项目实训》练习05

《大数据综合项目实训》练习 05


学生提交材料清单

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 进行如下分析:

    1. 统计 Hive 表 salesinfo 中 2021 年各商品的总销量和总销售额。

    2. 输出字段:product_name:商品名称;total_quantity:销量总数;total_sales:销售额(万元)

    3. 查询结果按销售额降序排序,取前 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>


image.png

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

Powered By Z-BlogPHP 1.7.3

版权:李翔
备案/许可证编号为:新ICP备2024006115号-1