在SpringBoot中使用WebSocket并注入自定义Bean

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cxfly957/article/details/84345507

关于WebSocket的使用,之前有介绍在SpringMVC中的使用方法,最近项目需要在SpringBoot中使用WebSocket,使用方法大同小异,在配置项方面有些许差别,特此记录。
环境:
SpringBoot 2.0.3.RELEASE
JDK 1.8

首先在pom.xml文件中引入相关依赖:

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

其次需要手动注入ServerEndpointExporter,这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint。这是与SpringMVC中的用法不同的一点。

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

WS的具体代码和springmvc就没什么差别了,这里放了一段常规的聊天室代码作为例子:

@Component
@ServerEndpoint(value ="/webChat/{userId}")
public class WebSocketChat {
    private Logger logger = LoggerFactory.getLogger(WebSocketChat.class);


    //此处是解决无法注入的关键
    private static ApplicationContext applicationContext;
    //要注入的service或者dao
    private  TestService testService;
    public static void setApplicationContext(ApplicationContext applicationContext) {
        WebSocketChat.applicationContext = applicationContext;
    }


    /**
     * 在线人数
     */
    public static int onlineNumber = 0;
    /**
     * 以用户的姓名为key,WebSocketChat类为value保存起来
     */
    private static Map<String, WebSocketChat> clients = new ConcurrentHashMap<String, WebSocketChat>();
    /**
     * 会话
     */
    private Session session;
    /**
     * 用户名称
     */
    private String userId;
    /**
     * 建立连接
     *
     * @param session
     */
    @OnOpen
    public void onOpen(@PathParam("userId") String userId, Session session)
    {
        onlineNumber++;
        logger.info("现在来连接的客户id:"+session.getId()+"用户名:"+userId);
        this.userId = userId;
        this.session = session;
        //设置能接收的消息体字节大小()
        session.setMaxTextMessageBufferSize(104857600);//100M
        logger.info("有新连接加入! 当前在线人数" + onlineNumber);
        clients.put(userId, this);
     
    }

    @OnError
    public void onError(Session session, Throwable error) {
        logger.info("连接发生错误");
        error.printStackTrace();

    }
    /**
     * 连接关闭
     */
    @OnClose
    public void onClose(){
        onlineNumber--;
        clients.remove(userId);
        logger.info("有连接关闭! 当前在线人数" + onlineNumber);
    }

    /**
     * 收到客户端的消息
     *
     * @param message 消息
     * @param session 会话
     */
    @OnMessage
    public void onMessage(String message, Session session) throws IOException {

        logger.info("message  length=="+message.length());

        JSONObject jsonObject = JSON.parseObject(message);
        try {
           // logger.info("来自客户端消息:" + message+"客户端的id是:"+session.getId());
            //消息类型
            String messageType = jsonObject.getString("messageType");
            String messageText = jsonObject.getString("messageText");
            String fromusername = jsonObject.getString("sendId");
            String tousername = jsonObject.getString("receiveId");
            //messageType 1(文字)/2(图片)/3(语音)/4(视频)/5(文件)
            testService = applicationContext.getBean(TestService.class);


            long MS = System.currentTimeMillis();//获取当前时间(精确到毫秒)
            String timeMS = String.valueOf(MS);


            if(messageType.equals("1")){
                testService.saveMsg(fromusername,tousername,messageType,messageText,timeMS);
            }else{
                testService.saveFile(fromusername,tousername,messageType,messageText,timeMS);
            }
            Map<String,Object> map4 = new HashMap<>();
            int voiceDuration =0;
            if(messageType.equals("3") || messageType.equals("4")){
                voiceDuration=jsonObject.getInteger("voiceDuration");
                map4.put("voiceDuration",voiceDuration);
            }
            map4.put("status",0);
            map4.put("messageText",messageText);
            map4.put("messageType",messageType);
            logger.info("map4Info==="+map4);
            if(tousername.equals("All")){//发送给所有人
                map4.put("tousername","所有人");
                sendMessageAll(JSON.toJSONString(map4),fromusername);
            }else{//指定发送给某人
               // map4.put("tousername",tousername);
                sendMessageTo(JSON.toJSONString(map4),tousername);
            }


        }
        catch (Exception e){
            String tousername = jsonObject.getString("receiveId");
            Map<String,Object> map4 = new HashMap<>();
            map4.put("status",1);
            map4.put("textMessage","发送失败!");
            sendMessageTo(JSON.toJSONString(map4),tousername);
            e.printStackTrace();
            logger.info("WebSocketChat发生了错误了");
        }

    }

   

    public void sendMessageTo(String message, String ToUserName) throws IOException {
        for (WebSocketChat item : clients.values()) {
            if (item.userId.equals(ToUserName) ) {
                if(item.session.isOpen()){
                    item.session.getBasicRemote().sendText(message);
                    break;
                }

            }
        }
    }

    public void sendMessageAll(String message,String meName) throws IOException {
        for (WebSocketChat item : clients.values()) {
            if(!item.userId.equals(meName)){
                if(item.session.isOpen()){
                    item.session.getBasicRemote().sendText(message);
                }

            }
        }
    }

    public static synchronized int getOnlineCount() {
        return onlineNumber;
    }

}

开头的 TestService 是自定义的一个用于操作数据库的类,由于websocket中是不能通过 @Autowired标签注入资源的,所以必须通过ApplicationContext获取bean。首先需要在启动类的main方法中将websocket类加入容器上下文。

 public static void main(String[] args) {
        SpringApplication springApplication = new SpringApplication(ChatApplication.class);
        ConfigurableApplicationContext configurableApplicationContext = springApplication.run(args);
        //解决WebSocket不能注入的问题
        WebSocketChat.setApplicationContext(configurableApplicationContext);
    }

然后就像上述代码所示在WebSocketChat类中开头加入如下代码即可获取到要注入的TestService 。

 //此处是解决无法注入的关键
    private static ApplicationContext applicationContext;
    //要注入的service或者dao
    private  TestService testService;
    public static void setApplicationContext(ApplicationContext applicationContext) {
        WebSocketChat.applicationContext = applicationContext;
    }

猜你喜欢

转载自blog.csdn.net/cxfly957/article/details/84345507