三、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方法】
Spring Boot 拦截器主要是用于在请求处理前和处理后执行一些特定操作,如日志记录、权限检查等。如果你想要在拦截器中发送通知到前端 Vue 中,可以考虑使用 WebSocket 技术。 具体来说,你可以在拦截器中创建一个 WebSocket 连接,然后通过该连接向前端 Vue 发送通知。在前端 Vue 中,你需要使用 WebSocket API 监听该连接,接收来自后端的通知信息。 以下是一个简单的示例代码: 拦截器中创建 WebSocket 连接并发送通知: ```java public class MyInterceptor extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 创建 WebSocket 连接 WebSocketClient client = new StandardWebSocketClient(); WebSocketSession session = client.doHandshake(new MyWebSocketHandler(), "ws://localhost:8080/ws").get(); // 向前端 Vue 发送通知 session.sendMessage(new TextMessage("Hello, Vue!")); return true; } } class MyWebSocketHandler extends TextWebSocketHandler { // WebSocket 处理器代码 } ``` 前端 Vue 中监听 WebSocket 连接并接收通知: ```javascript const socket = new WebSocket('ws://localhost:8080/ws'); socket.onmessage = function(event) { console.log('Received message: ' + event.data); // 在此处处理收到的通知信息 }; ``` 需要注意的是,上述代码仅供参考,你需要根据实际需求进行修改和完善。同时,还需要考虑到 WebSocket 连接的安全性和稳定性等问题。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值