美文网首页Netty学习Java架构师专题
Springboot整合Websocket基本案例(后端向前端主

Springboot整合Websocket基本案例(后端向前端主

作者: 愚公要移山 | 来源:发表于2019-12-26 15:45 被阅读0次

    在手机上相信都有来自服务器的推送消息,比如一些及时的新闻信息,这篇文章主要就是实现这个功能,只演示一个基本的案例。使用的是websocket技术。

    一、什么是websocket

    WebSocket协议是基于TCP的一种新的网络协议。它实现了客户端与服务器全双工通信,学过计算机网络都知道,既然是全双工,就说明了服务器可以主动发送信息给客户端。这与我们的推送技术或者是多人在线聊天的功能不谋而合。

    为什么不使用HTTP 协议呢?这是因为HTTP是单工通信,通信只能由客户端发起,客户端请求一下,服务器处理一下,这就太麻烦了。于是websocket应运而生。

    下面我们就直接开始使用Springboot开始整合。以下案例都在我自己的电脑上测试成功,你可以根据自己的功能进行修改即可。

    二、整合websocket

    1、环境配置

    名称 版本
    Idea 2018专业版(已破解)
    Maven 4.0.0
    SpringBoot 2.2.2
    websocket 2.1.3
    jdk 1.8

    下面我们新建一个普通的Springboot项目。

    2、添加依赖

        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-websocket</artifactId>
                <version>2.1.3.RELEASE</version>
            </dependency>
        </dependencies>
    

    3、在application.properties文件修改端口号

    一句话:server.port=8081

    4、新建config包,创建WebSocketConfig类

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

    5、新建service包,创建WebSocketServer类

    @ServerEndpoint("/websocket/{sid}")
    @Component
    public class WebSocketServer {
        static Log log= LogFactory.getLog(WebSocketServer.class);
        //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
        private static int onlineCount = 0;
        //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
        private static CopyOnWriteArraySet<WebSocketServer> webSocketSet
                = new CopyOnWriteArraySet<WebSocketServer>();
        //与某个客户端的连接会话,需要通过它来给客户端发送数据
        private Session session;
        //接收sid
        private String sid="";
        /**
         * 连接建立成功调用的方法
         */
        @OnOpen
        public void onOpen(Session session,@PathParam("sid") String sid) {
            this.session = session;
            webSocketSet.add(this);     //加入set中
            addOnlineCount();           //在线数加1
            log.info("有新窗口开始监听:"+sid+",当前在线人数为" + getOnlineCount());
            this.sid=sid;
            try {
                sendMessage("连接成功");
            } catch (IOException e) {
                log.error("websocket IO异常");
            }
        }
        /**
         * 连接关闭调用的方法
         */
        @OnClose
        public void onClose() {
            webSocketSet.remove(this);  //从set中删除
            subOnlineCount();           //在线数减1
            log.info("有一连接关闭!当前在线人数为" + getOnlineCount());
        }
        /**
         * 收到客户端消息后调用的方法
         * @param message 客户端发送过来的消息
         */
        @OnMessage
        public void onMessage(String message, Session session) {
            log.info("收到来自窗口"+sid+"的信息:"+message);
            //群发消息
            for (WebSocketServer item : webSocketSet) {
                try {
                    item.sendMessage(message);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        @OnError
        public void onError(Session session, Throwable error) {
            log.error("发生错误");
            error.printStackTrace();
        }
        //实现服务器主动推送
        public void sendMessage(String message) throws IOException {
            this.session.getBasicRemote().sendText(message);
        }
        //群发自定义消息
        public static void sendInfo(String message,@PathParam("sid") String sid) 
            throws IOException {
            log.info("推送消息到窗口"+sid+",推送内容:"+message);
            for (WebSocketServer item : webSocketSet) {
                try {
                    //这里可以设定只推送给这个sid的,为null则全部推送
                    if(sid==null) {
                        item.sendMessage(message);
                    }else if(item.sid.equals(sid)){
                        item.sendMessage(message);
                    }
                } catch (IOException e) {
                    continue;
                }
            }
        }
        public static synchronized int getOnlineCount() {
            return onlineCount;
        }
        public static synchronized void addOnlineCount() {
            WebSocketServer.onlineCount++;
        }
        public static synchronized void subOnlineCount() {
            WebSocketServer.onlineCount--;
        }
    }
    

    6、新建controller包,创建Mycontroller类

    @Controller
    public class MyController {
        //页面请求
        @GetMapping("/socket/{cid}")
        public ModelAndView socket(@PathVariable String cid) {
            ModelAndView mav=new ModelAndView("/socket");
            mav.addObject("cid", cid);
            return mav;
        }
        //推送数据接口
        @ResponseBody
        @RequestMapping("/socket/push/{cid}")
        public String pushToWeb(@PathVariable String cid,String message) {
            try {
                WebSocketServer.sendInfo(message,cid);
            } catch (IOException e) {
                e.printStackTrace();
                return "推送失败";
            }
            return "发送成功";
        }
    }
    

    7、新建一个websocket.html页面

    <html>
    <head>
        <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
        <script type="text/javascript">
            var socket;
            if (typeof (WebSocket) == "undefined") {
                console.log("您的浏览器不支持WebSocket");
            } else {
                console.log("您的浏览器支持WebSocket");
                //实现化WebSocket对象,指定要连接的服务器地址与端口  建立连接  
                socket = new WebSocket("ws://localhost:8081/websocket/1");
                //打开事件  
                socket.onopen = function () {
                    console.log("Socket 已打开");
                    socket.send("这是来自客户端的消息" + location.href + new Date());
                };
                //获得消息事件  
                socket.onmessage = function (msg) {
                    console.log(msg.data);
                };
                //关闭事件  
                socket.onclose = function () {
                    console.log("Socket已关闭");
                };
                //发生了错误事件  
                socket.onerror = function () {
                    alert("Socket发生了错误");
                }
            }
        </script>
    </head>
    </html>
    

    现在开发服务器和网页就可以看到效果了。一般情况下Springboot2+Netty+Websocket的组合方式更加的常用一下。这个只是给出了一个基本的案例,你可以根据自己的需求进行更改。


    最新的扁平化的宣传模板.png

    相关文章

      网友评论

        本文标题:Springboot整合Websocket基本案例(后端向前端主

        本文链接:https://www.haomeiwen.com/subject/zwfloctx.html