Springboot实现websocket
Posted 诺浅
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Springboot实现websocket相关的知识,希望对你有一定的参考价值。
Websocket
在前面的文章中我们讲到了websocket和传统的http有什么区别,以及websocket用来实现服务器推的优势,那么这篇文章就来说说,在Java中如果要实现一个websocket应该怎么实现,这里采用的是更加方便的Springboot的方式,如果项目中没有使用springboot框架,也是可以实现的,本文不涉及。
代码
服务端
1、先引入springboot-websocket的starter
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
2、定义一个WebSocketBean,用来保存组装的信息,这个Bean也可以自己添加其他的属性
@Getter
@Setter
public class WebSocketBean
private WebSocketSession webSocketSession;
private int clientId;
private String token;
3、连接或断开处理类
@Slf4j
public class MyWebsocketHandler extends AbstractWebSocketHandler
public static final Map<String, WebSocketBean> webSocketBeanMap;
/**
* 仅用用于标识客户端编号
*/
private static final AtomicInteger clientIdMaker;
static
webSocketBeanMap = new ConcurrentHashMap<>();
clientIdMaker = new AtomicInteger(0);
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception
// 当WebSocket连接正式建立后,将该Session加入到Map中进行管理
Map<String, Object> attributes = session.getAttributes();
WebSocketBean webSocketBean = new WebSocketBean();
webSocketBean.setWebSocketSession(session);
webSocketBean.setClientId(clientIdMaker.getAndIncrement());
webSocketBean.setToken(attributes.get("token").toString());
webSocketBeanMap.put(session.getId(), webSocketBean);
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception
//当连接关闭后,从Map中移除session实例
webSocketBeanMap.remove(session.getId());
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception
//传输过程中出现了错误
if (session.isOpen())
session.close();
webSocketBeanMap.remove(session.getId());
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception
//处理接收到的消息
log.info("Received message from client[ID:" + webSocketBeanMap.get(session.getId()).getClientId() +
"]; Content is [" + message.getPayload() + "].");
TextMessage textMessage = new TextMessage("Server has received your message.");
session.sendMessage(textMessage);
4、把连接监控类配置进spring,用于程序启动时启动websocket
@Configuration
@EnableWebSocket
public class WebSocketConfiguration implements WebSocketConfigurer
@Bean
public MyWebSocketInterceptor webSocketInterceptor()
return new MyWebSocketInterceptor();
@Bean
public ServerEndpointExporter serverEndpointExporter()
return new ServerEndpointExporter();
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry)
webSocketHandlerRegistry
.addHandler(new MyWebsocketHandler(), "/websocket")
.addInterceptors(webSocketInterceptor());
5、可以做一个简单的鉴权
@Slf4j
public class MyWebSocketInterceptor extends HttpSessionHandshakeInterceptor
private final Logger logger = LoggerFactory.getLogger(getClass());
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception
logger.info("[MyWebSocketInterceptor#BeforeHandshake] Request from " + request.getRemoteAddress().getHostString());
if (request instanceof ServletServerHttpRequest)
ServletServerHttpRequest serverHttpRequest = (ServletServerHttpRequest) request;
String token = serverHttpRequest.getServletRequest().getParameter("token");
//这里做一个简单的鉴权,只有符合条件的鉴权才能握手成功
if ("123456".equals(token))
// 保存认证用户
attributes.put("token", token);
return super.beforeHandshake(request, response, wsHandler, attributes);
else
log.error("token错误。token:[]!", token, new ConsumablesCabinetException("token错误"));
return false;
return super.beforeHandshake(request, response, wsHandler, attributes);
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex)
logger.info("[MyWebSocketInterceptor#afterHandshake] Request from " + request.getRemoteAddress().getHostString());
到此,websocket的服务端就完成了,启动工程,就会启动一个websocket服务,现在来实现客户端
客户端
客户端这里也是用java列出,实际上js等各种方式都可以实现
1、先引包
<dependency>
<groupId>org.java-websocket</groupId>
<artifactId>Java-WebSocket</artifactId>
<version>1.5.1</version>
</dependency>
2、客户端连接断开监控类
public class MyWebSocketClient extends WebSocketClient
private Logger logger = LoggerFactory.getLogger(getClass());
public MyWebSocketClient(URI serverUri)
super(serverUri);
@Override
public void onOpen(ServerHandshake serverHandshake)
logger.info("[MyWebSocketClient#onOpen]The WebSocket connection is open.");
@Override
public void onMessage(String s)
logger.info("[MyWebSocketClient#onMessage]The client has received the message from server." +
"The Content is [" + s + "]");
@Override
public void onClose(int i, String s, boolean b)
logger.info("[MyWebSocketClient#onClose]The WebSocket connection is close.");
@Override
public void onError(Exception e)
logger.info("[MyWebSocketClient#onError]The WebSocket connection is error.");
3、启动类
public class MyWebSocketMain
private static final AtomicInteger count = new AtomicInteger(0);
public static void main(String[] args)
URI uri = URI.create("ws://localhost:8001/websocket?token=123456");
MyWebSocketClient client = new MyWebSocketClient(uri);
try
// 在连接成功之前会一直阻塞
client.connectBlocking();
Timer timer = new Timer();
MyTimerTask timerTask = new MyTimerTask(client);
timer.schedule(timerTask, 1000, 2000);
catch (InterruptedException e)
e.printStackTrace();
static class MyTimerTask extends TimerTask
private final MyWebSocketClient client;
public MyTimerTask(MyWebSocketClient client)
this.client = client;
@Override
public void run()
client.send("Test message from client, the number is " + count.getAndIncrement());
运行服务端和客户端就可以看到服务器端不停的输出
Received message from client[ID:0]; Content is [Test message from client, the number is 0].
客户端不停的输出
The client has received the message from server.The Content is [Server has received your message.]
这样就说明成功了
以上是关于Springboot实现websocket的主要内容,如果未能解决你的问题,请参考以下文章
SpringBoot使用WebSocket实现服务端推送--集群实现
SpringBoot+Vue+Websocket 实现服务器端向客户端主动发送消息