SpringBoot+webSocket+echarts K线图(自动更新)

1、前端html代码

<!--
    THIS EXAMPLE WAS DOWNLOADED FROM https://echarts.apache.org/examples/zh/editor.html?c=candlestick-sh
-->
<!DOCTYPE html>
<html style="height: 100%">
    <head>
        <meta charset="utf-8">
        <script src="https://cdn.bootcss.com/sockjs-client/1.1.4/sockjs.min.js"></script>
        <script src="https://cdn.bootcss.com/stomp.js/2.3.3/stomp.min.js"></script>

        <style type="text/css">
            .tabs {
                text-align: center;
                height: 20%;
                padding-top: 15px;
            }

            .tabs li {
                display: inline-block;
                padding: 0 0 10px 0;
            }
            a {
                text-decoration: none;
                color: #1c84c6;
            }
            .tabs li a {
                display: block;
                min-width: 70px;
                padding: 6px 12px;
                background-color: #f5f5f5;
                color: #333;
                line-height: 1.42857143;
                text-align: center;
                border: 1px solid #ddd;
                border-radius: 2px;
            }
            .tabs li.active a {
                background-color: #1c84c6;
                border-color: #1c84c6;
                color: #fff;
            }
        </style>
    </head>
    <body style="height: 100%; margin: 0">
        <div class="tabs" style="display: block;">
            <ul>
                <li onclick="changeCond(1)" value="1"><a href="javascript:;">分时</a></li>
                <li onclick="changeCond(2)" value="2"><a href="javascript:;">日K</a></li>
                <li onclick="changeCond(3)" value="3"><a href="javascript:;">周K</a></li>
                <li onclick="changeCond(4)" value="4"><a href="javascript:;">月K</a></li>
            </ul>
        </div>


        <div id="container" style="height: 80%"></div>
        <div id="container_week" style="height: 80%;display: none"></div>

        <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts-nightly@5.1.2-dev.20210512/dist/echarts.min.js"></script>
        <script src="js/jquery-2.1.1.js"></script>
        <script src="js/candlestick-sh.js"></script>

    </body>
</html>
    

2、js代码

/**
 * Created by 42 on 2021/6/3.
 */
var dom = document.getElementById("container");
var myChart = echarts.init(dom);
var app = {};
var option;
var upColor = '#ec0000';
var upBorderColor = '#8A0000';
var downColor = '#00da3c';
var downBorderColor = '#008F28';
var type = 2;
//建立socket链接
var socket = new SockJS('http://17.18.41.189:8080/ws');
stompClient = Stomp.over(socket);
//stompClient.heartbeat.outgoing = 20000; //若使用STOMP 1.1 版本,默认开启了心跳检测机制(默认值都是10000ms)
stompClient.connect({}, onConnected, onError);

function onConnected() {
    stompClient.subscribe('/topic/public', onMessageReceived);
}

function onMessageReceived(payload) {

    var message = JSON.parse(payload.body);
    if(message.type === 'ECHARTS' && message.map) {
        message.candlestickDatas = message.map[type];

       if(message.candlestickDatas){
           var candlestickDatas  = message.candlestickDatas[0];
           var dateStr =candlestickDatas.splice(0, 1);
           console.log(candlestickDatas+"   "+dateStr)
            var flag =false;

           console.log(data0.categoryData[data0.categoryData.length-1]+" --  ")
           console.log(dateStr[0]+" ##  "+(data0.categoryData[data0.categoryData.length-1] == dateStr[0]))
           if(data0.categoryData[data0.categoryData.length-1]==dateStr[0]){

               data0.values[data0.categoryData.length-1]=candlestickDatas;
               flag =true;

           }
            if(!flag){
                data0.categoryData.push(dateStr[0]);
                data0.values.push(candlestickDatas);
            }

           myChart.setOption(option);
       }
    }

}

function onError(error) {
    var log = 'Could not connect to WebSocket server. Please refresh this page to try again!';
    console.log(log)
}

// 数据意义:开盘(open),收盘(close),最低(lowest),最高(highest)

var data0 = null;//splitData(rowData);
function splitData(rawData) {
    var categoryData = [];
    var values = []
    for (var i = 0; i < rawData.length; i++) {
        categoryData.push(rawData[i].splice(0, 1)[0]);
        values.push(rawData[i])
    }
    return {
        categoryData: categoryData,
        values: values
    };
}

function calculateMA(dayCount) {
    var result = [];
    for (var i = 0, len = data0.values.length; i < len; i++) {
        if (i < dayCount) {
            result.push('-');
            continue;
        }
        var sum = 0;
        for (var j = 0; j < dayCount; j++) {
            sum += data0.values[i - j][1];
        }
        result.push(sum / dayCount);
    }
    return result;
}


if (option && typeof option === 'object') {
    myChart.setOption(option);
}

changeCond(2);

function getSeriesName(type) {
    if(type == 1){
        return "分时";
    }else if(type == 2){
        return "日K";
    }else if(type == 3){
        return "周K";
    }else if(type == 4){
        return "月K";
    }
}
function changeCond(param) {
    type=param;
    // 1. 定义url
    var url = "http://192.168.41.189:18801/getEchartsDatas?type="+param;
    // 2. 请求参数
    // 3. 发送异步请求, 处理响应结果
    // 向服务器发送Get请求
    $.get(url, function(result) { // 用于处理结果

        console.log("result:  "+result);
        data0 = splitData(result);
        option = {
            title: {
                text: '上证指数',
                left: 0
            },
            tooltip: {
                trigger: 'axis',
                axisPointer: {
                    type: 'cross'
                }
            },
            legend: {
                data: [getSeriesName(param), 'MA5', 'MA10', 'MA20', 'MA30']
            },
            grid: {
                left: '10%',
                right: '10%',
                bottom: '15%'
            },
            xAxis: {
                type: 'category',
                data: data0.categoryData,
                scale: true,
                boundaryGap: false,
                axisLine: {onZero: false},
                splitLine: {show: false},
                splitNumber: 20,
                min: 'dataMin',
                max: 'dataMax'
            },
            yAxis: {
                scale: true,
                splitArea: {
                    show: true
                }
            },
            dataZoom: [
                {
                    type: 'inside',
                    start: 50,
                    end: 100
                },
                {
                    show: true,
                    type: 'slider',
                    top: '90%',
                    start: 50,
                    end: 100
                }
            ],
            series: [
                {
                    name: getSeriesName(param),
                    type: 'candlestick',
                    data: data0.values,
                    itemStyle: {
                        color: upColor,
                        color0: downColor,
                        borderColor: upBorderColor,
                        borderColor0: downBorderColor
                    },
                    markPoint: {
                        label: {
                            normal: {
                                formatter: function (param) {
                                    return param != null ? Math.round(param.value) : '';
                                }
                            }
                        },
                        data: [
                            {
                                name: 'XX标点',
                                coord: ['2013/5/31', 2300],
                                value: 2300,
                                itemStyle: {
                                    color: 'rgb(41,60,85)'
                                }
                            },
                            {
                                name: 'highest value',
                                type: 'max',
                                valueDim: 'highest'
                            },
                            {
                                name: 'lowest value',
                                type: 'min',
                                valueDim: 'lowest'
                            },
                            {
                                name: 'average value on close',
                                type: 'average',
                                valueDim: 'close'
                            }
                        ],
                        tooltip: {
                            formatter: function (param) {
                                return param.name + '<br>' + (param.data.coord || '');
                            }
                        }
                    },
                    markLine: {
                        symbol: ['none', 'none'],
                        data: [
                            [
                                {
                                    name: 'from lowest to highest',
                                    type: 'min',
                                    valueDim: 'lowest',
                                    symbol: 'circle',
                                    symbolSize: 10,
                                    label: {
                                        show: false
                                    },
                                    emphasis: {
                                        label: {
                                            show: false
                                        }
                                    }
                                },
                                {
                                    type: 'max',
                                    valueDim: 'highest',
                                    symbol: 'circle',
                                    symbolSize: 10,
                                    label: {
                                        show: false
                                    },
                                    emphasis: {
                                        label: {
                                            show: false
                                        }
                                    }
                                }
                            ],
                            {
                                name: 'min line on close',
                                type: 'min',
                                valueDim: 'close'
                            },
                            {
                                name: 'max line on close',
                                type: 'max',
                                valueDim: 'close'
                            }
                        ]
                    }
                },
                {
                    name: 'MA5',
                    type: 'line',
                    data: calculateMA(5),
                    smooth: true,
                    lineStyle: {
                        opacity: 0.5
                    }
                },
                {
                    name: 'MA10',
                    type: 'line',
                    data: calculateMA(10),
                    smooth: true,
                    lineStyle: {
                        opacity: 0.5
                    }
                },
                {
                    name: 'MA20',
                    type: 'line',
                    data: calculateMA(20),
                    smooth: true,
                    lineStyle: {
                        opacity: 0.5
                    }
                },
                {
                    name: 'MA30',
                    type: 'line',
                    data: calculateMA(30),
                    smooth: true,
                    lineStyle: {
                        opacity: 0.5
                    }
                },

            ]
        };
        myChart.setOption(option);
    }, "json");

}

3、java代码

@Scheduled(fixedRate = 10000)
public void sendQueueMessage() {
    System.out.println("定时广播推送!");
    ChatMessage chatMessage =new ChatMessage();
    chatMessage.setType(ChatMessage.MessageType.ECHARTS);
    chatMessage.setMap(this.getMap());
    //chatService.sendToUser(chatMessage);
    redisTemplate.convertAndSend(msgToAll, JsonUtil.parseObjToJson(chatMessage));
}


private Map<String,Object> getMap(){
    Map<String,Object> map= new HashMap<>();
    map.put("1",getData(500,DateUtil.getCurrentDateStr()));
    map.put("2",getData(20000,DateUtil.getCurrentDateStr()));
    map.put("3",getData(50000,DateUtil.getFriday()));
    map.put("4",getData(80000,DateUtil.getMonthFirstDay()));
    return map;
}

private List<Object> getData(int val,String date){
    List<Object> list = new ArrayList<>();
    list.add(date);
    list.add(getRandom(val));
    list.add(getRandom(val));
    list.add(getRandom(val));
    list.add(getRandom(val));
    List<Object> candlestickDatas = new ArrayList<>();
    candlestickDatas.add(list);
    return candlestickDatas;
}



private float getRandom(int val){
    int random=(int) (Math.random()*9000+1000);
    
    return (float)(val+random)/10;
}
@RequestMapping("/getEchartsDatas")
@ResponseBody
public String getEchartsDatas(int type) throws ParseException {
   String data=null;
   String nowDate = DateUtil.getCurrentDateStr();
   String startDate ="2020-01-01";
    if(type == 1){
    }else if(type ==2){
        data = buildData(DateUtil.getDateList(startDate,nowDate),10000);
    }else if(type ==3){
        data = buildData(DateUtil.getWeekDate("01/01/2020",DateUtil.DateToString(new Date(),DateUtil.DATE_FORMAT)),50000);
    }else if(type ==4){
        data = buildData(DateUtil.getMonthList(startDate,nowDate),80000);
    }
    return data;
}

private String buildData(List<String> dateList,int val){
    List<Object> l = null;
    List<Object> list = new ArrayList<>();
    for(String date:dateList ){
        l = new ArrayList<>();
        l.add(date);
        l.add(getRandom(val));
        l.add(getRandom(val));
        l.add(getRandom(val));
        l.add(getRandom(val));
        list.add(l);
    }
    return JSON.toJSONString(list);
}

 

 

demo链接地址:https://download.csdn.net/download/paj123456789/19405016

K线图:http://127.0.0.1:8080/candlestick-sh.html

群发和点对点发送地址:http://127.0.0.1:8080/index.html

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
为了实现Spring Boot应用程序中的自动刷新,可以使用WebSocket协议。WebSocket协议是一种在Web浏览器和服务器之间进行双向通信的协议。在Spring Boot中,可以使用Spring WebSocket模块来实现WebSocket功能。下面是一个简单的示例,演示如何使用Spring Boot和WebSocket实现自动刷新: 1.添加依赖 在pom.xml文件中添加以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> ``` 2.创建WebSocket配置类 创建一个WebSocket配置类,用于配置WebSocket相关的参数。在这个类中,我们需要实现WebSocketMessageBrokerConfigurer接口,并重写configureMessageBroker()和registerStompEndpoints()方法。 ```java @Configuration @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(MessageBrokerRegistry config) { config.enableSimpleBroker("/topic"); config.setApplicationDestinationPrefixes("/app"); } @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/ws").withSockJS(); } } ``` 3.创建WebSocket控制器 创建一个WebSocket控制器,用于处理WebSocket请求。在这个控制器中,我们需要使用@MessageMapping注解来处理客户端发送的消息,并使用@SendTo注解将处理结果发送给所有订阅了“/topic/greetings”主题的客户端。 ```java @Controller public class GreetingController { @MessageMapping("/hello") @SendTo("/topic/greetings") public Greeting greeting(HelloMessage message) throws Exception { Thread.sleep(1000); // simulated delay return new Greeting("Hello, " + message.getName() + "!"); } } ``` 4.创建HTML页面 创建一个HTML页面,用于测试WebSocket功能。在这个页面中,我们需要使用JavaScript代码来创建WebSocket连接,并使用STOMP协议来发送和接收消息。 ```html <!DOCTYPE html> <html> <head> <title>Hello WebSocket</title> <script src="https://cdn.jsdelivr.net/sockjs/1.1.4/sockjs.min.js"></script> <script src="https://cdn.jsdelivr.net/stomp.js/2.3.3/stomp.min.js"></script> <script> var stompClient = null; function connect() { var socket = new SockJS('/ws'); stompClient = Stomp.over(socket); stompClient.connect({}, function(frame) { console.log('Connected: ' + frame); stompClient.subscribe('/topic/greetings', function(greeting) { showGreeting(JSON.parse(greeting.body).content); }); }); } function disconnect() { if (stompClient !== null) { stompClient.disconnect(); } console.log("Disconnected"); } function sendName() { var name = document.getElementById('name').value; stompClient.send("/app/hello", {}, JSON.stringify({ 'name': name })); } function showGreeting(message) { document.getElementById('greetings').innerHTML += "<tr><td>" + message + "</td></tr>"; } </script> </head> <body> <div> <label for="name">Name:</label> <input type="text" id="name" /> <button onclick="sendName()">Send</button> <button onclick="disconnect()">Disconnect</button> </div> <table> <thead> <tr> <th>Greetings</th> </tr> </thead> <tbody id="greetings"> </tbody> </table> <script> connect(); </script> </body> </html> ``` 5.运行应用程序 运行Spring Boot应用程序,并在浏览器中打开HTML页面。在页面中输入名称并单击“Send”按钮,应该会看到一个新的问候语出现在页面上。如果您更改了控制器中的问候语消息,页面上的问候语也会相应更改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值