当前位置: 首页 > news >正文

SpringBoot——使用WebSocket功能

springboot自带websocket,通过几个简单的注解就可以实现websocket的功能;

启动类跟普通的springboot一样:

/*** 2023年3月2日下午4:16:57*/
package testspringboot.test7websocket;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.PropertySource;/*** @author XWF**/
@SpringBootApplication
@PropertySource(value = "test7.properties")
public class Test7Main {/*** @param args*/public static void main(String[] args) {SpringApplication.run(Test7Main.class, args);}}

还需要一个websocket的配置类:

/*** 2023年3月2日下午4:26:15*/
package testspringboot.test7websocket;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;/*** @author XWF**/
@Configuration
public class WebSocketConfig {@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}}

配置文件里只配置了一个端口:

主要的逻辑都放到@ServerEndpoint标签注释的类里,类似controller的功能;

可以使用4种注解处理业务:

  • @OnOpen:处理客户端的连接;
  • @OnClose:处理客户端断开;
  • @OnError:处理故障错误;
  • @OnMessage:处理具体消息,有三种消息类型:String类型,ByteBuffer类型,PongMessage类型,同一消息类型类里不能出现多次;

另外可以通过Session对象设置属性或者发送数据,session.getUserProperties()存取属性,session.getBasicRemote()或者session.getAsyncRemote()可以进行同步异步发送数据;

处理类:

/*** 2023年3月2日下午4:27:01*/
package testspringboot.test7websocket;import java.io.IOException;
import java.nio.ByteBuffer;import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.PongMessage;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;import org.springframework.stereotype.Component;/*** @author XWF**/
@Component
@ServerEndpoint(value = "/websockettest/{name}")
public class WebSocketHandler {@OnOpen  public void onOpen(@PathParam("name") String name, Session session) throws IOException {  System.out.println("onOpen:" + name);session.getUserProperties().put("name", name);}@OnClose  public void onClose(@PathParam("name") String name, Session session) throws IOException {System.out.println("onClose:" + name);System.out.println(session.getUserProperties().get("name") + "关闭了");}@OnError  public void onError(Session session, Throwable error) {System.out.println("onERROR");error.printStackTrace();  }@OnMessagepublic void textMessage(Session session, String msg) {System.out.println("收到:" + msg);try {session.getBasicRemote().sendText("hello");} catch (IOException e) {e.printStackTrace();}}@OnMessagepublic void binaryMessage(Session session, ByteBuffer msg) {System.out.println("Binary message: " + msg.toString());}@OnMessagepublic void pongMessage(Session session, PongMessage msg) {System.out.println("Pong message: " + msg.getApplicationData().toString());}}

测试websocket用的Apipost:

连接测试:

发送数据测试:

断开连接:

另外,也可以设置自己的编解码处理自己的消息,实现javax.websocket.Encoder.Text或者javax.websocket.Encoder.Binary接口实现编码器,实现javax.websocket.Decoder.Text或者javax.websocket.Decoder.Binary接口实现解码器,解码器最多两个,一个解码Text一个Binary;

在@ServerEndpoint注解里配置上自己的encoders和decoders就可以实现自定义编解码了;

自定义消息MsgA:

/*** 2023年3月3日下午3:12:47*/
package testspringboot.test7websocket;/*** @author XWF**/
public class MsgA {public int id;public String name;@Overridepublic String toString() {return "MsgA [id=" + id + ", name=" + name + "]";}}

编码器:

/*** 2023年3月3日下午3:14:02*/
package testspringboot.test7websocket;import javax.websocket.EncodeException;
import javax.websocket.Encoder.Text;
import javax.websocket.EndpointConfig;/*** @author XWF**/
public class MsgATextEncoder implements Text<MsgA>{@Overridepublic void init(EndpointConfig endpointConfig) {System.out.println("msga encoder init");}@Overridepublic void destroy() {System.out.println("msga encoder destroy");}// 进行编码操作,将对象编码成string@Overridepublic String encode(MsgA object) throws EncodeException {return object.toString();}}

解码器:

/*** 2023年3月3日下午3:16:52*/
package testspringboot.test7websocket;import javax.websocket.DecodeException;
import javax.websocket.Decoder.Text;
import javax.websocket.EndpointConfig;/*** @author XWF**/
public class MsgATextDecoder implements Text<MsgA> {@Overridepublic void init(EndpointConfig endpointConfig) {System.out.println("msga decoder init");}@Overridepublic void destroy() {System.out.println("msga decoder destroy");}// 进行解码操作,将string解码成需要的对象@Overridepublic MsgA decode(String s) throws DecodeException {MsgA msga = new MsgA();msga.id = Integer.parseInt(s.split(",")[0]);msga.name = s.split(",")[1];return msga;}// 验证消息是否可以解码,返回true可以解码,否则返回false@Overridepublic boolean willDecode(String s) {// 接收格式:id,nameif (s.split(",").length == 2) {try {Integer.parseInt(s.split(",")[0]);} catch (NumberFormatException e) {return false;}return true;} else {return false;}}}

处理类:

/*** 2023年3月3日下午3:07:45*/
package testspringboot.test7websocket;import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;import javax.websocket.EncodeException;
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;/*** @author XWF**/
@Component
@ServerEndpoint(value = "/websocketmsgtest", encoders = {MsgATextEncoder.class}, decoders = {MsgATextDecoder.class})
public class WebSocketMsgHandler {@OnOpenpublic void onOpen() {}@OnClosepublic void onClose() {}@OnErrorpublic void onError(Throwable error) {}@OnMessagepublic void textMessageA(Session session, MsgA msga) {System.out.println("收到:" + msga);MsgA sendMsg = new MsgA();sendMsg.id = 9999;sendMsg.name = "HELLO WORLD";try {session.getBasicRemote().sendObject(sendMsg);} catch (IOException e) {e.printStackTrace();} catch (EncodeException e) {e.printStackTrace();}sendMsg.id = 8888;sendMsg.name = "hello world";Future<Void> future = session.getAsyncRemote().sendObject(sendMsg);try {future.get(3, TimeUnit.SECONDS);System.out.println("发送完毕");} catch (InterruptedException | ExecutionException | TimeoutException e) {System.out.println("超时");e.printStackTrace();}}}

测试:

不按照解码格式要求请求会异常并断开连接:

正常测试:

http://www.lryc.cn/news/34053.html

相关文章:

  • 博弈论小课堂:非零和博弈(实现双赢)【纳什均衡点】
  • 数组中的逆序对
  • C++基础了解-01-基础语法
  • phpmyadmin 文件包含(CVE-2014-8959)
  • SpringBoot集成MyBatis
  • MySQL-索引
  • 【STM32存储器映射-寄存器基地址-偏移】
  • 【华为OD机试2023】最多颜色的车辆 C++ Java Python
  • 特斯拉后端面试(部分)
  • 【python】使用python将360个文件夹里的照片,全部复制到指定的文件夹中,并且按照顺序重新命名
  • 【C语言】3天速刷C语言(初识)
  • 如何搞定MySQL锁(全局锁、表级锁、行级锁)?这篇文章告诉你答案!太TMD详细了!!!
  • 云计算生态该怎么做?阿里云计算巢打了个样
  • 小樽C++ 多章⑧ (贰) 指针与数组
  • MXNet的机器翻译实践《编码器-解码器(seq2seq)和注意力机制》
  • RK3588平台开发系列讲解(同步与互斥篇)自旋锁介绍
  • Linux系统CPU占用率较高问题排查思路
  • 源码解析——HashMap
  • Elasticsearch 核心技术(六):内置的 8 种分词器详解 + 代码示例
  • Mysql8.0的特性
  • JDK动态代理(tedu)(内含源代码)
  • 【数据结构】二叉搜索树
  • 抢跑数字中国建设,青岛市统计系统考察团赴实在智能调研统计数字员工
  • 深浅拷贝——利用模拟实现basic_string深入理解
  • 大模型分布式系统
  • 【时序】时序预测任务模型选择如何选择?
  • 重温数据结构与算法之深度优先搜索
  • STM32F103驱动LD3320语音识别模块
  • 2023 最新可用Google镜像地址 长期更新
  • MATLAB算法实战应用案例精讲-【优化算法】蝗虫优化算法(GOA)及其算法变种(附matlab和python代码实现)