websocket 频道拦截器 介绍和使用

项目的完整地址
websocket 多人群聊Demo ,演示握手,channel拦截器使用,并获取拦截器里的值,模拟登陆,实时显示在线用户等功能_websocket channel_小哇666的博客-CSDN博客
 

本项目注释代码不多,更详细的注释,可看些项目,以下只列出核心代码
springboot整合websocket基础入门,常见注解使用 Demo (基于stomp协议发布订阅方式实现)_nginx配置stomp协议推送-CSDN博客


1 先创建 http握手 拦截器 HttpHandShakeIntecepter,因为一般会从握手拦截器里取值(个人理解)

package cn.huawei.intecepter;
import java.util.Map;
import javax.servlet.http.HttpSession;
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;

/**
 * 
 * 功能描述:http握手拦截器,可以通过这个类的方法获取resuest,和response
 *
 * 将 httprequest中的sessionId 保存起来
 *
 */
public class HttpHandShakeIntecepter implements HandshakeInterceptor{

	@Override
	public boolean beforeHandshake(ServerHttpRequest request,
			ServerHttpResponse response, WebSocketHandler wsHandler,
			Map<String, Object> attributes) throws Exception {

		if(request instanceof ServletServerHttpRequest) {
			ServletServerHttpRequest servletRequest = (ServletServerHttpRequest)request;
			HttpSession session =  servletRequest.getServletRequest().getSession();
			String huihuaId = session.getId();

			System.out.println("【握手拦截器】beforeHandshake 会话id="+huihuaId);

			attributes.put("huihuaId", huihuaId);
		}
		
		return true;
	}


	@Override
	public void afterHandshake(ServerHttpRequest request,
			ServerHttpResponse response, WebSocketHandler wsHandler,
			Exception exception) {

		if(request instanceof ServletServerHttpRequest) {
			ServletServerHttpRequest servletRequest = (ServletServerHttpRequest)request;
			HttpSession session =  servletRequest.getServletRequest().getSession();
			String huihuaId = session.getId();

			System.out.println("【握手拦截器】afterHandshake 会话id="+huihuaId);
		}
	}
}

2 创建频道拦截器 SocketChannelIntecepter,可以从握手拦截器里面取值

package cn.huawei.intecepter;
import cn.huawei.controller.v6.UserChatController;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.messaging.support.ChannelInterceptorAdapter;

/**
 * 功能描述:频道拦截器 ,类似管道,可以获取消息的一些meta数据
 *
 * 取得 http握手拦截器 中 存储的sessionid
 */
public class SocketChannelIntecepter extends ChannelInterceptorAdapter{

	/**
	 * 在完成发送之后进行调用,不管是否有异常发生,一般用于资源清理
	 */
	@Override
	public void afterSendCompletion(Message<?> message, MessageChannel channel,
			boolean sent, Exception ex) {
		System.out.println("频道拦截器->afterSendCompletion");
		super.afterSendCompletion(message, channel, sent, ex);
	}

	
	/**
	 * 在消息被实际发送到频道之前调用
	 */
	@Override
	public Message<?> preSend(Message<?> message, MessageChannel channel) {
		System.out.println("频道拦截器->preSend");
		return super.preSend(message, channel);
	}

	/**
	 * 发送消息调用后立即调用
	 */
	@Override
	public void postSend(Message<?> message, MessageChannel channel,
			boolean sent) {
		System.out.println("频道拦截器->postSend");

		//消息头访问器
		StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(message);
		// 避免非stomp消息类型,例如心跳检测
		if (headerAccessor.getCommand() == null ) return ;
		
		String huihuaId = headerAccessor.getSessionAttributes().get("huihuaId").toString();
		System.out.println("频道拦截器 -> 会话id = "+huihuaId);
		
		switch (headerAccessor.getCommand()) {
		case CONNECT:
			connect(huihuaId);
			break;
		case DISCONNECT:
			disconnect(huihuaId);
			break;
		case SUBSCRIBE:
			break;
		case UNSUBSCRIBE:
			break;
		default:
			break;
		}
	}

	//连接成功
	private void connect(String huihuaId){
	}

	//断开连接
	private void disconnect(String huihuaId){
		//用户下线操作
		UserChatController.onlineUser.remove(huihuaId);
	}
}

3 在websocket配置中配置拦截器

package cn.huawei.config;

import cn.huawei.intecepter.HttpHandShakeIntecepter;
import cn.huawei.intecepter.SocketChannelIntecepter;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.ChannelRegistration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    public void registerStompEndpoints(StompEndpointRegistry registry) {

        registry.addEndpoint("/endpoint-websocket")
                //配置握手拦截器
                .addInterceptors(new HttpHandShakeIntecepter())
                .setAllowedOrigins("*")
                .withSockJS();
    }

    /**
     * 配置消息代理(中介)
     * enableSimpleBroker 服务端推送给客户端的路径前缀
     * setApplicationDestinationPrefixes  客户端发送数据给服务器端的一个前缀
     */
    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {

        registry.enableSimpleBroker("/topic", "/chat");
        registry.setApplicationDestinationPrefixes("/app");

    }

    /**
     * 配置 频道拦截器
     */
    @Override
    public void configureClientInboundChannel(ChannelRegistration registration) {
        registration.interceptors(new SocketChannelIntecepter());
    }

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

4 测试,顺带可以看看拦截器加载的顺序,有得于理解

【握手拦截器】beforeHandshake 会话id=F3367AD9F1849BE6AB03178989DC1C3B
【握手拦截器】afterHandshake 会话id=F3367AD9F1849BE6AB03178989DC1C3B
频道拦截器->preSend
频道拦截器->postSend
频道拦截器 -> 会话id = F3367AD9F1849BE6AB03178989DC1C3B
频道拦截器->afterSendCompletion


 

以下是在Spring Boot项目中整合WebSocket的步骤,包括拦截器、消息处理器和WebSocket实现类的编写: 1. 添加依赖 在pom.xml文件中添加以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> ``` 2. 编写WebSocket配置类 创建一个WebSocketConfig类,用于配置WebSocket相关的内容,包括注册WebSocket处理器、拦截器等。 ```java @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Autowired private MyWebSocketHandler myWebSocketHandler; @Autowired private MyHandshakeInterceptor myHandshakeInterceptor; @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(myWebSocketHandler, "/websocket") .addInterceptors(myHandshakeInterceptor); } } ``` 在这个配置类中,我们注册了一个WebSocket处理器和一个握手拦截器WebSocket处理器用于处理WebSocket连接和消息,握手拦截器用于拦截WebSocket连接请求并进行一些处理。 3. 编写WebSocket处理器 创建一个WebSocket处理器类,用于处理WebSocket连接和消息。 ```java @Component public class MyWebSocketHandler extends TextWebSocketHandler { private static final Logger logger = LoggerFactory.getLogger(MyWebSocketHandler.class); private static final Map<String, WebSocketSession> sessions = new ConcurrentHashMap<>(); @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { logger.info("WebSocket连接建立成功:{}", session.getId()); sessions.put(session.getId(), session); } @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { logger.info("收到消息:{}", message.getPayload()); // 处理消息 } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { logger.info("WebSocket连接关闭:{},状态:{}", session.getId(), status); sessions.remove(session.getId()); } public static void sendMessage(String sessionId, String message) throws IOException { WebSocketSession session = sessions.get(sessionId); if (session != null && session.isOpen()) { session.sendMessage(new TextMessage(message)); } } } ``` 在这个处理器类中,我们重写了WebSocket处理器的三个方法:afterConnectionEstablished、handleTextMessage和afterConnectionClosed。afterConnectionEstablished方法在WebSocket连接建立成功后被调用,handleTextMessage方法用于处理收到的消息,afterConnectionClosed方法在WebSocket连接关闭后被调用。 4. 编写握手拦截器 创建一个握手拦截器类,用于拦截WebSocket连接请求并进行一些处理。 ```java @Component public class MyHandshakeInterceptor implements HandshakeInterceptor { private static final Logger logger = LoggerFactory.getLogger(MyHandshakeInterceptor.class); @Override public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception { logger.info("WebSocket握手拦截器:beforeHandshake"); // 进行一些处理 return true; } @Override public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) { logger.info("WebSocket握手拦截器:afterHandshake"); } } ``` 在这个握手拦截器类中,我们重写了握手拦截器的两个方法:beforeHandshake和afterHandshake。beforeHandshake方法在WebSocket连接请求到达服务器端时被调用,afterHandshake方法在WebSocket连接握手成功后被调用。 5. 编写WebSocket实现类 创建一个WebSocket实现类,用于实现WebSocket的具体业务逻辑。 ```java @Controller public class MyWebSocketController { @MessageMapping("/hello") @SendTo("/topic/greetings") public String greeting(String message) throws Exception { Thread.sleep(1000); // 模拟处理时间 return "Hello, " + message + "!"; } } ``` 在这个WebSocket实现类中,我们使用了@MessageMapping注解来指定处理消息的路径,使用@SendTo注解来指定返回消息的路径。 6. 测试WebSocket连接 在客户端中,可以使用JavaScript代码来测试WebSocket连接: ```javascript var socket = new WebSocket("ws://localhost:8080/websocket"); socket.onopen = function(event) { console.log("WebSocket连接已建立"); socket.send("Hello, WebSocket!"); }; socket.onmessage = function(event) { console.log("收到消息:" + event.data); }; socket.onclose = function(event) { console.log("WebSocket连接已关闭"); }; ``` 以上就是在Spring Boot项目中整合WebSocket的步骤,包括拦截器、消息处理器和WebSocket实现类的编写。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值