springboot整合websocket遇到的小问题

今天尝试了通过springboot整合websocket来初步学习使用websocket,然后发现启动的时候报错了,发这篇文章分享一下。

springboot整合websocket的步骤很简单:

第一步:创建一个springboot项目,在这里命名为websocket

在IntelliJ IDEA里创建一个springboot项目,创建过程中只需要修改项目名和选择java的版本为8, 然后点击Next等待片刻就创建好了。

第二步:pom.xml中添加websocket的依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

 不需要指定版本,默认和springboot版本一致,修改springboot版本为2.5.9,完整的配置文件如下

<?xml version="1.0" encoding="UTF-8"?>
<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><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.9</version><relativePath/></parent><groupId>com.example</groupId><artifactId>websocket</artifactId><version>0.0.1-SNAPSHOT</version><properties><java.version>1.8</java.version><lombok.version>1.18.22</lombok.version><fastjson.version>2.0.8</fastjson.version></properties><dependencies><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><!--lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>${lombok.version}</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency><!--fastjson--><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>${fastjson.version}</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>

 第三步:添加websocket的配置类

 在项目的根目录下创建config包,在config包下创建一个配置类WebSocketConfig

package com.example.websocket.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;/*** @author heyunlin* @version 1.0*/
@Configuration
public class WebSocketConfig {@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}}

第四步:使用websocket

在项目根目录下创建一个endpoint包,在endpoint包下创建一个WebSocket类,在类上添加@Component和@ServerEndpoint注解,并通过@ServerEndpoint的value属性指定请求路径,用法类似于@RequestMapping。

package com.example.websocket.endpoint;import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PathVariable;import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;/*** websocket访问路径:ws://localhost:8082/websocket/用户ID* @author heyunlin* @version 1.0*/
@Slf4j
@Component
@ServerEndpoint("/websocket/{userId}")
public class WebSocket {private Session session;private String userId;private final CopyOnWriteArraySet<WebSocket> webSockets = new CopyOnWriteArraySet<>();private final ConcurrentHashMap<String, Session> hashMap = new ConcurrentHashMap<>();/*** 链接成功调用的方法*/@OnOpenpublic void onOpen(Session session, @PathVariable String userId) {this.session = session;this.userId = userId;webSockets.add(this);hashMap.put(userId, session);log.debug("和用户{}创建连接。", this.userId);}/*** 链接关闭调用的方法*/@OnClosepublic void onClose() {webSockets.remove(this);hashMap.remove(this.userId);log.debug("用户{}关闭了websocket连接。", this.userId);}/*** 收到客户端消息后调用的方法*/@OnMessagepublic void onMessage(String message) {log.debug("收到用户{}发送的消息:", this.userId);}/*** 发送错误时的处理* @param error Throwable*/@OnErrorpublic void onError(Throwable error) {error.printStackTrace();}/*** 发送单条消息* @param userId 用户ID* @param message 消息内容*/public void sendMessage(String userId, String message) {if (hashMap.containsKey(userId)) {Session session = hashMap.get(userId);if (session.isOpen()) {session.getAsyncRemote().sendText(message);}}}}

第五步:启动项目

然后启动报错了ovo

java.lang.IllegalStateException: Failed to register @ServerEndpoint class: class com.example.websocket.endpoint.WebSocketat org.springframework.web.socket.server.standard.ServerEndpointExporter.registerEndpoint(ServerEndpointExporter.java:159) ~[spring-websocket-5.3.15.jar:5.3.15]at org.springframework.web.socket.server.standard.ServerEndpointExporter.registerEndpoints(ServerEndpointExporter.java:134) ~[spring-websocket-5.3.15.jar:5.3.15]at org.springframework.web.socket.server.standard.ServerEndpointExporter.afterSingletonsInstantiated(ServerEndpointExporter.java:112) ~[spring-websocket-5.3.15.jar:5.3.15]at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:972) ~[spring-beans-5.3.15.jar:5.3.15]at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.15.jar:5.3.15]at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.15.jar:5.3.15]at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) ~[spring-boot-2.5.9.jar:2.5.9]at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:767) [spring-boot-2.5.9.jar:2.5.9]at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:447) [spring-boot-2.5.9.jar:2.5.9]at org.springframework.boot.SpringApplication.run(SpringApplication.java:338) [spring-boot-2.5.9.jar:2.5.9]at org.springframework.boot.SpringApplication.run(SpringApplication.java:1356) [spring-boot-2.5.9.jar:2.5.9]at org.springframework.boot.SpringApplication.run(SpringApplication.java:1345) [spring-boot-2.5.9.jar:2.5.9]at com.example.websocket.WebsocketApplication.main(WebsocketApplication.java:10) [classes/:na]
Caused by: javax.websocket.DeploymentException: A parameter of type [class java.lang.String] was found on method[onOpen] of class [java.lang.reflect.Method] that did not have a @PathParam annotationat org.apache.tomcat.websocket.pojo.PojoMethodMapping.getPathParams(PojoMethodMapping.java:347) ~[tomcat-embed-websocket-9.0.56.jar:9.0.56]at org.apache.tomcat.websocket.pojo.PojoMethodMapping.<init>(PojoMethodMapping.java:221) ~[tomcat-embed-websocket-9.0.56.jar:9.0.56]at org.apache.tomcat.websocket.server.WsServerContainer.addEndpoint(WsServerContainer.java:155) ~[tomcat-embed-websocket-9.0.56.jar:9.0.56]at org.apache.tomcat.websocket.server.WsServerContainer.addEndpoint(WsServerContainer.java:279) ~[tomcat-embed-websocket-9.0.56.jar:9.0.56]at org.apache.tomcat.websocket.server.WsServerContainer.addEndpoint(WsServerContainer.java:229) ~[tomcat-embed-websocket-9.0.56.jar:9.0.56]at org.springframework.web.socket.server.standard.ServerEndpointExporter.registerEndpoint(ServerEndpointExporter.java:156) ~[spring-websocket-5.3.15.jar:5.3.15]... 12 common frames omittedDisconnected from the target VM, address: '127.0.0.1:53445', transport: 'socket'Process finished with exit code 1

重点看这行

Caused by: javax.websocket.DeploymentException: A parameter of type [class java.lang.String] was found on method[onOpen] of class [java.lang.reflect.Method] that did not have a @PathParam annotation

意思是onOpen()方法上的一个String类型的参数上没有用@PathParam注解,检查了一下,确实没有用这个注解,用的是@PathVariable,这两个注解的作用是类似的,都是获取rest风格请求的参数。修改一下onOpen()方法

package com.example.websocket.endpoint;import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;/*** websocket访问路径:ws://localhost:8082/websocket/用户ID* @author heyunlin* @version 1.0*/
@Slf4j
@Component
@ServerEndpoint("/websocket/{userId}")
public class WebSocket {private Session session;private String userId;private final CopyOnWriteArraySet<WebSocket> webSockets = new CopyOnWriteArraySet<>();private final ConcurrentHashMap<String, Session> hashMap = new ConcurrentHashMap<>();/*** 链接成功调用的方法*/@OnOpenpublic void onOpen(Session session, @PathParam("userId") String userId) {this.session = session;this.userId = userId;webSockets.add(this);hashMap.put(userId, session);log.debug("和用户{}创建连接。", this.userId);}/*** 链接关闭调用的方法*/@OnClosepublic void onClose() {webSockets.remove(this);hashMap.remove(this.userId);log.debug("用户{}关闭了websocket连接。", this.userId);}/*** 收到客户端消息后调用的方法*/@OnMessagepublic void onMessage(String message) {log.debug("收到用户{}发送的消息:", this.userId);}/*** 发送错误时的处理* @param error Throwable*/@OnErrorpublic void onError(Throwable error) {error.printStackTrace();}/*** 发送单条消息* @param userId 用户ID* @param message 消息内容*/public void sendMessage(String userId, String message) {if (hashMap.containsKey(userId)) {Session session = hashMap.get(userId);if (session.isOpen()) {session.getAsyncRemote().sendText(message);}}}}

修改之后能正常启动了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/17997.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

div绑定键盘点击事件

为箭头绑定绑定键盘方向键 <div class"toggle-nav"><spanv-if"leftToggleSt"click"toggleGoods(1)"keyup.left"toggleGoods(1)"class"toggle-left"><a-icon type"left" class"icon" /&…

CHI read trans flow

Read transactions with DMT and without snoops 对于不产生snoop的read trans&#xff0c;建议使用DMT功能&#xff0c;如下图所示&#xff1a; 注意点&#xff1a; a. SNF并不需要给HNF回响应&#xff0c;因为RN发送的compack可以释放HNF处记录的请求; Read transaction wi…

MATLAB|考虑自动重合闸与分布式能源的配电网可靠性评估研究

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

【Leetcode】36. 有效的数独

一、题目 1、题目描述 请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。 数字 1-9 在每一行只能出现一次。 数字 1-9 在每一列只能出现一次。 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图) 注意:…

Element-UI 在表单通过按钮动态增加Tree树形控件

文章目录 问题背景动态增加的Tree控件创建el-tree控件数据动态增加的el-tree控件编辑数据前需进行设置勾选状态新增/编辑请求前需转换格式 问题背景 在表单中动态增加的Tree控件中&#xff0c;注册一个 ref 引用&#xff0c;报错如下&#xff1a; this.$refs[‘showRegionsTre…

spring AOP中pointcut表达式详解

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是「奇点」&#xff0c;江湖人称 singularity。刚工作几年&#xff0c;想和大家一同进步&#x1f91d;&#x1f91d; 一位上进心十足的【Java ToB端大厂…

Qt中的信号与槽(Signals and Slots)

Qt中的信号与槽&#xff08;Signals and Slots&#xff09;是一种用于对象间通信的机制&#xff0c;常用于处理用户界面事件和数据更新等情况。通过信号与槽&#xff0c;可以实现对象之间的解耦和灵活的交互。 信号&#xff08;Signal&#xff09;是对象发出的事件或通知&…

基于vscode连接到远程服务中debug

本文章主要讲解以下两点的任务 1.在windows的vscode中去debug 本机子系统wsl2中运行的docker容器 该篇文件参考知乎上这篇文章 vscode远程连接到本机 wsl2子系统 中正在运行的 docker容器&#xff0c;该docker中有一个flask实例&#xff0c;通过vscode远程debug它 1.1安装v…

Modbus tcp转ETHERCAT在Modbus软件中的配置方法

Modbus tcp和ETHERCAT是两种不同的协议&#xff0c;这给工业生产带来了很大的麻烦&#xff0c;因为这两种设备之间无法通讯。但是&#xff0c;远创智控YC-ECT-TCP网关的出现&#xff0c;却为这个难题提供了解决方案。 YC-ECT-TCP网关能够连接到Modbus tcp总线和ETHERCAT总线中…

Kubernetes —Pod 和容器日志

日志架构 应用日志可以让你了解应用内部的运行状况。日志对调试问题和监控集群活动非常有用。 大部分现代化应用都有某种日志记录机制。同样地&#xff0c;容器引擎也被设计成支持日志记录。 针对容器化应用&#xff0c;最简单且最广泛采用的日志记录方式就是写入标准输出和标…

容器【双例集合、TreeMap容器的使用、 Iterator接口、Collections工具类】(四)-全面详解(学习总结---从入门到深化)

目录 通过元素自身实现比较规则 通过比较器实现比较规则 双例集合 TreeMap容器的使用 Iterator接口 Collections工具类 通过元素自身实现比较规则 在元素自身实现比较规则时&#xff0c;需要实现Comparable接口中的 compareTo方法&#xff0c;该方法中用来定义比较规则。T…

【IoT物联网】IoT小程序在展示中央空调采集数据和实时运行状态上的应用

利用前端语言实现跨平台应用开发似乎是大势所趋&#xff0c;跨平台并不是一个新的概念&#xff0c;“一次编译、到处运行”是老牌服务端跨平台语言Java的一个基本特性。随着时代的发展&#xff0c;无论是后端开发语言还是前端开发语言&#xff0c;一切都在朝着减少工作量&#…