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

目录

前言

一、后台管理设计与实现

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进行地震预警展示,最后展示预警可视化效果。地址灾害不可预测,但是我们在灾后应该快速提供应急救援,将尽量减少人民群众的生命财产损失。行文仓促,定有不足之处,不管是批评或者指导,不妨来博文中指导一二,不胜感激。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

智能写作工具,一键改写文章不费力

改写是一种用来创作原创文章的方式&#xff0c;也是用来提升文章质量的方法。无论我们在创作中通过改写来提升文章的质量&#xff0c;还是用改写帮助我们达到原创文章的生成&#xff0c;文章改写都可以实现我们这些目的&#xff0c;然而&#xff0c;想要高效率轻松改写文章我们…

三分钟设计自己的工厂!基于昇腾AI处理器昇思MindSpore打造的智能化工大模型为化工研发效率带来10+倍提升

前言&#xff1a;华为与大连化物所深度合作&#xff0c;联合推出智能化工大模型&#xff0c;AI赋能化工领域&#xff0c;拥抱科学创新&#xff0c;提供了数据驱动化工研发的新范式。 2024年3月22日&#xff0c;在北京国家会议中心召开的昇思人工智能框架峰会上发布了由华为AI4…

VForm3的文件上传方式

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 http://122.227.135.243:9666/ 更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码&#xff1a…

智能条件单无需盯盘!

一般我们说到量化交易都觉得很困难&#xff0c;写策略难&#xff0c;看python难&#xff0c;不会使用程序难&#xff0c;电脑交易不方便难&#xff0c;今天我们来看看手机电脑都可以使用的量化基础条件单的操作。 迈入量化第一步&#xff0c;条件单的使用&#xff01; 今天小编…

企业微信hook接口协议,标签变动回调

个人标签新增回调 {"labellist": [{"op": 3, "bDeleted": 0, //0代表新增"create_time": 1678114162, "label_groupid": 14073749131792038, "label_type": 2, "source_appid": 0, "business_typ…

Python 装饰器

Python 装饰器 1. 简单的装饰器 下面是一个简单的装饰器示例&#xff0c;它记录被装饰函数的调用信息&#xff1a; def my_decorator(func):""" 中层函数&#xff1a;接收被装饰的函数 """def wrapper():""" 内层函数&#xf…

嵌入式4-25

整理思维导图在课上练习的基础上&#xff0c;完成拷贝赋值函数完成下列类 #include <iostream> using namespace std;class person {string name;int age;char sex; public:int *p;person(){cout<<"person无参构造"<<endl;};person(const string n…

专业护眼灯什么牌子好?2024年专业护眼灯品牌排行分享

专业护眼灯什么牌子好&#xff1f;各位家长可能已经注意到一个令人关切的现象&#xff1a;戴眼镜的孩子人数在不断上升&#xff0c;许多孩子正在接受眼部治疗。眼睛健康的问题变得越来越普遍&#xff0c;这无疑令人担忧。在当今数字化时代&#xff0c;孩子们每日需长时间阅读和…

对腾讯文档AI助手技术架构的简单分析

腾讯文档全面接入了AI&#xff0c;今天腾讯技术大佬tensorchen作者发表了一篇文章《腾讯文档AI助手技术实践》&#xff0c; 里面讲解了从技术应用架构以及AI大模型赋能角度&#xff0c;介绍腾讯文档AI智能助手的探索和实践之路。作为一款集多功能为一体的AI产品&#xff0c;腾…

Web前端开发之HTML_3

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

(八)Servlet教程——创建Web项目以及Servlet的实现

1. 打开Idea编辑器 2. 点击界面上的“新建项目”按钮 3. 设置好项目名称和位置 应用服务器选择之前设置好的Tomcat服务器 构建系统默认选择Maven 4. 点击“下一步”按钮 5. 点击“完成”按钮&#xff0c;Idea就创建好了项目&#xff0c;创建完成后的目录结构如下图所示 6. 此…

2024.4.25

#include <iostream> #include <iomanip> using namespace std; class Person{const string name;int age;char sex; public:Person(const string name):name(name){cout << "第一个Person构造函数" << endl;}Person():name("zhangsan&…

js网络请求---fetch和XMLHttpRequest的用法

fetch 语法规则 let promise fetch(url, [options]) //url —— 字符串&#xff1a;要访问的 URL。 //options —— 对象&#xff1a;可选参数&#xff1a;method&#xff0c;header 等。 fetch函数返回一个promise&#xff0c;若存在网络问题&#xff0c;或网址不存在&…

Java通过邮件发送验证码和通过手机号发送验证码

前提&#xff1a;我将验证码存入了map集合&#xff0c;进行验证。 private static HashMap<String, Integer> emailMap new HashMap<>();一、通过邮箱发送验证码&#xff1a; 1、准备条件&#xff1a;引入hutool依赖&#xff0c; <!--hutool--><depend…

【C语言】深入理解KMP算法及C语言实现

一、KMP算法简介 KMP算法&#xff08;Knuth-Morris-Pratt算法&#xff09;是一种高效的字符串匹配算法&#xff0c;由Donald Knuth、James H. Morris和 Vaughan Pratt共同发明。KMP算法的核心思想是当一次字符比较失败时&#xff0c;利用已经得到的部分匹配信息&#xff0c;将模…

Kubernetes TDengine 系列|安装 TDengine 的 Grafana 插件|Grafana监控TDengine数据

为了让Grafana 能够监控到TDengine 数据&#xff0c;快速集成搭建数据监测报警系统&#xff0c;所以直接安装TDengine 插件。 目录 一、安装 TDengine 的 Grafana 插件1、下载TDengine grafana插件2、解压到指定目录3、配置未签名插件 二、配置数据源&#xff0c;简单查询TDen…

想在游泳健身的同时畅听音乐,随时哈氪漫游这款IP68防水的骨传导耳机

平时健身的过程中&#xff0c;音乐是许多健身爱好者的忠实伴侣。无论是在室内的健身房&#xff0c;还是户外的自然风光中&#xff0c;一副优质的耳机可以极大地提升我们的锻炼体验。现在市面上专为运动设计的耳机选择非常多&#xff0c;我喜欢用骨传导耳机&#xff0c;目前在用…

Linux--忘记root密码解决办法

Linux忘记密码解决的方法有两种&#xff1a; 方法一&#xff1a; 第一步&#xff1a;打开虚拟机时&#xff0c;疯狂按方向键&#xff0c;让该虚拟机不进入系统停留在开机界面&#xff0c;按方向键使光标停留在第一行&#xff0c;按字母E编辑它&#xff0c;如 按E后&#xff0…

数据结构 - 链表详解(二)—— 带头双向循环链表

链表的介绍 链表的结构一共有八种&#xff1a;带头单向循环链表、带头单向非循环链表、带头双向循环链表、带头双向非循环链表、无头单向循环链表、无头单向非循环链表、无头双向循环链表、无头双向非循环链表。 今天我们来详解带头双向循环链表 带头双向循环链表是一种数据结…

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

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