spring boot Websocket

  • pom 依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>
  • 注册websocket服务

/**
 * @ClassName WebSocketConfig
 * @Description TODO
 * @Author gm
 * @Date 2021/1/3 16:02
 */
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
    
    //websocket事件处理(连接的建立和断开、客户端消息接收)
    @Autowired  
    private HttpAuthHandler httpAuthHandler;
   //握手拦截器
    @Autowired
    private MyInterceptor myInterceptor;

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry
                .addHandler(httpAuthHandler, "myWS")
                .addInterceptors(myInterceptor)
                .setAllowedOrigins("*");
        System.out.println(" websocket-register-succes");
    }

}
  • websocket事件处理handler

/**
 * 处理websocket事件
 *
 * @ClassName EchoWebSocketHandler
 * @Description TODO
 * @Author gm
 * @Date 2021/1/3 16:18
 */
@Component
public class HttpAuthHandler extends TextWebSocketHandler {
    /**
     * socket 建立成功事件
     *
     * @param session
     * @throws Exception
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
//        Object token = session.getAttributes().get("token");
//        if (token != null) {
//            // 用户连接成功,放入在线用户缓存
//            WsSessionManager.add(token.toString(), session);
//        } else {
//            throw new RuntimeException("用户登录已经失效!");
//        }
        //展示使用id  回头做了token换上
        Object token = session.getId();
        System.out.println("token = " + token);
        if (token != null) {
            // 用户连接成功,放入在线用户缓存
            WsSessionManager.add(token.toString(), session);
        } else {
            throw new RuntimeException("用户登录已经失效!");
        }
    }

    /**
     * 接收消息事件
     *
     * @param session
     * @param message
     * @throws Exception
     */
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        // 获得客户端传来的消息
        String payload = message.getPayload();
        Object token = session.getAttributes().get("token");
        System.out.println("server 接收到 " + token + " 发送的 " + payload);
        session.sendMessage(new TextMessage("server 发送给 " + token + " 消息 " + payload + " " + LocalDateTime.now().toString()));
    }

    /**
     * socket 断开连接时
     *
     * @param session
     * @param status
     * @throws Exception
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        Object token = session.getAttributes().get("token");
        if (token != null) {
            // 用户退出,移除缓存
            WsSessionManager.remove(token.toString());
        }
    }

}
  • 握手拦截器

/**
 * 握手拦截器
 *
 * @ClassName MyInterceptor
 * @Description TODO
 * @Author gm
 * @Date 2021/1/3 16:29
 */
@Component
public class MyInterceptor implements HandshakeInterceptor {

    /**
     * 握手前
     *
     * @param request
     * @param response
     * @param wsHandler
     * @param attributes
     * @return
     * @throws Exception
     */
    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
        System.out.println("握手开始");
        return true;
    }

    /**
     * 握手后
     *
     * @param request
     * @param response
     * @param wsHandler
     * @param exception
     */
    @Override
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
        System.out.println("握手完成");
    }

}
  • 连接session的管理

/**
 * 管理session
 *
 * @ClassName WsSessionManager
 * @Description TODO
 * @Author gm
 * @Date 2021/1/3 16:27
 */
@Slf4j
public class WsSessionManager {
    /**
     * 保存连接 session 的地方
     */
    private static ConcurrentHashMap<String, WebSocketSession> SESSION_POOL = new ConcurrentHashMap<>();

    /**
     * 添加 session
     *
     * @param key
     */
    public static void add(String key, WebSocketSession session) {
        // 添加 session
        SESSION_POOL.put(key, session);
    }

    /**
     * 删除 session,会返回删除的 session
     *
     * @param key
     * @return
     */
    public static WebSocketSession remove(String key) {
        // 删除 session
        return SESSION_POOL.remove(key);
    }

    /**
     * 删除并同步关闭连接
     *
     * @param key
     */
    public static void removeAndClose(String key) {
        WebSocketSession session = remove(key);
        if (session != null) {
            try {
                // 关闭连接
                session.close();
            } catch (IOException e) {
                // todo: 关闭出现异常处理
                e.printStackTrace();
            }
        }
    }

    /**
     * 获得 session
     *
     * @param key
     * @return
     */
    public static WebSocketSession get(String key) {
        // 获得 session
        return SESSION_POOL.get(key);
    }
}
  •  对应前端vue

<template>
  <div style="text-align: center">
    <van-nav-bar
        title="websocket相关"
        left-text="返回"
        left-arrow
        @click-left="navClickLeft"
    >
    </van-nav-bar>
    <van-row>
      <van-col span="24">
        <van-button type="primary" @click="send">发送</van-button>

        <van-button type="primary" @click="closeSession">关闭会话</van-button>
      </van-col>
    </van-row>
    <van-row>
      <van-field
          v-model="sendMessage"
          name="发送消息"
          label="发送消息"
          placeholder="发送消息"
      />
    </van-row>
    <van-row>
      <van-field
          v-model="getMessage"
          name="收到的消息"
          label="收到的消息"
          placeholder="收到的消息"
      />
    </van-row>
  </div>
</template>

<script scoped>
import config from "@/global/config";
export default {
  name: "websocket",
  props: {},
  components: {},
  computed: {},
  data() {
    return {
      homePath: '/demo/home',
      websocket: {},
      testWebsocketUrl: 'ws://'+config.SERVER_HOST+'/myWS',
      sendMessage: '',
      getMessage: ''

    }
  },
  methods: {
    navClickLeft() {
      this.$router.push(this.homePath)
    },
    send() {

      this.websocket.send(this.sendMessage);
    },
    closeSession() {
      this.websocket.close();
    },
    initWebsocket() {
      let self = this;
      //判断当前浏览器是否支持WebSocket, 主要此处要更换为自己的地址
      if ('WebSocket' in window) {
        this.websocket = new WebSocket(this.testWebsocketUrl);
      } else {
        alert('Not support websocket')
      }
      //连接发生错误的回调方法
      this.websocket.onerror = () => {

        self.setMessage("error");
      };

      //连接成功建立的回调方法
      this.websocket.onopen = (event) => {

      }

      //接收到消息的回调方法
      this.websocket.onmessage = (event) => {
        self.setMessage(event.data);
      }

      //连接关闭的回调方法
      this.websocket.onclose = () => {

        self.setMessage("close");
      }

      //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
      window.onbeforeunload = () => {

        self.websocket.close();
      }
    },
    setMessage(message) {
      this.getMessage = message;

      this.$dialog.confirm({
        message: message,
        theme: 'round-button',
      }).then(() => {

      });
    }
  },
  mounted() {
  },
  created() {
    this.initWebsocket();
  }
}
</script>

<style scoped>

</style>

 

posted @ 2021-03-09 15:06  故木  阅读(114)  评论(0编辑  收藏  举报