geoserver+mysql+openlayer 简单搭建与实现图层实时更新
一geoserver的搭建非常简单
官网下载geoserver最新版本http://blog.geoserver.org/ 我使用的是 GeoServer 2.14.2版本 。
下载独立版本直接解压 进入bin启动即可,访问http://localhost:8089/geoserver/web 用户名 admin 密码geoserver
如下图:说明geoserver搭建成功
geoserver 支持postgis空间数据库如果要支持mysql必须的安装插件geoserver-2.14.2-mysql-plugin 解压内容如下
将jar拷贝入:.\GeoServer 2.14.2\webapps\geoserver\WEB-INF\lib 下刷新geoserver界面出现如下说明mysql插件配置成功
现在就是连接mysq,点击mysql database出现如下界面
填入用户名密码就可以了。发布mysql数据时可以整张表发布也可通过sqlview 发布条件数据。这个就看业务需求
发布mysql数据时候注意:
直接从数据中计算即可
通过sqlview发布数据的时候注意:
至此geoserver+mysql整合完成。
前端我是用的 npm+webback+vue+websocket 废话少说直接上代码(有些粗糙待细斟酌只是实现功能演示用)
<template> <div id="map"> <input @click="fitToChengdu" value="显示成都" type="button"/> <input @click="toline" value="加载图层" type="button"/> <input @click="deleteline" value="删除图层" type="button"/> <div><span>当前层级:</span><span id="zoom"></span><span>分辨率:</span><span id="resolution"></span></div> <!-- <div id="anchor"><img src="../png/test.png" alt="示例锚点" v-on:click="testvalue"/></div>--> </div> </template> <script> import "ol/ol.css"; import {Map, View, Overlay, Feature} from "ol"; import TileLayer from "ol/layer/Tile"; import {Image, Vector} from "ol/layer"; import GeoJSON from "ol/format/GeoJSON"; import {Style, Stroke, Icon} from "ol/style"; import VectorLayer from "ol/layer/Vector"; import OSM from "ol/source/OSM"; import XYZ from "ol/source/XYZ"; import Point from "ol/geom/Point"; import VectorSource from "ol/source/Vector"; import ImageWMS from "ol/source/ImageWMS"; import TileDebug from "ol/source/TileDebug"; import page from "../png/定点.png"; import TileWMS from "ol/source/TileWMS" export default { data() { return { websocket: null, centers: [-73.99710639567148, 40.742270050255556], map: null, anchor: 'testS', offlineMapLayer: null, baseLayer: null, vectorxx0: null, vectorxx1: null, vectorxx2: null, vectorxx3: null, vectorxx4: null, vectorxx5: null, vectorxxre: null, wmsSource:null, wmsSources:null, line:null, wmsLayer:null, extent: [108.06 - 550 * 1000 / 200000, 30.67 - 344 * 1000 / 200000, 108.06 + 550 * 1000 / 200000, 30.67 + 344 * 1000 / 200000], maps: new OSM(), layer: new VectorLayer({source: new VectorSource()}), styleicon: "" }; }, created() { //页面刚进入时开启长连接 this.initWebSocket() }, destroyed() { //页面销毁时关闭长连接 this.websocketclose(); }, mounted() { this.vectorxx1 = new Image({ source: new ImageWMS({ // format: new GeoJSON(), url: 'http://localhost:8089/geoserver/wms', params: {'LAYERS': 'shp:word1', 'VERSION': '1.1.0'}, }), // style: function(feature, resolution) { // return new Style({ // stroke: new Stroke({ // color: 'blue', // width: 1 // }) // }); // } }), this.vectorxx2 = new Image({ source: new ImageWMS({ // format: new GeoJSON(), url: 'http://localhost:8089/geoserver/wms', params: {'LAYERS': 'shp:word2', 'VERSION': '1.1.0'}, }), // style: function(feature, resolution) { // return new Style({ // stroke: new Stroke({ // color: 'blue', // width: 1 // }) // }); // } }); this.vectorxx3 = new Image({ source: new ImageWMS({ // format: new GeoJSON(), url: 'http://localhost:8089/geoserver/wms', params: {'LAYERS': 'shp:word3', 'VERSION': '1.1.0'}, }), // style: function(feature, resolution) { // return new Style({ // stroke: new Stroke({ // color: 'blue', // width: 1 // }) // }); // } }); this.vectorxx5 = new Image({ source: new ImageWMS({ // format: new GeoJSON(), url: 'http://localhost:8089/geoserver/wms', params: {'LAYERS': 'mysqlworkspace:city10', 'VERSION': '1.1.0'}, }), // style: function(feature, resolution) { // return new Style({ // stroke: new Stroke({ // color: 'blue', // width: 1 // }) // }); // } }), this.vectorxx4 = new Image({ source: new ImageWMS({ // format: new GeoJSON(), url: 'http://localhost:8089/geoserver/wms', params: {'LAYERS': 'wordtest:word4', 'VERSION': '1.1.0'}, }), // style: function(feature, resolution) { // return new Style({ // stroke: new Stroke({ // color: 'blue', // width: 1 // }) // }); // } }); // this.anchor = new Feature({ // geometry: new Point([104, 30]) // }); // console.log(this.anchor); // this.anchor.setStyle(new Style({ // image: new Icon({ // src: page, // anchor: [0.5, 1] // }) // })); // this.layer.getSource().addFeature(this.anchor); // this.offlineMapLayer =new Image({ // // source: new OSM() // source: new ImageStatic({ // url: page, // 熊猫基地地图 // imageExtent: this.extent // 映射到地图的范围 // }) // }) this.vectorxx0 = new Vector({ source: new VectorSource({ format: new GeoJSON({ geometryName: 'SHAPE' }), url: 'http://localhost:8089/geoserver/wordtest/wms?service=WMS&version=1.1.0&request=GetMap&layers=wordtest%3At_pots&bbox=103.07%2C29.67%2C105.07%2C31.67&width=768&height=768&srs=EPSG%3A404000&format=application/openlayers' }), style: function (feature, resolution) { return new Style({ stroke: new Stroke({ color: 'red', width: 1 }) }); } }); // this.map.addLayer(this.vectorxx0); /* 有关html运用*/ // this.anchor = new Overlay({ // element: document.getElementById('anchor') // }); // // 关键的一点,需要设置附加到地图上的位置 // this.anchor.setPosition([104, 30]); // this.map.addOverlay(this.anchor); this.map = new Map({ target: "map", // logo: {src: '..\\png\\test.png'}, layers: [ // new TileLayer({ // source: this.maps // }), // new TileLayer({ // source: new TileDebug({ // projection: 'EPSG:4326', // tileGrid: this.maps.getTileGrid() // }) // }) // this.layer // this.vectorxx1, // this.vectorxx2, // this.vectorxx3, // this.vectorxx4, // this.vectorxx5, ], view: new View({ projection: "EPSG:4326", //使用这个坐标系 extent: [-0, -90, 90, 83.64513000000001], center: this.centers, //成都 zoom: 3, minZoom: 3, maxZoom: 6, }), }); this.wmsSource = new ImageWMS({ crossOrigin: 'anonymous', params: { 'LAYERS': 'mysqlworkspace:city', //图层 'VERSION': '1.1.0', }, serverType: 'geoserver', url: 'http://localhost:8089/geoserver/wms' }); this. wmsLayer = new Image({ source: this.wmsSource }) this.map.addLayer(this.vectorxx1) this.map.addLayer(this.vectorxx2) this.map.addLayer(this.vectorxx3) this.map.addLayer(this.vectorxx4) this.map.addLayer(this.wmsLayer) }, watch: { "map": function () { this.map.getView().on('change:resolution', function () { document.getElementById('zoom').innerHTML = this.getZoom() + ','; document.getElementById('resolution').innerHTML = this.getResolution(); // console.log(this.anchor); // this.styleicon = this.anchor.getStyle(); // // // 重新设置图标的缩放率,基于层级10来做缩放 // this.styleicon.getImage().setScale(this.getZoom() / 10); // this.anchor.setStyle(style); }) }, }, methods: { deleteline() { // this.map.removeLayer(this.vectorxx5) console.log(this.map.getLayers()) this.map.removeLayer(this.map.getLayers().item(4)) console.log(this.map.getLayers()) }, toline() { this.getJson() console.log(this.map.getLayers()) }, fitToChengdu() { this.map.getView().fit([104, 30.6, 104.12, 30.74], this.map.getSize()); }, testvalue() { document.getElementById('anchor').innerHTML = "3" }, //初始化weosocket initWebSocket() { const wsuri = "ws://localhost:8888/websocket";//ws地址 this.websocket = new WebSocket(wsuri); this.websocket.onopen = this.websocketonopen; this.websocket.onerror = this.websocketonerror; this.websocket.onmessage = this.websocketonmessage; this.websocket.onclose = this.websocketclose; }, websocketonerror() { console.log("WebSocket连接发生错误"); }, //连接成功建立的回调方法 websocketonopen() { console.log("open"); }, //接收到消息的回调方法 websocketonmessage(e) { //注意:长连接我们是后台直接1秒推送一条数据, //但是点击某个列表时,会发送给后台一个标识,后台根据此标识返回相对应的数据, //这个时候数据就只能从一个出口出,所以让后台加了一个键,例如键为1时,是每隔1秒推送的数据,为2时是发送标识后再推送的数据,以作区分 console.log(e.data + " 00000000000000000000000000"); // this.toline() this.getJsons() }, getJson() { this.map.removeLayer(this.map.getLayers().item(4)) // this.map.getView().setZoom(4) /* this.vectorxxre = new Image({ source: new ImageWMS({ format: new GeoJSON(), url: 'http://localhost:8089/geoserver/wms', params: {'LAYERS': 'mysqlworkspace:city10', 'VERSION': '1.1.0'}, }), })*/ this.baseLayer = new TileWMS({ url: 'http://localhost:8089/geoserver/wms', params: {'LAYERS': 'mysqlworkspace:sqlpot', 'VERSION': '1.1.0'}, serverType: 'geoserver' }); this.vectorxxre = new TileLayer({ source: this.baseLayer }); console.log(this.vectorxxre + ".......................") this.map.addLayer(this.vectorxxre) }, getJsons() { // window.location.reload(); // this.map.removeLayer(this.map.getLayers().item(5)) // this.map.removeLayer(this.map.getLayers().item(4)) // this.line = new Image({ // source: new ImageWMS({ // crossOrigin: 'anonymous', // url: 'http://localhost:8089/geoserver/wms', // params: {'LAYERS': 'mysqlworkspace:line', 'VERSION': '1.1.0'}, // // }), // // style: function(feature, resolution) { // // return new Style({ // // stroke: new Stroke({ // // color: 'blue', // // width: 1 // // }) // // }); // // } // }); // this.baseLayer = new TileWMS({ // url: 'http://localhost:8089/geoserver/wms', // params: {'LAYERS': 'mysqlworkspace:sqlpot', 'VERSION': '1.1.0'}, // serverType: 'geoserver' // }); // // this.vectorxxre = new TileLayer({ // source: this.baseLayer // }); // // console.log(this.vectorxxre + ".......................") // this.map.addLayer(this.vectorxxre) // this.map.addLayer(this.line) this. wmsSources = new ImageWMS({ crossOrigin: 'anonymous', params: { LAYERS: 'mysqlworkspace:sqlpot', 'VERSION': '1.1.0', }, serverType: 'geoserver', url: 'http://localhost:8089/geoserver/wms' }); this.wmsLayer.setSource(this.wmsSource); this.map.getView().setResolution(this.map.getView().getResolution() + Math.random() * 0.00000009);//随机数缩放实现刷新 /* console.log(this.vectorxxre + ".......................") console.log(this.vectorxx5 + ".......................") /!* this.vectorxxre = new Image({ source: new ImageWMS({ format: new GeoJSON(), url: 'http://localhost:8089/geoserver/wms', params: {'LAYERS': 'mysqlworkspace:city10', 'VERSION': '1.1.0'}, }), })*!/ this.baseLayer = new TileWMS({ url: 'http://localhost:8089/geoserver/wms', params: {'LAYERS': 'mysqlworkspace:sqlpot', 'VERSION': '1.1.0'}, serverType: 'geoserver' }); this.vectorxxre = new TileLayer({ source: this.baseLayer }); console.log(this.vectorxxre + ".......................") this.map.addLayer(this.vectorxxre)*/ }, websocketsend(agentData) {//数据发送 this.websocket.send(agentData); }, websocketclose(e) { //关闭 console.log("connection closed (" + e.code + ")"); }, } } </script> <style> #map { height: 100%; } /*隐藏ol的一些自带元素*/ .ol-attribution, .ol-zoom { display: none; } /*@keyframes zoom*/ /*{*/ /*from {top: 0; left: 0; width: 32px; height: 32px;}*/ /*50% {top: -16px; left: -16px; width: 64px; height: 64px;}*/ /*to {top: 0; left: 0; width: 32px; height: 32px;}*/ /*}*/ /*@-moz-keyframes zoom !* Firefox *!*/ /*{*/ /*from {top: 0; left: 0; width: 32px; height: 32px;}*/ /*50% {top: -16px; left: -16px; width: 64px; height: 64px;}*/ /*to {top: 0; left: 0; width: 32px; height: 32px;}*/ /*}*/ /*@-webkit-keyframes zoom !* Safari 和 Chrome *!*/ /*{*/ /*from {top: 0; left: 0; width: 32px; height: 32px;}*/ /*50% {top: -16px; left: -16px; width: 64px; height: 64px;}*/ /*to {top: 0; left: 0; width: 32px; height: 32px;}*/ /*}*/ /*@-o-keyframes zoom !* Opera *!*/ /*{*/ /*from {top: 0; left: 0; width: 32px; height: 32px;}*/ /*50% {top: -16px; left: -16px; width: 64px; height: 64px;}*/ /*to {top: 0; left: 0; width: 32px; height: 32px;}*/ /*}*/ /*!* 应用css动画到图标元素上 *!*/ /*#anchor*/ /*{*/ /*display: block;*/ /*position: absolute;*/ /*animation: zoom 5s;*/ /*animation-iteration-count: infinite; !* 一直重复动画 *!*/ /*-moz-animation: zoom 5s; !* Firefox *!*/ /*-moz-animation-iteration-count: infinite; !* 一直重复动画 *!*/ /*-webkit-animation: zoom 5s; !* Safari 和 Chrome *!*/ /*-webkit-animation-iteration-count: infinite; !* 一直重复动画 *!*/ /*-o-animation: zoom 5s; !* Opera *!*/ /*-o-animation-iteration-count: infinite; !* 一直重复动画 *!*/ /*}*/ input { float: left; color: red; } span { float: left; font-size: 15px; color: red; } </style>
后端是springboot+websocket 代码如下:
indexController
import com.websocket.wensocketdemo.server.WebSocketServer; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import java.io.IOException; import java.util.HashMap; import java.util.Map; @Controller public class indexController { @RequestMapping("/") public String Index() { return "index"; } @RequestMapping(value="/push",method= RequestMethod.POST) @ResponseBody public Map<String,Object> pushVideoListToWeb(@RequestParam("str") String str) { Map<String,Object> result =new HashMap<>(); try { WebSocketServer.sendInfo("有新客户呼入,sltAccountId:"+str); result.put("operationResult", true); }catch (IOException e) { result.put("operationResult", true); } return result; } }
WebSocketServer
import java.io.IOException; import java.util.concurrent.CopyOnWriteArraySet; import javax.websocket.OnClose; import javax.websocket.OnError; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.ServerEndpoint; import org.springframework.stereotype.Component; @ServerEndpoint(value = "/websocket") @Component public class WebSocketServer { //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。 private static int onlineCount = 0; //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。 private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>(); //与某个客户端的连接会话,需要通过它来给客户端发送数据 private Session session; /** * 连接建立成功调用的方法*/ @OnOpen public void onOpen(Session session) { this.session = session; webSocketSet.add(this); //加入set中 addOnlineCount(); //在线数加1 System.out.println("有新连接加入!当前在线人数为" + getOnlineCount()); try { System.out.println("连接成功"); // sendMessage("连接成功"); } catch (Exception e) { System.out.println("websocket IO异常"); } } /** * 连接关闭调用的方法 */ @OnClose public void onClose() { webSocketSet.remove(this); //从set中删除 subOnlineCount(); //在线数减1 System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount()); } /** * 收到客户端消息后调用的方法 * * @param message 客户端发送过来的消息*/ @OnMessage public void onMessage(String message) { System.out.println("来自客户端的消息:" + message); //群发消息 for (WebSocketServer item : webSocketSet) { try { item.sendMessage(message); } catch (IOException e) { e.printStackTrace(); } } } /** * * @param session * @param error */ @OnError public void onError(Session session, Throwable error) { System.out.println("发生错误"); error.printStackTrace(); } public void sendMessage(String message) throws IOException { this.session.getBasicRemote().sendText(message); } /** * 群发自定义消息 * */ public static void sendInfo(String message) throws IOException { System.out.println(message); for (WebSocketServer item : webSocketSet) { try { item.sendMessage(message); } catch (IOException e) { continue; } } } public static synchronized int getOnlineCount() { return onlineCount; } public static synchronized void addOnlineCount() { WebSocketServer.onlineCount++; } public static synchronized void subOnlineCount() { WebSocketServer.onlineCount--; } }
实现后端与前端长连接实时通信如果数据有所改变实时更新地图数据。最后附上一张成果图(仅供交流学习)
转载自:https://blog.csdn.net/qingshu0400/article/details/87775316