栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

WebSocket+SpringBoot消息主动推送

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

WebSocket+SpringBoot消息主动推送

概 述

通常在web前端通知客户的时候,一种方式是通过Http/Https轮询来实现,另外一种方式是通过WebSocket 这种轻量Tcp连接来实现,我们这边介绍的就是消息推送。

Http+WebSocket 原理解析

方案的实现

前端实现webSocket 的方式如下两种方式仅供参考:

  • 第一种一种是使用sockjs。
  • 第二种是使用h5的标准。使用Html5标准自然更方便简单,所以记录的是配合h5的使用方法。
    前端代码
    index.html



    
    Title


    Welcome

后端实现

  • 包的引入
        
            org.springframework.boot
            spring-boot-starter-websocket
        
  • 配置类(WebSocketConfig)
    使用@ServerEndpoint创立websocket endpoint [配置端点类以及具体实现:WebSocketServer] 首先要注入ServerEndpointExporter,这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint。 要注意,如果使用独立的servlet容器,而不是直接使用springboot的内置容器,就不要注入ServerEndpointExporter,因为它将由容器自己提供和管理。
  • 配置类的实现
package com.dianxin.msg.websocketconfig;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import javax.websocket.server.ServerEndpointConfig;

public class MyEndpointConfigure extends ServerEndpointConfig.Configurator implements ApplicationContextAware {
    private static volatile BeanFactory context;
 
	@Override
	public  T getEndpointInstance(Class clazz) throws InstantiationException {
		return context.getBean(clazz);
	}
 
	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		MyEndpointConfigure.context = applicationContext;
	}
}
package com.dianxin.msg.websocketconfig;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;


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

    
    @Bean
    public MyEndpointConfigure newConfigure() {
        return new com.dianxin.msg.websocketconfig.MyEndpointConfigure();
    }
}

Service 层实现

package com.dianxin.msg.service;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;


@Component
@ServerEndpoint(value = "/socket/{name}/{token}")
public class WebSocketServer {

    //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
    private static AtomicInteger online = new AtomicInteger();

    //concurrent包的线程安全Set,用来存放每个客户端对应的WebSocketServer对象。
    private static Map sessionPools = new HashMap<>();

    
    public void sendMessage(Session session, String message) throws IOException{
        if(session != null){
            session.getBasicRemote().sendText(message);
        }
    }


    
    @OnOpen
    public void onOpen(Session session, @PathParam(value = "name") String userName, @PathParam(value = "token") String token){
        sessionPools.put(userName, session);
        addOnlineCount();
        System.out.println(userName + "加入webSocket!当前人数为" + online);
        try {
            sendMessage(session, "欢迎" + userName + "加入连接!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    
    @OnClose
    public void onClose(@PathParam(value = "name") String userName){
        sessionPools.remove(userName);
        subOnlineCount();
        System.out.println(userName + "断开webSocket连接!当前人数为" + online);
    }

    
    @OnMessage
    public void onMessage(String message) throws IOException{
        for (Session session: sessionPools.values()) {
            try {
                sendMessage(session, message);
            } catch(Exception e){
                e.printStackTrace();
                continue;
            }
        }
    }

    
    @OnError
    public void onError(Session session, Throwable throwable){
        System.out.println("发生错误");
        throwable.printStackTrace();
    }

    
    public void sendInfo(String userName, String message){
        Session session = sessionPools.get(userName);
        try {
            sendMessage(session, message);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    
    public Session getSession(String userName){
        Session session = sessionPools.get(userName);
        return session;
    }

    public static void addOnlineCount(){
        online.incrementAndGet();
    }

    public static void subOnlineCount() {
        online.decrementAndGet();
    }
}

Controller 层实现(用来测试)

package com.dianxin.msg.controller;


import com.dianxin.msg.service.WebSocketServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;



@RequestMapping("/webSocket")
@RestController
public class WebSocketController {


    @Autowired
    private WebSocketServer webSocketServer;

    
    @RequestMapping(value = "/socket", method = RequestMethod.GET)
    public void testSocket1(@RequestParam String userName, @RequestParam String message){
        webSocketServer.sendInfo(userName, message);
    }


    
    @RequestMapping(value = "/socket/all", method = RequestMethod.GET)
    public void pushAllSocket(@RequestParam String message){
        try {
            webSocketServer.onMessage(message);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/884622.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号