springboot websocket 消息推送

                             springboot  websocket 实现消息推送

什么是WebSocket

WebSocket为浏览器和服务器之间提供了双工异步通信功能,也就是说我们可以利用浏览器给服务器发送消息,服务器也可以给浏览器发送消息,目前主流浏览器的主流版本对WebSocket的支持都算是比较好的,但是在实际开发中使用WebSocket工作量会略大,而且增加了浏览器的兼容问题,这种时候我们更多的是使用WebSocket的一个子协议stomp,利用它来快速实现我们的功能。 

1.第一步

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
            <version>2.1.1.RELEASE</version>
        </dependency>

2.创建websocketConfig

@Configuration
@EnableWebSocketMessageBroker
@ComponentScan("com.sensetime.fis.senseguard")
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
    
    @Autowired
    private PrincipalHandshakeHandler myDefaultHandshakeHandler;
    @Autowired
    private WebSocketInterceptor sessionAuthHandshakeInterceptor;
    
    /**
     * 配置消息代理类
     * 
     * @param registry
     */
    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        // 广播式应配置一个/topic消息代理
        // 推送消息前缀
        registry.enableSimpleBroker("/topic"); 
        // 应用请求前缀
        registry.setApplicationDestinationPrefixes("/app"); 
        // 推送用户前缀
        registry.setUserDestinationPrefix("/user");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
        // 定义ws连接入口
        stompEndpointRegistry.addEndpoint("/websocket").setAllowedOrigins("*").addInterceptors(sessionAuthHandshakeInterceptor)
        .setHandshakeHandler(myDefaultHandshakeHandler).withSockJS()
                .setInterceptors(new WebSocketInterceptor());
    }

    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
 

3.握手前配置 PrincipalHandshakeHandler

@Component
public class PrincipalHandshakeHandler extends DefaultHandshakeHandler {
    @Override
    protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler,
            Map<String, Object> attributes) {
        HttpSession httpSession = getSession(request);
        String token = (String) httpSession.getAttribute("token");

        if (!StringUtils.isEmpty(token)) {
            return new ExportPrincipal(token);
        }
        return null;
    }

    private HttpSession getSession(ServerHttpRequest request) {
        ServletServerHttpRequest serverRequest = (ServletServerHttpRequest) request;
        return serverRequest.getServletRequest().getSession(true);
    }

4.拦截器配置 WebSocketInterceptor


/**
 * 
 * @ClassName: MyWebSocketInterceptor
 * @Description: 创建握手 此类用来获取登录用户信息并交由websocket管理
 * @author libo
 * @date 2017年9月26日 上午10:31:30
 * HandshakeInterceptor WebSocket握手请求的拦截器. 检查握手请求和响应, 对WebSocketHandler传递属性
 */
@Component
public class WebSocketInterceptor extends TextWebSocketHandler implements HandshakeInterceptor {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 在握手之前执行该方法, 继续握手返回true, 中断握手返回false. 通过attributes参数设置WebSocketSession的属性
     */
    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
            Map<String, Object> attributes) throws Exception {
        HttpSession httpSession = getSession(request);
        String token = getToken(request.getURI().toString());
        httpSession.setAttribute("token", token);
        return true;
    }

    /**
     * 在握手之后执行该方法. 无论是否握手成功都指明了响应状态码和相应头.
     */
    @Override
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
            Exception exception) {
        String token = getToken(request.getURI().toString());
        logger.info("TOKEN为【{}】的用户建立消息连接已完成", token);
    }

    private String getToken(String uri) {
        int index = uri.indexOf("accessToken=");
        return uri.substring(index + 12, uri.length());
    }

    /**
     * 用户进入系统监听
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        logger.info("xxx用户进入系统。。。");
        logger.info("用户信息:" + session.getAttributes());
        System.out.println(session.getAttributes());
        System.out.println("xxx用户进入系统。。。");

        Map<String, Object> map = session.getAttributes();
        for (String key : map.keySet()) {
            System.out.println("key:" + key + " and value:" + map.get(key));
        }
    }

    @SuppressWarnings("unused")
    private HttpSession getSession(ServerHttpRequest request) {
        ServletServerHttpRequest serverRequest = (ServletServerHttpRequest) request;
        return serverRequest.getServletRequest().getSession(true);
    }
 

5.推送

@Autowired
private SimpMessagingTemplate simpMessagingTemplate;

simpMessagingTemplate.convertAndSendToUser(task.getWebsocketId(), "/topic/records/subscribe", result);

后端整个流程就是这样了,前端简历连接订阅完成后,就可以接受后端给的推送消息。

猜你喜欢

转载自blog.csdn.net/m0_37598953/article/details/86304079