Springboot集成WebSocket+Thymeleaf+Echarts完成数据的实时推送

完成效果图:

项目准备提要:

<!-- 分页插件 -->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.2.5</version>
</dependency>
<!-- 热加载 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <optional>true</optional>
</dependency>
<!-- commons-lang3 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
</dependency>
<!-- google.guava -->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>28.0-jre</version>
</dependency>
<!-- thymeleaf模板 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- websocket -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

WebSocket配置

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

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

}
package com.lazyknow.websocket;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.CopyOnWriteArraySet;

import javax.annotation.PostConstruct;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.lazyknow.entity.user.User;
import com.lazyknow.service.user.UserService;
import com.lazyknow.vo.UserVo;

@ServerEndpoint(value = "/socket/{cmd}/{id}")
@Component
public class WebSocketHandler {

    public static Logger logger = LoggerFactory.getLogger(WebSocketHandler.class);
    
    //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
    private static CopyOnWriteArraySet<WebSocketHandler> webSocketSet = new CopyOnWriteArraySet<WebSocketHandler>();
    private String uid = "";
    private Session session;
    // 用于查询用户信息
    @Autowired
    private UserService userService;
    private static UserService userServiceMapper;

    @PostConstruct
    public void init(){
        WebSocketHandler.userServiceMapper = this.userService;
    }

    /**
     * 开启WebSocket请求
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("cmd") String cmd,@PathParam("id") String id) throws Exception {
        this.session = session;
        webSocketSet.add(this);
        uid = id;
        // 可以根据不同类型在选择执行的SQL
        if("user".equals(cmd)) {
        	List<String> skirt = Lists.newArrayList();
        	List<Integer> nums = Lists.newArrayList();
        	// 查询前10页数据
            for (int i = 0; i < 10; i++) {
            	PageInfo<User> user = userServiceMapper.findUserInfo(i, 20);
            	List<User> list = user.getList();
            	for (User info : list) {
            		skirt.add(info.getId()+"");
            		nums.add(info.getAge());
            		UserVo vo = new UserVo();
                	vo.setSkirt(skirt);
                	vo.setNumber(nums);
                	Thread.sleep(300);
                    this.sendMessage(JSON.toJSONString(vo));
				}
    		}
        }else {
        	this.onClose();
        }
    }
    
    @OnMessage
    public void onMessage(String message, Session session) throws IOException {
    	logger.info("参数信息:{},uid:{}",message,uid);
        //群发消息
        for (WebSocketHandler item : webSocketSet) {
            try {
            	item.sendMessage(JSON.toJSONString(message));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    	
    }

    @OnClose
    public void onClose(){
    	webSocketSet.remove(this);
        if (session != null){
            try {
                session.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    /**
     * 自定义消息推送、可群发、单发
     * */
    public static void sendInfo(String message,@PathParam("id") String id) throws IOException {
    	logger.info("推送消息到前端:{},推送信息:{}",id,message);
        for (WebSocketHandler item : webSocketSet) {
            try {
            	//这里可以设定只推送给这个id的,为null则全部推送
            	if(id==null) {
            		item.sendMessage(message);
            	}else if(item.uid.equals(id)){
            		item.sendMessage(message);
            	}
            } catch (IOException e) {
                continue;
            }
        }
    }


    @OnError
    public void onError(Session session, Throwable error) {
    	logger.error("连接异常!");
        error.printStackTrace();
    }
    
    // 发送信息
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }
    

}

前端页面

<!DOCTYPE HTML>
<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">
<head>
    <title>页面展示</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<link rel="stylesheet" type="text/css" href="/static/css/bootstrap.min.css">
<script src="/static/js/jquery-3.2.1.js"></script>
<script src="/static/js/echarts.min.js"></script>
<script type="text/javascript">
 	var userID="888";
	var websocket=null;

	$(function(){
	    connectWebSocket();
	})

	//建立WebSocket连接
	function connectWebSocket(){
	
	    console.log("开始...");
	
	    //建立webSocket连接
	    websocket = new WebSocket("ws://127.0.0.1:8888/socket/user/id="+userID);
	
	    //打开webSokcet连接时,回调该函数
	    websocket.onopen = function (data) {
	        console.info("onpen=>",data);
	    }
	
	    //关闭webSocket连接时,回调该函数
	    /* websocket.onclose = function () {
	        //关闭连接
	        console.log("onclose");
	    } */
	
	    //接收信息
	    websocket.onmessage = function (event) {
	        console.info("info==>",event.data);
	        var val = JSON.parse(event.data);
	        console.info("json-info==>",val);
	        
	        var skirt=val.skirt;
	        var nums=val.number;
	        var dom = document.getElementById("chartColumn");
	        var myChart = echarts.init(dom);
	        var option = null;
	        option = {
	        	title: {
	                   text: '股票基金走势图'
	            },
	            tooltip: {},
	            xAxis: {
	                type: 'category',
	                data: skirt,
	                axisLabel: {
	                    color: "#333"
	                }
	            },
	            yAxis: {
	                type: 'value',
	                axisLabel: {
	                    color: "#333"
	                }

	            },
	            series: [{
	                //data: [100, 932, 901, 934, 1290, 1330, 1320],
	                data: nums,
	                type: 'line',
	                smooth: true
	            }]
	        };
	        ;
	        if (option && typeof option === "object") {
	            myChart.setOption(option, true);
	        }
	    }
	
	}
	//发送消息
	function send(){
	    var postValue={};
	    postValue.id=userID;
	    postValue.cmd="测试信息";
	    websocket.send(JSON.stringify(postValue));
	}
	//关闭连接
	function closeWebSocket(){
	    if(websocket != null) {
	        websocket.close();
	    }
	}
</script>

<body>
	<!-- 为 ECharts 准备一个具备大小(宽高)的 DOM -->
    <div id="chartColumn" style="width: 1500px;height:530px;margin: auto;margin-top:50px; border: 1px solid #ddd;"></div>
</body>
</html>

还有一些Springboot和thymeleaf的常规配置,这里就不全部写下了。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值