javax.websocket
javax.websocket-api
1.1
provided
org.springframework.boot
spring-boot-starter-freemarker
org.springframework.boot
spring-boot-starter-websocket
org.springframework.boot
spring-boot-starter-tomcat
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration
public class WebSocketConfig {
/**
* 注入一个ServerEndpointExporter,该Bean会自动注册使用@ServerEndpoint注解申明的websocket endpoint
*/
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
【注】这里在本地启动的时候可以正常进行,但是将项目打包部署到Linux服务器的时候可能会出现报错,原因可能为线程不同步,提前创建了WebSocket对象但是对应的配置JavaBean还未生成;也有可能是Pom.xml的tomcat配置没有排除,spring内置了tomcat服务器,但是云端就会出现问题(仅提供bug修改参考意见)
此工具类实现将在线的用户添加到哈希map中进行存储,采用ConcurrentHashMap来确保线程安全性
import com.minprogram.renthouse.controller.MyWebSocketServer;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* @Author zd
* @Date 2021/9/6 15:00
* @Version 1.0
*/
public class WebSocketMapUtil {
public static ConcurrentMap webSocketMap = new ConcurrentHashMap();
public static void put(String key, MyWebSocketServer myWebSocketServer){
webSocketMap.put(key, myWebSocketServer);
}
public static MyWebSocketServer get(String key){
return webSocketMap.get(key);
}
public static void remove(String key){
webSocketMap.remove(key);
}
public static Collection getValues(){
return webSocketMap.values();
}
//判断用户是否存在于Map中
public static boolean isContain(String key){
return webSocketMap.containsKey(key);
}
}
【注】一定要使用反射的方式来获取service或者mapper层的方法,否则会报错
/**
* @Author zd
* @Date 2021/9/2 16:53
* @Version 1.0
*/
@Component
@ServerEndpoint(value = "/WebSocket/{openId}") // 这里存放的是小程序前端输入的用户识别码,即openid
@Slf4j
public class MyWebSocketServer {
@Autowired
private UserMapper userMapper = MyApplicationContextAware.getApplicationContext().getBean(UserMapper.class);
// 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
private static int onlineCount = 0;
private Session session;
private String openId;
/**
* 连接建立后触发的方法
*/
@OnOpen
public void onOpen(Session session, @PathParam("openId") String openId) {
this.session = session;
this.openId=openId;
log.info("onOpen-SessionId:{}",session.getId());
WebSocketMapUtil.put(openId, this);
addOnlineCount();
log.info("有新连接加入,openId:【{}】!当前在线人数为:{}", openId, getOnlineCount());
}
/**
* 连接关闭后触发的方法
*/
@OnClose
public void onClose() {/*从map中删除*/
WebSocketMapUtil.remove(this.openId);
subOnlineCount();//在线人数减少
log.info("====== onClose:【{}】,目前在线人数:{} ======",this.openId,getOnlineCount());
}
/**
* 接收到客户端消息时触发的方法
*/
@OnMessage
public void onMessage(String requestBody) throws Exception {/*获取服务端到客户端的通道*/
实现发送逻辑
}
/**
* 发生错误时触发的方法
*/
@OnError
public void onError(Session session, Throwable error) throws Exception {
log.info("{}连接发生错误{}",session.getId(),error.getMessage());
error.printStackTrace();
}
// 发送给某人消息的方法
public void SendMsgToSB(String uopenid,String nid) throws Exception {
//1.判断用户openid是否存在于websocket之中
// 存在:数据标记为已读(2)存入数据库然后直接推送 不存在:数据标记为未读(1)存入数据库,不推送
// String msg= SensitivewordFilter.filterText(requestData.getString("msg"));
notedto ndto = new notedto();
ndto.setNid(Integer.parseInt(nid));
Note n = adminMapper.getNoteDetail(ndto);
if(WebSocketMapUtil.isContain(uopenid)){
addToDataBases(n.getNId(),"unRead",uopenid);
List