基于Spring集成WebSocket消息推送

常规的WebSocket服务,有不同的连接来源(比方说浏览器开发模式、业务平台、自己写的测试页面等。如果要屏蔽这些外来人员,可通过session控制)

服务器端

1.依赖包,和spring同一版本
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-websocket</artifactId>
    <version>${spring.version}</version>
</dependency>
2.WebSocket配置监听
@Configuration
@EnableWebMvc
@EnableWebSocket
public class SpringWebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer {

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
        webSocketHandlerRegistry.addHandler(webSocketHandler(), "/ws")
                .addInterceptors(new WebSocketInterceptor()).setAllowedOrigins("*");
        webSocketHandlerRegistry.addHandler(webSocketHandler(), "/sj")
                .addInterceptors(new WebSocketInterceptor()).setAllowedOrigins("*").withSockJS();
    }

    @Bean
    public TextWebSocketHandler webSocketHandler() {
        return new MsgWebSocketHandler();
    }
}

此处除了常规的websocket监听url,还设置了备选方案sockjs(部分浏览器不支持websocket可使用sockjs)

3.WebSocket拦截配置
@Component
public class WebSocketInterceptor extends HttpSessionHandshakeInterceptor {
    private Logger logger = LoggerFactory.getLogger(WebSocketInterceptor.class);

    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
        logger.info("beforeHandshake");
        //todo 待添加
        return super.beforeHandshake(request, response, wsHandler, attributes);
    }

    @Override
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) {
        logger.info("afterHandshake");
        super.afterHandshake(request, response, wsHandler, ex);
    }
}

可以基于自身业务情况,在握手之前(beforeHandshake),对session里的内容进行读取处理。

4.WebSocket消息处理
public class MsgWebSocketHandler extends TextWebSocketHandler {
    private Logger logger = LoggerFactory.getLogger(MsgWebSocketHandler.class);
    private static ConcurrentHashMap<String, WebSocketSession> sessionMap = new ConcurrentHashMap<>();
    private static Pattern msgPattern = Pattern.compile(".*::.*::.*");

    /**
    * 接收消息并处理
    * 格式 ==> 指令类型::对方身份证::extension
    * @param session
    * @param message
    * @throws Exception
    */
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        logger.info("ws msg={}", message.toString());
        logger.info("ws msg payload={}", message.getPayload());

        //解析信息
        UserDetail userDetail = (UserDetail) session.getAttributes().get(Constants.USER_KEYNAME);
        if (userDetail == null) return;//游客忽略
        if (StringUtils.isBlank(message.getPayload())) return;

        Matcher matcher = msgPattern.matcher(message.getPayload());
        if (!matcher.matches()) {
            logger.warn("ws msg format error!");
            return;
        }

        String[] infos = message.getPayload().split("::");
        String type = infos[0];
        String target = infos[1];
        String extension = userDetail.getUsernumber()+"@@"+infos[2];

        String payload = String.format("%s::%s::%s", type, userDetail.getUsername(), extension);
        TextMessage textMsg = new TextMessage(payload);
        //todo 此处要基于target找到对应session,然后发送消息
        session.sendMessage(textMsg);
    }

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        UserDetail userDetail = (UserDetail) session.getAttributes().get(Constants.USER_KEYNAME);
        if (userDetail != null) {
            sessionMap.put(userDetail.getUsernumber(), session);
            logger.info("ws conn established {}", userDetail.getUsernumber());
            logger.info("ws conn {}", String.valueOf(sessionMap.size()));
        } else {
            logger.warn("ws conn established with visitor id={}", session.getId());
        }
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        UserDetail userDetail = (UserDetail) session.getAttributes().get(Constants.USER_KEYNAME);
        if (userDetail != null) {
            sessionMap.remove(userDetail.getUsernumber());
            logger.info("ws conn close, session {} out", userDetail.getUsernumber());
            logger.info("ws conn {}", String.valueOf(sessionMap.size()));
        } else {
            logger.warn("ws conn close with visitor id={}", session.getId());
        }
    }
}

此处,基于session,判断了当前连接是否是访问业务平台过来的还是其他直连过来的。通过一个map保存session信息

浏览器前端

前端WebSocket注册
<script type="text/javascript" src="<%=path%>/js/main/sockjs.js"></script>
<script type="text/javascript" >
    var ws = null;
    var url = window.location.host+"/backAdmin";

        $(function () {
        if ('WebSocket' in window) {
            ws = new WebSocket("ws://"+url+"/ws");
        } else if ("MozWebSocket" in window) {
            ws = new MozWebSocket("ws://"+url+"/ws");
        } else {
            ws = new SockJS("http://"+url+"/sj");
        }

        ws.onopen = onOpen;
        ws.onmessage = onMessage;
        ws.onerror = onError;
        ws.onclose = onClose;
    });

    function onOpen(result) {
                    console.log(result);
    }
    function onMessage(result) {
        console.log(result);
    }
    function onError(result) {
        console.log(result);
    }
    function onClose(result) {
        console.log(result);
    }

    function doSend(msg) {
        if (ws.readyState == ws.OPEN) {
            ws.send(msg);
        } else {
            console.error('ws lost connection!');
        }
    }
    window.close = function () {
        ws.onclose();
    }
</script>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值