李翔-大数据技术

Big data technology!

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

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


学生提交材料清单

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 地区销售统计

【题目要求】

  • 创建 Spark 项目 SparkTask ,并导入 Pom.xml 文件;

  • 创建 Scala 类 RegionSalesAnalysis,路径为: src/main/scala/org/example/RegionSalesAnalysis.scala

  • 使用 Spark SQL 分析 Hive 表 salesinfo

    1. 统计2024年各地区(region)的订单数量和销售金额;

    2. 按销售金额降序排序;

    3. 将结果写入 Hive 表 region_sales_result

【参考代码】

package org.example

import org.apache.spark.sql.SparkSession

object RegionSalesAnalysis {
 def main(args: Array[String]): Unit = {

   // 设置 Hadoop 访问用户名(避免权限问题)
   System.setProperty("HADOOP_USER_NAME", "root")

   // 1. 创建 SparkSession,并开启 Hive 支持(用于访问 Hive 表)
   val spark = SparkSession.builder()
     .appName("RegionSalesStat")
     .master("local[*]")
     .enableHiveSupport()
     .getOrCreate()

   println("1. SparkSession 创建完成,Hive 功能已启用")

   // 2. 选择使用的数据库(salesdb)
   spark.sql("USE salesdb")

   // 3. 执行销售统计 SQL 查询:
   println("2.正在统计 2024 年各地区的订单数量与销售额......")  
   val result = spark.sql(
     """
       |SELECT
       |  region,
       |  COUNT(*) AS order_count,
       |  ROUND(SUM(quantity * unit_price)/10000, 2) AS total_sales
       |FROM salesinfo
       |WHERE year(sale_date) = 2024
       |GROUP BY region
       |HAVING total_sales IS NOT NULL
       |ORDER BY total_sales DESC
       |""".stripMargin)

   println(s"3. 数据分析后,共计 ${result.count()} 条记录")
   result.show(truncate = false)

   // 4. 将统计结果保存为 Hive 表
   result.write
     .mode("overwrite")  // 如果表已存在,则覆盖
     .saveAsTable("salesdb.region_sales_result")

   // 5. 释放资源,关闭 SparkSession
   println("4. 所有数据成功写入目标表,准备关闭 Spark...")
   spark.stop()
   println("5. 程序执行完毕。")
 }
}

四、Spring Boot 接口开发 + Vue 可视化


4.1 后端接口开发

【题目要求】

  • 创建 Spring Boot 项目 ,名称为Backend,并导入 Pom.xml 文件;

  • 创建类 RegionController,路径为: src/main/java/com/example/backend/controller/RegionController.java

  • 使用 Spring Boot 创建接口 /region-sales,请求方式为 GET

  • 在接口中通过 JDBC 查询 Hive 表 region_sales_result

  • 查询字段包括:region, order_count, 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 RegionController {

   @GetMapping("/region-sales") // 定义 GET 请求接口路径:/region-sales
   public List<Map<String, Object>> getRegionSales() {
       List<Map<String, Object>> result = new ArrayList<>(); // 用于存储返回的结果列表

       try {
           // 1. 加载 Hive JDBC 驱动类
           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. 执行查询语句:从 Hive 的统计结果表中获取数据
           ResultSet rs = stmt.executeQuery(
               "SELECT region, order_count, total_sales FROM region_sales_result");

           // 5. 遍历结果集,将每行数据封装成 Map 并加入结果列表
           while (rs.next()) {
               Map<String, Object> map = new HashMap<>();
               map.put("region", rs.getString("region"));             // 地区名
               map.put("order_count", rs.getInt("order_count"));      // 订单数
               map.put("total_sales", rs.getDouble("total_sales"));   // 总销售额(单位:万元)
               result.add(map); // 加入结果列表
           }

           // 6. 关闭连接资源
           rs.close();
           stmt.close();
           conn.close();

       } catch (Exception e) {
           // 7. 打印异常信息,便于排查问题
           e.printStackTrace();
       }

       // 8. 返回结果列表,Spring Boot 会自动转换为 JSON 响应
       return result;
   }
}



4.2 Vue + ECharts 可视化

【题目要求】

  • 创建 VUE 项目 ,名称为Frontend

  • 创建组件文件 components/RegionChart.vue 和主页面 App.vue、配置文件vite.config.js

  • 使用 Vue3 + ECharts 创建折线图组件;

  • 从 接口/api/region-sales 获取数据;

  • 显示2024年不同地区的销售金额(单位:万元)变化的趋势。

【参考代码】

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>
   <!-- 引入的图表组件,用于展示区域销售数据 -->
   <RegionChart />
 </div>
</template>

<!-- 脚本逻辑区域 -->
<script setup>
 // 引入封装好的区域图表组件
 import RegionChart from './components/RegionChart.vue'
</script>

<!-- 页面样式区域 -->
<style>
/* 设置整个页面的背景色和默认字体样式 */
body {
 background-color: #f0f2f5; /* 浅灰背景色 */
 margin: 0;
 padding: 20px;
 font-family: "Microsoft YaHei", sans-serif;
}

/* 图表容器样式:限制最大宽度、居中显示 */
.chart-wrapper {  
 max-width: 1400px;         /* 设置容器的最大宽度为 1400 像素 */
 margin: 0;                 /* 页面贴边显示(去除浏览器默认外边距) */
 padding: 20px;             /* 页面内部留出 内边距 20px(上下左右)*/
 font-family: sans-serif;  
}
</style>

components/RegionChart.vue

<template>
 <!-- 图表容器:通过 ref 绑定 DOM 元素 -->
 <div ref="chartRef" class="chart-container"></div>
</template>

<script setup>
import { ref, onMounted } from 'vue'
import * as echarts from 'echarts'
import axios from 'axios'

// 1. 定义图表 DOM 引用
const chartRef = ref()

// 2. 渲染图表方法(异步请求数据 + 初始化图表)
const renderChart = async () => {
 // 从后端接口获取各地区销售统计数据(来源:Hive)
 const res = await axios.get('/api/region-sales')
 const data = res.data

 // 提取横轴(地区)和纵轴(销售额,保留2位小数)
 const xData = data.map(item => item.region)
 const yData = data.map(item => item.total_sales.toFixed(2))

 // 初始化 ECharts 图表实例
 const chart = echarts.init(chartRef.value)

 // 配置图表选项
 chart.setOption({
   title: {
     text: '2024年各地区销售趋势', // 图表标题
     subtext: '单位:万元',       // 副标题  
     left: 'center'
   },
   tooltip: {
     trigger: 'axis', // 鼠标悬停触发提示框
     formatter: function (params) {
       const d = params[0];
       // 返回格式化的提示信息
       return `${d.name}<br/>${d.seriesName}:${d.value} 万元`
     }
   },
   xAxis: {
     type: 'category',     // 类别轴:地区名
     data: xData,
     axisLabel: { fontSize: 14 } // 坐标标签字体大小
   },
   yAxis: {
     type: 'value',        // 数值轴
     name: '销售金额(万元)',
     axisLabel: {
       fontSize: 14,
       formatter: value => `${value} 万` // 格式化为“万元”
     }
   },
   series: [{
     type: 'line',         // 折线图类型
     name: '销售金额',
     data: yData,          // 纵轴数据:销售额
     smooth: true,         // 平滑线条
     symbol: 'circle',     // 拐点样式
     lineStyle: {
       width: 3,
       color: '#2b6cb0'    // 设置线条颜色为更深蓝色
     },
     label: {
       show: true,
       position: 'top'     // 数据值显示在折线顶端
     }
   }]
 })
}

// 3. Vue 生命周期钩子:页面加载完成后渲染图表
onMounted(() => renderChart())
</script>

<style scoped>
.chart-container {
 width: 100%;                       /* 宽度占满父容器 */
 height: 400px;                     /* 固定高度 400px,确保 ECharts 能正确显示 */
 min-width: 700px;                  /* 最小宽度为 700px,防止图表在小屏下过小 */
 background: #fff;                  /* 卡片白色背景 */
 border-radius: 12px;               /* 圆角边框 */
 padding: 20px;                     /* 内边距 */
 box-shadow: 0 6px 18px rgba(0, 0, 0, 0.08);  /* 阴影效果 */  
 border: none;
}
</style>

image.png


发表评论:

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

Powered By Z-BlogPHP 1.7.3

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