• spring boot 集成 websocket 实现消息主动


    来源:https://www.cnblogs.com/leigepython/p/11058902.html

    pom.xml

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     3     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
     4     <modelVersion>4.0.0</modelVersion>
     5     <parent>
     6         <groupId>org.springframework.boot</groupId>
     7         <artifactId>spring-boot-starter-parent</artifactId>
     8         <version>2.1.1.RELEASE</version>
     9         <relativePath/> <!-- lookup parent from repository -->
    10     </parent>
    11     <groupId>com.zhengcj</groupId>
    12     <artifactId>spring-boot-09-websocket</artifactId>
    13     <version>0.0.1-SNAPSHOT</version>
    14     <name>spring-boot-09-websocket</name>
    15     <description>Demo project for Spring Boot</description>
    16 
    17     <properties>
    18         <java.version>1.8</java.version>
    19     </properties>
    20 
    21     <dependencies>
    22         <dependency>
    23             <groupId>org.springframework.boot</groupId>
    24             <artifactId>spring-boot-starter-thymeleaf</artifactId>
    25         </dependency>
    26         <dependency>
    27             <groupId>org.springframework.boot</groupId>
    28             <artifactId>spring-boot-starter-web</artifactId>
    29         </dependency>
    30         <dependency>
    31             <groupId>org.springframework.boot</groupId>
    32             <artifactId>spring-boot-starter-websocket</artifactId>
    33         </dependency>
    34 
    35         <dependency>
    36             <groupId>org.springframework.boot</groupId>
    37             <artifactId>spring-boot-starter-test</artifactId>
    38             <scope>test</scope>
    39         </dependency>
    40     </dependencies>
    41 
    42     <build>
    43         <plugins>
    44             <plugin>
    45                 <groupId>org.springframework.boot</groupId>
    46                 <artifactId>spring-boot-maven-plugin</artifactId>
    47             </plugin>
    48         </plugins>
    49     </build>
    50     
    51 
    52 </project>

    SpringBoot09WebsocketApplication.java

     1 package com.zhengcj.websocket;
     2 
     3 import org.springframework.boot.SpringApplication;
     4 import org.springframework.boot.autoconfigure.SpringBootApplication;
     5 
     6 /**
     7  * 地址:https://www.cnblogs.com/leigepython/p/11058902.html
     8  * @author zhengcj
     9  *
    10  */
    11 @SpringBootApplication
    12 public class SpringBoot09WebsocketApplication {
    13 
    14     public static void main(String[] args) {
    15         SpringApplication.run(SpringBoot09WebsocketApplication.class, args);
    16     }
    17 
    18 }

    WebSocketConfig.java

     1 package com.zhengcj.websocket.config;
     2 
     3 import org.springframework.context.annotation.Bean;
     4 import org.springframework.context.annotation.Configuration;
     5 import org.springframework.web.socket.server.standard.ServerEndpointExporter;
     6 
     7 /**
     8  * @author zhengcj
     9  * @Date 2020年4月27日 上午11:37:26
    10  * @version
    11  * @Description  socket配置类,往 spring 容器中注入ServerEndpointExporter实例
    12  *
    13  */
    14 @Configuration
    15 public class WebSocketConfig {
    16     @Bean
    17     public ServerEndpointExporter serverEndpointExporter() {
    18         return new ServerEndpointExporter();
    19     }
    20 
    21 }

    WebSocketServer.java

      1 package com.zhengcj.websocket.common;
      2 
      3 import java.io.IOException;
      4 import java.util.HashMap;
      5 import java.util.Map;
      6 import java.util.concurrent.atomic.AtomicInteger;
      7 
      8 import javax.websocket.OnClose;
      9 import javax.websocket.OnError;
     10 import javax.websocket.OnMessage;
     11 import javax.websocket.OnOpen;
     12 import javax.websocket.Session;
     13 import javax.websocket.server.PathParam;
     14 import javax.websocket.server.ServerEndpoint;
     15 
     16 import org.springframework.stereotype.Component;
     17 
     18 /**
     19  * WebSocket服务端代码,包含接收消息,推送消息等接口
     20  * @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,
     21  *  注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
     22  * @author zhengcj
     23  * @Date 2020年4月27日 下午1:36:13
     24  * @version
     25  * @Description
     26  */
     27 @Component
     28 @ServerEndpoint(value = "/socket/{name}")
     29 public class WebSocketServer {
     30 
     31     // 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
     32     private static AtomicInteger online = new AtomicInteger();
     33     // concurrent包的线程安全Set,用来存放每个客户端对应的WebSocketServer对象。
     34 //    private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();
     35     private static Map<String, Session> sessionPools = new HashMap<>();
     36 
     37     /**
     38      * 发送消息方法
     39      * @param session 客户端与socket建立的会话
     40      * @param message 消息
     41      * @throws IOException
     42      */
     43     public void sendMessage(Session session, String message) throws IOException {
     44         if (session != null) {
     45             session.getBasicRemote().sendText(message);
     46         }
     47     }
     48 
     49     /**
     50      * 连接建立成功调用
     51      * @param sessionv 客户端与socket建立的会话
     52      * @param userName 客户端的userName
     53      */
     54     @OnOpen
     55     public void onOpen(Session session, @PathParam(value = "name") String userName) {
     56         sessionPools.put(userName, session);
     57         addOnlineCount();
     58         System.out.println(userName + "加入webSocket!当前人数为" + online);
     59         try {
     60             sendMessage(session, "欢迎" + userName + "加入连接!");
     61         } catch (IOException e) {
     62             e.printStackTrace();
     63         }
     64     }
     65 
     66     /**
     67      * 关闭连接时调用
     68      * @param userName 关闭连接的客户端的姓名
     69      */
     70     @OnClose
     71     public void onClose(@PathParam(value = "name") String userName) {
     72         sessionPools.remove(userName);
     73         subOnlineCount();
     74         System.out.println(userName + "断开webSocket连接!当前人数为" + online);
     75     }
     76 
     77     /**
     78      * 收到客户端消息时触发(群发)
     79      * @param message
     80      * @throws IOException
     81      */
     82     @OnMessage
     83     public void onMessage(String message) throws IOException {
     84         System.out.println("群发信息:"+message);
     85         for (Session session : sessionPools.values()) {
     86             try {
     87                 sendMessage(session, message);
     88             } catch (Exception e) {
     89                 e.printStackTrace();
     90                 continue;
     91             }
     92         }
     93     }
     94 
     95     /**
     96      * 发生错误时候
     97      * @param session
     98      * @param throwable
     99      */
    100     @OnError
    101     public void onError(Session session, Throwable throwable) {
    102         System.out.println("发生错误");
    103         throwable.printStackTrace();
    104     }
    105 
    106     /**
    107      * 给指定用户发送消息
    108      * 
    109      * @param userName
    110      *            用户名
    111      * @param message
    112      *            消息
    113      * @throws IOException
    114      */
    115     public void sendInfo(String userName, String message) {
    116         Session session = sessionPools.get(userName);
    117         try {
    118             sendMessage(session, message);
    119         } catch (Exception e) {
    120             e.printStackTrace();
    121         }
    122     }
    123 
    124     public static void addOnlineCount() {
    125         online.incrementAndGet();
    126     }
    127 
    128     public static void subOnlineCount() {
    129         online.decrementAndGet();
    130     }
    131 }

    WebMvcConfig.java

     1 package com.zhengcj.websocket.config;
     2 
     3 import org.springframework.context.annotation.Configuration;
     4 import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
     5 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
     6 
     7 /** 
     8  * @author zhengcj
     9  * @Date 2020年4月27日 下午1:38:31
    10  * @version
    11  * @Description 
    12  *
    13  * 在SpringBoot2.0及Spring 5.0 WebMvcConfigurerAdapter已被废弃,目前找到解决方案就有
    14  * 1 直接实现WebMvcConfigurer (官方推荐)
    15  * 2 直接继承WebMvcConfigurationSupport
    16  * @ https://blog.csdn.net/lenkvin/article/details/79482205
    17  */
    18 @Configuration
    19 public class WebMvcConfig implements WebMvcConfigurer{
    20     /**
    21      * 为各个页面提供路径映射
    22      * @param registry
    23      */
    24     @Override
    25     public void addViewControllers(ViewControllerRegistry registry) {
    26         registry.addViewController("/zhengcj").setViewName("zhengcj");
    27         registry.addViewController("/yuzh").setViewName("yuzh");
    28     }
    29 }

    SocketController.java

     1 package com.zhengcj.websocket.controller;
     2 
     3 import java.io.IOException;
     4 
     5 import javax.annotation.Resource;
     6 
     7 import org.springframework.web.bind.annotation.GetMapping;
     8 import org.springframework.web.bind.annotation.RequestParam;
     9 import org.springframework.web.bind.annotation.RestController;
    10 
    11 import com.zhengcj.websocket.common.WebSocketServer;
    12 
    13 /** 
    14  * @author zhengcj
    15  * @Date 2020年4月27日 下午1:44:32
    16  * @version
    17  * @Description 
    18  *
    19  */
    20 @RestController
    21 public class SocketController {
    22     @Resource
    23     private WebSocketServer webSocketServer;
    24 
    25     /**
    26      * 给指定用户推送消息
    27      * @param userName 用户名
    28      * @param message 消息
    29      * @throws IOException
    30      */
    31     @GetMapping("/socket")
    32     public void pushOneUser(@RequestParam String userName, @RequestParam String message){
    33         System.err.println("====socket===="+message);
    34         webSocketServer.sendInfo(userName, message);
    35     }
    36 
    37     /**
    38      * 给所有用户推送消息
    39      * @param message 消息
    40      * @throws IOException
    41      */
    42     @GetMapping("/socket/all")
    43     public void pushAllUser(@RequestParam String message){
    44         try {
    45             System.err.println("====socket/all===="+message);
    46             webSocketServer.onMessage(message);
    47         } catch (IOException e) {
    48             e.printStackTrace();
    49         }
    50     }
    51 }

    yuzh.html

    <!DOCTYPE HTML>
    <html>
    <head>
    <title>WebSocket</title>
    </head>
    
    <body>
    	Welcome
    	<br />
    	<input id="text" type="text" />
    	<button onclick="send()">Send</button>
    	<button onclick="closeWebSocket()">Close</button>
    	<div id="message"></div>
    </body>
    
    <script type="text/javascript">
    	var websocket = null;
    
    	//判断当前浏览器是否支持WebSocket
    	if ('WebSocket' in window) {
    		websocket = new WebSocket("ws://localhost:8080/socket/yuzh");
    	} 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>
    

      zhengcj.html

    <!DOCTYPE HTML>
    <html>
    <head>
    <title>WebSocket</title>
    </head>
    
    <body>
    	Welcome
    	<br />
    	<input id="text" type="text" />
    	<button onclick="send()">Send</button>
    	<button onclick="closeWebSocket()">Close</button>
    	<div id="message"></div>
    </body>
    
    <script type="text/javascript">
    	var websocket = null;
    
    	//判断当前浏览器是否支持WebSocket
    	if ('WebSocket' in window) {
    		websocket = new WebSocket("ws://localhost:8080/socket/zhengcj");
    	} 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>
    

      

  • 相关阅读:
    5:《地牢守卫者》代码分析:EnemyController
    4:《地牢守卫者》代码分析:Enemy
    1:《地牢守卫者》代码解析PlayerController
    0:地牢守卫者开发框架
    7:《地牢守卫者》代码分析:DarkElf,DrakElfController
    6:《地牢守卫者》代码分析:GoblinPawn,GoblinController
    ABAP学习(1):基本语法介绍
    项目实例:车辆信息统计报表管理系统导出PDF怎么调样式?
    软件制作:模拟登陆之WebBrowser
    编程经验:邮件发送接收
  • 原文地址:https://www.cnblogs.com/zcjyzh/p/14272537.html
Copyright © 2020-2023  润新知