三、WebSocket相关的拦截器和监听器

拦截器:

package com.liaoxiang.websocket_demo.intercepter;

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 javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * @auther Mr.Liao
 * @date 2019/3/22 18:20
 */
public class HttpHandShakeInterceptor implements HandshakeInterceptor {
    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response,
                                   WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
        System.out.println("【HttpHandShakeInterceptor-beforeHandshake方法】");
        ServletServerHttpRequest httpRequest = (ServletServerHttpRequest) request;
        HttpServletRequest servletRequest = httpRequest.getServletRequest();
        String sessionID = servletRequest.getSession().getId();
        System.out.println("【SessionId】------>"+sessionID);
        attributes.put("sessionID", sessionID);
        return true;
    }

    @Override
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response,
                               WebSocketHandler wsHandler, Exception exception) {
        System.out.println("【HttpHandShakeInterceptor-afterHandshake方法】");
    }
}

package com.liaoxiang.websocket_demo.intercepter;

import com.liaoxiang.websocket_demo.controller.ChatRoomController;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.messaging.support.ChannelInterceptor;

/**
 * @auther Mr.Liao
 * @date 2019/3/22 19:43
 */
public class SocketChannelInterceptor implements ChannelInterceptor {
    /**
     * 在消息被实际发送到频道之前调用
     */
    @Override
    public Message<?> preSend(Message<?> message, MessageChannel channel) {
        System.out.println("【SocketChannelInterceptor-preSend方法】");
        return message;
    }
    /**
     * 在消息被实际发送之后,立即调用
     */
    @Override
    public void postSend(Message<?> message, MessageChannel channel, boolean sent) {
        System.out.println("【SocketChannelInterceptor-postSend方法】");
        // 消息头访问器
        StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(message);
        if (headerAccessor.getCommand() == null) return;
        String sessionID = headerAccessor.getSessionAttributes().get("sessionID").toString();
        switch (headerAccessor.getCommand()){
            case CONNECT:
                // 连接成功的处理
                connect(sessionID);
                break;
            case DISCONNECT:
                // 断开连接后的处理
                disconnect(sessionID);
                break;
            case SUBSCRIBE:
                break;
            case UNSUBSCRIBE:
                break;
        }

    }

    /**
     * 连接成功
     */
    private void connect(String sessionID){
        System.out.println("【SocketChannelInterceptor-连接成功】");
    }

    /**
     * 断开连接
     */
    private void disconnect(String sessionID){
        System.out.println("【SocketChannelInterceptor-断开连接】");
        ChatRoomController.onlineUser.remove(sessionID);
    }

    /**
     * 总会执行,不管是否有异常发生,一般用于资源清理
     */
    @Override
    public void afterSendCompletion(Message<?> message, MessageChannel channel, boolean sent, Exception ex) {
        System.out.println("【SocketChannelInterceptor-afterSendCompletion方法】");
    }
}

注册拦截器:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
    /**
     * 注册端点,发送或者订阅消息前,需要连接此端点
     * @param registry
     */
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/endpoint-websocket") //端点名称
                .addInterceptors(new HttpHandShakeInterceptor()) //注册Http拦截器
                .setAllowedOrigins("*") // 跨域访问
                .withSockJS(); // 使用sockJS协议
    }
    /**
     * 配置消息代理
     * enableSimpleBroker: 服务端推送消息给客户端的一个前缀
     *     SendTo("/topic/game_chat")
     * setApplicationDestinationPrefixes: 客户端发送消息给服务端的前缀
     *     this.stompClient.send('/app/v1/chat',{},JSON.stringify({'content':msg}))
     */
    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.enableSimpleBroker("/game", "/chat", "/monitor","/topic");
        registry.setApplicationDestinationPrefixes("/app");
    }

    /**
     * 注册Channel拦截器
     */
    @Override
    public void configureClientInboundChannel(ChannelRegistration registration) {
        registration.interceptors(new SocketChannelInterceptor());
    }

    @Override
    public void configureClientOutboundChannel(ChannelRegistration registration) {
        registration.interceptors(new SocketChannelInterceptor());
    }
}

监听器:

package com.liaoxiang.websocket_demo.listener;

import org.springframework.context.ApplicationListener;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.messaging.SessionConnectEvent;

/**
 * @auther Mr.Liao
 * @date 2019/3/22 15:41
 */
@Component
public class ConnectEventListener implements ApplicationListener<SessionConnectEvent> {
    @Override
    public void onApplicationEvent(SessionConnectEvent sessionConnectEvent) {
        StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(sessionConnectEvent.getMessage());
        System.out.println("【ConnectEventListener事件类型监听器】---->"+headerAccessor.getMessageType());
    }
}

package com.liaoxiang.websocket_demo.listener;

import org.springframework.context.ApplicationListener;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.messaging.SessionSubscribeEvent;

import java.util.Objects;

/**
 * @auther Mr.Liao
 * @date 2019/3/22 15:41
 */
@Component
public class SubscribeEventListener implements ApplicationListener<SessionSubscribeEvent> {
    /**
     * 订阅消息触发事件,调用这个方法
     * StompHeaderAccessor:简单消息传递协议中处理消息头的基类
     *     通过这个类,可以获取消息类型(例如:发布订阅,建立连接断开连接), 会话id等
     */
    @Override
    public void onApplicationEvent(SessionSubscribeEvent sessionSubscribeEvent) {
        StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(sessionSubscribeEvent.getMessage());
        System.out.println("【SubscribeEventListener订阅事件监听器】---->"+headerAccessor.getMessageType());
        System.out.println("【SubscribeEventListener订阅事件监听器: SessionID】---->"+ Objects.requireNonNull(headerAccessor.
                getSessionAttributes()).get("sessionID"));
    }
}

建立连接:
【HttpHandShakeInterceptor-beforeHandshake方法】
【SessionId】------>FD19B9E5900BB3FAAB1E9FDDE70397AB
【HttpHandShakeInterceptor-afterHandshake方法】
【SocketChannelInterceptor-preSend方法】
【SocketChannelInterceptor-postSend方法】
【SocketChannelInterceptor-连接成功】
【SocketChannelInterceptor-afterSendCompletion方法】
【SocketChannelInterceptor-preSend方法】
【ConnectEventListener事件类型监听器】---->CONNECT
【SocketChannelInterceptor-postSend方法】
【SocketChannelInterceptor-afterSendCompletion方法】
【SocketChannelInterceptor-preSend方法】
【SocketChannelInterceptor-postSend方法】
【SocketChannelInterceptor-afterSendCompletion方法】
【SubscribeEventListener订阅事件监听器】---->SUBSCRIBE
【SubscribeEventListener订阅事件监听器: SessionID】---->FD19B9E5900BB3FAAB1E9FDDE70397AB

断开连接:
【SocketChannelInterceptor-preSend方法】
【SocketChannelInterceptor-postSend方法】
【SocketChannelInterceptor-断开连接】
【SocketChannelInterceptor-afterSendCompletion方法】
【SocketChannelInterceptor-preSend方法】
【SocketChannelInterceptor-preSend方法】
【SocketChannelInterceptor-postSend方法】
【SocketChannelInterceptor-afterSendCompletion方法】
【SocketChannelInterceptor-postSend方法】
【SocketChannelInterceptor-断开连接】
【SocketChannelInterceptor-afterSendCompletion方法】
【SocketChannelInterceptor-preSend方法】
【SocketChannelInterceptor-postSend方法】
【SocketChannelInterceptor-afterSendCompletion方法】
  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值