• SpringBoot之整合WebSocket服务并兼容IE8浏览器的方式


    SpringBoot之整合WebSocket服务并兼容IE8浏览器的方式

    1. SpringBoot整合WebSocket过程请查看 SpringBoot之WebSocket服务搭建
    2. 以下WebSocket兼容IE8浏览器的方式就是在 SpringBoot之WebSocket服务搭建基础上完成的。

    1. web-socket-js

    1. 为了兼容IE8浏览器,WebSocket采用Adobe Flash来实现,而Flash由于安全策略问题,会向TCP:843端口发送请求文件,服务器应该返回安全策略文件给客户端;

    2. 这里是使用开源项目web-socket-js对IE8中使用webSocket进行兼容适配与实现;

    3. web-socket-js官网地址:https://github.com/gimite/web-socket-js

    1.下载web-socket-js

    从官网中下载并提取swfobject.jsweb_socket.jsWebSocketMain.swf等三个文件

    2. 配置

    将上面三个文件放在SpringBoot静态资源目录下

    1. 在·src\main\resources\static目录下新建myjs文件夹,并将swfobject.jsweb_socket.js`放在myjs中
    2. WebSocketMain.swf放在跟目录src\main\resources\

    2. FlashSocket安全服务策略文件843端口配置

    1. 配置方式1_xxx.xml配置方式

    此配置方式只需要两步:

    1. 编写一个flash安全服务策略文件监听843端口的监听器线程类;
    2. 在spring boot应用启动后,随即启动监听843端口的监听器线程;
    3. 配置flash通信协议的策略文件
    1. 编写flash843端口监听类

    兼容IE8方式1:将crossdomain.xml改名后放在跟目录下的方式

    package org.yuan.mysoket;
    
    import java.io.BufferedInputStream;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;
    /**
     * 兼容IE8方式1:将crossdomain.xml改名后放在跟目录下的方式
     * 为了兼容IE8浏览器,WebSocket采用Adobe Flash来实现,而Flash由于安全策略问题,会向TCP:843端口发送请求文件,服务器应该返回安全策略文件给客户端。
     */
    public class WebSocketPolicyListener implements Runnable {
        private ServerSocket server;
    
        public WebSocketPolicyListener() {
            try {
                server = new ServerSocket(843);
                System.out.println("Adobe Flash安全策略监听启动");
            } catch (IOException e) {
                System.err.println();
                e.printStackTrace();
            }
        }
    
        @Override
        public void run() {
    
            while (true) {
                System.out.println("线程run");
                try {
                    Socket s = server.accept();
                    //获取安全策略请求文件
                    BufferedInputStream bin = new BufferedInputStream(s.getInputStream());//打开文件流//
                    //网络操作调用avaiable()方法时,可能数据并没有到达,这时需要等待数据变为可用
                    int avaiable = 0;
                    //当有可用数据时,退出循环
                    while (avaiable == 0) {
                        avaiable = bin.available();
                    }
                    byte[] buf = new byte[avaiable];
                    int count = bin.read(buf);
                    String request = new String(buf, 0, count);
                    System.out.println("安全策略文件请求:\n" + request);
    
                    //如果是安全策略文件请求,将安全策略文件发给客户端
                    if (request.indexOf("") != -1) {
                        //获取文件路径,我放在src目录下
                        String path = WebSocketPolicyListener.class.getResource("/").getPath() + "websocket-policy.xml";
                        FileInputStream fin = new FileInputStream(path);
                        buf = new byte[1024];
                        StringBuilder sb = new StringBuilder();
                        while ((count = fin.read(buf)) > 0) {
                            s.getOutputStream().write(buf, 0, count);
                            sb.append(new String(buf, 0, count));
                        }
                        System.out.println("安全策略文件响应:\n" + sb.toString());
                        fin.close();//关闭文件流
                    }
    
                    s.close();//关闭Socket流
                } catch (IOException e) {
                    e.printStackTrace();
                }
    
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    2. SpringBoot应用启时启动843监听程序配置

    实现CommandLineRunner接口,并在run方法中启动WebSocketPolicyListener

    package org.yuan.config;
    
    import org.springframework.boot.CommandLineRunner;
    import org.springframework.stereotype.Component;
    import org.yuan.mysoket.WebSocketPolicyListener;
    
    @Component
    public class InitConfig implements CommandLineRunner {
        @Override
        public void run(String... args) throws Exception {
            WebSocketPolicyListener webSocketPolicyListener = new WebSocketPolicyListener();
            new Thread(webSocketPolicyListener).start();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    3. 配置flash通信协议的策略文件

    默认的策略文件名为crossdomain.xml;

    1. 这里我自己定义为ebsocket-policy.xml,并将此文件放在项目跟目录下;

    2. src\main\resources\websocket-policy.xml

    websocket-policy.xml内容如下

    
    <cross-domain-policy>
        <site-control permitted-cross-domain-policies="all"/>
        <allow-http-request-headers-from domain="*" headers="*"/>
        <allow-access-from domain="*" to-ports="2001"/>
    cross-domain-policy>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2. 配置方式2_Java编码方式

    1.编写监听843端口的服务类

    SocketService.java类如下J

    package org.yuan.config;
    
    import java.io.*;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    /**
     * 兼容IE8方式2:将crossdomain.xml中的内容直接写入Java代码中
     * 这个socket主要还是为了flash的socket
     */
    public class SocketService {
    
        private ServerSocket serverSocket = null;
    
        private static Object locker = new Object();
    
        // 线程池
        private static ExecutorService executorService = null;
    
        public synchronized void initSocketServer() {
            try {
                if (executorService == null) {
                    executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 20);
                } else {
                    return;
                }
                //启动843端口
                serverSocket = new ServerSocket(843);
                Runnable runnable = new Server();
                Thread thread = new Thread(runnable);
                thread.start();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        public void closeServer() {
            locker = null;
            if (serverSocket != null && !serverSocket.isClosed()) {
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
        class Server implements Runnable {
            @Override
            public void run() {
                try {
                    while (locker != null) {
                        if (serverSocket == null || serverSocket.isClosed()) {
                            continue;
                        }
                        //接收客户端的连接
                        Socket incoming = serverSocket.accept();
                        Runnable runnable = new ThreadClient(incoming);
                        executorService.execute(runnable);
                    }
                } catch (Exception e) {
                    //此处有一种异常,当关掉Tomcat时,会去关闭ServerSocket对象,
                    //从而抛出异常java.net.SocketException: socket closed,
                    //原因是ServerSocket对象正在等待客户端连接或正在连接中
                    e.printStackTrace();
                }
            }
        }
    
        class ThreadClient implements Runnable {
    
            private Socket incoming;
    
            private ThreadClient(Socket socket) {
                incoming = socket;
            }
    
            public void run() {
                InputStreamReader isr = null;
                BufferedReader br = null;
                OutputStreamWriter osw = null;
                BufferedWriter bw = null;
                try {
                    isr = new InputStreamReader(incoming.getInputStream(), "UTF-8");
                    br = new BufferedReader(isr);
                    osw = new OutputStreamWriter(incoming.getOutputStream(), "UTF-8");
                    bw = new BufferedWriter(osw);
                    //读取客户端发送的数据
                    StringBuilder sb = new StringBuilder();
                    int c;
                    while ((c = br.read()) != -1) {
                        if (c != '\0') {
                            sb.append((char) c);
                        } else {
                            break;
                        }
                    }
                    String info = sb.toString();
                    System.out.println(String.format("客户端发送的数据:%s", info));
                    //接收到客户端请求之后,将策略文件发送出去
                    if (info.contains("")) {
                        bw.write("\0");
                        bw.flush();
                        System.out.println(String.format("将安全策略文件发送至:%s", incoming.getInetAddress()));
                    } else {
                        bw.write("请求无法识别\0");
                        bw.flush();
                        System.out.println(String.format("请求无法识别:%s", incoming.getInetAddress()));
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        if (br != null) {
                            br.close();
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    try {
                        if (isr != null) {
                            isr.close();
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    try {
                        if (bw != null) {
                            bw.close();
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    try {
                        if (osw != null) {
                            osw.close();
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    try {
                        if (incoming != null) {
                            incoming.close();
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    2. 实现ServletContextListener监听接口并在实现方法中启动843端口监听类
    1. 实现ServletContextListener监听接口并在实现方法中启动843端口监听类;
    2. 编写MyServletContextListener类让其实现ServletContextListener接口,并实现其中的两个方法

    MyServletContextListener.java具体内容如下

    package org.yuan.config;
    
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    import javax.servlet.annotation.WebListener;
    
    /**
     * 

    * Description:
    *

    * Author:jinshengyuan
    * Datetime: 2020-06-16 15:25 *

    * */
    @WebListener public class MyServletContextListener implements ServletContextListener { private SocketService service; @Override public void contextInitialized(ServletContextEvent sce) { service = new SocketService(); service.initSocketServer(); } @Override public void contextDestroyed(ServletContextEvent sce) { service.closeServer(); } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    3. 编写页面进行调试

    index.html内容如下

    
    
    <html><head>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      <title>Sample of web_socket.jstitle>
      
      
      <script type="text/javascript" src="/myjs/swfobject.js">script>
      <script type="text/javascript" src="/myjs/web_socket.js">script>
    
    
      <script type="text/javascript">
        
        // Set URL of your WebSocketMain.swf here:
        WEB_SOCKET_SWF_LOCATION = "WebSocketMain.swf";
        // Set this to dump debug message from Flash to console.log:
        WEB_SOCKET_DEBUG = true;
        
        // Everything below is the same as using standard WebSocket.
        
        var ws;
        
        function init() {
    
          // Connect to Web Socket.
          // Change host/port here to your own Web Socket server.
          ws = new WebSocket("ws://localhost:2001/myChat");
    
          // Set event handlers.
          ws.onopen = function() {
            output("onopen");
          };
          ws.onmessage = function(e) {
            // e.data contains received string.
            output("onmessage: " + e.data);
          };
          ws.onclose = function() {
            output("onclose");
          };
          ws.onerror = function() {
            output("onerror");
          };
    
        }
        
        function onSubmit() {
          var input = document.getElementById("input");
          // You can send message to the Web Socket using ws.send.
          ws.send(input.value);
          output("send: " + input.value);
          input.value = "";
          input.focus();
        }
        
        function onCloseClick() {
          ws.close();
        }
        
        function output(str) {
          var log = document.getElementById("log");
          var escaped = str.replace(/&/, "&").replace(/</, "<").
            replace(/>/, ">").replace(/"/, """); // "
          log.innerHTML = escaped + "
    "
    + log.innerHTML; }
    script> head><body onload="init();"> <form onsubmit="onSubmit(); return false;"> <input type="text" id="input"> <input type="submit" value="Send"> <button onclick="onCloseClick(); return false;">closebutton> form> <div id="log">div> body>html>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77

    4. 启动应用进行测试

    启动SpringBoot应用后,浏览器中输入地址进行测试:http://localhost:2001

  • 相关阅读:
    基于Java毕业设计中药分类管理系统源码+系统+mysql+lw文档+部署软件
    简单介绍API分类接口
    C++DAY40
    设计模式(七)桥接
    ubuntu常用命令
    My Ninety-eighth Page - 不同子序列 - By Nicolas
    【华为OD机试真题 python】最长连续子序列 【2022 Q4 | 100分】
    C语言中realloc函数解析
    【Web】Ctfshow Nodejs刷题记录
    引用类型详解
  • 原文地址:https://blog.csdn.net/yuanjinshenglife/article/details/136267435