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 {

@Bean

public 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();

}

@OnMessage

public void textMessage(Session session, String msg) {

System.out.println("收到:" + msg);

try {

session.getBasicRemote().sendText("hello");

} catch (IOException e) {

e.printStackTrace();

}

}

@OnMessage

public void binaryMessage(Session session, ByteBuffer msg) {

System.out.println("Binary message: " + msg.toString());

}

@OnMessage

public 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;

@Override

public 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{

@Override

public void init(EndpointConfig endpointConfig) {

System.out.println("msga encoder init");

}

@Override

public void destroy() {

System.out.println("msga encoder destroy");

}

// 进行编码操作,将对象编码成string

@Override

public 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 {

@Override

public void init(EndpointConfig endpointConfig) {

System.out.println("msga decoder init");

}

@Override

public void destroy() {

System.out.println("msga decoder destroy");

}

// 进行解码操作,将string解码成需要的对象

@Override

public 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

@Override

public boolean willDecode(String s) {

// 接收格式:id,name

if (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 {

@OnOpen

public void onOpen() {

}

@OnClose

public void onClose() {

}

@OnError

public void onError(Throwable error) {

}

@OnMessage

public 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 future = session.getAsyncRemote().sendObject(sendMsg);

try {

future.get(3, TimeUnit.SECONDS);

System.out.println("发送完毕");

} catch (InterruptedException | ExecutionException | TimeoutException e) {

System.out.println("超时");

e.printStackTrace();

}

}

}

测试:

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

正常测试:

文章链接

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。