Websocket timing of push message to the browser

Disclaimer: This article is a blogger original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.
This link: https://blog.csdn.net/weixin_35654814/article/details/102733218

HTML5 WebSocket is new protocol, its purpose is to establish a bidirectional communication channel is not limited between the browser and the server, for example, the server may send a message at any time to the browser.

Presented here using Quartz scheduler function and WebSock push message to the browser on the server

Browser interaction page

webSockpage.html file

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>WebSock测试</title>
<script>
var websocket = null;
    //判断当前浏览器是否支持WebSocket
    if ('WebSocket' in window) {
        websocket = new WebSocket("ws://localhost:8080/photoOne/websocket");
    }
    else {
        alert("当前浏览器 Not support websocket");
    }

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

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

    //接收到消息的回调方法
    websocket.onmessage = function (event) {
        setMessageInnerHTML(event.data);
    }

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

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

    //将消息显示在网页上
    function setMessageInnerHTML(innerHTML) {
        document.getElementById("d1").innerHTML += innerHTML + "<br/>";
    }

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

    /*//发送消息
    function send() {
        var message = document.getElementById("text").value;
        websocket.send(message);
    }*/
</script>
</head>
<body>
	<div class="box" align="center">
		<h1>WebSock接收后台推送的消息...</h1>
		
		<div class="bottom">
			<div id="d1"></div>
		</div>
	</div>
</body>
</html>

WebSock server

WebSockServer.java file

package cn.hpc.ssm.controller;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArraySet;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;

/**
 * @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,
 * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
 */

@ServerEndpoint("/websocket")
public class WebSocketServer {
	
	
	//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
	private static int onlineCount = 0;
	
	//concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
	private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();
	
	//与某个客户端的连接会话,需要通过它来给客户端发送数据
	private Session session;
	
	/**
     * 连接建立成功调用的方法
     * @param session  可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
	 * @throws IOException 
     */
	@OnOpen
	public void onOpen(Session session) throws IOException{
		this.session = session;
		webSocketSet.add(this);//加入set中
		addOnlineCount();           //在线数加1
		System.out.println("有新连接加入!当前在线人数为" + getOnlineCount());
		this.sendMessage("连接成功!!!");
	}
	
	/**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(){
        webSocketSet.remove(this);  //从set中删除
        subOnlineCount();           //在线数减1
        System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount());
    }
    /**
     * 收到客户端消息后调用的方法
     * @param message 客户端发送过来的消息
     * @param session 可选的参数
     */
    @OnMessage
    public void onMessage(String message, Session session) {
    	Map<String, String> map = session.getPathParameters();
        System.out.println("来自客户端用户"+map.get("userId")+"的消息:" + message);
        //群发消息
        for(WebSocketServer item: webSocketSet){
            try {
                item.sendMessage(message);
            } catch (IOException e) {
                e.printStackTrace();
                continue;
            }
        }
    }
    
//    public void sendMessageTo(String message, String To) throws IOException {
//        for (WebSocket item : clients.values()) {
//            if (item.username.equals(To) )
//                item.session.getAsyncRemote().sendText(message);
//        }
//    }
//
//    public void sendMessageAll(String message) throws IOException {
//        for (WebSocket item : clients.values()) {
//            item.session.getAsyncRemote().sendText(message);
//        }
//    }


    /**
     * 发生错误时调用
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error){
        System.out.println("发生错误");
        error.printStackTrace();
    }

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

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

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

    public static synchronized void subOnlineCount() {
        WebSocketServer.onlineCount--;
    }

	public static CopyOnWriteArraySet<WebSocketServer> getWebSocketSet() {
		return webSocketSet;
	}

	public static void setWebSocketSet(
			CopyOnWriteArraySet<WebSocketServer> webSocketSet) {
		WebSocketServer.webSocketSet = webSocketSet;
	}

	public Session getSession() {
		return session;
	}

	public void setSession(Session session) {
		this.session = session;
	}
    
    
	

}

Springmvc structure used herein, the browser first communication terminal and the server WebSock, operating results

Quartz used next timing of execution and call server push messaging WebSock

First, the timing of the scheduling function integrated in the spring xml configuration file, the major function code. And integration of Quartz reference Spring


..............

<!-- 要执行的任务类 -->
    <bean id="RunClass" class="cn.hpc.ssm.controller.TriggersRunClass"></bean>

    <!-- 将需要执行的定时任务注入job中 -->
    <bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject" ref="RunClass"/>
        <!-- 任务类中需要执行的方法 -->
        <property name="targetMethod" value="runMethod"></property>
        <!-- 上一次未执行完成的,要等待有再执行。 -->
        <property name="concurrent" value="false" />
    </bean>

    <!-- 基本的定时器,会绑定具体的任务。 指定调度间隔进行调用 
    <bean id="trigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
        <property name="jobDetail" ref="jobDetail"/>
        <property name="startDelay" value="3000"/>
        <property name="repeatInterval" value="2000"/>
    </bean>-->
    
    <!-- 指定时间刻度进行调用 -->
    <bean id="trigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
		<property name="jobDetail" ref="jobDetail"/>
		<!-- 指定时间执行,时间说明见description.txt文件,5秒执行一次  -->
		<property name="cronExpression" value="0/5 * * * * ?"/>
	</bean>
    

    <bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="triggers">
            <list>
                <ref bean="trigger"/>
            </list>
        </property>
    </bean>

.............

TriggersRunClass class can be seen as a timing task execution, runMethod method to perform a method of scheduling tasks.

WebSock call objects in the class runMethod method TriggersRunClass Method push messages to the client

TriggersRunClass class file

package cn.hpc.ssm.controller;

import java.io.IOException;
import java.util.Date;
import java.util.concurrent.CopyOnWriteArraySet;

public class TriggersRunClass {
	
	//定时执行的方法
	public void runMethod() {
		
		//获取WebSocketServer对象的映射。
		CopyOnWriteArraySet<WebSocketServer> webSocketSet = WebSocketServer.getWebSocketSet();
		if (webSocketSet.size() != 0){
            for (WebSocketServer item : webSocketSet) {
                try {
                    //向客户端推送消息
                	item.getSession().getBasicRemote().sendText("每隔5秒,向客户端推送一次数据,本地时间:"+new Date().toLocaleString());
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
        }else {
            System.out.println("WebSocket未连接");
        }
		
	}
}

operation result

We can see every 5 seconds to perform a scheduling method and call WebSock server push messages

Note: the need to introduce Quartz jar (quartz-1.5.2.jar) and javaee the jar (javaee-api-8.0.jar)

Guess you like

Origin blog.csdn.net/weixin_35654814/article/details/102733218