基于SpringBoot和Leaflet的地震台网信息预警可视化

news2025/1/12 6:52:33

目录

前言

一、后台管理设计与实现

1、Model层

2、业务层

3、控制层

二、前端预警可视化设计与实现

1、网页结构

2、数据绑定

三、效果展示

总结


前言

        在之前的几篇博客中,我们讲解了如何在Leaflet中进行预警信息提示效果,以及基于XxlCrawler进行中国地震台网信息的采集、入库以及如何进行反爬处理。博文目录如下,感兴趣的朋友可以点击标题进入:

序号博客地址
1基于Leaflet.js的Marker闪烁特效的实现-模拟预警
2基于Java的XxlCrawler网络信息爬取实战-以中国地震台网为例
3使用SpringBoot将中国地震台网数据保存PostGIS数据库实践
4在Java中使用XxlCrawler时防止被反爬的几种方式

        在实际应用中,我们不仅需要将数据及时的采集回来,同时也需要实现对数据进行可视化。不仅对二维数据的列表展示,同时还需要对数据进行空间可视化。

        本文即对采集回来的中国地震台网数据进行预警可视化进行深入讲解。首先讲解后台的代码和功能设计,然后基于L.Icon.Pulse进行地震预警展示,最后展示预警可视化效果。地址灾害不可预测,但是我们在灾后应该快速提供应急救援,将尽量减少人民群众的生命财产损失。如果您目前也有类似的需求,不妨来博文中指导一二。

一、后台管理设计与实现

        后台管理使用SpringBoot框架来开发,数据库访问层依然采用熟悉的Mybatis-Plus框架。本小节将主要基于MVC结构介绍后台的相关设计与实现。数据后台提供数据访问支持,为前台的数据展示提供有效支撑。

1、Model层

        model层包含地震台网数据的实体类,在之前的博客中有过介绍,这里也将主要的代码分享出来。让大家在熟悉这部分代码时,不至于有不适感:

package com.yelang.project.extend.earthquake.domain.crawler;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.google.gson.annotations.SerializedName;
import com.yelang.framework.handler.PgGeometryTypeHandler;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
@TableName(value ="biz_ceic_earthquake",autoResultMap = true)
public class CeicEarthquake implements Serializable{
	private static final long serialVersionUID = -1212153879708670015L;
	@TableId(value="pk_id")
	private Long pkId;//主键
	@SerializedName("AUTO_FLAG")
	@TableField(value="auto_flag")
	private String autoFlag;
	@SerializedName("CATA_ID")
	@TableField(value="cata_id")
	private String cataId;
	@SerializedName("CATA_TYPE")
	@TableField(value="cata_type")
	private String cataType;
	@SerializedName("EPI_DEPTH")
	@TableField(value="epi_depth")
	private BigDecimal epiDepth = new BigDecimal("0.0");
	@SerializedName("EPI_LAT")
	@TableField(value="epi_lat")
	private String epiLat;//纬度
	@SerializedName("EPI_LON")
	@TableField(value="epi_lon")
	private String epiLon;
	@SerializedName("EQ_CATA_TYPE")
	@TableField(value="eq_cata_type")
	private String eqCataType;
	@SerializedName("EQ_TYPE")
	@TableField(value="eq_type")
	private String eqType;
	@SerializedName("IS_DEL")
	@TableField(value="is_del")
	private String isDel;
	@SerializedName("LOCATION_C")
	@TableField(value="location_c")
	private String locationC;
	@SerializedName("LOCATION_S")
	@TableField(value="location_s")
	private String locationS;
	@SerializedName("LOC_STN")
	@TableField(value="loc_stn")
	private String locStn;
	@SerializedName("M")
	@TableField(value="m")
	private String m;
	@SerializedName("M_MB")
	@TableField(value="mmb")
	private String mmb;
	@SerializedName("M_MB2")
	@TableField(value="mmb2")
	private String mmb2;
	@SerializedName("M_ML")
	@TableField(value="mml")
	private String mml;
	@SerializedName("M_MS")
	@TableField(value="mms")
	private String mms;
	@SerializedName("M_MS7")
	@TableField(value="mms7")
	private String mms7;
	@SerializedName("NEW_DID")
	@TableField(value="new_did")
	private String newDid;
	@SerializedName("O_TIME")
	@TableField(value="o_time")
	private Date oTime;
	@SerializedName("O_TIME_FRA")
	@TableField(value="o_time_fra")
	private String oTimeFra;
	@SerializedName("SAVE_TIME")
	@TableField(value="save_time")
	private Date saveTime;
	@SerializedName("SUM_STN")
	@TableField(value="sum_stn")
	private String sumStn;
	@SerializedName("SYNC_TIME")
	@TableField(value="sync_time")
	private Date syncTime;
	@SerializedName("id")
	@TableField(value="epi_id")
	private String epiId;
	@TableField(typeHandler = PgGeometryTypeHandler.class)
	private String geom;
	@TableField(exist=false)
	private String geomJson;
}

        Maper层没有其它特殊的业务,仅实现了基础的BaseMapper,方法体内没有扩展业务。在此不再赘述。 

2、业务层

        业务层作为控制层和模型层的中间层,主要负责数据的传递以及业务逻辑的处理。在地震可视化中,需要扩展的方法是需要提供按照震中位置和震级进行模糊 查询,同时提供按照地震主键查询地震详情的接口。在进行地震预警时,通过ajax获取详情实现地震位置的可视化。

根据震中位置和震级模糊查询的核心方法如下:

@Override
public List<CeicEarthquake> getList(CeicEarthquake earthquake) {
	QueryWrapper<CeicEarthquake> queryWrapper = new QueryWrapper<CeicEarthquake>();
	if (StringUtils.isNotBlank(earthquake.getLocationC())) {
		queryWrapper.like("location_c", earthquake.getLocationC());
	}
	if (StringUtils.isNotBlank(earthquake.getM())) {
		queryWrapper.eq("m", earthquake.getM());
	}
	queryWrapper.orderByDesc("o_time");
	return this.baseMapper.selectList(queryWrapper);
}

3、控制层

        控制层是对接前台,接收前台请求,调用业务层的业务方法,查询相关数据或者保存相关数据的入口。前端地图展示和列表展示都是通过控制层实现。在控制层中,主要实现以下三个方法:

序号方法说明
1 public String index()跳转到首页
2public TableDataInfo list(CeicEarthquake earthquake)根据震中位置和震级查询信息
3public AjaxResult detail(@PathVariable("pkId")Long pkId)根据数据ID查询数据详情

        关键代码如下:

package com.yelang.project.extend.earthquake.controller;
import java.util.List;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.yelang.framework.aspectj.lang.annotation.Log;
import com.yelang.framework.aspectj.lang.enums.BusinessType;
import com.yelang.framework.web.controller.BaseController;
import com.yelang.framework.web.domain.AjaxResult;
import com.yelang.framework.web.page.TableDataInfo;
import com.yelang.project.extend.earthquake.domain.EarthquakeInfo;
import com.yelang.project.extend.earthquake.domain.crawler.CeicEarthquake;
import com.yelang.project.extend.earthquake.service.ICeicEarthquakeService;

@Controller
@RequestMapping("/ceiceq/info")
public class CeicEarthquakeInfoController extends BaseController{
	private String prefix = "ceicearthquake/info";
    @Autowired
    private ICeicEarthquakeService ceicEarthQuakeService;
    @RequiresPermissions("ceiceq:info:view")
    @GetMapping()
    public String index(){
        return prefix + "/index";
    }

    @RequiresPermissions("ceiceq:info:list")
    @PostMapping("/list")
    @ResponseBody
    public TableDataInfo list(CeicEarthquake earthquake){
        startPage();
        List<CeicEarthquake> list = ceicEarthQuakeService.getList(earthquake);
        return getDataTable(list);
    }
    
    @PostMapping("/detail/{pkId}")
    @ResponseBody
    public AjaxResult detail(@PathVariable("pkId")Long pkId){
        AjaxResult ar = AjaxResult.success();
        ar.put("data", ceicEarthQuakeService.getById(pkId));
        return ar;
    }
}

        到此,我们已经将相关的服务接口开发完成,同时完成了对数据库数据的访问和调用。在完成后端的应用开发之后,我们来进行前端可视化的开发。

二、前端预警可视化设计与实现

        为了在前端方便的对地震信息进行综合展示,我们计划将数据和底图使用Leaflet来进行集成。使用之前介绍过的预警信息实现方式。本小节主要是面向前端的设计与实现。

1、网页结构

        为了比较直观的展示信息,同时将列表和地图定位技术进行结合。我们决定采用栅格布局的模式,台网地震信息和地图分别占50%。在html的框架中大致采用如下的结构来展示:

<div class="row">
        	<div class="col-sm-6">
	        	<div class="col-sm-12 search-collapse" style="display: none;">
	                <form id="formId">
	                    <div class="select-list">
	                        <ul>
	                            <li>
	                                <label>发震位置:</label>
	                                <input type="text" name="locationC"/>
	                            </li>
	                            <li>
	                                <label>震级:</label>
	                                <input type="text" name="m"/>
	                            </li>
	                            <li>
	                                <a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
	                                <a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
	                            </li>
	                        </ul>
	                    </div>
	                </form>
	            </div>
	            <div class="btn-group-sm" id="toolbar" role="group">
	                <a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="eq:info:export">
	                    <i class="fa fa-download"></i> 导出
	                </a>
	            </div>
	            <div class="col-sm-12 select-table table-striped">
	                <table id="bootstrap-table"></table>
	            </div>
        	</div>
        	<div class="col-sm-6">
        		<!-- leaflet map元素 -->
				<div id="mapid" style="width: 100%;"></div>
        	</div>
        </div>

2、数据绑定

        在定义好网页框架结构之后,我们需要将列表和后台的接口进行对接,同时将地图和底图进行绑定。关于如何在Leaflet中进行底图绑定,应该很多朋友都比较了解了。这里不再进行过多的说明。这里仅说明如何进行table的绑定和预警可视化。

        table绑定:为了将地震信息,如震发地点、震级、地震深度、经纬度等信息在列表中展示出来。这里采用layui的table组件。数据绑定的关键代码如下:

var options = {
         url: prefix + "/list",
         exportUrl: prefix + "/export",
         modalName: "台网地震信息",
         columns: [
         {
              field: 'id',
              title: '',
              visible: false
         },
         {
            field: 'locationC',
            title: '震中位置',
            formatter: function(value, row, index) {
           return parseFloat(row.m) >= '6.0' ? "<font color='red'>"+ value +"</font>" : value;
                    }
                },
                {
                    field: 'epiLon',
                    title: '经度',
                    formatter: function(value, row, index) {
                        return parseFloat(row.m) >= '6.0' ? "<font color='red'>"+ value +"</font>" : value;
                    }
                },
                {
                    field: 'epiLat',
                    title: '纬度',
                    formatter: function(value, row, index) {
                        return parseFloat(row.m) >= '6.0' ? "<font color='red'>"+ value +"</font>" : value;
                    }
                    
                },
                {
                    field: 'm',
                    title: '震级',
                    formatter: function(value, row, index) {
                        return parseFloat(row.m) >= '6.0' ? "<font color='red'>"+ value +"</font>" : value;
                    }
                },
                {
                    field: 'epiDepth',
                    title: '深度',
                    formatter: function(value, row, index) {
                        return parseFloat(row.m) >= '6.0' ? "<font color='red'>"+ value +"</font>" : value;
                    }
                },
                {
                	field: 'otime',
                    title: '发震时间',
                    formatter: function(value, row, index) {
                        return parseFloat(row.m) >= '6.0' ? "<font color='red'>"+ value +"</font>" : value;
                    }
                },
                {
                    title: '操作',
                    align: 'center',
                    formatter: function(value, row, index) {
                        var actions = [];
                        actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="preview(\'' + row.pkId + '\')"><i class="fa fa-send-o"></i></a> ');
                        return actions.join('');
                    }
                }]
            };
            $.table.init(options);

        预警绑定:预警信息绑定是参考中国地震台网的信息,在列表中点击地震信息,在右边的地图中可以直接定位,同时点击预警点,可以把相应的主要信息以弹窗的形式展示出来。这里的主要逻辑就是通过ajax去后台查询台网地震信息详情。然后根据经纬度绑定marker,同时将marker在地图上进行展示。

function preview(pkId){
        	$.ajax({  
		        type:"post",  
		        url:prefix + "/detail/" + pkId,  
		        dataType:"json",  
		        cache:false,
		        processData:false,
		        success:function(result){
		        	if(result.code == web_status.SUCCESS){
		        		var eqInfo = result.data;
		        		var content = "<strong>发震时间:</strong>"+eqInfo.otime + "<br/><strong>震中位置:</strong>"+eqInfo.locationC;
    				    content += "<br/><strong>震源深度(千米):</strong>"+eqInfo.epiDepth + "<br/><strong>震级:</strong>"+eqInfo.m;
		        		var marker = L.marker([eqInfo.epiLat, eqInfo.epiLon],
		        				{icon: L.icon.pulse({iconSize:[25,25],color:'#e50b3d',fillColor:"#e50b3d"})}).bindPopup(content).addTo(mymap);
		        	    showLayerGroup.clearLayers();
		        		showLayerGroup.addLayer(marker);
		        		mymap.setView(showLayerGroup.getBounds().getCenter(),8);//同时设置中心位置和级别
		        	}
		        },
		        error:function(){
		        	$.modal.alertWarning("获取信息失败");
		        }
		    });
        }

        至此,前端的主要代码也编写完毕,最后我们将工程启动起来,然后进行前后台的联调。 展示最终的效果。

三、效果展示

        本小节主要展示基于SpringBoot和Leaflet的地震台网信息预警可视化效果。从列表搜索到地图定位,让大家对开发出来的效果有一个直观的感受。同时为了将大于(含)6级的地震信息进行醒目的提示,在列表中我们对这些数据进行标红。

默认系统功能界面

        默认情况下,列表的搜索功能是关闭的,如果您在使用过程中需要进行数据检索,可以点击搜索按钮打开检索栏。

系统检索支持页面

         在系统中,点击操作按钮栏中的定位功能。会自动实现当前地震信息在地图上的定位。

地震地图定位示意图 

台湾花莲某地地震 

青岛某地地震示意图 

四川某地地震示意图 

总结

        以上就是本文的主要内容, 本文即对采集回来的中国地震台网数据进行预警可视化进行深入讲解。首先讲解后台的代码和功能设计,然后基于L.Icon.Pulse进行地震预警展示,最后展示预警可视化效果。地址灾害不可预测,但是我们在灾后应该快速提供应急救援,将尽量减少人民群众的生命财产损失。行文仓促,定有不足之处,不管是批评或者指导,不妨来博文中指导一二,不胜感激。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1623869.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux笔记】基本指令(一)

一道残阳铺水中 半江瑟瑟半江红 目录 Linux基本指令 罗列目录内容&#xff1a;ls 指令 显示当前目录位置信息&#xff1a;pwd 指令 切换工作目录&#xff1a;cd 指令 创建文件修改时间戳&#xff1a;touch指令 创建空目录&#xff1a;mkdir指令 删除空目录&#xff1a;rmdir指…

【14-Ⅱ】Head First Java 学习笔记

HeadFirst Java 本人有C语言基础&#xff0c;通过阅读Java廖雪峰网站&#xff0c;简单速成了java&#xff0c;但对其中一些入门概念有所疏漏&#xff0c;阅读本书以弥补。 第一章 Java入门 第二章 面向对象 第三章 变量 第四章 方法操作实例变量 第五章 程序实战 第六章 Java…

uniapp如何隐藏默认的页面头部导航栏,uniapp开发小程序如何隐藏默认的页面头部导航栏

uniapp如何隐藏默认的页面头部导航栏 默认效果 隐藏后 在pages.json文件中插入 在uni-app中&#xff0c;设置navigationStyle为custom来自定义导航栏&#xff0c;可以隐藏默认的头部了。 {"path": "pages/index/index","name": "index&qu…

STM32与OLED显示屏通信(四针脚和七阵脚)

系列文章目录 STM32单片机系列专栏 C语言术语和结构总结专栏 文章目录 1. 单片机调试 2. OLED简介 3. 接线 4. OLED驱动函数 4.1 四针脚版本 OLED.c OLED.h OLED_Font.h 4.2 七针脚版本 引脚连接 OLED.c OLED.h OLED_Font.h 5. 主函数 工程文件模板 1. 单片机…

Selenium 保存会话信息避免重复登录实战!

前言 • 在一些实际开发场景中&#xff0c;我们在使用 Selenium 做自动化测试时需要保留用户的会话信息&#xff0c;从而避免重复登录&#xff0c;今天这篇文章就带大家实战如何使用 Selenium 保存会话信息。 版本 • Python 3.x 整体思路 • 当我们打开页面时&#xff0c;…

C语言-自定义类型结构体详细讲解

遇到困难时不要抱怨&#xff0c;既然改变不了过去&#xff0c;那么就努力改变未来&#xff01;&#x1f493;&#x1f493;&#x1f493; 目录 •&#x1f319;知识回顾 • &#x1f34b;知识点一&#xff1a;结构体类型的声明 ​编辑 • &#x1f330;1.结构体的声明 ​编…

web自动化系列-selenium的基本方法介绍

web自动化 &#xff0c;一个老生常谈的话题 &#xff0c;很多人的自动化之路就是从它开始 。它学起来简单 &#xff0c;但做起来又比较难以驾驭 &#xff1b;它的执行效率慢 、但又是最接近于用户的操作场景 &#xff1b; 1.web自动化中的三大亮点技术 我们先聊聊 &#xff0…

MySQL多版本并发控制mvcc原理浅析

文章目录 1.mvcc简介1.1mvcc定义1.2mvcc解决的问题1.3当前读与快照读 2.mvcc原理2.1隐藏字段2.2版本链2.3ReadView2.4读视图生成原则 3.rc和rr隔离级别下mvcc的不同 1.mvcc简介 1.1mvcc定义 mvcc(Multi Version Concurrency Control)&#xff0c;多版本并发控制&#xff0c;是…

2024深圳杯C题的8页思路分析+所有代码可执行+参考文献+持续更新参考论文(已经更新了代码与图像)

比赛题目的完整版思路可执行代码数据参考论文都会在第一时间更新上传的&#xff0c;大家可以参考我往期的资料&#xff0c;所有的资料数据以及到最后更新的参考论文都是一次付费后续免费的。注意&#xff1a;&#xff08;建议先下单占坑&#xff0c;因为随着后续我们更新资料数…

每周一算法:最短路计数

题目描述 给出一个 N N N个顶点 M M M 条边的无向无权图&#xff0c;顶点编号为 1 1 1 到 N N N。 问从顶点 1 1 1 开始&#xff0c;到其他每个点的最短路有几条。 输入格式 第一行包含 2 2 2 个正整数 N , M N,M N,M&#xff0c;为图的顶点数与边数。 接下来 M M …

vue3实现全局事件总线

1、vue3中使用全局事件总线是变化最大的。在vue2中&#xff0c;我们在new Vue中在beforeCreate钩子函数中使用vue.prototype.$busthis来创建全局事件总线。vue3中我需要借助第三方库来完成创建全局事件总线。 2、安装依赖 npm i mitt -s3、封装event-bus.js文件 import mitt …

Web前端开发之HTML_3

标签之表格Form表单块元素与行内元素&#xff08;内联元素&#xff09;HTML5新增标签 1. 标签之表格 <table></table> 1.1 表格&#xff08;快速生成&#xff1a;table>tr*2>td*3{单元格}&#xff09; 表格由行、列、单元格组成。单元格有同行等高、同列等…

【C++】:拷贝构造函数和赋值运算符重载

目录 一&#xff0c;拷贝构造函数1. 什么是拷贝构造函数2. 拷贝构造函数的特性3. 实践总结 二&#xff0c;赋值运算符重载2.1 运算符重载2.2 赋值运算符重载 一&#xff0c;拷贝构造函数 1. 什么是拷贝构造函数 拷贝构造函数是特殊的构造函数。是用一个已经存在的对象&#x…

ArtNeRF、Attention Control、Pixel is a Barrier、FilterPrompt

本文首发于公众号&#xff1a;机器感知 ArtNeRF、Attention Control、Pixel is a Barrier、FilterPrompt ArtNeRF: A Stylized Neural Field for 3D-Aware Cartoonized Face Synthesis Recent advances in generative visual models and neural radiance fields have greatly …

文件上传复习(upload-labs18-19关)

Pass-18&#xff08;条件竞争&#xff09; 代码和第17关大差不差&#xff0c;所以查看提示 需要用到代码审计 上传图片木马配合解析漏洞进行getshell 新建一句话木马 18.php&#xff0c;代码为&#xff1a; <?php fputs(fopen(../upload/shell18.php,w),<?php phpin…

js的算法-交换排序(冒泡)

交换排序 所谓交换排序&#xff0c;是指根据序列中两个元素关键字的比较结果来对换这两个记录在序列中的位置。基于交换的排序算法很多&#xff0c;本次介绍冒泡排序和快速排序。 冒泡 基本思想 从后往前&#xff08;或从前往后&#xff09;两两比较相邻元素的值&#xff0…

新风口下的必应bing国内广告投放该怎么做?

必应Bing作为全球搜索引擎市场的重要参与者&#xff0c;正逐渐显现出其在国内市场的独特价值和潜力。随着互联网生态的多元化发展&#xff0c;必应Bing凭借其高质量用户群和精准投放能力&#xff0c;成为了企业寻求新增长点的新风口。 一、洞察先机&#xff0c;精准定位市场 …

考研数学|跟武忠祥做《660》很吃力,要不要换张宇❓

不建议&#xff01; 我就是个妥妥的二战选手&#xff0c;一战听完汤家凤的课发现大量的题还是不会做&#xff0c;于是冒险把张宇的基础课听完一遍&#xff0c;毫不夸张的硕导致我最后没有强化阶段直接进入冲刺。可想而知&#xff0c;这能考好吗&#xff1f;21年数三87分&#…

ChromaDB教程

使用 Chroma DB&#xff0c;管理文本文档、将文本嵌入以及进行相似度搜索。 随着大型语言模型 &#xff08;LLM&#xff09; 及其应用的兴起&#xff0c;我们看到向量数据库越来越受欢迎。这是因为使用 LLM 需要一种与传统机器学习模型不同的方法。 LLM 的核心支持技术之一是…

JavaEE:File类查询一个文件的路径(举例+源码 )

一、File类概述 Java 中通过 java.io.File 类来对一个文件&#xff08;包括目录&#xff09;进行抽象的描述。File 类中的方法可以对文件路径以及文件名等信息进行查询&#xff0c;也可以对文件进行各项增删改操作&#xff0c;本文主要介绍 File 类的查询方法。 二、代码示例 …