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

springboot整合websocket

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

springboot整合websocket

springboot整合websocket

最近在学习websocket,做份笔记和大家分享一下

1、引入相关依赖

springboot相关依赖就不写了,这里只写websocket的依赖



    org.springframework.boot
    spring-boot-starter-websocket


2、写配置文件

这里注意不要漏了 @EnableWebSocket,用于开启websocket支持,同时 @Configuration将配置类注入spring容器

package com.websocket.config;

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

@Configuration
//开启websocket支持
@EnableWebSocket
public class WebsocketConfig
{
    
    @Bean
    public ServerEndpointExporter serverEndpointExporter()
    {
        return new ServerEndpointExporter();
    }

    
    @Bean
    public ServletServerContainerFactoryBean createWebSocketContainer()
    {
        ServletServerContainerFactoryBean bean = new ServletServerContainerFactoryBean();
        //文本缓冲区大小
        bean.setMaxTextMessageBufferSize(8192);
        //字节缓冲区大小
        bean.setMaxBinaryMessageBufferSize(8192);
        return bean;
    }
}


3、开始愉快的使用啦

这里先介绍几个websocket的注解

注解作用备注
@ServerEndpoint用于声明websocket响应类,有点像@RequestMapping@ServerEndpoint("/websocket")
@OnOpenwebsocket连接时触发参数有:Session session, EndpointConfig config
@OnMessage有消息时触发参数很多,一会再说
@OnClose连接关闭时触发参数有:Session session, CloseReason closeReason
@OnError有异常时触发参数有:Session session, Throwable throwable

3.1(重要) 将@ServerEndpoint标注在类上,然后依次创建4个方法,参数见上表,方法名随意

注意类上需要有 @Component 扫描哦,我这里用的时@Controller

@Log4j2
@Controller
@ServerEndpoint("/websocket")
public class baseWebsocketController
{

	//使用 ConcurrentHashMap, 保证线程安全, static全局共享 session
	
	//这里之所以static,是因为这个类不是单例的!!
	//他虽然有@Controller注解,但是不适用Ioc容器中拿对象,每一次请求过来都是一个新的对象
	
    //存放 session
    private final static Map sessions = new ConcurrentHashMap<>();

    //onopen 在连接创建(用户进入聊天室)时触发
    @OnOpen
    public void openSession(Session session, EndpointConfig config)
    {
        
    }

	//响应字符串
    @OnMessage
    public void onMessage(Session session, String message)
    {
        
    }

	//响应字节流
    @OnMessage
    public void onMessage(Session session, byte[] message)
    {
        
    }

    //onclose 在连接断开(用户离开聊天室)时触发
    @OnClose
    public void closeSession(Session session, CloseReason closeReason)
    {
        
    }

    @OnError
    public void sessionError(Session session, Throwable throwable)
    {
        
    }
}

说明

细心的小伙伴可能发现,我有两个 @OnMessage, 这是因为websocket能发送三种请求(我知道的三种),一种是字符串,一种是字节流(用于上传文件),一种是ping-pong(乒乓机制),因为js不好发送ping请求,我这里就只有响应字符串和字节流两种方法。

接下来的篇幅将只演示字符串的,字节流咱再另一篇说,不然太多了看的头痛
3.2 往方法里面写点简单的东西

里面注释写个很清楚哦,慢慢瞅,咱就解释一下流程:
1、再OnOpen中将session存起来,并通知其他用户,有人来啦。
2、有消息来的时候,再OnMessage中,通知其他用户
3、OnClose中,通知其他用户,别人溜了
4、OnError中,有异常就关闭websocket

@Log4j2
@Controller
@ServerEndpoint("/websocket")
public class baseWebsocketController
{

    //使用 ConcurrentHashMap, 保证线程安全, static全局共享 session

    //这里之所以static,是因为这个类不是单例的!!
    //他虽然有@Controller注解,但是不适用Ioc容器中拿对象,每一次请求过来都是一个新的对象

    //存放 session
    private final static Map sessions = new ConcurrentHashMap<>();

    //onopen 在连接创建(用户进入聊天室)时触发
    @OnOpen
    public void openSession(Session session, EndpointConfig config)
    {
        //将session存起来, 用于服务器向浏览器发送消息
        sessions.put(session.getId(), session);
        sendAll("[" + session.getId() + "]进入房间");
    }

    //响应字符串
    @OnMessage
    public void onMessage(Session session, String message)
    {
        sendAll("[" + session.getId() + "]" + message);
    }

    //响应字节流
    @OnMessage
    public void onMessage(Session session, byte[] message)
    {
        //这个咱以后再说
    }

    //onclose 在连接断开(用户离开聊天室)时触发
    @OnClose
    public void closeSession(Session session, CloseReason closeReason)
    {
        //记得移除相对应的session
        sessions.remove(session.getId());
        
        sendAll("[" + session.getId() + "]离开了房间");
    }

    @OnError
    public void sessionError(Session session, Throwable throwable)
    {
        //通常有异常会关闭session
        try {
            session.close();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void sendAll(String message)
    {
        for (Session s : sessions.values()) {
            //获得session发送消息的对象
            //Basic是同步, 会阻塞
            //Async是异步, 这个会有多线程并发导致异常, 发送消息太快也会有并发异常, 需要有 消息队列 来辅助使用
            final RemoteEndpoint.Basic remote = s.getBasicRemote();
            try {
                //发送消息
                remote.sendText(message);
            }
            catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

3.3 写个页面使用websocket





  
  websocket-demo
  
  


  

4、最后填下坑 4.1@OnOpen、@OnMessage…那些参数是咋来滴?

当然是看注释啦!转到源码,再类的上边有一大串注释,百度翻译看下就行。
我上边还有漏的哦~~

4.2 里面有一段是这个
and Zero to n String or Java primitive parameters
annotated with the {@link javax.websocket.server.PathParam} annotation for server endpoints.

意思是可以再路径中加入参数,然后用 @PathParam注解获得该参数(是不是和web很像呢)

也就是说,可以这样

@ServerEndpoint("/websocket/{username}")

然后这样获得参数(所有方法都可以加),而且可以不止一个

//响应字符串
@OnMessage
public void onMessage(@PathParam("username") String username, Session session, String message)
{
    sendAll("[" + username + "]" + message);
}

再html连接时,url就这么写

let username = $('#username').val();
let url = 'ws://127.0.0.1:8080/websocket';
url = url+'/'+username;

所以啊,刚刚我们demo的用户名是可以显示出来的(这个就交给大家了,懒 >_<)。

End

以后有时间写下关于websocket文件上传的,着急的小伙伴下面评论,我开个小灶丫~

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

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

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