整合百度地图,显示停车场位置,停车位详情,使用WebSocket实现动态刷新

我会在近段时间内把之前的项目上遇到的一些我觉得需要记录的需求、问题给写下来,来弥补之前没有写博客的习惯。

需求:当管理员登录智慧停车项目后台时,首页需要展示当前地区的停车场信息,以及每个停车场的停车位详情。
初期效果图如下:
在这里插入图片描述
以上需要实现的功能有:
将停车场作为标注点显示在地图上,根据停车场的剩余车位数改变标注点的颜色,绿色的为车位充足,以此类推。
当鼠标移动到标注点上时,显示停车场信息,点击标注点或详情时展示该停车场的停车位详情。
点击车位展示停放车辆详细信息。
由于项目后期会添加大量的停车场和停车位,但是如何保证页面实时展示每个停车场,每个停车位的最新信息,这里使用的是WebSocket来动态和后台交换数据,实现动态刷新部分停车场、停车位信息。(由于项目尚未正式上线,效果中无法演示)
首先是页面部分:

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<c:set var="ctx" value="${pageContext.request.contextPath}" />
<%@ include file="/WEB-INF/views/include/taglib.jsp"%>
<html>
<head>
<title>百度地图</title>
<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=填写你的ak"></script>
	<title>停车场地图展示</title>
	<script src="${ctxStatic}/js/2.1.1-jquery.min.js"></script>
	<script type="text/javascript" src="${ctxStatic}/layer/layer.js"></script>
	<script type="text/javascript" src="http://api.map.baidu.com/library/GeoUtils/1.2/src/GeoUtils_min.js"></script>
	<style>

		.fix-rt{
			width: 474px;
			height: 100%;
			background: #eee;
			position: fixed;
			right: -474px;
			top: 0;
		}
		.btn-close{
			display: block;
			width: 0;
			height: 0;
			border: 16px solid transparent;
			border-left:16px solid #666;
			position: absolute;
			top: 50%;
			left: 5px;
			font-size: 0;
		}


	</style>
</head>
<body>
	<div id="allmap" style="width:100%;height:100%"></div>
	<input type="hidden" id="cityName" value="${cityName}">
	<div id="pri" style=" display: none;" area="" city ="" qu ="" areainfo=""></div>
	<div class="fix-rt">
		<a href="#" class="btn-close">关闭</a>
		<iframe id="detail" src="" width="106%" height="99%" frameborder="0"></iframe>
	</div>
</body>
<script type="text/javascript">
	var map = new BMap.Map("allmap");
    var cityName=$("#cityName").val();

	var Longitude = "113.634865";//设置经度的初始值
	var Atitude = "34.754389";//设置纬度的初始值
	var point = new BMap.Point(Longitude,Atitude);
	 map.centerAndZoom(point,13);
    map.setMapStyle({style:'googlelite'});

这一步你需要先申请一个百度开发者账号,然后去申请秘钥,这一步直接百度就行,非常简单详细。
到这里页面已经加载一个郑州市的地图,这里我的经纬度是写死的,当然也可以根据需要灵活配置。
在这里插入图片描述
接下来,要向后台发送请求获取停车场信息,得到后台返回的数据:

	var overlays = [];
    var parkList = [];
    $.ajax({
		async:false,
        type:"POST",
        url:"${ctx}/test",
        dataType:"JSON",
        success:function (data) {
            parkList=data;
        }
    })

    for(var i=0;i<parkList.length;i++){
        var Longitude=parkList[i].longitude;
        var Atitude=parkList[i].latitude;
        var point = new BMap.Point(Longitude,Atitude);
        overlays.push(point);
        var spaces = parkList[i].spaces;	//停车场车位数
        var spacesLast = parkList[i].spacesLast;	//停车场剩余车位数
        var rate= spacesLast/spaces;
        var greIcon = new BMap.Icon("${ctxStatic}/images/gre.png", new BMap.Size(35,37));
        var redIcon = new BMap.Icon("${ctxStatic}/images/red.png", new BMap.Size(35,37));
        var orangeIcon = new BMap.Icon("${ctxStatic}/images/orange.png", new BMap.Size(35,37));
        if(rate > 0.5){
            var marker = new BMap.Marker(point,{icon:greIcon});
        }else if(rate > 0 && rate < 0.5){
            var marker = new BMap.Marker(point,{icon:orangeIcon});
        }else{
            var marker = new BMap.Marker(point,{icon:redIcon});
        }
        console.log(rate);
        if(rate<0.5){
			console.log("warning");
        }
        var label = new BMap.Label(parkList[i].spacesLast, {
            offset : new BMap.Size(6, 4)
        });
        var color='';
        if(rate > 0.5){
            color='green';
        }else if(rate > 0 && rate < 0.5){
            color='orange';
        }else{
            color='#ff0000';
        }
        label.setStyle({
            background:'none',color:color,border:'none'//只要对label样式进行设置就可达到在标注图标上显示数字的效果
        });

        marker.setLabel(label);//显示标注中的剩余车位数字
        map.addOverlay(marker);    //增加点
        //marker.addEventListener("click",attribute);//增加点的单击事件
        addClickHandler(parkList[i],marker);

	}

以上实现了为地图添加标注点的功能,addClickHandler方法是为标注点增加单击事件,也就是右边滑出的停车场详情,这一步就不再写了,只是一些js的应用,可以根据具体业务需求实现相关的功能。
接下来是WebSocket
页面代码:

var server=location.hostname;
    var port=location.port;
    var websocket = null;
    //判断当前浏览器是否支持WebSocket
    if ('WebSocket' in window) {
        websocket = new WebSocket("ws://"+server+":"+port+"/parkStationMap");
    }
    else {
        alert('当前浏览器 Not support websocket')
    }

    //连接发生错误的回调方法
    websocket.onerror = function () {
        alert("WebSocket连接发生错误");
    };

    //连接成功建立的回调方法
    websocket.onopen = function () {
        console.log("WebSocket连接成功");
        websocket.send("dwq");
    }

    //接收到消息的回调方法
    websocket.onmessage = function (event) {
    	//WebSocket可以传送json格式的数据,在这里将json字符串装换成json对象
        var s = JSON.parse(event.data);
        console.log(s.parkStation.id);
        //可以写自己具体的功能代码

    }

    //连接关闭的回调方法
    websocket.onclose = function () {
        console.log("WebSocket连接关闭");
    }

    //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
    window.onbeforeunload = function () {
        closeWebSocket();
    }


    //关闭WebSocket连接
    function closeWebSocket() {
        websocket.close();
    }

    //发送消息
    function send() {
        var message = document.getElementById('text').value;
        websocket.send(message);
    }

接下来是服务器端:

/**
 * @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,
 * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
 */
@ServerEndpoint("/parkStationMap")
public class ParkStationMapWebSocket {
    //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
    private static int onlineCount = 0;

    private static final Log logger = LogFactory.getLog(ParkStationMapWebSocket.class);

    //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
   //private static CopyOnWriteArraySet<ParkStationMapWebSocket> webSocketSet = new CopyOnWriteArraySet<ParkStationMapWebSocket>();

    //与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;
    private ParkStationMapSessionManager parkStationMapSessionManager=new ParkStationMapSessionManager();

    /**
     * 连接建立成功调用的方法
     * @param session  可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
     */
    @OnOpen
    public void onOpen(Session session){
        this.session = session;
        parkStationMapSessionManager.addSession(session);     //加入set中
        addOnlineCount();           //在线数加1
        logger.debug("有新连接加入!当前在线人数为" + getOnlineCount());
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session){
        parkStationMapSessionManager.removeSession(session);  //从set中删除
        subOnlineCount();           //在线数减1
        System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount());
    }

    /**
     * 收到客户端消息后调用的方法
     * @param message 客户端发送过来的消息
     * @param session 可选的参数
     */
    @OnMessage
    public void onMessage(String message, Session session) throws IOException {
        System.out.println("来自客户端的消息:" + message);
        //MobileController.sessionId=session.getId();

        System.out.println("来自客户端的消息:" + session.getId());
        //这里展示一下可以传递多种json格式的数据
        JSONObject json= new JSONObject();
        Demo demo=new Demo();
        Demo1 demo1=new Demo1();
        demo.setName("yzy");
        demo.setSex("nan");
        demo1.setName("dwq");
        demo.setDemo1(demo1);
        Map<String,Object> map=new HashMap<>();
        map.put("name","yzy");
        map.put("age","15");
        map.put("demo",demo);
        String s2 = JSON.toJSONString(map);
        System.out.println(s2);

        //sendMessage(s2);
    }

    /**
     * 发生错误时调用
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error){
        try {
            session.close();
            logger.error(error.getMessage(),error);
        } catch(Exception e) {
            logger.error(e.getMessage(),e);
        }
    }

    /**
     * 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。
     * @param message
     * @throws IOException
     */
    public void sendMessage(String message) throws IOException{
        System.out.println("sessid:"+this.session.getId());
        this.session.getBasicRemote().sendText(message);
        //this.sessionManage.getAsyncRemote().sendText(message);
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        ParkStationMapWebSocket.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        ParkStationMapWebSocket.onlineCount--;
    }
}
  • 3
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
使用WebSocket实现数据库更新时前端页面的实时刷新,你可以按照以下步骤进行操作: 1. 在后端,使用WebSocket协议与前端建立连接。你可以使用一些流行的WebSocket库,如Socket.io(Node.js)或Tornado(Python)来简化这个过程。 2. 在前端,使用JavaScript的WebSocket API与后端建立连接。可以使用以下代码示例: ```javascript const socket = new WebSocket('ws://your-server-url'); socket.onopen = () => { console.log('WebSocket连接已建立'); }; socket.onmessage = (event) => { console.log('收到消息:', event.data); // 在收到消息时执行相应的操作,如更新页面内容 }; socket.onclose = () => { console.log('WebSocket连接已关闭'); }; ``` 3. 在后端,监听数据库的更新操作。当数据库发生更新时,通过WebSocket向前端发送消息。具体实现方式取决于你使用的数据库和后端语言。 例如,如果你使用Node.js和MongoDB,可以使用MongoDB的Change Streams功能来监听数据库的变化,并通过WebSocket发送消息给前端。以下是一个简单的示例: ```javascript const { MongoClient } = require('mongodb'); const WebSocket = require('ws'); const url = 'mongodb://localhost:27017'; const dbName = 'your-database-name'; const collectionName = 'your-collection-name'; const wss = new WebSocket.Server({ port: 8080 }); (async function () { const client = await MongoClient.connect(url, { useUnifiedTopology: true }); const db = client.db(dbName); const collection = db.collection(collectionName); const changeStream = collection.watch(); changeStream.on('change', (change) => { const message = JSON.stringify(change); wss.clients.forEach((client) => { if (client.readyState === WebSocket.OPEN) { client.send(message); // 向前端发送更新消息 } }); }); })(); ``` 这样,当数据库中的数据发生变化时,后端会将变化信息通过WebSocket发送给前端,前端页面可以根据接收到的消息来实时更新内容。 请注意,以上代码只是一个简单的示例,实际上,你需要根据你的具体需求和技术栈进行相应的配置和开发。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值