SpringBoot集成WebSocket实现多个服务通信
之前在网上搜的都是html页面做的客户端,这个是纯java代码做客户端发送消息
spring boot + webSocket实现多个项目之间进行通信操作
作为spring cloud微服务多个服务之间进行通信
首先至少得有一个websocket服务端 与一个或多个 websocket客户端
已提供源码免费下载,Spring Cloud alibaba nacos注册中心+【websocket服务端和websocket客户端】两个服务
参考文章,感谢博主的分享:https://blog.csdn.net/m0_37845840/article/details/80055243
客户端:
package com.example.socketclient.websocket;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.websocket.*;
import java.io.IOException;
import java.net.InetAddress;
import java.net.URI;
/**
* @author Administrator
* @description
* @date 2021-01-07 10:36
*/
@Component
@ClientEndpoint
public class WebSocketClient {
@Value("${websocket.server.url}")
private String serverUrl;
private Session session;
@PostConstruct
void init() {
try {
// 本机地址
String hostAddress = InetAddress.getLocalHost().getHostAddress();
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
String wsUrl = "ws://" + serverUrl + "/" + hostAddress;
URI uri = URI.create(wsUrl);
session = container.connectToServer(WebSocketClient.class, uri);
send("2222222");
} catch (DeploymentException | IOException e) {
e.printStackTrace();
}
}
/**
* 打开连接
* @param session
*/
@OnOpen
public void onOpen(Session session) {
System.out.println("打开");
this.session = session;
}
/**
* 接收消息
* @param text
*/
@OnMessage
public void onMessage(String text) {
System.out.println(text);
}
/**
* 异常处理
* @param throwable
*/
@OnError
public void onError(Throwable throwable) {
throwable.printStackTrace();
}
/**
* 关闭连接
*/
@OnClose
public void onClosing() throws IOException {
System.out.println("关闭");
session.close();
}
/**
* 主动发送消息
*/
public void send(String message) {
this.session.getAsyncRemote().sendText(message);
}
public void close() throws IOException{
if(this.session.isOpen()){
this.session.close();
}
}
}
package com.example.socketclient;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class SocketClientApplication {
public static void main(String[] args) {
SpringApplication.run(SocketClientApplication.class, args);
}
}
spring:
profiles:
active: test
## 本地开发自测环境配置
server:
port: 9001
spring:
application:
name: Socket-Client
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
websocket:
server:
url: 127.0.0.1:9000
服务端
package com.example.socketserver.config;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
@Order(value = 1)
// 类实现ApplicationRunner或CommandLineRunner接口都可以实现预加载
public class MyApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
// 获取数据库表已存储的各个服务的IP地址数据
// 进行socket重新连接操作
System.out.println("=====ApplicationRunner=====");
}
}
package com.example.socketserver.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
* @author Administrator
* @description
* @date 2021-01-07 10:00
*/
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
package com.example.socketserver.websocket;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author Administrator
* @description
* @date 2021-01-07 10:09
*/
@Component
@ServerEndpoint(value = "/{ip}")
public class WebSocketServer {
// 在多线程访问的时候,使用线程安全的ConCurrentHashMap对象
private static ConcurrentHashMap<String, Session> connections = new ConcurrentHashMap<>();
private static ApplicationContext applicationContext;
public static void setApplicationContext(ApplicationContext applicationContext) {
WebSocketServer.applicationContext = applicationContext;
}
/**
* 打开连接
* @param session
* @param ip
*/
@OnOpen
public void onOpen(Session session, @PathParam("ip") String ip) {
System.out.println("=====接受到的请求地址=====" + ip);
// 接收到客户端的请求,可以做一些其他业务逻辑处理,比如可以把该IP存储到数据库
// 避免当前服务断开后,与客户端服务失去连接
// 这时就可以使用到预加载处理,项目当中自定义的MyApplicationRunner类
connections.put(ip, session);
}
/**
* 接收消息
* @param text
*/
@OnMessage
public void onMessage(String text) {
System.out.println(text);
}
/**
* 异常处理
* @param throwable
*/
@OnError
public void onError(Throwable throwable) {
throwable.printStackTrace();
}
/**
* 关闭连接
* @param ip
*/
@OnClose
public void onClosing(@PathParam("ip") String ip) throws IOException {
connections.remove(ip);
}
/**
* 根据IP发送消息
* @param ip
* @param text
*/
public void send(String ip, String text) {
try {
Session session = connections.get(ip);
if (session != null && session.isOpen()) {
session.getAsyncRemote().sendText(text);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 遍历群发消息
* @param text
*/
public void send(String text) {
for (ConcurrentHashMap.Entry<String, Session> entry : connections.entrySet()) {
send(entry.getKey(), text);
}
}
}
package com.example.socketserver;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class SocketServerApplication {
public static void main(String[] args) {
SpringApplication.run(SocketServerApplication.class, args);
}
}
spring:
profiles:
active: test
## 本地开发自测环境配置
server:
port: 9000
spring:
application:
name: Socket-Server
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848