zoukankan      html  css  js  c++  java
  • SpringBoot整合WebSocket实现三种模式发送消息

    1. 简介

      WebSocket是HTML5开始提供的一种在单个TCP连接上进行全双工通讯的协议。
      WebSocket的出现是为了解决Http协议只能在客户端发送请求后服务端响应请求的问题,它允许服务端主动向客户端发送请求。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
      在大多数情况下,为了实现消息推送,往往采用Ajax轮询方式,它遵循的是Http协议,在特定的时间内向服务端发送请求,Http协议的请求头较长,可能仅仅需要获取较小的数据而需要携带较多的数据,而且对于消息不是特别频繁的时候,大部分的轮询都是无意的,造成了极大的资源浪费。
      HTML5定义的WebSocket协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。

    2. 本文简要

      本文基于SpringBoot框架整合WebSocket,实现三种模式发送消息:

    • 自己给自己发送消息
    • 自己给其他用户发送消息
    • 自己给指定用户发送消息

    3. 示例代码

    • 创建工程
    • 修改pom.xml
    <project xmlns="http://maven.apache.org/POM/4.0.0"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    	<modelVersion>4.0.0</modelVersion>
    	<groupId>com.c3stones</groupId>
    	<artifactId>spring-boot-websocket-demo</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<name>spring-boot-websocket-demo</name>
    	<description>Spring Boot WebSocket Demo</description>
    
    	<parent>
    		<groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-starter-parent</artifactId>
    		<version>2.2.8.RELEASE</version>
    	</parent>
    
    	<dependencies>
    		<dependency>
    			<groupId>cn.hutool</groupId>
    			<artifactId>hutool-all</artifactId>
    			<version>5.4.1</version>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-websocket</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-thymeleaf</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-web</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-test</artifactId>
    			<scope>test</scope>
    		</dependency>
    	</dependencies>
    
    	<build>
    		<plugins>
    			<plugin>
    				<groupId>org.springframework.boot</groupId>
    				<artifactId>spring-boot-maven-plugin</artifactId>
    			</plugin>
    		</plugins>
    	</build>
    
    </project>
    
    • 创建配置文件
        在resources目录下创建application.yml。
    server:
      port: 8080
      
    spring:
      thymeleaf:
        prefix: classpath:/view/
        suffix: .html
        encoding: UTF-8
        servlet:
          content-type: text/html
        # 生产环境设置true
        cache: false  
    
    • 添加WebSocket配置类
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.socket.server.standard.ServerEndpointExporter;
    
    /**
     * WebSocket配置类
     * 
     * @author CL
     *
     */
    @Configuration
    public class WebSocketConfig {
    
    	/**
    	 * 注入ServerEndpointExporter
    	 * <p>
    	 * 该Bean会自动注册添加@ServerEndpoint注解的WebSocket端点
    	 * </p>
    	 * 
    	 * @return
    	 */
    	@Bean
    	public ServerEndpointExporter serverEndpointExporter() {
    		return new ServerEndpointExporter();
    	}
    
    }
    
    • 创建启动类
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    /**
     * 启动类
     * 
     * @author CL
     *
     */
    @SpringBootApplication
    public class Application {
    
    	public static void main(String[] args) {
    		SpringApplication.run(Application.class, args);
    	}
    
    }
    
    
    3.1 自己给自己发送消息
    • 创建服务端点
    import java.io.IOException;
    import java.util.concurrent.atomic.AtomicInteger;
    
    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;
    
    import lombok.extern.slf4j.Slf4j;
    
    /**
     * <b style="color: blue"> 自己给自己发送消息 </b>
     * 
     * @author CL
     *
     */
    @Slf4j
    @Component
    @ServerEndpoint(value = "/selfToSelf")
    public class SelfToSelfServer {
    
    	/**
    	 * 在线数
    	 * <p>
    	 * 多线程环境下,为了保证线程安全
    	 * </p>
    	 */
    	private static AtomicInteger online = new AtomicInteger(0);
    
    	/**
    	 * 建立连接
    	 * 
    	 * @param session 客户端连接对象
    	 */
    	@OnOpen
    	public void onOpen(Session session) {
    		// 在线数加1
    		online.incrementAndGet();
    		log.info("客户端连接建立成功,Session ID:{},当前在线数:{}", session.getId(), online.get());
    	}
    
    	/**
    	 * 接收客户端消息
    	 * 
    	 * @param message 客户端发送的消息内容
    	 * @param session 客户端连接对象
    	 */
    	@OnMessage
    	public void onMessage(String message, Session session) {
    		log.info("服务端接收消息成功,Session ID:{},消息内容:{}", session.getId(), message);
    
    		// 处理消息,并响应给客户端
    		this.sendMessage(message, session);
    	}
    
    	/**
    	 * 处理消息,并响应给客户端
    	 * 
    	 * @param message 客户端发送的消息内容
    	 * @param session 客户端连接对象
    	 */
    	private void sendMessage(String message, Session session) {
    		try {
    			String response = "Server Response ==> " + message;
    			session.getBasicRemote().sendText(response);
    
    			log.info("服务端响应消息成功,接收的Session ID:{},响应内容:{}", session.getId(), response);
    		} catch (IOException e) {
    			log.error("服务端响应消息异常:{}", e.getMessage());
    		}
    	}
    
    	/**
    	 * 关闭连接
    	 * 
    	 * @param session 客户端连接对象
    	 */
    	@OnClose
    	public void onClose(Session session) {
    		// 在线数减1
    		online.decrementAndGet();
    		log.info("客户端连接关闭成功,Session ID:{},当前在线数:{}", session.getId(), online.get());
    	}
    
    	/**
    	 * 连接异常
    	 * 
    	 * @param session 客户端连接对象
    	 * @param error   异常
    	 */
    	@OnError
    	public void onError(Session session, Throwable error) {
    		log.error("连接异常:{}", error);
    	}
    
    }
    
    • 创建测试页面
        在resource下创建views文件夹,并创建测试页面selfToSelfClient.html:
    <!DOCTYPE HTML>
    <html>
    <head>
    	<title>WebSocket - Self To Self</title>
    </head>
    <body>
    	<input id="message" type="text" />
        <button onclick="sendMessage()">发送</button>
        <button onclick="closeWebSocket()">关闭</button>
        <hr/>
        <div id="response"></div>
    </body>
    <script type="text/javascript">
    	var websocket = null;
    	
    	// 判断当前浏览器是否支持WebSocket
    	if ('WebSocket' in window) {
    	    websocket = new WebSocket("ws://localhost:8080/selfToSelf");
    	} else {
    	    alert("当前浏览器不支持WebSocket");
    	}
    	
    	// 建立连接成功时的回调方法
        websocket.onopen = function (event) {
        	printMessage("green", "建立连接成功!!!");
        }
    	
    	// 连接异常时的回调方法
        websocket.onerror = function (event) {
        	printMessage("red", "连接异常!!!");
        };
    
        // 客户端接收消息时的回调方法
        websocket.onmessage = function (event) {
        	printMessage("blue", event.data);
        }
    
        // 关闭连接时的回调方法
        websocket.onclose = function() {
        	printMessage("yellow", "关闭连接成功!!!");
        }
    
        // 监听窗口关闭事件,当窗口关闭时,主动关闭连接,防止连接未断开时关闭窗口,服务端抛出异常
        window.onbeforeunload = function() {
            websocket.close();
        }
        
        // 发送消息
        function sendMessage() {
        	if (websocket.readyState != 1) {
        		printMessage("red", "未建立连接或者连接已处于关闭状态!");
        	} else {
        		 var message = document.getElementById('message').value;
        	     websocket.send(message);
        	}
        }
        
     	// 关闭连接
        function closeWebSocket() {
            websocket.close();
        }
     	
      	// 打印消息
        function printMessage(color, text) {
            document.getElementById("response").innerHTML += "<font color='" + color +"'>" + text + "</font><br/>";
        }
    </script>
    </html>
    
    • 创建跳转页面Controller
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    /**
     * 页面视图Controller
     * 
     * @author CL
     *
     */
    @Controller
    public class ViewController {
    
    	/**
    	 * 跳转到<b> 自己给自己发送消息 </b>页面
    	 * 
    	 * @return
    	 */
    	@RequestMapping(value = "/selfToSelf")
    	public String selfToSelf() {
    		return "selfToSelfClient";
    	}
    
    }
    
    • 测试
      2020-12-29 19:21:39.916  INFO 1096 --- [nio-8080-exec-2] com.c3stones.server.SelfToSelfServer     : 客户端连接建立成功,Session ID:0,当前在线数:1
      2020-12-29 19:21:43.564  INFO 1096 --- [nio-8080-exec-3] com.c3stones.server.SelfToSelfServer     : 服务端接收消息成功,Session ID:0,消息内容:测试1
      2020-12-29 19:21:43.583  INFO 1096 --- [nio-8080-exec-3] com.c3stones.server.SelfToSelfServer     : 服务端响应消息成功,接收的Session ID:0,响应内容:Server Response ==> 测试1
      2020-12-29 19:21:45.290  INFO 1096 --- [nio-8080-exec-4] com.c3stones.server.SelfToSelfServer     : 客户端连接关闭成功,Session ID:0,当前在线数:0    
      
      • 浏览器截图
    3.2 自己给其他用户发送消息
    • 创建服务端点
    import java.util.Map;
    import java.util.concurrent.ConcurrentHashMap;
    import java.util.concurrent.atomic.AtomicInteger;
    
    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;
    
    import lombok.extern.slf4j.Slf4j;
    
    /**
     * <b style="color: blue"> 自己给其他用户发送消息 </b>
     * 
     * @author CL
     *
     */
    @Slf4j
    @Component
    @ServerEndpoint(value = "/selfToOther")
    public class SelfToOtherServer {
    
    	/**
    	 * 在线数
    	 * <p>
    	 * 多线程环境下,为了保证线程安全
    	 * </p>
    	 */
    	private static AtomicInteger online = new AtomicInteger(0);
    
    	/**
    	 * 在线客户端连接集合
    	 * <p>
    	 * 多线程环境下,为了保证线程安全
    	 * </p>
    	 */
    	private static Map<String, Session> onlineMap = new ConcurrentHashMap<>();
    
    	/**
    	 * 建立连接
    	 * 
    	 * @param session 客户端连接对象
    	 */
    	@OnOpen
    	public void onOpen(Session session) {
    		// 在线数加1
    		online.incrementAndGet();
    		// 存放客户端连接
    		onlineMap.put(session.getId(), session);
    		log.info("客户端连接建立成功,Session ID:{},当前在线数:{}", session.getId(), online.get());
    	}
    
    	/**
    	 * 接收客户端消息
    	 * 
    	 * @param message 客户端发送的消息内容
    	 * @param session 客户端连接对象
    	 */
    	@OnMessage
    	public void onMessage(String message, Session session) {
    		log.info("服务端接收消息成功,Session ID:{},消息内容:{}", session.getId(), message);
    
    		// 处理消息,并响应给客户端
    		this.sendMessage(message, session);
    	}
    
    	/**
    	 * 处理消息,并响应给客户端
    	 * 
    	 * @param message 客户端发送的消息内容
    	 * @param session 客户端连接对象
    	 */
    	private void sendMessage(String message, Session session) {
    		String response = "Server Response ==> " + message;
    		for (Map.Entry<String, Session> sessionEntry : onlineMap.entrySet()) {
    			Session s = sessionEntry.getValue();
    			// 过滤自己
    			if (!(session.getId()).equals(s.getId())) {
    				log.info("服务端响应消息成功,接收的Session ID:{},响应内容:{}", s.getId(), response);
    				s.getAsyncRemote().sendText(response);
    			}
    		}
    	}
    
    	/**
    	 * 关闭连接
    	 * 
    	 * @param session 客户端连接对象
    	 */
    	@OnClose
    	public void onClose(Session session) {
    		// 在线数减1
    		online.decrementAndGet();
    		// 移除关闭的客户端连接
    		onlineMap.remove(session.getId());
    		log.info("客户端连接关闭成功,Session ID:{},当前在线数:{}", session.getId(), online.get());
    	}
    
    	/**
    	 * 连接异常
    	 * 
    	 * @param session 客户端连接对象
    	 * @param error   异常
    	 */
    	@OnError
    	public void onError(Session session, Throwable error) {
    		log.error("连接异常:{}", error);
    	}
    
    }
    
    • 创建测试页面
        在resource下的views文件夹创建测试页面selfToOtherClient.html:
    <!DOCTYPE HTML>
    <html>
    <head>
    	<title>WebSocket - Self To Other</title>
    </head>
    <body>
    	<input id="message" type="text" />
        <button onclick="sendMessage()">发送</button>
        <button onclick="closeWebSocket()">关闭</button>
        <hr/>
        <div id="response"></div>
    </body>
    <script type="text/javascript">
    	var websocket = null;
    	
    	// 判断当前浏览器是否支持WebSocket
    	if ('WebSocket' in window) {
    	    websocket = new WebSocket("ws://localhost:8080/selfToOther");
    	} else {
    	    alert("当前浏览器不支持WebSocket");
    	}
    	
    	// 建立连接成功时的回调方法
        websocket.onopen = function (event) {
        	printMessage("green", "建立连接成功!!!");
        }
    	
    	// 连接异常时的回调方法
        websocket.onerror = function (event) {
        	printMessage("red", "连接异常!!!");
        };
    
        // 客户端接收消息时的回调方法
        websocket.onmessage = function (event) {
        	printMessage("blue", event.data);
        }
    
        // 关闭连接时的回调方法
        websocket.onclose = function() {
        	printMessage("yellow", "关闭连接成功!!!");
        }
    
        // 监听窗口关闭事件,当窗口关闭时,主动关闭连接,防止连接未断开时关闭窗口,服务端抛出异常
        window.onbeforeunload = function() {
            websocket.close();
        }
        
        // 发送消息
        function sendMessage() {
        	if (websocket.readyState != 1) {
        		printMessage("red", "未建立连接或者连接已处于关闭状态!");
        	} else {
        		 var message = document.getElementById('message').value;
        	     websocket.send(message);
        	}
        }
        
     	// 关闭连接
        function closeWebSocket() {
            websocket.close();
        }
     	
      	// 打印消息
        function printMessage(color, text) {
            document.getElementById("response").innerHTML += "<font color='" + color +"'>" + text + "</font><br/>";
        }
    </script>
    </html>
    
    • 添加跳转页面方法
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    /**
     * 页面视图Controller
     * 
     * @author CL
     *
     */
    @Controller
    public class ViewController {
    
    	/**
    	 * 跳转到<b> 自己给自己发送消息 </b>页面
    	 * 
    	 * @return
    	 */
    	@RequestMapping(value = "/selfToSelf")
    	public String selfToSelf() {
    		return "selfToSelfClient";
    	}
    	
    	/**
    	 * 跳转到<b> 自己给其他用户发送消息 </b>页面
    	 * 
    	 * @return
    	 */
    	@RequestMapping(value = "/selfToOther")
    	public String selfToOther() {
    		return "selfToOtherClient";
    	}
    
    }
    
    • 测试
      2020-12-29 19:53:52.654  INFO 6420 --- [nio-8080-exec-2] com.c3stones.server.SelfToOtherServer    : 客户端连接建立成功,Session ID:0,当前在线数:1
      2020-12-29 19:54:01.044  INFO 6420 --- [nio-8080-exec-5] com.c3stones.server.SelfToOtherServer    : 客户端连接建立成功,Session ID:1,当前在线数:2
      2020-12-29 19:54:14.494  INFO 6420 --- [nio-8080-exec-8] com.c3stones.server.SelfToOtherServer    : 客户端连接建立成功,Session ID:2,当前在线数:3
      2020-12-29 19:54:27.705  INFO 6420 --- [nio-8080-exec-9] com.c3stones.server.SelfToOtherServer    : 服务端接收消息成功,Session ID:0,消息内容:测试1
      2020-12-29 19:54:27.705  INFO 6420 --- [nio-8080-exec-9] com.c3stones.server.SelfToOtherServer    : 服务端响应消息成功,接收的Session ID:1,响应内容:Server Response ==> 测试1
      2020-12-29 19:54:27.753  INFO 6420 --- [nio-8080-exec-9] com.c3stones.server.SelfToOtherServer    : 服务端响应消息成功,接收的Session ID:2,响应内容:Server Response ==> 测试1
      2020-12-29 19:54:43.084  INFO 6420 --- [nio-8080-exec-2] com.c3stones.server.SelfToOtherServer    : 服务端接收消息成功,Session ID:1,消息内容:测试2
      2020-12-29 19:54:43.085  INFO 6420 --- [nio-8080-exec-2] com.c3stones.server.SelfToOtherServer    : 服务端响应消息成功,接收的Session ID:0,响应内容:Server Response ==> 测试2
      2020-12-29 19:54:43.086  INFO 6420 --- [nio-8080-exec-2] com.c3stones.server.SelfToOtherServer    : 服务端响应消息成功,接收的Session ID:2,响应内容:Server Response ==> 测试2
      2020-12-29 19:54:48.474  INFO 6420 --- [nio-8080-exec-5] com.c3stones.server.SelfToOtherServer    : 服务端接收消息成功,Session ID:2,消息内容:测试3
      2020-12-29 19:54:48.474  INFO 6420 --- [nio-8080-exec-5] com.c3stones.server.SelfToOtherServer    : 服务端响应消息成功,接收的Session ID:0,响应内容:Server Response ==> 测试3
      2020-12-29 19:54:48.475  INFO 6420 --- [nio-8080-exec-5] com.c3stones.server.SelfToOtherServer    : 服务端响应消息成功,接收的Session ID:1,响应内容:Server Response ==> 测试3
      
      • 浏览器截图


    3.3 自己给指定用户发送消息
    • 创建服务端点
    import java.io.IOException;
    import java.util.Map;
    import java.util.concurrent.ConcurrentHashMap;
    import java.util.concurrent.atomic.AtomicInteger;
    
    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;
    
    import cn.hutool.json.JSONObject;
    import cn.hutool.json.JSONUtil;
    import lombok.extern.slf4j.Slf4j;
    
    /**
     * <b style="color: blue"> 自己给指定用户发送消息 </b>
     * 
     * @author CL
     *
     */
    @Slf4j
    @Component
    @ServerEndpoint(value = "/selfToSpecific")
    public class SelfToSpecificServer {
    
    	/**
    	 * 在线数
    	 * <p>
    	 * 多线程环境下,为了保证线程安全
    	 * </p>
    	 */
    	private static AtomicInteger online = new AtomicInteger(0);
    
    	/**
    	 * 在线客户端连接集合
    	 * <p>
    	 * 多线程环境下,为了保证线程安全
    	 * </p>
    	 */
    	private static Map<String, Session> onlineMap = new ConcurrentHashMap<>();
    
    	/**
    	 * 建立连接
    	 * 
    	 * @param session 客户端连接对象
    	 */
    	@OnOpen
    	public void onOpen(Session session) {
    		// 在线数加1
    		online.incrementAndGet();
    		// 存放客户端连接
    		onlineMap.put(session.getId(), session);
    		log.info("客户端连接建立成功,Session ID:{},当前在线数:{}", session.getId(), online.get());
    	}
    
    	/**
    	 * 接收客户端消息
    	 * 
    	 * @param message 客户端发送的消息内容
    	 * @param session 客户端连接对象
    	 */
    	@OnMessage
    	public void onMessage(String message, Session session) {
    		log.info("服务端接收消息成功,Session ID:{},消息内容:{}", session.getId(), message);
    
    		// 解析出指定用户
    		JSONObject jsonObj = JSONUtil.parseObj(message);
    		if (jsonObj != null) {
    			Session s = onlineMap.get(jsonObj.get("sessionId"));
    			// 处理消息,并响应给客户端
    			this.sendMessage(jsonObj.get("message").toString(), s);
    		}
    	}
    
    	/**
    	 * 处理消息,并响应给客户端
    	 * 
    	 * @param message 客户端发送的消息内容
    	 * @param session 客户端连接对象
    	 */
    	private void sendMessage(String message, Session session) {
    		try {
    			String response = "Server Response ==> " + message;
    			session.getBasicRemote().sendText(response);
    
    			log.info("服务端响应消息成功,接收的Session ID:{},响应内容:{}", session.getId(), response);
    		} catch (IOException e) {
    			log.error("服务端响应消息异常:{}", e.getMessage());
    		}
    	}
    
    	/**
    	 * 关闭连接
    	 * 
    	 * @param session 客户端连接对象
    	 */
    	@OnClose
    	public void onClose(Session session) {
    		// 在线数减1
    		online.decrementAndGet();
    		// 移除关闭的客户端连接
    		onlineMap.remove(session.getId());
    		log.info("客户端连接关闭成功,Session ID:{},当前在线数:{}", session.getId(), online.get());
    	}
    
    	/**
    	 * 连接异常
    	 * 
    	 * @param session 客户端连接对象
    	 * @param error   异常
    	 */
    	@OnError
    	public void onError(Session session, Throwable error) {
    		log.error("连接异常:{}", error);
    	}
    
    }
    
    • 创建测试页面
        在resource下的views文件夹创建测试页面selfToSpecificClient.html:
    <!DOCTYPE HTML>
    <html>
    <head>
    	<title>WebSocket - Self To Specific</title>
    </head>
    <body>
    	消息:<input id="message" type="text" /><br/>
    	Session Id:<input id="sessionId" type="text" /><br/>
        <button onclick="sendMessage()">发送</button>
        <button onclick="closeWebSocket()">关闭</button>
        <hr/>
        <div id="response"></div>
    </body>
    <script type="text/javascript">
    	var websocket = null;
    	
    	// 判断当前浏览器是否支持WebSocket
    	if ('WebSocket' in window) {
    	    websocket = new WebSocket("ws://localhost:8080/selfToSpecific");
    	} else {
    	    alert("当前浏览器不支持WebSocket");
    	}
    	
    	// 建立连接成功时的回调方法
        websocket.onopen = function (event) {
        	printMessage("green", "建立连接成功!!!");
        }
    	
    	// 连接异常时的回调方法
        websocket.onerror = function (event) {
        	printMessage("red", "连接异常!!!");
        };
    
        // 客户端接收消息时的回调方法
        websocket.onmessage = function (event) {
        	printMessage("blue", event.data);
        }
    
        // 关闭连接时的回调方法
        websocket.onclose = function() {
        	printMessage("yellow", "关闭连接成功!!!");
        }
    
        // 监听窗口关闭事件,当窗口关闭时,主动关闭连接,防止连接未断开时关闭窗口,服务端抛出异常
        window.onbeforeunload = function() {
            websocket.close();
        }
        
        // 发送消息
        function sendMessage() {
        	if (websocket.readyState != 1) {
        		printMessage("red", "未建立连接或者连接已处于关闭状态!");
        	} else {
        		 var message = document.getElementById('message').value;
        		 var sessionId = document.getElementById('sessionId').value;
        		 
        		 var obj = new Object();
        		 obj.message = message;
        		 obj.sessionId = sessionId;
        	     websocket.send(JSON.stringify(obj));
        	}
        }
        
     	// 关闭连接
        function closeWebSocket() {
            websocket.close();
        }
     	
      	// 打印消息
        function printMessage(color, text) {
            document.getElementById("response").innerHTML += "<font color='" + color +"'>" + text + "</font><br/>";
        }
    </script>
    </html>
    
    • 添加跳转页面方法
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    /**
     * 页面视图Controller
     * 
     * @author CL
     *
     */
    @Controller
    public class ViewController {
    
    	/**
    	 * 跳转到<b> 自己给自己发送消息 </b>页面
    	 * 
    	 * @return
    	 */
    	@RequestMapping(value = "/selfToSelf")
    	public String selfToSelf() {
    		return "selfToSelfClient";
    	}
    
    	/**
    	 * 跳转到<b> 自己给其他用户发送消息 </b>页面
    	 * 
    	 * @return
    	 */
    	@RequestMapping(value = "/selfToOther")
    	public String selfToOther() {
    		return "selfToOtherClient";
    	}
    
    	/**
    	 * 跳转到<b> 自己给指定用户发送消息 </b>页面
    	 * 
    	 * @return
    	 */
    	@RequestMapping(value = "/selfToSpecific")
    	public String selfToSpecific() {
    		return "selfToSpecificClient";
    	}
    
    }
    
    • 测试
      2020-12-29 20:27:47.043  INFO 9004 --- [nio-8080-exec-2] c.c3stones.server.SelfToSpecificServer   : 客户端连接建立成功,Session ID:0,当前在线数:1
      2020-12-29 20:27:49.558  INFO 9004 --- [nio-8080-exec-4] c.c3stones.server.SelfToSpecificServer   : 客户端连接建立成功,Session ID:1,当前在线数:2
      2020-12-29 20:27:56.886  INFO 9004 --- [nio-8080-exec-7] c.c3stones.server.SelfToSpecificServer   : 服务端接收消息成功,Session ID:0,消息内容:{"message":"测试1","sessionId":"1"}
      2020-12-29 20:28:06.785  INFO 9004 --- [nio-8080-exec-7] c.c3stones.server.SelfToSpecificServer   : 服务端响应消息成功,接收的Session ID:1,响应内容:Server Response ==> 测试1
      2020-12-29 20:28:19.007  INFO 9004 --- [io-8080-exec-10] c.c3stones.server.SelfToSpecificServer   : 服务端接收消息成功,Session ID:1,消息内容:{"message":"测试2","sessionId":"0"}
      2020-12-29 20:28:19.008  INFO 9004 --- [io-8080-exec-10] c.c3stones.server.SelfToSpecificServer   : 服务端响应消息成功,接收的Session ID:0,响应内容:Server Response ==> 测试2
      
      • 浏览器截图

    4. 项目地址

      spring-boot-websocket-demo

  • 相关阅读:
    深入理解jvm分享培训pdf(转载) 老李
    innobackupex自动备份脚本(增量备份,自动压缩)
    多线程调用生成主键流水号存储过程产生主键冲突问题解决方案
    mysql 5.7新数据库sys解析(一)
    根据日期累加金额的mysql
    mysql字符串分割函数(行转列)
    使用innobackupex备份mysql数据库
    css学习inlineblock详解及dispaly:inline inlineblock block 三者区别精要概括
    html良好结构之豆瓣风格
    HTML5学习笔记html5与传统html区别
  • 原文地址:https://www.cnblogs.com/cao-lei/p/14211746.html
Copyright © 2011-2022 走看看