资讯动态

Hadoop+Hive+HBase本地环境搭建与ECharts数据对接实战

发布时间:2026/10/26 12:49:48 来源:尧图企业网站定制
简介本资源是一套完整的招聘信息大数据分析平台毕业设计实现面向计算机、人工智能、通信等专业本科生及初学者解决招聘数据采集、存储、计算与可视化全流程实践问题适用于毕业设计、课程大作业及大数据技术入门学习。压缩包共201个文件含28个Java核心业务代码、28个JavaScript前端交互逻辑、26个PNG图表素材、12个配置与说明文本以及1个完整论文PDF和多个CSS样式文件如layui.css、style.css等整体11.33MB结构清晰模块划分明确。已有281人学习下载项目经实际调试运行验证答辩获98分高分附带可直接部署的HadoopHiveHBase数据处理链路与ECharts动态可视化看板涵盖数据清洗、宽表构建、多维统计及岗位热力图、薪资分布等典型分析场景为学习者提供从环境搭建、代码解读到结果呈现的全路径参考。1. 招聘数据跑不起来不是数据太少是 pipeline 卡在 Hive 小文件 HBase 写入抖动 ECharts 数据格式错位这三道坎上你手里的“高分毕设”源码解压后run.sh一执行就卡在hive -f init.sql日志里满屏Failed to open new session或者 HBase shell 里list能看到表但scan job_info返回空又或者 ECharts 页面永远显示“加载中…”F12 看 Network 面板/api/job-stats接口返回500 Internal Server Error后端日志却只有一行NullPointerException at com.xxx.HBaseDao.getJobCountByCity(HBaseDao.java:47)。这不是你代码写得差——这是典型的大数据毕设「三明治陷阱」上层可视化ECharts要干净 JSON中间计算层Hive吐不出结构化结果底层存储HBase又接不住原始招聘文本的脏乱差。本项目真正值钱的不是那套带Override的 Java DAO而是把Hadoop 伪分布式环境稳住、Hive 表按招聘字段语义建对、HBase RowKey 设计防热点、ECharts 前端取数逻辑与后端 REST 接口字段严格对齐这四件事闭环落地的经验。适合正在被导师催“平台要有真实数据、要有交互图表、要有可演示流程”的大四同学也适合想用最小成本单机 16G 内存 Ubuntu 20.04 虚拟机复现完整链路的一线工程师。2. 从零搭起可验证的 HadoopHiveHBase 本地环境不装 ZooKeeper不配 HA但必须过hdfs dfs -ls /这关毕业设计不需要生产级集群但必须让hadoop fs -ls /不报错、hive -e show databases;有响应、hbase shell里status detailed显示1 live servers。很多同学卡在第一步本质是环境变量和配置文件的“隐性耦合”没理清——Hadoop 的core-site.xml里fs.defaultFS指向hdfs://localhost:9000Hive 的hive-site.xml里hive.metastore.uris却默认连thrift://localhost:9083需要先启 Metastore而 HBase 的hbase-site.xml又要求hbase.rootdir必须指向 HDFS 路径。三者版本稍不匹配比如 Hadoop 3.3.6 Hive 3.1.3 HBase 2.4.18就会出现“HDFS 能读Hive 找不到元数据HBase 写不进”的雪崩。2.1 选版本组合避开编译地狱直接用预编译二进制包提示不要自己编译 Hadoop/Hive/HBase 源码。毕设时间紧预编译包的lib/native已含适配主流 Linux 发行版的 native 库能省掉 80% 的UnsatisfiedLinkError报错。我们锁定以下组合经实测 Ubuntu 20.04 OpenJDK 11 下 100% 通过Hadoop 3.3.6 https://downloads.apache.org/hadoop/common/hadoop-3.3.6/hadoop-3.3.6.tar.gzHive 3.1.3 https://downloads.apache.org/hive/hive-3.1.3/apache-hive-3.1.3-bin.tar.gzHBase 2.4.18 https://downloads.apache.org/hbase/2.4.18/hbase-2.4.18-bin.tar.gz下载后统一解压到/opt/目录下并建立软链接方便后续维护sudo tar -xzf hadoop-3.3.6.tar.gz -C /opt/ sudo tar -xzf apache-hive-3.1.3-bin.tar.gz -C /opt/ sudo tar -xzf hbase-2.4.18-bin.tar.gz -C /opt/ sudo ln -sf /opt/hadoop-3.3.6 /opt/hadoop sudo ln -sf /opt/apache-hive-3.1.3-bin /opt/hive sudo ln -sf /opt/hbase-2.4.18 /opt/hbase2.2 配置核心环境变量HADOOP_HOME、HIVE_HOME、HBASE_HOME必须显式声明很多教程教你在~/.bashrc里写export HADOOP_HOME$HOME/hadoop但实际运行start-dfs.sh时脚本内部会调用hadoop-config.sh它依赖HADOOP_HOME是绝对路径且不能含~。务必用绝对路径并确保PATH中hadoop命令优先于系统自带如 Ubuntu 自带的hadoop包。# 编辑 ~/.bashrc追加以下内容注意替换为你的真实用户名如 ubuntu export JAVA_HOME/usr/lib/jvm/java-11-openjdk-amd64 export HADOOP_HOME/opt/hadoop export HIVE_HOME/opt/hive export HBASE_HOME/opt/hbase export PATH$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin:$HIVE_HOME/bin:$HBASE_HOME/bin:$PATH # 生效环境变量 source ~/.bashrc验证是否生效echo $HADOOP_HOME # 应输出 /opt/hadoop hadoop version # 应输出 Hadoop 3.3.62.3 Hadoop 伪分布式四步配置core-site.xml、hdfs-site.xml、mapred-site.xml、yarn-site.xml关键点所有配置文件都放在$HADOOP_HOME/etc/hadoop/下且文件名必须完全一致大小写敏感。常见错误是把core-site.xml写成core.xml或core_site.xml导致 Hadoop 完全读不到配置。core-site.xml定义默认文件系统为本地 HDFS?xml version1.0 encodingUTF-8? ?xml-stylesheet typetext/xsl hrefconfiguration.xsl? configuration property namefs.defaultFS/name valuehdfs://localhost:9000/value /property /configurationhdfs-site.xml关闭权限检查毕设无需安全指定 NameNode 和 DataNode 存储目录?xml version1.0 encodingUTF-8? ?xml-stylesheet typetext/xsl hrefconfiguration.xsl? configuration property namedfs.replication/name value1/value /property property namedfs.namenode.name.dir/name valuefile:/opt/hadoop/data/namenode/value /property property namedfs.datanode.data.dir/name valuefile:/opt/hadoop/data/datanode/value /property property namedfs.permissions.enabled/name valuefalse/value /property /configurationmapred-site.xml启用 MapReduce 框架YARN 模式?xml version1.0 encodingUTF-8? ?xml-stylesheet typetext/xsl hrefconfiguration.xsl? configuration property namemapreduce.framework.name/name valueyarn/value /property /configurationyarn-site.xml配置 ResourceManager 地址和 NodeManager 启动参数?xml version1.0 encodingUTF-8? ?xml-stylesheet typetext/xsl hrefconfiguration.xsl? configuration property nameyarn.nodemanager.aux-services/name valuemapreduce_shuffle/value /property property nameyarn.resourcemanager.hostname/name valuelocalhost/value /property property nameyarn.nodemanager.resource.memory-mb/name value4096/value /property property nameyarn.scheduler.maximum-allocation-mb/name value4096/value /property /configuration注意yarn.nodemanager.resource.memory-mb和yarn.scheduler.maximum-allocation-mb必须小于你虚拟机总内存建议设为总内存的 60%。若设为 8192 但虚拟机只有 6G 内存start-yarn.sh会静默失败。2.4 启动并验证 HDFS/YARNjps是你的第一道健康检查执行前必须格式化 NameNode仅首次hdfs namenode -format然后依次启动# 启动 HDFSNameNode DataNode start-dfs.sh # 启动 YARNResourceManager NodeManager start-yarn.sh验证进程是否存活jps正常输出应包含2134 NameNode 2256 DataNode 2389 ResourceManager 2492 NodeManager 2601 Jps逻辑说明jps是 JDK 自带的进程查看工具比ps aux | grep java更精准。NameNode 和 DataNode 必须同时存在否则hdfs dfs -ls /会报Connection refusedResourceManager 和 NodeManager 缺一不可否则 Hive 的INSERT OVERWRITE TABLE ... SELECT ...会卡在ACCEPTED状态不动。最后验证 HDFS 可读写hdfs dfs -mkdir -p /user/hive/warehouse hdfs dfs -ls /user # 应看到 /user/hive 目录3. Hive 建库建表避坑指南为什么你的job_info表总查不到数据Hive 表查不到数据90% 的原因是元数据Metastore没连上或表位置LOCATION指向了 HDFS 上不存在的路径或字段分隔符与原始 CSV 文件不一致。毕设里常见的“导入数据后SELECT COUNT(*) FROM job_info返回 0”往往不是数据没导入而是 Hive 根本没把文件当数据源读。3.1 Hive Metastore 必须独立启动别信hive --service metastore 能后台常驻Hive 3.1.3 默认使用 Derby 作为嵌入式元数据库但 Derby 不支持多会话并发即你开两个终端一个hive一个beeline第二个必报错。毕设必须改用 MySQL 作为 Metastore 后端——不是为了高可用而是为了避免“启动 Hive 就卡死”这个玄学问题。步骤一安装 MySQL 并创建 metastore 数据库# Ubuntu 安装 MySQL 8.0推荐兼容 Hive 3.1.3 sudo apt update sudo apt install mysql-server sudo mysql -u root -p在 MySQL 中执行CREATE DATABASE hive_metastore CHARACTER SET latin1; CREATE USER hiveuserlocalhost IDENTIFIED BY hivepass123; GRANT ALL PRIVILEGES ON hive_metastore.* TO hiveuserlocalhost; FLUSH PRIVILEGES; EXIT;步骤二下载 MySQL JDBC 驱动并放入 Hive libwget https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-8.0.33.tar.gz tar -xzf mysql-connector-java-8.0.33.tar.gz cp mysql-connector-java-8.0.33/mysql-connector-java-8.0.33.jar $HIVE_HOME/lib/步骤三配置hive-site.xml指向 MySQL Metastore?xml version1.0 encodingUTF-8? ?xml-stylesheet typetext/xsl hrefconfiguration.xsl? configuration !-- 指定 Metastore 服务地址 -- property namehive.metastore.uris/name valuethrift://localhost:9083/value /property !-- 指定元数据库类型 -- property namejavax.jdo.option.ConnectionURL/name valuejdbc:mysql://localhost:3306/hive_metastore?createDatabaseIfNotExisttrueamp;useSSLfalseamp;serverTimezoneUTC/value /property property namejavax.jdo.option.ConnectionDriverName/name valuecom.mysql.cj.jdbc.Driver/value /property property namejavax.jdo.option.ConnectionUserName/name valuehiveuser/value /property property namejavax.jdo.option.ConnectionPassword/name valuehivepass123/value /property !-- 关键禁用 Hive 自动创建表结构 -- property namedatanucleus.autoCreateSchema/name valuefalse/value /property !-- 关键禁用 Hive 自动更新表结构 -- property namedatanucleus.fixedDatastore/name valuetrue/value /property !-- 指定 HDFS 上的 warehouse 目录 -- property namehive.metastore.warehouse.dir/name valuehdfs://localhost:9000/user/hive/warehouse/value /property /configuration参数说明datanucleus.autoCreateSchemafalse是血泪经验——Hive 第一次连 MySQL 时若设为true会尝试建几十张表但 MySQL 8.0 默认sql_mode含STRICT_TRANS_TABLES导致建表失败如CREATE TABLE COLUMNS_V2中COMMENT字段长度超限。设为false后我们手动初始化 schema。步骤四手动初始化 Metastore Schemaschematool -dbType mysql -initSchema若报错Table VERSION doesnt exist说明初始化失败删掉 MySQL 中hive_metastore库重来若成功会输出Initialization script completed。步骤五启动 Metastore 服务前台运行便于看日志nohup hive --service metastore $HIVE_HOME/logs/metastore.log 21 验证 Metastore 是否监听 9083 端口netstat -tuln | grep 9083 # 应看到 tcp6 0 0 :::9083 :::* LISTEN3.2 创建招聘数据表job_info的 DDL 必须匹配原始 CSV 字段顺序与分隔符假设你拿到的招聘数据是jobs.csv首行为字段名用英文逗号分隔内容类似job_id,job_title,company_name,salary_min,salary_max,city,experience,education,job_desc 1001,Java开发工程师,北京某某科技有限公司,15000,25000,北京,3-5年,本科,熟悉Spring Boot...对应 Hive 表 DDL 必须严格匹配-- 进入 hive CLI hive -- 创建数据库避免污染 default 库 CREATE DATABASE IF NOT EXISTS recruit_db; USE recruit_db; -- 创建外部表重点EXTERNAL且 LOCATION 指向 HDFS 路径 CREATE EXTERNAL TABLE IF NOT EXISTS job_info ( job_id STRING, job_title STRING, company_name STRING, salary_min INT, salary_max INT, city STRING, experience STRING, education STRING, job_desc STRING ) ROW FORMAT DELIMITED FIELDS TERMINATED BY , LINES TERMINATED BY \n STORED AS TEXTFILE LOCATION hdfs://localhost:9000/user/hive/warehouse/recruit_db.db/job_info;逻辑说明EXTERNAL TABLE是关键。它告诉 Hive “数据不在 Hive 管控下删表不删数据”避免误删原始 CSVLOCATION必须是 HDFS 路径不是本地/home/user/jobs.csv且该路径需提前在 HDFS 中创建并上传数据。上传数据到 HDFS# 创建 HDFS 目录 hdfs dfs -mkdir -p /user/hive/warehouse/recruit_db.db/job_info # 上传本地 CSV注意CSV 文件不能有 BOM 头用 vim :set nobomb 保存 hdfs dfs -put /home/ubuntu/jobs.csv /user/hive/warehouse/recruit_db.db/job_info/ # 验证上传成功 hdfs dfs -ls /user/hive/warehouse/recruit_db.db/job_info/ # 应看到 jobs.csv3.3 Hive 小文件问题实战INSERT OVERWRITE后生成 100 个 1KB 文件用SET hive.merge.mapfilestrue招聘数据量不大几万条但 Hive 默认 MapReduce 任务会切分成多个小文件写入 HDFS导致后续SELECT * FROM job_info扫描效率极低且 HBase BulkLoad 无法处理碎片文件。解决方法在 Hive CLI 中执行以下设置再做 INSERT-- 进入 hive CLI 后先执行这些优化参数 SET hive.merge.mapfilestrue; SET hive.merge.mapredfilestrue; SET hive.merge.size.per.task256000000; -- 256MB SET hive.exec.reducers.bytes.per.reducer256000000; -- 然后执行 INSERT例如清洗城市字段 INSERT OVERWRITE TABLE job_info_clean SELECT job_id, TRIM(job_title) as job_title, TRIM(company_name) as company_name, salary_min, salary_max, CASE WHEN city RLIKE ^[京津沪渝]|(北京|上海|天津|重庆) THEN 直辖市 WHEN city RLIKE ^(广东|江苏|浙江|山东|河南) THEN 省份 ELSE city END as city_category, experience, education, SUBSTR(job_desc, 1, 200) as job_desc_short FROM job_info;参数说明hive.merge.mapfilestrue让 Hive 在 Map 阶段结束后自动合并小文件hive.merge.size.per.task设为 256MB确保最终每个输出文件至少 256MB对毕设数据量足够reducers.bytes.per.reducer控制 Reduce 任务数量避免生成过多 reducer 输出文件。4. HBase 表设计与数据写入RowKey 不是随便拼的job_id:city:timestamp是自杀式设计HBase 不是“Hadoop 上的 MySQL”它的性能生死线在RowKey 设计。毕设里常见错误是把job_id直接当 RowKey结果所有写请求打到同一个 RegionServer 上put操作延迟飙升到 5s前端刷新页面等得怀疑人生。真正的招聘分析场景你需要按城市维度快速聚合岗位数、按公司维度查所有职位、按薪资范围范围扫描——这决定了 RowKey 必须是复合的、可散列的、可前缀扫描的。4.1 招聘场景下的 HBase 表结构设计job_info_hbase表的三列族我们设计一张表job_info_hbase含三个列族Column Familycf1存储基础属性job_title,company_name,city,experiencecf2存储薪资信息salary_min,salary_max,salary_avgcf3存储文本摘要job_desc_short,keywords建表命令在hbase shell中执行# 进入 hbase shell hbase shell # 创建表预分区 16 个 region防热点 create job_info_hbase, {NAME cf1, TTL 2592000}, # cf1 保留 30 天 {NAME cf2, TTL 2592000}, {NAME cf3, TTL 2592000}, {SPLITS [0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f]} # 验证建表成功 list describe job_info_hbase逻辑说明SPLITS参数将表按十六进制前缀预分区使0001,1a2b,f3e4等不同 RowKey 散列到不同 RegionServer避免写入热点。TTL 设为 30 天2592000 秒防止测试数据长期占满 HBase 存储。4.2 RowKey 设计用md5(city _ company_name).substring(0,4) _ job_id实现城市公司双散列错误示范RowKey job_id→ 所有job_id1001,1002... 连续写入打到同一 Region。正确做法让 RowKey 前缀具备业务查询意义且前缀本身是散列的。招聘分析最常查的是“某城市有多少岗位”所以 RowKey 前缀必须是城市相关但不能是纯城市名如beijing_1001→ 所有北京岗位挤一起。我们采用RowKey md5(city _ company_name).substring(0,4) _ job_id例如city北京,company_name百度→md5(北京_百度) a1b2c3d4...→ 前4位a1b2job_id1001→ 最终 RowKey a1b2_1001这样同一城市的岗位被散列到 16 个前缀0000_,0001_, ...,ffff_下彻底防热点同时按a1b2_前缀 scan就能拿到百度在北京的所有岗位。Java 写入代码片段HBaseDao.java关键部分public void insertJob(JobEntity job) throws IOException { Configuration config HBaseConfiguration.create(); config.set(hbase.zookeeper.quorum, localhost); config.set(hbase.zookeeper.property.clientPort, 2181); Connection connection ConnectionFactory.createConnection(config); Table table connection.getTable(TableName.valueOf(job_info_hbase)); // 生成 RowKeymd5(city_company).substring(0,4) _ job_id String rowKeyStr DigestUtils.md5Hex(job.getCity() _ job.getCompanyName()).substring(0, 4) _ job.getJobId(); Put put new Put(Bytes.toBytes(rowKeyStr)); put.addColumn(Bytes.toBytes(cf1), Bytes.toBytes(job_title), Bytes.toBytes(job.getJobTitle())); put.addColumn(Bytes.toBytes(cf1), Bytes.toBytes(company_name), Bytes.toBytes(job.getCompanyName())); put.addColumn(Bytes.toBytes(cf1), Bytes.toBytes(city), Bytes.toBytes(job.getCity())); put.addColumn(Bytes.toBytes(cf2), Bytes.toBytes(salary_min), Bytes.toBytes(job.getSalaryMin())); put.addColumn(Bytes.toBytes(cf2), Bytes.toBytes(salary_max), Bytes.toBytes(job.getSalaryMax())); put.addColumn(Bytes.toBytes(cf3), Bytes.toBytes(job_desc_short), Bytes.toBytes(job.getJobDescShort())); table.put(put); table.close(); connection.close(); }依赖说明DigestUtils.md5Hex()来自 Apache Commons Codec需在pom.xml中添加dependency groupIdcommons-codec/groupId artifactIdcommons-codec/artifactId version1.15/version /dependency4.3 从 Hive 导出数据到 HBase用org.apache.hadoop.hbase.mapreduce.TableOutputFormat批量写入手动put一条条写太慢。Hive 提供INSERT ... SELECT ...直接写 HBase 的能力但需配置hbase-site.xml到 Hive classpath并启用 HBase Storage Handler。步骤一拷贝 HBase 配置和 JAR 包到 Hivecp $HBASE_HOME/conf/hbase-site.xml $HIVE_HOME/conf/ cp $HBASE_HOME/lib/hbase-client-2.4.18.jar $HIVE_HOME/lib/ cp $HBASE_HOME/lib/hbase-common-2.4.18.jar $HIVE_HOME/lib/ cp $HBASE_HOME/lib/hbase-protocol-2.4.18.jar $HIVE_HOME/lib/ cp $HBASE_HOME/lib/htrace-core-3.1.0-incubating.jar $HIVE_HOME/lib/步骤二在 Hive 中创建 HBase 关联表-- 创建 Hive 外部表映射到 HBase 表 CREATE EXTERNAL TABLE hbase_job_info ( rowkey STRING, job_title STRING, company_name STRING, city STRING, salary_min INT, salary_max INT, job_desc_short STRING ) STORED BY org.apache.hadoop.hive.hbase.HBaseStorageHandler WITH SERDEPROPERTIES ( hbase.columns.mapping :key,cf1:job_title,cf1:company_name,cf1:city,cf2:salary_min,cf2:salary_max,cf3:job_desc_short ) TBLPROPERTIES ( hbase.table.name job_info_hbase, hbase.mapred.output.outputtable job_info_hbase ); -- 将 Hive 清洗后的数据插入 HBase 表 INSERT OVERWRITE TABLE hbase_job_info SELECT CONCAT(SUBSTR(MD5(CONCAT(city, _, company_name)), 1, 4), _, job_id) AS rowkey, job_title, company_name, city, salary_min, salary_max, job_desc_short FROM job_info_clean;注意hbase.columns.mapping中:key表示 HBase RowKey必须是第一个字段cf1:job_title表示列族cf1下的列job_title。此 SQL 会触发 MapReduce 任务将 Hive 表数据批量写入 HBase速度比 Java 单条put快 10 倍以上。5. ECharts 数据接口与前端渲染JSON 字段名错一位饼图就变空白ECharts 页面白屏、图表不渲染、控制台报Cannot read property length of undefined99% 是后端/api/job-stats接口返回的 JSON 结构与前端echarts.init(dom).setOption({})中series.data期望的格式不一致。毕设里最常踩的坑是后端返回{ data: [ { name: 北京, value: 120 } ] }但前端代码写成了response.data.list或response.items。5.1 Spring Boot 后端接口JobStatsController.java必须返回标准 ECharts 数据结构以“各城市岗位数饼图”为例ECharts 饼图series.data要求数组元素为{ name: 北京, value: 120 }。后端必须严格按此结构返回RestController RequestMapping(/api) public class JobStatsController { Autowired private HBaseDao hBaseDao; /** * 获取各城市岗位数统计用于 ECharts 饼图 * 返回格式{ data: [ {name: 北京, value: 120}, {name: 上海, value: 98} ] } */ GetMapping(/job-count-by-city) public ResponseEntityMapString, Object getJobCountByCity() { try { ListMapString, Object result hBaseDao.getJobCountByCity(); MapString, Object response new HashMap(); response.put(data, result); // 关键外层必须包一层 data return ResponseEntity.ok(response); } catch (Exception e) { e.printStackTrace(); return ResponseEntity.status(500).build(); } } }HBaseDao.getJobCountByCity()方法用 Scan 扫描job_info_hbase表按cf1:city列聚合public ListMapString, Object getJobCountByCity() throws IOException { Configuration config HBaseConfiguration.create(); config.set(hbase.zookeeper.quorum, localhost); Connection connection ConnectionFactory.createConnection(config); Table table connection.getTable(TableName.valueOf(job_info_hbase)); // 扫描全表提取 cf1:city 列 Scan scan new Scan(); scan.addFamily(Bytes.toBytes(cf1)); scan.addColumn(Bytes.toBytes(cf1), Bytes.toBytes(city)); ResultScanner scanner table.getScanner(scan); MapString, Integer cityCount new HashMap(); for (Result result : scanner) { byte[] cityBytes result.getValue(Bytes.toBytes(cf1), Bytes.toBytes(city)); if (cityBytes ! null) { String city Bytes.toString(cityBytes); cityCount.put(city, cityCount.getOrDefault(city, 0) 1); } } scanner.close(); table.close(); connection.close(); // 转为 ECharts 要求的 [{name: 北京, value: 120}] 格式 ListMapString, Object echartsData new ArrayList(); for (Map.EntryString, Integer entry : cityCount.entrySet()) { MapString, Object item new HashMap(); item.put(name, entry.getKey()); item.put(value, entry.getValue()); echartsData.add(item); } return echartsData; }5.2 前端 ECharts 初始化$.ajax成功回调里必须chart.setOption()且series.data指向response.dataHTML 页面中引入 EChartsCDN 方式最稳避免 webpack 构建问题!DOCTYPE html html head meta charsetutf-8 title招聘数据分析平台/title script srchttps://cdn.jsdelivr.net/npm/echarts5.4.3/dist/echarts.min.js/script /head body div idcity-pie stylewidth: 600px; height: 400px;/div script // 初始化图表 const chartDom document.getElementById(city-pie); const myChart echarts.init(chartDom); // 发起 AJAX 请求 $.ajax({ url: /api/job-count-by-city, type: GET, dataType: json, success: function(response) { // 关键response.data 是后端返回的数组 const seriesData response.data || []; // 配置 option const option { title: { text: 各城市岗位分布, left: center }, tooltip: { trigger: item }, legend: { orient: vertical, right: 10, top: middle }, series: [{ name: 岗位数, type: pie, radius: 50%, data: seriesData, // ←←← 必须是 response.data不是 response 或 response.list emphasis: { itemStyle: { shadowBlur: 10, shadowOffsetX: 0, shadowColor: rgba(0, 0, 0, 0.5) } } }] }; // 渲染图表 myChart.setOption(option); }, error: function(xhr, status, error) { console.error(API 请求失败:, error); myChart.setOption({ title: { text: 数据加载失败, left: center }, series: [{ type: pie, data: [] }] }); } }); /script /body /html逻辑说明response.data是后端response.put(data, result)写入的 key前端必须用response.data取值。若后端返回{ items: [...] }前端就必须写response.items否则series.data为undefinedECharts 会静默失败。5.3 ECharts 常见渲染失败排查三步定位法现象原因解决页面空白控制台无报错HTML 中div idchart的 width/height 为 0如父容器display:none或未设尺寸给#chart加stylewidth:600px;height:400px;本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑