spring boot + webSocket实现多个项目之间进行通信操作
作为spring cloud微服务多个服务之间进行通信
首先至少得有一个websocket服务端 与一个或多个 websocket客户端
已提供源码免费下载,Spring Cloud alibaba nacos注册中心+【websocket服务端和websocket客户端】两个服务
https://download.csdn.net/download/m0_37845840/14038629
一、首先无论是服务端还是客户端都需要添加的maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
二、Application启动类
由于WebSocketServer服务端类使用的是@Component注解
所以启动类需要用@ComponentScan对该类进行扫描
import com.test.www.socket.WebSocketServer;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
@EnableScheduling
@ComponentScan("com.test.www")
@MapperScan(value = {"com.test.www.mapper"})
public class Application {
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(Application.class);
ConfigurableApplicationContext configurableApplicationContext = springApplication.run(args);
WebSocketServer.setApplicationContext(configurableApplicationContext);
}
}
三、WebSocketServer服务端的WebSocketConfig配置类
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
四、WebSocketServer服务端接受客户端请求连接的类
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) {
}
/**
* 异常处理
* @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);
}
}
}
五、SocketClient客户端服务发起连接的类
session.getBasicRemote().sendText()为同步发送
session.getAsyncRemote().sendText()为异步发送
当并发发送数据的时候避免阻塞,一般都使用异步
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.websocket.*;
import java.io.IOException;
import java.net.InetAddress;
import java.net.URI;
@Component
@ClientEndpoint
public class SocketClient {
// 服务端的IP和端口号
private static final String URL = "192.168.1.1:8080";
private Session session;
@PostConstruct
void init() {
try {
// 本机地址
String hostAddress = InetAddress.getLocalHost().getHostAddress();
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
String wsUrl = "ws://" + URL + "/" + hostAddress;
URI uri = URI.create(wsUrl);
session = container.connectToServer(SocketClient.class, uri);
} catch (DeploymentException | IOException e) {
e.printStackTrace();
}
}
/**
* 打开连接
* @param session
*/
@OnOpen
public void onOpen(Session session) {
this.session = session;
}
/**
* 接收消息
* @param text
*/
@OnMessage
public void onMessage(String text) {
}
/**
* 异常处理
* @param throwable
*/
@OnError
public void onError(Throwable throwable) {
throwable.printStackTrace();
}
/**
* 关闭连接
*/
@OnClose
public void onClosing() throws IOException {
session.close();
}
/**
* 主动发送消息
*/
public void send(JSONObject json) {
try {
session.getAsyncRemote().sendText(json.toJSONString());
} catch (IOException e) {
e.printStackTrace();
}
}
}