栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringBoot 整合 websocket(一)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringBoot 整合 websocket(一)

这里写自定义目录标题
  • websocket
    • SpringBoot 整合websocket
      • 引入jar包
      • 配置websocket
      • 消息体定义
      • websocket
      • 前端socket.html
      • 效果
      • 思考

websocket

WebSocket是一种在单个TCP连接上进行全双工通信的协议。简单点说其实就是浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。例如现在很多网站的站内通信,点赞通知等及时通讯交互都可以用这个实现。具体的技术原理大家找度娘。

SpringBoot 整合websocket 引入jar包

SpringBoot 整合 websocket非常简单,只要引入websocket包即可


	org.springframework.boot
    spring-boot-starter-websocket

配置websocket
@Configuration
@ConditionalOnWebApplication
public class WebSocketConfig {

	
	@Bean
	public ServerEndpointExporter serverEndpointExporter() {
		return new ServerEndpointExporter();
	}
}
消息体定义

websocket的作用主要就是为了客户端和服务端通讯使用,既然是通讯,那么肯定有一些基本的参数,例如发送者、接收者,消息正文,消息发送时间等,这里可以定义一个消息体的对象。

public class WebSocketMsgVO implements Serializable {
	private static final long serialVersionUID = 6853050643035639834L;
	private String fromId;
	private String fromName;
	private String toId;
	private String toName;
	private String createDateTime;
	private String content;//消息正文
	private String sendMsgType;//发送消息的类型 :open/auto/dialog 
	private Map data = new HashMap();
}

前面6个字段看名字就知道什么意思了,就不多说了,主要是后面两个字段做个说明。
sendMsgType : 发送消息的类型,例如在浏览器连接上websocket时,服务器主动给浏览器推送“连接成功”提醒的消息(我这里定义成open),再例如会发送一些自动消息(auto),如果是2个客户之间正常的即时通话则定义为dialog。

data : 主要是为了扩展使用,例如不同的功能模块可以有一些特殊的信息,那么就放在这里。

websocket
@Component
@ServerEndpoint("/webSocket/{id}")
public class WebSocketServer {

	// 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
	private static AtomicInteger onlineNum = new AtomicInteger();

	// concurrent包的线程安全Set,用来存放每个客户端对应的WebSocketServer对象。
	private static ConcurrentHashMap sessionPools = new ConcurrentHashMap<>();

	// 建立连接成功调用
	@OnOpen
	public void onOpen(final Session session, @PathParam(value = "id") final String id) {
		session.setMaxIdleTimeout(10 * 60 * 1000);
		try {
			synchronized (WebSocketServer.sessionPools) {
				if (WebSocketServer.sessionPools.containsKey(id)) {
					WebSocketServer.sessionPools.remove(id);
				} else {
					WebSocketServer.addOnlineCount();
				}
				WebSocketServer.sessionPools.put(id, session);
			}
			System.out.println(id + "加入webSocket!当前人数为" + WebSocketServer.onlineNum);
			final WebSocketMsgVO messageVO = new WebSocketMsgVO();
			messageVO.setToId(id);
			messageVO.setContent("欢迎" + id + "加入连接!");
			messageVO.setSendMsgType("open");
			sendMessage(session, HnJsonUtils.jsonToString(messageVO));
		} catch (final IOException e) {
			e.printStackTrace();
		}
	}

	// 关闭连接时调用
	@OnClose
	public void onClose(@PathParam(value = "id") final String id) {
		synchronized (WebSocketServer.sessionPools) {
			if (WebSocketServer.sessionPools.containsKey(id)) {
				WebSocketServer.sessionPools.remove(id);
				WebSocketServer.subOnlineCount();
			}
		}
		System.out.println(id + "断开webSocket连接!当前人数为" + WebSocketServer.onlineNum);
	}

	// 收到客户端信息
	@OnMessage
	public void onMessage(final String message) throws IOException {
		System.out.println("收到客户端消息:" + message);
		try {
			if (!WebSocketServer.sessionPools.isEmpty()) {
				final WebSocketMsgVO messageVO = HnJsonUtils.jsonToBean(message, WebSocketMsgVO.class);
				if (WebSocketServer.sessionPools.containsKey(messageVO.getToId())) {
					sendMessage(WebSocketServer.sessionPools.get(messageVO.getToId()), message);
				}
			}
		} catch (final Exception e) {
			e.printStackTrace();
		}
	}

	// 错误时调用
	@OnError
	public void onError(final Session session, final Throwable throwable) {
		System.out.println("发生错误");
		throwable.printStackTrace();
	}

	// 发送消息
	private void sendMessage(final Session session, final String message) throws IOException {
		if (session != null) {
			synchronized (session) {
				System.out.println("发送数据:" + message);
				session.getBasicRemote().sendText(message);
			}
		}
	}

	public static void addOnlineCount() {
		WebSocketServer.onlineNum.incrementAndGet();
	}

	public static void subOnlineCount() {
		WebSocketServer.onlineNum.decrementAndGet();
	}
}

从代码中的各个方法名称基本就能看出来websocket的工作原理和流程。
1.客户端连接服务器端,触发onOpen()
2.当客户端发送消息,服务器端通过onMessage()接收,并通过sendMessage()推送到相应的接收者浏览器,然后由前端的websocket来接收处理消息。

前端socket.html



    
    WebSocket
    


hello socket

【fromId】:

【toId】:

【内容】:

【操作】:

【操作】:

    效果

    思考

    以上就是最简单的实现websocket即时通讯的方法,但这里只是实现了单个通道下即时通讯的功能,在正式的项目中可能还是有问题的,例如正式环境下是有多个服务器做负载均衡的,这个时候就会导致不同的客户端在与服务器握手时会连接道不同的服务器上,这样也就导致发送到服务器上的消息在推送时找不到对应的客户端,那么就需要换另外的做法了。这块下次有时间在写了 。

    转载请注明:文章转载自 www.mshxw.com
    本文地址:https://www.mshxw.com/it/1041168.html
    我们一直用心在做
    关于我们 文章归档 网站地图 联系我们

    版权所有 (c)2021-2022 MSHXW.COM

    ICP备案号:晋ICP备2021003244-6号