前言
地理信息系统(GIS)技术在城市规划、交通管理等领域发挥着重要作用。湖南省交通网络密集,如何高效地管理和展示道路长度信息具有重要意义。本文介绍基于 Java 后端与 Leaflet 前端构建湖南省道路长度 WebGIS 系统的实践方案。

通过本实践,利用 Java 和 Leaflet 的结合为系统构建提供技术平台。文章首先介绍基础空间数据,然后介绍 Java 后台应用程序构建,最后介绍 Leaflet 进行 WebGIS 界面构建。
一、基础空间数据简介
在上一篇博客中,我们详细介绍了如何将 OSM 数据转换成公路里程信息表。为了实现地级市空间范围的展示及行政驻地标注,这里对涉及的基础空间数据进行简单介绍。
1、涉及相关表
| 序号 | 表名 | 说明 |
|---|---|---|
| 1 | biz_urban_road_mileage_info | 城市道路里程信息表,业务信息表 |
| 2 | biz_geographic_name | 城市名称信息表,点状空间数据表 |
| 3 | biz_city | 市级行政区划信息表,面状空间数据 |
我们需要在地图上展示湖南省各地市的行政区划范围,在各地市的政府驻地标注信息,显示当前行政区名称和道路里程。声明:这份数据来源于 OSM,时效性可能不是最新的,如需权威数据可从官网获取,代码和 SQL 查询逻辑一致可供参考。
2、省域道路长度检索
采用空间数据库表关联业务表进行关联查询实现,SQL 如下:
SELECT t1.*, T3.province_code, t3.province_name, st_asgeojson ( t3.geom ) geomJson, st_x ( t2.geom ) lon, st_y ( t2.geom ) lat FROM biz_urban_road_mileage_info t1, biz_geographic_name t2, biz_city t3 WHERE t1.parent_code = '430000' AND t1.city_code = t3.city_code AND T1.city_name = t2.NAME AND st_contains ( t3.geom, t2.geom );
执行以上 SQL 后,在客户端可以看到结果。SQL 中默认使用湖南省(代号 430000)作为查询条件,实际情况下需要动态替换为别的省份信息即可。
二、Java 后台实现
有了基础空间数据知识后,接下来介绍如何使用 Java 进行后台程序的实现。以 Java 经典 MVC 三层架构讲解。
1、道路视图对象
根据业务需要定义地市的行政驻地位置,扩展一个子类包装成视图对象。后台将根据业务获得查询结果后,将数据按视图对象返回。核心代码如下:
package com.yelang.project.extend.earthquake.domain;
import java.io.Serializable;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@Data
@ToString(callSuper=true)
@EqualsAndHashCode(callSuper=false)
public class UrbanRoadMileageInfoVO extends UrbanRoadMileageInfo implements Serializable {
private static final long serialVersionUID = 1101541707654186490L;
@TableField(exist = false,value= "province_code")
private String provinceCode;
@TableField(exist = false,value= "province_name")
private String provinceName;
@TableField(exist = false)
private String geomJson;
private String lat;
private String lon;
}
2、Mapper 空间检索查询
使用 MybatisPlus 进行数据库检索支持,将 SQL 写入到 Mapper 对象中。核心代码如下:
package com.yelang.project.extend.earthquake.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yelang.project.extend.earthquake.domain.UrbanRoadMileageInfo;
import com.yelang.project.extend.earthquake.domain.UrbanRoadMileageInfoVO;
public interface UrbanRoadMileageInfoMapper extends BaseMapper<UrbanRoadMileageInfo> {
static final String LIST_BYPROVINCE_SQL = "SELECT t1.city_code,MAX(t1.city_name) AS city_name," +
" SUM(CASE WHEN r.fclass IN ('motorway', 'motorway_link') THEN ST_Length(r.geom::geography) ELSE 0 END) AS highway_length, " +
" SUM(CASE WHEN r.fclass IN ('trunk', 'trunk_link') THEN ST_Length(r.geom::geography) ELSE 0 END) AS trunk_length, " +
" SUM(CASE WHEN r.fclass IN ('primary', 'primary_link') THEN ST_Length(r.geom::geography) ELSE 0 END) AS primary_length, " +
" SUM(CASE WHEN r.fclass IN ('secondary', 'secondary_link') THEN ST_Length(r.geom::geography) ELSE 0 END) AS secondary_length," +
" SUM(CASE WHEN r.fclass IN ('tertiary', 'tertiary_link') THEN ST_Length(r.geom::geography) ELSE 0 END) AS tertiary_length, " +
" SUM(CASE WHEN r.fclass IN ('residential', 'living_street') THEN ST_Length(r.geom::geography) ELSE 0 END) AS residential_length, " +
" SUM(CASE WHEN r.fclass IN ('service', 'unclassified') THEN ST_Length(r.geom::geography) ELSE 0 END) AS service_length, " +
" SUM(CASE WHEN r.fclass IN ('footway', 'pedestrian', 'path') THEN ST_Length(r.geom::geography) ELSE 0 END) AS pedestrian_length, " +
" SUM(CASE WHEN r.fclass = 'cycleway' THEN ST_Length(r.geom::geography) ELSE 0 END) AS cycleway_length, " +
" SUM(CASE WHEN r.fclass = 'track' THEN ST_Length(r.geom::geography) ELSE 0 END) AS track_length," +
+
+
+
;
List<UrbanRoadMileageInfo> ;
+
+
+
+
+
+
;
List<UrbanRoadMileageInfoVO> ;
}
通过以上代码就能实现地市道路长度的求解。
3、控制 API 实现
业务层作为控制层和数据库层的桥梁,控制层 API 主要分为页面跳转和获取各地级市信息列表。核心方法如下:
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.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.yelang.framework.web.controller.BaseController;
import com.yelang.framework.web.domain.AjaxResult;
import com.yelang.project.extend.earthquake.domain.UrbanRoadMileageInfoVO;
import com.yelang.project.extend.earthquake.service.IUrbanRoadMileageInfoService;
@Controller
@RequestMapping("/eq/urbanroadmileageinfo")
public class UrbanRoadMileageInfoController extends BaseController {
private String prefix = "earthquake/urbanroadmileageinfo";
@Autowired
private IUrbanRoadMileageInfoService urbanRoadMileageInfoService;
@RequiresPermissions("eq:urbanroadmileageinfo:map")
@GetMapping("/")
public String main(ModelMap mmap){
return prefix + "/main";
}
@RequiresPermissions("eq:urbanroadmileageinfo:list")
@GetMapping("/data/{pcode}")
@ResponseBody
public AjaxResult {
List<UrbanRoadMileageInfoVO> dataList = urbanRoadMileageInfoService.getRoadMileageList(pcode);
AjaxResult.success().put(, dataList);
}
}
三、WebGIS 界面实现
本节重点介绍 WebGIS 界面实现,主要涉及图例数据、各地市的空间范围及行政驻地标注信息。
1、里程图例及初始化
为了在页面中展示包含道路里程的信息,根据不同的道路长度来进行明显的区分展示,采用不同间距的道路里程图例设置。初始化颜色配置数组,设置代码如下:
//里程颜色配置
var colorList = [
{name:"5千公里以下",color:"#00FF00",rgb:new Color(0, 255, 0),colorDesc:"绿色"},
{name:"5千 -8 千公里",color:"#FFFF00",rgb:new Color(255, 255, 0),colorDesc:"黄色"},
{name:"8 千 -1.1 万公里",color:"#FFA500",rgb:new Color(255, 165, 0),colorDesc:"蓝色"},
{name:"1.1 万 -1.4 万公里",color:"#113fc1",rgb:new Color(255, 0, 0),colorDesc:"橙色"},
{name:"1.4 万 -1.6 万公里",color:"#800080",rgb:new Color(128, 0, ),:},
{:,:,: (, , ),:}
];
为了方便在展示的时候将不同的里程长度与颜色值进行对应,使用简单的值域判断,颜色识别转换的方法如下:
function getColorByLength(length){
if(length >= 0 && length <= 5000) { return "#00FF00"; }
if(length >= 5001 && length <= 8000) { return "#FFFF00"; }
if(length >= 8001 && length <= 11000) { return "#FFA500"; }
if(length >= 11001 && length <= 14000) { return "#113fc1"; }
if(length >= 14001 && length <= 16000) { return "#800080"; }
if(length >= 16001) { return "#FF0000"; }
}
2、各地市信息展示
为了便于在界面上进行直观的展示,我们在数据库保存的长度单位为米,但是在页面上展示比较多,因此需要对数据进行特别的处理,处理逻辑比较简单,就是进行除法计算,然后对小数点进行保留展示。核心代码如下:
function buildShowInfo(index,color,data){
var length = parseFloat(data.totalLength) / (1000.0 * 10000 );
var result = "<div + color + '; animation-spaceInDown onclick='showDetails('+data.cityCode+')'><div>' + data.cityName ;
result += "<span>:" + length.toFixed(2) + "万公里</span></div>";
result += "</div>";
return result;
}
道路地图的标注方法如下:
function previewRoadMap(pid,provinceCode,name){
previewProvince(pid,name);
$.ajax({
type:"get",
url:ctx + "eq/urbanroadmileageinfo/data/" + provinceCode,
data:{},
dataType:"json",
cache:false,
processData:false,
success:function(result){
if(result.code == web_status.SUCCESS){
collisionLayer.clearLayers();
var dataArray = result.data;
if(dataArray != null && dataArray.length > 1){
var legendData = new Array();
for(var i = 0;i< dataArray.length;i++){
var areaData = dataArray[i];
var tempTotalLength = parseFloat(areaData.totalLength) / 1000.0;
var color = getColorByLength(tempTotalLength);
var areaLayer = L.geoJSON(JSON.parse(areaData.geomJson),{: {:color,:color,:,:, : }}).(mymap);
myIcon = L.({ : , : , :[,], :[,], : (i,color,areaData) });
showLayerGroup.(areaLayer);
L.([areaData., areaData.], { : myIcon}).(collisionLayer);
}
collisionLayer.(showLayerGroup);
}
}
},
:(){
$.modal.();
}
});
}
这里需要注意的是,为了在标注的地方支持鼠标点击,下一步需要展示该地级市的更详细的道路分级统计信息,因此保留一个操作入口,函数操作如下:
function showDetails(cityCode){
console.log(cityCode);
}
这个扩展函数可以根据我们的业务需要进行扩展,这里仅展示打印信息,我们可以打开新的展示页面。
四、成果展示
经过空间数据表的查询检索实践,后台 Java 的接口实现以及 WebGIS 页面实践。下面我们来看看最终的一个效果,结合地图和数据来进行介绍。
1、总体展示

从湖南省的总体情况来看,按照道路里程降序排序如下所示:
430100 长沙市 17753221.56551351
430400 衡阳市 14434666.394707818
430600 岳阳市 14222249.927994445
430900 益阳市 13073704.1462314
430700 常德市 11931665.375579692
431100 永州市 10818152.494340602
431000 郴州市 10666092.158735342
431200 怀化市 10115713.30456733
430500 邵阳市 9892107.19298748
430200 株洲市 7374936.096146714
433100 湘西土家族苗族自治州 6795835.819083372
431300 娄底市 5727464.899432551
430300 湘潭市 4861742.381742725
430800 张家界市 3836270.2965029962
通过表格可以很明显的看到,省会长沙市、衡阳市、岳阳市位列前三。从空间聚集来看,基本是分布在东部和东南部。
2、分区域说明

从区域来看,道路里程较长的集中在东北部的岳阳、益阳、常德等地区和南部的衡阳市。

湘西北的道路里程确实比较弱,可能与山区的地质环境有关系,不太适合修路。可见把交通基础条件打造好,也是十分必要的。

南部地区除衡阳外,邵阳、永州、郴州等地市的道路里程是排名中等,还是有较大的发展空间,但随着如今人口的流出,未来的交通发展更需要好好的规划规划。
五、总结
以上就是本文的主要内容,通过本实践构建一个功能完善、性能稳定的湖南省道路长度 WebGIS 展示系统。通过将 Java 和 Leaflet 的结合为湖南省道路长度 WebGIS 系统的构建提供了一个良好的技术平台。在未来的展望中,我们希望能够进一步完善系统的功能,如增加道路拥堵情况的实时监测与分析、与其他交通信息系统的集成等。同时,随着技术的不断发展,我们还将探索新的技术应用,如人工智能、大数据等,为湖南省的道路管理提供更加智能化、精准化的解决方案。


