springboot 原生java_springboot实现服务器端消息推送(H5原生支持)

随着互联网的发展,传统的HTTP协议已经很难满足Web应用日益复杂的需求了。近年来,随着HTML5的诞生,WebSocket协议被提出,它实现了浏览器与服务器的全双工通信,扩展了浏览器与服务端的通信功能,使服务端也能主动向客户端发送数据。

伴随着HTML5推出的WebSocket,真正实现了Web的实时通信,使B/S模式具备了C/S模式的实时通信能力。WebSocket的工作流程是这 样的:浏览器通过JavaScript向服务端发出建立WebSocket连接的请求,在WebSocket连接建立成功后,客户端和服务端就可以通过 TCP连接传输数据。因为WebSocket连接本质上是TCP连接,不需要每次传输都带上重复的头部数据,所以它的数据传输量比轮询和Comet技术小 了很多。本文不详细地介绍WebSocket规范,主要介绍下WebSocket在Java Web中的实现。

JavaEE 7中出了JSR-356:Java API for WebSocket规范。不少Web容器,如Tomcat,Nginx,Jetty等都支持WebSocket。Tomcat从7.0.27开始支持 WebSocket,已下内容基于tomcat 7.x的websocket实现,这种方式配置相对简单,但是对于不支持websocket的浏览器则不适用,如果想在不支持websocket的浏览器实现服务器端的消息推送,可参考我的另一篇博客https://www.cnblogs.com/hhhshct/p/8849449.html。

1、核心注解@ServerEndpoint,这是JavaEE 7标准里的注解,tomcat7以上已经对其进行了实现,如果是用传统方法使用tomcat发布项目,则需要我们在pom.xml引入对应的依赖。

javax

javaee-api

7.0

provided

springboot的内置tomcat时,就不需要引入javaee-api了,并且springboot为我们提供websocket的相关starter包,会自定配置一些基础组件,我们使用时只需引入以下依赖

org.springframework.boot

spring-boot-starter-websocket

2、首先要配置ServerEndpointExporter的实例到springboot容器中,这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint为自己的子类

packagecom.example.demo;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.web.socket.server.standard.ServerEndpointExporter;

@Configurationpublic classWebSocketConfig {

@BeanpublicServerEndpointExporter serverEndpointExporter() {return newServerEndpointExporter();

}

}

3、websocket的具体实现,需要通过注解的方式重写其各个方法,实现自定义的需求,虽然@Component默认是单例模式的,但springboot还是会为每个websocket连接初始化一个bean,所以可以用一个静态set保存起来。

packagecom.example.demo;importjava.io.IOException;importjava.util.concurrent.CopyOnWriteArraySet;importjavax.websocket.OnClose;importjavax.websocket.OnError;importjavax.websocket.OnMessage;importjavax.websocket.OnOpen;importjavax.websocket.Session;importjavax.websocket.server.ServerEndpoint;importorg.springframework.stereotype.Component;

@ServerEndpoint(value= "/websocket")

@Componentpublic classMyWebSocket {//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。

private static int onlineCount = 0;//concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。

private static CopyOnWriteArraySet webSocketSet = new CopyOnWriteArraySet();//与某个客户端的连接会话,需要通过它来给客户端发送数据

privateSession session;/*** 连接建立成功调用的方法*/@OnOpenpublic voidonOpen(Session session) {this.session =session;

webSocketSet.add(this); //加入set中

addOnlineCount(); //在线数加1

System.out.println("有新连接加入!当前在线人数为" +getOnlineCount());try{

sendMessage("当前在线人数为" +getOnlineCount());

}catch(IOException e) {

System.out.println("IO异常");

}

}/*** 连接关闭调用的方法*/@OnClosepublic voidonClose() {

webSocketSet.remove(this); //从set中删除

subOnlineCount(); //在线数减1

System.out.println("有一连接关闭!当前在线人数为" +getOnlineCount());

}/*** 收到客户端消息后调用的方法

*

*@parammessage 客户端发送过来的消息*/@OnMessagepublic voidonMessage(String message, Session session) {

System.out.println("来自客户端的消息:" +message);//群发消息

for(MyWebSocket item : webSocketSet) {try{

item.sendMessage(message);

}catch(IOException e) {

e.printStackTrace();

}

}

}

@OnErrorpublic voidonError(Session session, Throwable error) {

System.out.println("发生错误");

error.printStackTrace();

}public void sendMessage(String message) throwsIOException {this.session.getBasicRemote().sendText(message);

}/*** 群发自定义消息

**/

public static void sendInfo(String message) throwsIOException {for(MyWebSocket item : webSocketSet) {try{

item.sendMessage(message);

}catch(IOException e) {continue;

}

}

}public static synchronized intgetOnlineCount() {returnonlineCount;

}public static synchronized voidaddOnlineCount() {

MyWebSocket.onlineCount++;

}public static synchronized voidsubOnlineCount() {

MyWebSocket.onlineCount--;

}

}

4、前端代码,编写index.html放置到resource/static包下

My WebSocket

Send Close

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值