【WebSocket】笔记

环境:jdk1.8、idea、Spring Boot 2.0.4

一、非注解写法

pom.xml

	<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- Spring Web Socket依赖 start-->
        <dependency>
            <groupId>javax.websocket</groupId>
            <artifactId>javax.websocket-api</artifactId>
            <version>1.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-websocket</artifactId>
            <version>4.3.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-messaging</artifactId>
            <version>4.3.12.RELEASE</version>
        </dependency>
	<!-- Spring Web Socket依赖 end-->
		
		<!-- commin-lang -->
    	<dependency>
         	<groupId>commons-lang</groupId>
         	<artifactId>commons-lang</artifactId>
         	<version>2.6</version>
    	</dependency>
		
	<!-- fastjson -->
	<dependency>
         <groupId>com.alibaba</groupId>
         <artifactId>fastjson</artifactId>
         <version>1.2.47</version>
    </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>

application.yml

server:
  port: 8001

Entity

public class User {

    private String phone;

    private String name;

    private Integer userId;

    private Integer id;
    
    ……Getter and Setter……
    
    public String toString() {
        return "User [phone=" + phone + ", name=" + name + ", userId=" + userId
                + "]";
    }

}

Interceptor

import com.zhao.entity.User;
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;

import java.util.Map;

/**
 * 拦截器
 * @author zhaoYang
 * @Title: web-socket
 * @Package com.zhao.websocket
 * @date 2018/10/31 17:01
 */
public class DemoWebSocketInterceptor implements HandshakeInterceptor {


    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse serverHttpResponse,
                                   WebSocketHandler webSocketHandler, Map<String, Object> map) throws Exception {
        System.out.println("执行beforeHandshake方法*****拦截器(1)");
        if (request instanceof ServletServerHttpRequest) {
            System.out.println("执行beforeHandshake方法*****拦截器(2)");
            // 保存session中已登录的用户到websocket的上下文环境中。在推送消息的时候,需要根据当前登录用户获取点位权限
            User u=new User();
            u.setId(1);
            u.setName("test");
            u.setUserId(1);
            // client传Sec-WebSocket-Protocol过来,server必须返回Sec-WebSocket-Protocol回去
            serverHttpResponse.getHeaders().add("Sec-WebSocket-Protocol",(request).getHeaders().get("Sec-WebSocket-Protocol").get(0));
            map.put("userId",((ServletServerHttpRequest) request).getServletRequest().getParameter("userId"));
            map.put("token",(request).getHeaders().get("Sec-WebSocket-Protocol").get(0));

            System.out.println("=========拦截器 "+map);
        }
        return true;
    }

    @Override
    public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse,
                               WebSocketHandler webSocketHandler, Exception e) {
        System.out.println("执行afterHandshake方法*****拦截器");
    }
}

Handler

import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * @author zhaoYang
 * @Title: web-socket
 * @Package com.zhao.websocket.handler
 * @date 2018/10/31 17:08
 */
@Component
public class DemoWebSocketHandler implements WebSocketHandler {

    private static final Map<String,WebSocketSession> userSocketSessionMapThreadLocal = new HashMap<>();

    /**
     * 建立连接
     * @param webSocketSession
     * @throws Exception
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession webSocketSession) throws Exception {
        System.out.println("=========================建立连接 "+webSocketSession.getAttributes().get("userId").toString());
        userSocketSessionMapThreadLocal.put(webSocketSession.getAttributes().get("userId").toString(),webSocketSession);

    }

    /**
     * 接收客户端发来的消息
     * @param webSocketSession
     * @param webSocketMessage
     * @throws Exception
     */
    @Override
    public void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> webSocketMessage) throws Exception {
		Object payload = webSocketMessage.getPayload();
        System.out.println(payload);
    }

    /**
     * 传输错误异常
     * @param webSocketSession
     * @param throwable
     * @throws Exception
     */
    @Override
    public void handleTransportError(WebSocketSession webSocketSession, Throwable throwable) throws Exception {

    }

    /**
     * 连接关闭
     * 在此刷新页面就相当于断开WebSocket连接,原本在静态变量userSocketSessionMap中的
     * WebSocketSession会变成关闭状态(close),但是刷新后的第二次连接服务器创建的
     * 新WebSocketSession(open状态)又不会加入到userSocketSessionMap中,所以这样就无法发送消息
     * 因此应当在关闭连接这个切面增加去除userSocketSessionMap中当前处于close状态的WebSocketSession,
     * 让新创建的WebSocketSession(open状态)可以加入到userSocketSessionMap中
     * @param webSocketSession
     * @param closeStatus
     * @throws Exception
     */
    @Override
    public void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus closeStatus) throws Exception {
        System.out.println("=========================连接关闭");
    }

    @Override
    public boolean supportsPartialMessages() {
        return false;
    }

    /**
     * 广播推送消息,如需点对点发送,即可根据userSocketSessionMapThreadLocal对应的key进行发送
     * @throws IOException
     */
    public void sendMessage(String message) throws IOException {
        System.out.println("=========================sendMessage");
        Iterator iter = userSocketSessionMapThreadLocal.entrySet().iterator();
        while (iter.hasNext()) {
            Map.Entry entry = (Map.Entry) iter.next();
            //String key = (String) entry.getKey();
            WebSocketSession ws =  (WebSocketSession) entry.getValue();
            //发送WebSocket消息
//            JSONObject jsonObject = new JSONObject();
//            String message=jsonObject.fromObject(result).toString();
//            ws.sendMessage(new TextMessage(message.getBytes()));

            ws.sendMessage(new TextMessage(message.getBytes()));
        }
    }
}

Config

import com.zhao.websocket.handler.DemoWebSocketHandler;
import com.zhao.websocket.interceptor.DemoWebSocketInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

/**
 * @author zhaoYang
 * @Title: web-socket
 * @Package com.zhao.websocket.config
 * @date 2018/10/31 17:06
 */
@Component
@EnableWebSocket
@EnableWebMvc
public class DemoWebSocketConfig implements WebSocketConfigurer {

    @Autowired
    DemoWebSocketHandler demoWebSocketHandler;

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
        System.out.println("=========================config");
        //添加Web Socket处理器,添加握手拦截器
        webSocketHandlerRegistry.addHandler(demoWebSocketHandler, "/demoWebSocket").
                setAllowedOrigins("*") // 添加允许跨域访问
                .addInterceptors(new DemoWebSocketInterceptor());
    }
}

Controller

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zhao.websocket.handler.DemoWebSocketHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * @author zhaoYang
 * @Title: web-socket
 * @Package com.zhao.websocket.controller
 * @date 2018/10/31 17:38
 */
@RestController
public class WebSocketController {

    @Autowired
    DemoWebSocketHandler demoWebSocketHandler;

    @RequestMapping(value = "webSocket",method = RequestMethod.GET)
    public String webSocket(){
        try {
            Map<String,Object> result=new HashMap<>();
            result.put("a","1");
            result.put("b","2");
            result.put("c","3");
            JSONObject jsonObject=JSONObject.parseObject(JSON.toJSONString(result));
            String message=jsonObject.toJSONString();
            demoWebSocketHandler.sendMessage(message);
        }catch (Exception e){
            e.printStackTrace();
        }
        return "success";
    }

}

html

<!DOCTYPE html>
<html lang="en">
<body>
<div id="msg"></div>
<input type="text" id="text">
<input type="submit" value="send" onclick="send()">
</body>
<script>
    var msg = document.getElementById("msg");
	var token='dcvuahsdnfajw12kjfasfsdf34';
    var websocket = new WebSocket("ws://127.0.0.1:8001/demoWebSocket?userId=1",[token]);
    //监听连接打开
    websocket.onopen = function (evt) {
		console.log("onopen");
        msg.innerHTML = "The connection is open";
    };

    //监听服务器数据推送
    websocket.onmessage = function (evt) {
		console.log("onmessage ");
        msg.innerHTML += "<br>" + evt.data;
    };

    //监听连接关闭
    websocket.onclose = function (evt) {
        console.log("onclose ");
		//alert("连接关闭");
    };

    function send() {
        var text = document.getElementById("text").value
        websocket.send(text);
    }
</script>
</html>

启动项目,并打开页面

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

调用Controller接口,触发服务端主动推送消息给客户端

localhost:8001/webSocket
在这里插入图片描述

在这里插入图片描述

客户端推送消息给服务端

在这里插入图片描述

在这里插入图片描述

End

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值