(Turn + Share) using spring boot + WebSocket achieve timing push messaging (based annotation) / MarkerHub April 4 Author: gentle breeze waves unclear

Little Hub reads:

The combination of Springboot+websocket can complete many functions such as instant chat, notification, etc. Let's take a look at a small example to learn about duplex communication!

Preface

There are also websocket-related articles in the previous article. Why do you have to rewrite one this time? The first article requires different business scenarios, and the second article websocket is basically based on annotations and simple operation.
In fact, there are many technologies that can realize timing message push. Dwr, goeasy, comer4j, netPush and other technologies can also fully realize this function.

  • The message push of the previous DWR document is also used, but the performance is not very good in the actual project. After all, the technology is relatively old, and the compatibility of some browser versions is not very good, and it is prone to message loss. Study the source code for a long time Many changes cannot solve this problem.

  • GoEasy actually performs quite well in terms of message push, but it is charged. Our project basically uses open source products to correspond to the compliance test of charged products. It must not pass, so it is not considered.

  • The latter two technologies have not been studied in detail, and I currently feel that webSocket can perfectly solve my current business needs.

Introduction to websocket

The websocket protocol is a supplementary protocol to the http protocol, a new feature of html5, and a persistent protocol. In fact, the relationship between websocket and http is not very big, but both belong to the application layer protocol. For more concepts, you can refer to the detailed description in the following article, and then we will start the actual combat.

https://www.cnblogs.com/fuqiang88/p/5956363.html

websocket timed push

This tutorial is based on springboot as a scaffolding. Students who have never used springboot can read previous articles, or go directly to the spring official website to pull a springboot basic project.

Add dependency

Add a webSocket dependency to the springboot project. Generally, the introduction of a new technology in springboot only refers to a dependency of this technology starter, and other configurations are basically solved by springboot.

<dependency>

  <groupId>org.springframework.boot</groupId>

  <artifactId>spring-boot-starter-websocket</artifactId>

</dependency>

Configuration

Create a new Java configuration class and inject the ServerEndpointExporter configuration. If you are using springboot's built-in tomcat, this configuration is necessary. If you are using an external tomcat container, please ignore this step. Looking at the description in the spring source code, using this configuration can turn off the scanning of websocket endpoints by the servlet container. This has not been studied in depth for the time being.

@Configuration

public class WebSocketConfig {

 @Bean

 public ServerEndpointExporter serverEndpointExporter() {

   return new ServerEndpointExporter();

  }
}

Core code

The next most core class is actually to provide a front-end and back-end interaction class to implement message reception and push.

  • @ServerEndpoint(value = "/wsdemo") The front end interacts with the back end through this URI to establish a connection

  • @Component Needless to say, leave this class to spring management

  • @OnOpen websocket Annotation for establishing a connection, the front end will enter the annotation method when the above URI is triggered, which is similar to the onpage method in the previous article about DWR

  • @OnClose, as the name implies, closes the connection and destroys the session

  • @OnMessage The method to be executed after receiving the message from the front end

@ServerEndpoint(value = "/wsdemo")
@Component
public class MyWebSocket {
	private static int onlineCount = 0;
	private static CopyOnWriteArraySet<MyWebSocket> webSocketSet = new CopyOnWriteArraySet<MyWebSocket>();
	private Session session;
	@OnOpen
	public void onOpen(Session session) {
		this.session = session;
		webSocketSet.add(this);		
		addOnlineCount();		
		System.out.println("有新连接加入!当前在线人数为" + getOnlineCount());	
		try {		
			sendMessage("连接已建立成功.");		
		} catch (Exception e) {		
			System.out.println("IO异常");		
		}
	}

	@OnClose	
	public void onClose() {	
		webSocketSet.remove(this);		
		subOnlineCount();	
		System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount());	
	}

	@OnMessage	
	public void onMessage(String message, Session session) {	
		System.out.println("来自客户端的消息:" + message);	
	}

	@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 synchronized int getOnlineCount() {	
		return onlineCount;	
	}

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

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

	public Session getSession() {	
		return session;	
	}

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

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

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

Timed task

Use spring's Schedule to establish timing tasks

  • @EnableScheduling Enable spring timing task function

  • @Scheduled(cron = "0/10 * * * * ?") is used to identify the method of timing execution. Here, the return value of the main method must be void and there is no input parameter. Corresponding timing time configuration can be Baidu cron grammar, choose the appropriate cycle according to your own business.
    In this category, we obtain the webSocketSet through the static method provided by MyWebSocket above to obtain all websocket sessions related to this business, which can be used in timing tasks Verify the content of the session (authorization verification, etc.), and send messages

@Component
@EnableScheduling
public class TimeTask {
	private static Logger logger = LoggerFactory.getLogger(TimeTask.class);
	@Scheduled(cron = "0/1 * * * * ?")
	public void test(){
		System.err.println("********* 定时任务执行 **************");	
		CopyOnWriteArraySet<MyWebSocket> webSocketSet =	MyWebSocket.getWebSocketSet();	
		int i = 0 ;	
		webSocketSet.forEach(c->{		
			try {			
				c.sendMessage(" 定时发送 " + new Date().toLocaleString());			
			} catch (IOException e) {			
				e.printStackTrace();			
			}		
		});
		System.err.println("/n 定时任务完成.......");	
	}
}

Front page

The front-end page can be used for reference, mainly to change the calling url to your own project URL

<!DOCTYPE HTML>
<html>
  <head><title>My WebSocket</title></head>
  <body> Welcome<br/>
	<input type="text" />
    <button onclick="send()">Send</button>
   <button onclick="closeWebSocket()">Close</button>
  </body>
	<script type="text/javascript">
		var websocket = null;
		//判断当前浏览器是否支持WebSocket ,主要此处要更换为自己的地址
		if('WebSocket' in window){
			websocket = new WebSocket("ws://localhost:8886/wsdemo");
		}else{
			alert('Not support websocket')
		}
		//连接发生错误的回调方法
		websocket.onerror = function(){
			setMessageInnerHTML("error");
		};
		//连接成功建立的回调方法
		websocket.onopen = function(event){
			setMessageInnerHTML("open");
		}
	
		//接收到消息的回调方法
		websocket.onmessage = function(event){
			setMessageInnerHTML(event.data);
		}
	
		//连接关闭的回调方法
		websocket.onclose = function(){
			setMessageInnerHTML("close");
		}
		//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
		window.onbeforeunload = function(){
			websocket.close();
		}
	
		//将消息显示在网页上
		function setMessageInnerHTML(innerHTML){
			document.getElementById('message').innerHTML += innerHTML + '<br/>';
		}
		//关闭连接
		function closeWebSocket(){
			websocket.close();
		}
		//发送消息
		function send(){
			var message = document.getElementById('text').value;
			websocket.send(message);
		}
	</script>
</html>

 

                                     ------------------------------------------- < END >---------------------------------------

MarkerHub  April 4

 

Guess you like

Origin blog.csdn.net/qq_31653405/article/details/107206610