一:webscoket简介
Webscoket是一个基于HTTP的持久化协议,服务端、客户端可以双向通信,不同于http,只能客户端请求服务端,服务端再返回,而WebScoket可以使服务端向客户端发起连接,客户端同样也可以像服务端发起请求。
WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
二:集成spring环境
1)webscoket的jar:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
2)webscoket配置类,该类被spring容器加载(在spring扫描包的路径下)
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
@Configuration
@EnableWebSocket
public class WebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer {
@Bean
public WebSocketHandler myHandler() {
return new MyWebSocketHandler();
}
//接收到ws://开头的请求会触发webscoket拦截器,例如:ws://localhost:9101//ws?uid=1
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(myHandler(), "/ws").addInterceptors(new HandShake());
registry.addHandler(myHandler(), "/ws/sockjs").addInterceptors(new HandShake()).withSockJS();
}
}
3)创建webscoket拦截器,在spring容器中也就是在spring扫描的包路径下
import java.util.Map;
import javax.servlet.http.HttpSession;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;
/**
* webscoke拦截器实现
*/
public class HandShake implements HandshakeInterceptor {
//客户端建立与服务端连接时触发该拦截器,attributes可以在webscoket处理器中的 WebSocketSession获取到设置的参数信息
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Map<String, Object> attributes) throws Exception {
//true:放行,false:拦截
return true;
}
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Exception exception) {
}
}
4)创建webscoket处理器,在spring扫描包的路径下。
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import io.github.dunwu.spring.websocket.entity.Message;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;
import java.io.IOException;
import java.util.Date;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
@Component
public class MyWebSocketHandler implements WebSocketHandler {
private static final Logger logger = LoggerFactory.getLogger(MyWebSocketHandler.class);
/**
* 建立连接后执行
*/
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
}
/**
* 消息处理,在客户端通过Websocket API发送的消息会经过这里,然后进行相应的处理
*/
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
}
/**
* 消息传输错误处理
*/
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
if (session.isOpen()) {
session.close();
}
}
/**
* 客户端关闭连接后触发
*/
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
}
@Override
public boolean supportsPartialMessages() {
return false;
}
/**
* 给所有在线用户发送消息
*
* @param message
* @throws IOException
*/
public void broadcast(final TextMessage message) throws IOException {
}
/**
* 给某个用户发送消息
*
* @param userName
* @param message
* @throws IOException
*/
private void sendMessageToUser(Long uid, TextMessage message) throws IOException {
session.sendMessage(message);
}
四:webscoket客户端配置
webscoket是基于H5的,所以可以直接new Websocket()创建对象
var websocket;
var path="localhost:8080";
//创建webscoket对象
if ('WebSocket' in window) {
websocket = new WebSocket("ws://" + path + "/ws?uid="+uid);
} else if ('MozWebSocket' in window) {
websocket = new MozWebSocket("ws://" + path + "/ws?uid="+uid);
} else {
websocket = new SockJS("http://" + path + "/ws/sockjs?uid="+uid);
}
//webscoket与服务器建立连接后触发
websocket.onopen = function(event) {
console.log("WebSocket:已连接");
console.log(event);
};
//服务端调用webscoketSession.sendMessage()方法后,客户端触发此方法onmessage
websocket.onmessage = function(event) {
var data=JSON.parse(event.data);
console.log("WebSocket:收到一条消息",data);
};
//通信发生错误时触发
websocket.onerror = function(event) {
console.log("WebSocket:发生错误 ");
console.log(event);
};
//关闭连接时触发
websocket.onclose = function(event) {
console.log("WebSocket:已关闭");
console.log(event);
}
//客户端发送消息到服务端
var data={};//自定义发送json数据
data["from"]="xxx"
data["fromName"]="xxx"
data["to"]="xxx";
data["text"]="xxx";
websocket.send(JSON.stringify(data));
//关闭连接
websocket.close();