JAVA 整合websocket
2019-10-28 本文已影响0人
不二不二熊
SSM整合websocket
一、maven配置
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>4.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.java-websocket</groupId>
<artifactId>Java-WebSocket</artifactId>
<version>1.3.0</version>
</dependency>
二、ContextXML配置
- contextXML添加约束
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="
http://www.springframework.org/schema/websocket
http://www.springframework.org/schema/websocket/spring-websocket-4.0.xsd"
- 配置拦截器
<!-- =============== websocket CONFIG BEGIN ================ -->
<!-- 配置处理器 -->
<bean id="websocket" class="xxx.MyWebSocketHander" />
<!-- 配置拦截器 -->
<websocket:handlers>
<!-- 跟前端请求的url相关 -->
<websocket:mapping path="/webSocket" handler="websocket" />
<websocket:handshake-interceptors>
<bean class="xxx.HandshakeInterceptor" />
</websocket:handshake-interceptors>
</websocket:handlers>
<!-- =============== websocket CONFIG END ================ -->
三、java配置
拦截器
public class HandshakeInterceptor extends HttpSessionHandshakeInterceptor {
/**
* 系统日志
*/
private transient static final Logger logger = LoggerFactory.getLogger(HandshakeInterceptor.class);
/***
* 创建握手(handshake)接口/拦截器
* 这个的主要作用是可以在握手前做一些事,把所需要的东西放入到attributes里面,
* @param request 请求
* @param response 响应
* @param wsHandler 处理函数
* @param attributes 属性
* @return boolean 操作结果
* @exception/throws 无
*/
@Override
public boolean beforeHandshake(
ServerHttpRequest request,
ServerHttpResponse response,
WebSocketHandler wsHandler,
Map<String, Object> attributes
) throws Exception {
/**
* 获取请求参数,首先我们要获取HttpServletRequest对象才能获取请求参数;
* 当ServerHttpRequset的层次结构打开后其子类可以获取到我们想要的http对象,那么就简单了。
我这里是把获取的请求数据绑定到session的map对象中(attributes)
*/
logger.info(" HandshakeInterceptor: beforeHandshake, attributes is : " + attributes);
return super.beforeHandshake(request, response, wsHandler, attributes);
}
/**
* 握手后
* 握手后所做的操作
* @param request 请求
* @param response 响应
* @param wsHandler 操作拦截器
* @param ex 异常
* @return void 无
* @exception/throws 无
*/
@Override
public void afterHandshake(
ServerHttpRequest request,
ServerHttpResponse response, WebSocketHandler wsHandler,
Exception ex
) {
logger.info(" HandshakeInterceptor: afterHandshake ");
super.afterHandshake(request, response, wsHandler, ex);
}
}
处理器
public class MyWebSocketHander implements WebSocketHandler {
/**
* 保存所有的用户session
*/
private static final ArrayList<WebSocketSession> users = new ArrayList<WebSocketSession>();
/**
* 系统日志
*/
private transient static final Logger logger = LoggerFactory.getLogger(MyWebSocketHander.class);
/**
* 连接就绪时
* 连接就绪时所做操作
* @param webSocketSession 用户会话
* @return void 无
* @exception/throws 无
*/
@Override
public void afterConnectionEstablished(WebSocketSession webSocketSession) throws Exception {
logger.info("connection success ...... ");
users.add(webSocketSession);
}
/**
* 处理信息
* 处理信息
* @param webSocketSession 用户会话
* @param webSocketMessage 用户消息
* @return void 无
* @exception/throws 无
*/
@Override
public void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> webSocketMessage) throws Exception {
Gson gson = new Gson();
Map<String, Object> msg = gson.fromJson(webSocketMessage.getPayload().toString(),
new TypeToken<Map<String, Object>>() {}.getType());
// 处理消息 msgContent消息内容
TextMessage textMessage = new TextMessage(msg.get("msgContent").toString(), true);
logger.info("页面传递的消息为: "+ msg.get("msgContent").toString());
// 调用方法(发送消息给所有人)
sendMsgToAllUsers(textMessage);
}
/**
* 向所有用户发送消息
* 向所有用户发送消息
* @param textMessage 消息
* @return void 无
* @exception/throws IOException 发送消息异常
*/
public void sendMsgToAllUsers(TextMessage textMessage) {
for (WebSocketSession user : users) {
try {
synchronized(user){
user.sendMessage(textMessage);
}
} catch (IOException e) {
e.printStackTrace();
logger.error(",",e);
//异常掉线移除
users.remove(user);
}
}
}
/**
* 处理传输时异常
* 处理传输时异常
* @param webSocketSession 用户会话
* @param throwable 异常
* @return void 无
* @exception/throws 无
*/
@Override
public void handleTransportError(WebSocketSession webSocketSession, Throwable throwable) throws Exception {
logger.info(" Transport occur error ......");
}
/**
* 关闭连接时
* 关闭连接时所做操作
* @param webSocketSession 用户会话
* @param closeStatus 关闭状态
* @return void 无
* @exception/throws 无
*/
@Override
public void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus closeStatus) throws Exception {
logger.info("connection close ......");
users.remove(webSocketSession);
}
/**
* 重写信息
* 重写信息
* @param 无
* @return boolean 无
* @exception/throws 无
*/
@Override
public boolean supportsPartialMessages() {
return false;
}
}
配置类
@Configuration
@EnableWebMvc
@EnableWebSocket
public class MyWebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer {
/**
* 系统日志
*/
private transient static final Logger logger = LoggerFactory.getLogger(MyWebSocketConfig.class);
/**
* websocket注册
* websocket注册
* @param registry 注册处理器
* @return void 无
* @exception/throws 无
*/
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
// 这里的url要与页面的url一致
// 前台 可以使用websocket环境
registry.addHandler(myWebSocketHandler(),"/webSocket.do").addInterceptors(new HandshakeInterceptor());
//至于这里为什么要加info,我遇见的情况是,当我使用sockjs来代替websocket时,连接的后面会自动加上info
//前台 不可以使用websocket环境,则使用sockjs进行模拟连接
registry.addHandler(myWebSocketHandler(), "/sockjs/webSocket/info").addInterceptors(new HandshakeInterceptor())
.withSockJS();
}
/***
* websocket 处理类
* websocket 处理类
* @param 无
* @return org.springframework.web.socket.WebSocketHandler websocket处理器
* @author 邱仁
* @exception/throws 无
*/
@Bean
public WebSocketHandler myWebSocketHandler(){
return new MyWebSocketHander();
}
}
四、前端页面
<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">
<meta charset="UTF-8">
<script src="https://cdn.bootcss.com/sockjs-client/1.4.0/sockjs.min.js"></script>
<script src="https://cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
<title>webSocket-用户66</title>
</head>
<body onbeforeunload="closeWebSocket()">
<div class="page-header" id="tou">
webSocket测试
</div>
<div class="well" id="msg"></div>
<div class="col-lg">
<div class="input-group">
<input type="text" class="form-control" placeholder="发送信息..." id="message">
<span class="input-group-btn">
<button class="btn btn-default" type="button" id="send">发送</button>
</span>
</div>
</div>
</body>
<script type="text/javascript">
var websocket;
// 首先判断是否 支持 WebSocket
if('WebSocket' in window) {
websocket = new WebSocket("ws://localhost:8080/websocket");
} else if('MozWebSocket' in window) {
websocket = new MozWebSocket("ws://localhost:8080/websocket");
} else {
websocket = new SockJS("http://localhost:8080/itmb-event/sockjs/webSocket");
}
// 打开时
websocket.onopen = function(evnt) {
console.log("websocket.onopen ");
};
// 处理消息时
websocket.onmessage = function(evnt) {
$("#msg").append("<p>(<font color='red'>" + evnt.data + "</font>)</p>");
console.log(" websocket.onmessage ");
};
websocket.onerror = function(evnt) {
console.log(" websocket.onerror ");
};
websocket.onclose = function(evnt) {
console.log(" websocket.onclose ");
};
//点击了发送消息按钮的响应事件
$("#send").click(function(){
alert("ddd")
// 获取消息内容
var text = $("#message").val();
// 判断
if(text == null || text == ""){
alert(" content can not empty!!");
return false;
}
var msg = {
msgContent: text,
postsId: 1
};
// 发送消息
websocket.send(JSON.stringify(msg));
});
function closeWebSocket() {
console.log("关闭WebSocket连接!");
websocket.close();
}
</script>
</html>
springboot整合websocket
一、maven配置
<!-- webSocket -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
<version>2.1.8.RELEASE</version>
</dependency>
二、配置类
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
@Slf4j
@ServerEndpoint(value = "/websocket")
@Component
public class WebSocketServer {
/**
* 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
*/
private static int onlineCount = 0;
/**
* concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
*/
private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();
/**
* 与某个客户端的连接会话,需要通过它来给客户端发送数据
*/
private Session session;
/**
* 连接建立成功调用的方法*/
@OnOpen
public void onOpen(Session session) {
this.session = session;
//加入set中
webSocketSet.add(this);
//在线数加1
addOnlineCount();
log.info("有新连接加入!当前在线人数为" + getOnlineCount());
try {
sendMessage("连接成功");
} catch (IOException e) {
log.error("webSocket IO异常");
}
}
// //连接打开时执行
// @OnOpen
// public void onOpen(@PathParam("user") String user, Session session) {
// currentUser = user;
// System.out.println("Connected ... " + session.getId());
// }
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose() {
//从set中删除
webSocketSet.remove(this);
//在线数减1
subOnlineCount();
log.info("有一连接关闭!当前在线人数为" + getOnlineCount());
}
/**
* 收到客户端消息后调用的方法
*
* @param message 客户端发送过来的消息*/
@OnMessage
public void onMessage(String message, Session session) {
log.info("来自客户端的消息:" + message);
//群发消息
for (WebSocketServer item : webSocketSet) {
try {
item.sendMessage(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
*
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error) {
log.error("发生错误");
error.printStackTrace();
}
public void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
}
/**
* 群发自定义消息
* */
public static void sendInfo(String message) throws IOException {
log.info(message);
for (WebSocketServer item : webSocketSet) {
try {
item.sendMessage(message);
} catch (IOException e) {
continue;
}
}
}
public static synchronized int getOnlineCount() {
return onlineCount;
}
public static synchronized void addOnlineCount() {
WebSocketServer.onlineCount++;
}
public static synchronized void subOnlineCount() {
WebSocketServer.onlineCount--;
}
}
三、后台推送给前端
@Controller
@RequestMapping("/socketSend")
@Slf4j
public class SendMsg {
@GetMapping("/send/{msg}")
@ResponseBody
public void pushVideoListToWeb(@PathVariable(name = "msg") String msg) {
try {
WebSocketServer.sendInfo(msg);
} catch (IOException e) {
}
}
}