1、websocket介绍
WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。WebSocket API也被W3C定为标准。
WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
2、java中安装websocket依赖
<!-- 引入websocket-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
3、java定义实体类
@Data
public class WebSocketDto {
private int code;
private String message;
private String timestamp;
}
4、java定义filter配置类与SessionHandler过滤类
@Slf4j
public class SessionHandlerFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("SessionHandler过滤器初始化成功");
}
@Override
public void destroy() {
log.info("SessionHandler过滤器销毁成功");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpSession session = request.getSession();
session.setAttribute("clientIp", request.getRemoteAddr());
filterChain.doFilter(request, servletResponse);
}
}
@Configuration
public class FilterConfig {
@Bean("SessionHandlerFilter")
public FilterRegistrationBean getSessionHandlerFilterBean(){
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new SessionHandlerFilter());
bean.addUrlPatterns("/websocket/*","/serverWebsocket/*");
return bean;
}
}
5、java定义websocketconfig类与websocket使用类
public class WebSocketServerConfigurator extends ServerEndpointConfig.Configurator {
@Override
public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response){
HttpSession httpSession = (HttpSession) request.getHttpSession();
if(httpSession!=null){
Map<String, Object> userProperties = sec.getUserProperties();
// 存入httpSession
userProperties.put(HttpSession.class.getName(),httpSession);
}
}
}
@Component
@Slf4j
@ServerEndpoint(value = "/xxx/{xxx}",configurator = WebSocketServerConfigurator.class)
public class ServerWebSocket {
/**
* 线程安全无序的集合
*/
private static final CopyOnWriteArraySet<Session> SESSIONS = new CopyOnWriteArraySet<>();
/**
* 存储在线连接数
*/
private static final ConcurrentHashMap<String,Session> SESSION_POOL = new ConcurrentHashMap<>();
@OnOpen
public void onOpen(Session session, @PathParam(value = "userId") String userId){
try {
HttpSession httpSession = (HttpSession) session.getUserProperties().get(HttpSession.class.getName());
String remoteAddr = (String) httpSession.getAttribute("clientIp");
String poolKey = userId;
if(StringUtils.isNotEmpty(remoteAddr)){
poolKey = userId + "_" + remoteAddr;
}
SESSIONS.add(session);
SESSION_POOL.put(poolKey,session);
log.info("【WebSocket消息】有新的连接{},总数为:{}", poolKey, SESSIONS.size());
} catch (Exception e) {
e.printStackTrace();
}
}
@OnClose
public void onClose(Session session){
try {
SESSIONS.remove(session);
log.info("【WebSocket】连接断开,总数为:"+SESSIONS.size());
} catch (Exception e) {
e.printStackTrace();
}
}
@OnMessage
public void onMessage(String message){
log.info("【WebSocket】收到客户端消息:"+message);
}
/**
* 此为广播消息
* @param message
*/
public synchronized void sendAllMessage(String message){
// 这是给前端发送通讯的位置
for (Session session : SESSIONS) {
try {
if(session.isOpen()){
session.getBasicRemote().sendText(message);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
6、前端代码实现
initWebSocket() {
const _this = this;
if (typeof (WebSocket) === 'undefined') {
_this.message.error('您的浏览器不支持WebSocket,无法获取数据')
return false
}
// ws请求完整地址
const requstWsUrl = this.wsUrl
websock = new WebSocket(requstWsUrl)
websock.onmessage = function initWebSocket(e) {
_this.websocketonmessage(e)
}
websock.onopen = function initWebSocket() {
_this.websocketOpen()
}
websock.onerror = function initWebSocket() {
_this.message.error('ws连接异常,请稍候重试')
_this.errorCallback()
}
websock.onclose = function initWebSocket(e) {
this.websocketclose(e)
}
},
7、websocket的踩坑事项
使用websocket的时候,要注意与http同时请求,假设http一直在请求可能会出现websocket长连接失效的问题,等到我找到一个合适的解决方案再补全。
1199

被折叠的 条评论
为什么被折叠?



