英特尔i5 67i5 7300hq gtx1050ti12g内存 gtx960显卡 玩吃鸡第特效可以吗

4288人阅读
tomcat相关(4)
spring(4)
1.场景需求
后台攻城狮和前端攻城狮一起开发时,经常受到前端攻城狮的骚扰,动不动就来一句,那谁,帮我看一下接口访问出什么错了。。。我刚刚上传的参数过来了吗。。。你返回的是什么。。。我请求过去了吗。。。
好吧,就是这样的一种情况,然后我希望让他们自己去看后台日志,而又不想给他们登陆服务器的权限TAT。那就想办法把访问日志实时输出到web页面,这样他们打开页面就可以了。
2.特别鸣谢
1)特别感谢的启发,该文章中利用的是linux中的tail日志,本文即是受此启发,基本思路一模一样,感谢感谢。
2)感谢国产博客中各种websocket教程,获益颇多,本文其实也是一个websocket教程,只是稍作拓展。
3.进入正题
配置websocket,大部分web项目都会用到spring框架吧,所有这里贴spring websocket的配置,不用spring的请自行去掉spring部分。spring使用4.0以上,tomcat使用7.0.68版本。
1)pom.xml中包的引入:
&com.fasterxml.jackson.core&
&jackson-annotations&
&com.fasterxml.jackson.core&
&jackson-core&
&com.fasterxml.jackson.core&
&jackson-databind&
&org.springframework&
&spring-messaging&
&4.0.5.RELEASE&
&org.springframework&
&spring-websocket&
&4.0.5.RELEASE&
&org.springframework&
&spring-webmvc&
&4.0.5.RELEASE&
&com.google.code.gson&
&javax.servlet&
&javax.servlet-api&
&provided&
2)websocket逻辑代码,需要一个config和一个handle
configuration:
package com.he.
import org.springframework.context.annotation.B
import org.springframework.context.annotation.C
import org.springframework.web.socket.config.annotation.EnableWebS
import org.springframework.web.socket.config.annotation.WebSocketC
import org.springframework.web.socket.config.annotation.WebSocketHandlerR
import org.springframework.web.socket.server.support.HttpSessionHandshakeI
* WebScoket配置处理器
* 日 下午1:15:09
@Configuration
@EnableWebSocket
public class WebsocketConfig implements WebSocketConfigurer {
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(myHandler(), "/ws").addInterceptors(new HttpSessionHandshakeInterceptor());
registry.addHandler(myHandler(), "/ws/sockjs").addInterceptors(new HttpSessionHandshakeInterceptor()).withSockJS();
public WebsocketHandler myHandler() {
return new WebsocketHandler();
package com.he.
import java.io.IOE
import java.util.D
import java.util.HashM
import java.util.I
import java.util.M
import java.util.Map.E
import org.apache.log4j.L
import org.
import org.springframework.web.socket.CloseS
import org.springframework.web.socket.TextM
import org.springframework.web.socket.WebSocketM
import org.springframework.web.socket.WebSocketS
import org.springframework.web.socket.handler.TextWebSocketH
import com.google.gson.G
import com.google.gson.GsonB
import com.he.entity.M
@Component
public class WebsocketHandler extends TextWebSocketHandler {
protected static final Logger LOG = Logger.getLogger(WebsocketHandler.class);
public static final Map&Object, WebSocketSession& userSocketSessionM
userSocketSessionMap = new HashMap&Object, WebSocketSession&();
* 建立连接后
public void afterConnectionEstablished(WebSocketSession session)
throws Exception {
String uid = (String) session.getAttributes().get("uid");
if (userSocketSessionMap.get(uid) == null) {
userSocketSessionMap.put(uid, session);
LOG.warn("======建立连接完成======");
* 消息处理,在客户端通过Websocket API发送的消息会经过这里,然后进行相应的处理
public void handleMessage(WebSocketSession session, WebSocketMessage&?& message) throws Exception {
if(message.getPayloadLength()==0)return;
Message msg=new Gson().fromJson(message.getPayload().toString(),Message.class);
String msgString = message.getPayload().toString();
LOG.warn("收到的消息是:" + msgString);
LOG.warn("发送的对象是:" + msg.getTo());
msg.setDate(new Date());
sendMessageToUser(msg.getTo(), new TextMessage(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(msg)));
LOG.warn("======消息处理结束======");
* 消息传输错误处理
public void handleTransportError(WebSocketSession session,
Throwable exception) throws Exception {
if (session.isOpen()) {
session.close();
Iterator&Entry&Object, WebSocketSession&& it = userSocketSessionMap
.entrySet().iterator();
LOG.warn("======消息传输错误======");
while (it.hasNext()) {
Entry&Object, WebSocketSession& entry = it.next();
if (entry.getValue().getId().equals(session.getId())) {
userSocketSessionMap.remove(entry.getKey());
System.out.println("Socket会话已经移除:用户ID" + entry.getKey());
* 关闭连接后
public void afterConnectionClosed(WebSocketSession session,
CloseStatus closeStatus) throws Exception {
LOG.warn("Websocket:" + session.getId() + "已经关闭");
Iterator&Entry&Object, WebSocketSession&& it = userSocketSessionMap
.entrySet().iterator();
LOG.warn("======关闭连接======");
while (it.hasNext()) {
Entry&Object, WebSocketSession& entry = it.next();
if (entry.getValue().getId().equals(session.getId())) {
userSocketSessionMap.remove(entry.getKey());
LOG.warn("Socket会话已经移除:用户ID" + entry.getKey());
public boolean supportsPartialMessages() {
return false;
* 给所有在线用户发送消息
* IOException
public void broadcast(final TextMessage message) throws IOException {
Iterator&Entry&Object, WebSocketSession&& it = userSocketSessionMap
.entrySet().iterator();
LOG.warn("======群发======");
while (it.hasNext()) {
final Entry&Object, WebSocketSession& entry = it.next();
if (entry.getValue().isOpen()) {
new Thread(new Runnable() {
public void run() {
if (entry.getValue().isOpen()) {
entry.getValue().sendMessage(message);
} catch (IOException e) {
e.printStackTrace();
}).start();
* 给某个用户发送消息
* userName
* IOException
public void sendMessageToUser(String uid, TextMessage message)
throws IOException {
WebSocketSession session = userSocketSessionMap.get(uid);
LOG.warn("======给某个用户发送消息======");
if (session != null && session.isOpen()) {
session.sendMessage(message);
3)web.xml中配置spring和springMVC,因为借助与springMVC来拦截处理websocket请求,如果用其他MVC框架,请自行替换。不想换也可以用springMVC,侵入性很低,并且本来就可以多种MVC共存。
&context-param&
&param-name&contextConfigLocation&/param-name&
&param-value&
/WEB-INF/classes/applicationContext.xml
&/param-value&
&/context-param&
&servlet-name&SpringMVC&/servlet-name&
&servlet-class&org.springframework.web.servlet.DispatcherServlet&/servlet-class&
&init-param&
&param-name&contextConfigLocation&/param-name&
&param-value&/WEB-INF/classes/applicationContext.xml&/param-value&
&/init-param&
&load-on-startup&1&/load-on-startup&
&/servlet&
&servlet-mapping&
&servlet-name&SpringMVC&/servlet-name&
&url-pattern&*.do&/url-pattern&
&/servlet-mapping&
注意web.xml的头部:
&?xml version="1.0" encoding="UTF-8"?&
version="3.0" xmlns="/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="/xml/ns/javaee
/xml/ns/javaee/web-app_3_0.xsd"&
4)spring的xml文件中对websocket的配置:
id="websocket" class="com.he.websocket.WebsocketHandler" /&
path="/ws.do" handler="websocket" /&
class="org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor" /&
base-package="com.he.websocket.WebsocketConfig" /&
base-package="com.he.websocket.WebsocketHandler" /&
注意spring的xml的头部:
&?xml version="1.0" encoding="UTF-8"?&
xmlns="http://www.springframework.org/schema/beans"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/websocket
http://www.springframework.org/schema/websocket/spring-websocket.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
5)日志接收页面:
&!DOCTYPE html&
charset="utf-8"&
&tail log&
src="///jquery/2.1.4/jquery.js"&&
height:100%;
width:100%;
id="log-container" style="height: 100%; overflow-y: background: #333; color: # padding: 10"&
$(document).ready(function() {
var websocket = new WebSocket('ws://localhost:8080/websocket/ws.do');
websocket.onmessage = function(event) {
$("#log-container div").append(event.data + "&p& &/p&");
$("#log-container").scrollTop($("#log-container div").height() - $("#log-container").height());
此页面打开时发送了一个websocket请求,ws.do,会被springMVC拦截处理。连接建立之后每当收到新的消息会追加到当前文本的末尾并换行(p标签用来换行)。
6)控制日志的实时打印示例:
PrintWriter out = response.getWriter()
MyWebSocketHandler.broadcast(new TextMessage(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson("访问test接口")))
out.println("访问test接口")
每次返回给前端某些值的时候通过一个广播将该值传送到web页面。如果不想广播,只需要在程序中对log的session进行特别的标签,然后定向传送即可。
效果示意图:浏览器输入localhost:8080/projectName/log.html,然后访问localhost:8080/projectName/test,每次访问test接口,网页上实时显示tomcat输出的日志。
需要完整代码留邮箱,看到就发送,发送的工程是一个基本的web工程,只集成spring websocket,本文的所有效果和引用都有。或者发邮件到提醒我。
本例中为方便消息的处理用到如下两个实体类(我也是沿用了别人教程代码):
Message.java:
public class Message {
public Long from;
public String fromN
public Long getFrom() {
return from;
public void setFrom(Long from) {
this.from = from;
public Long getTo() {
public void setTo(Long to) {
public String getText() {
public void setText(String text) {
this.text =
public String getFromName() {
return fromN
public void setFromName(String fromName) {
this.fromName = fromN
public Date getDate() {
public void setDate(Date date) {
this.date =
user.java:
public class User {
public Long getId() {
public void setId(Long id) {
public String getName() {
public void setName(String name) {
this.name =
public String getPassword() {
public void setPassword(String password) {
this.password =
应大家需求,完成工程的代码放在了github上面啦!传上去的代码进一步完善了一下,把建立连接的时候上传参数的问题处理了一下;把存放session的容器换成了线程安全型的!欢迎大家在线讨论!
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:18698次
排名:千里之外
原创:13篇
评论:107条
(3)(3)(4)(3)(1)基于WebSocket的实时动态图表 - 推酷
基于WebSocket的实时动态图表
本文介绍一下基于WebSocket的实时数据双向通讯的小范畴应用,来实现实时动态图表的展示功能。其实实现图表动态更新又岂止是只有这一种方法。用户页面端的js心跳轮询一样可以获取来自后台的最新数据,只是我感觉那是伪实时。
首先介绍一下什么是WebSocket?
WebSocket是HTML5开始提供的一种在单个TCP 连接上进行全双工通讯的协议。 WebSocket通讯协议定于2011年被IETF定为标准RFC 6455,WebSocketAPI被W3C定为标准。 在WebSocket API中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。 两者之间就直接可以数据互相传送。或者看一下来自国内知乎上的解释:
项目需求:
其实标题说的很清晰了,就是要实现图标的实时动态更新,当时我的第一感觉就是要采用WebSocket去解决这个问题。而我的数据来源是来自MQ(消息队列),也就是触发数据推送就是在消息消费的地方。
关于STOMP:
这里需要提一下STOMP,这也是我在调研过程中,在Spring中发现的一个新协议。全称:Simple Text-Orientated Messaging Protocol. 协议官网:
。个人将它理解成为WebSocket协议的一个封装实现。当然Spring针对STOMP的实现做了很好的封装,官方文档的解释也是很全面的。
系统配置:
全系统采用JavaConfig模式配置。所以给出的配置方式均为class文件,有喜好xml配置方式的,可自行转换。
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.setApplicationDestinationPrefixes(&/app&); //接受请求前缀
registry.enableSimpleBroker(&/topic&);
//返回请求前缀
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint(&/getLoanPoints&).withSockJS();
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
public void configureMessageBroker(MessageBrokerRegistryregistry) {
registry.setApplicationDestinationPrefixes("/app"); //接受请求前缀
registry.enableSimpleBroker("/topic");
//返回请求前缀
public void registerStompEndpoints(StompEndpointRegistryregistry) {
registry.addEndpoint("/getLoanPoints").withSockJS();
WebSocket消息发送接口
WebSocket消息处理接口
public interface WebSocketCommonHandler&T& {
* WebSocket发送消息方法
* @param t
void send(T t);
public interface WebSocketCommonHandler&T& {
* WebSocket发送消息方法
* @param t
void send(T t);
WebSocket消息处理接口抽象类
public abstract class AbstractWebSocketCommonHandler
implements WebSocketCommonHandler
@Autowired
private SimpMessagingT
* 设置消息返回路由
public abstract String setTopic();
* WebSocket发送消息方法
* @param o
public void send(T o) {
String topic = setTopic();
if (StringUtils.isEmpty(topic) || o == null) {
throw new RuntimeException(&Topic is Empty or Object is null!&);
this.template.convertAndSend(topic, o);
public abstract class AbstractWebSocketCommonHandler&T& implements WebSocketCommonHandler&T& {
@Autowired
private SimpMessagingT
* 设置消息返回路由
public abstract String setTopic();
* WebSocket发送消息方法
* @param o
public void send(T o) {
String topic = setTopic();
if (StringUtils.isEmpty(topic) || o == null) {
throw new RuntimeException("Topic is Empty or Object is null!");
this.template.convertAndSend(topic, o);
WebSocket消息发送实现类
WebSocket消息处理实现类
@Component
public class DemoWebSocketHandler extends AbstractWebSocketCommonHandler&DataVo& {
* 设置消息返回路由
public String setTopic() {
return &/topic/addLoanPoint&;
@Component
public class DemoWebSocketHandler extends AbstractWebSocketCommonHandler&DataVo& {
* 设置消息返回路由
public String setTopic() {
return "/topic/addLoanPoint";
消息处理及WebSocket数据推送
消息消费监听器及WebSocket数据推送
public class DemoMessageListener implements MessageListener {
private static final Logger LOGGER = LoggerFactory.getLogger(RepayMessageListener.class);
@Autowired
private DemoWebSocketHandler demoWebSocketH
public void onMessage(List&Message& list) throws Exception {
for (Message message : list) {
(&还款消息体是:& + message.getText());
Gson gson = new Gson();
Demo demo = gson.fromJson(message.getText(), Demo.class);
DataVo dataVo = new DataVo();
dataVo.setType(2);
dataVo.setDate(demo.getTime());
dataVo.setValue(demo.getValue());
dataVo.setName(demo.getName());
demoWebSocketHandler.send(dataVo);
public class DemoMessageListener implements MessageListener {
private static final LoggerLOGGER = LoggerFactory.getLogger(RepayMessageListener.class);
@Autowired
private DemoWebSocketHandlerdemoWebSocketH
public void onMessage(List&Message& list) throws Exception {
for (Messagemessage : list) {
("还款消息体是:" + message.getText());
Gsongson = new Gson();
Demodemo = gson.fromJson(message.getText(), Demo.class);
DataVodataVo = new DataVo();
dataVo.setType(2);
dataVo.setDate(demo.getTime());
dataVo.setValue(demo.getValue());
dataVo.setName(demo.getName());
demoWebSocketHandler.send(dataVo);
到此为止,这都是后台系统的一些相关实现,而对于上面的消息消费这款,不同的消息中间件,实现方式可能会有所不同,但我们此处大体思路无非是,接收消息,将消息Json转对象,然后做相应处理,再把响应数据交由Handler的send方法发送到对应的路由地址。
接下来是前端的一些,连接服务器及监听路由地址的方法实现,我开始已经提到,我用了STOMP去实现了前端的WebSocket管理,所以前段用的的js库有两个:socketjs-1.0.3.js和stomp.js,具体下载地址Google一下就可以拿到了。
首先封装一个WebSocket工具js
WebSocket工具js
JavaScript
var websocket = (function () {
var stompClient =
* 创建WebSocket链接
* @param url
* @param databackurl
* @param callback
var createConnectFunc = function connect(url, databackurl, callback) {
var socket = new SockJS(url);
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
console.log('Connected: ' + frame);
stompClient.subscribe(databackurl, function (response) {
if (typeof callback === &function&) {
callback(response);
console.log(&Not Function!&);
* 断开WebSocket链接
var disconnectFunc = function disconnect() {
if (stompClient != null) {
stompClient.disconnect();
console.log(&WebSocket has Disconnected!&);
* 发送数据到服务端
* @param url
* @param data
var sendDataFunc = function sendDate(url, data) {
stompClient.send(&/app& + url, {}, JSON.stringify(data));
* 判断是否已经链接
* @returns {boolean}
var hasConnectedFunc = function hasConnected(){
if (stompClient != null) {
createConnect: createConnectFunc,
sendData: sendDataFunc,
disconnect: disconnectFunc,
hasConnected: hasConnectedFunc
var websocket = (function () {
var stompClient =
* 创建WebSocket链接
* @param url
* @param databackurl
* @param callback
var createConnectFunc = function connect(url, databackurl, callback) {
var socket = new SockJS(url);
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
console.log('Connected: ' + frame);
stompClient.subscribe(databackurl, function (response) {
if (typeof callback === "function") {
callback(response);
console.log("Not Function!");
* 断开WebSocket链接
var disconnectFunc = function disconnect() {
if (stompClient != null) {
stompClient.disconnect();
console.log("WebSocket has Disconnected!");
* 发送数据到服务端
* @param url
* @param data
var sendDataFunc = function sendDate(url, data) {
stompClient.send("/app" + url, {}, JSON.stringify(data));
* 判断是否已经链接
* @returns {boolean}
var hasConnectedFunc = function hasConnected(){
if (stompClient != null) {
createConnect: createConnectFunc,
sendData: sendDataFunc,
disconnect: disconnectFunc,
hasConnected: hasConnectedFunc
以及demo.js是针对页面的业务方法,比如下面是创建echarts的line图,已经接收处理路由数据
JavaScript
var demo = (function () { // 基于准备好的dom,初始化echarts实例 var myChart = echarts.init(document.getElementById('main'));
var loanDataValues = [];
var repayDataValues = [];
// 使用刚指定的配置项和数据显示图表。
var showChartFunc = function () {
myChart.setOption({
show: false,
text: '图表详情'
tooltip: {
trigger: 'item',
formatter: function (params) {
var date = new Date(params.value[0]);
data = date.getFullYear() + '-'
+ (date.getMonth() + 1) + '-'
+ date.getDate() + ' '
+ date.getHours() + ':'
+ date.getMinutes() + ':'
+ date.getSeconds();
return data + '&br/&'
+ '金额:' + params.value[1] + '&br/&'
+ '公司:' + params.value[2];
data: ['Demo1金额', 'Demo2金额']
toolbox: {
show: true,
feature: {
mark: {show: true},
dataView: {show: true, readOnly: false},
restore: {show: true},
saveAsImage: {show: true}
type: 'time',
splitNumber:10,
boundaryGap: ['20%', '20%'],
min: 'dataMin',
max: 'dataMax'
type: 'value',
scale: true,
name: '金额(元)',
boundaryGap: ['20%', '20%']
dataZoom: {
type: 'inside',
name: 'Demo1金额',
type: 'line',
smooth: true,
symbol: 'circle',
data: loanDataValues
name: 'Demo2金额',
type: 'line',
smooth: true,
symbol: 'rect',
data: repayDataValues
* 实时接受消息并绘制图标
* @param message
var addPointFunc = function addPoint(message) {
var dataVo = JSON.parse(message.body);
addData(dataVo);
showChartFunc();
function addData(dataVo) {
if (dataVo.type == 1) {
loanDataValues.push([dataVo.date, dataVo.value, dataVo.name]);
} else if (dataVo.type == 2) {
repayDataValues.push([dataVo.date, dataVo.value, dataVo.name]);
* WebSocket连接
var connectFunc = function connect() {
websocket.createConnect(&/getLoanPoints&, &/topic/addLoanPoint&, addPointFunc);
* 发送数据到服务器(暂时不用)
var sendValueFunc = function sendValue() {
var value = document.getElementById('name').
websocket.sendData(&/getLoanPoints&, value);
* 获取当日借贷信息
var getLoanFunc = function () {
$.getJSON('getLoanInfo').done(function (data) {
if (data.success) {
loanDataValues = data.loanInfos.
repayDataValues = data.repayInfos.
showChartFunc();
alert(data.message);
getLoan: getLoanFunc,
connect: connectFunc
var demo = (function () {
// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('main'));
var loanDataValues = [];
var repayDataValues = [];
// 使用刚指定的配置项和数据显示图表。
var showChartFunc = function () {
myChart.setOption({
show: false,
text: '图表详情'
tooltip: {
trigger: 'item',
formatter: function (params) {
var date = new Date(params.value[0]);
data = date.getFullYear() + '-'
+ (date.getMonth() + 1) + '-'
+ date.getDate() + ' '
+ date.getHours() + ':'
+ date.getMinutes() + ':'
+ date.getSeconds();
return data + '&br/&'
+ '金额:' + params.value[1] + '&br/&'
+ '公司:' + params.value[2];
data: ['Demo1金额', 'Demo2金额']
toolbox: {
show: true,
feature: {
mark: {show: true},
dataView: {show: true, readOnly: false},
restore: {show: true},
saveAsImage: {show: true}
type: 'time',
splitNumber:10,
boundaryGap: ['20%', '20%'],
min: 'dataMin',
max: 'dataMax'
type: 'value',
scale: true,
name: '金额(元)',
boundaryGap: ['20%', '20%']
dataZoom: {
type: 'inside',
name: 'Demo1金额',
type: 'line',
smooth: true,
symbol: 'circle',
data: loanDataValues
name: 'Demo2金额',
type: 'line',
smooth: true,
symbol: 'rect',
data: repayDataValues
* 实时接受消息并绘制图标
* @param message
var addPointFunc = function addPoint(message) {
var dataVo = JSON.parse(message.body);
addData(dataVo);
showChartFunc();
function addData(dataVo) {
if (dataVo.type == 1) {
loanDataValues.push([dataVo.date, dataVo.value, dataVo.name]);
} else if (dataVo.type == 2) {
repayDataValues.push([dataVo.date, dataVo.value, dataVo.name]);
* WebSocket连接
var connectFunc = function connect() {
websocket.createConnect("/getLoanPoints", "/topic/addLoanPoint", addPointFunc);
* 发送数据到服务器(暂时不用)
var sendValueFunc = function sendValue() {
var value = document.getElementById('name').
websocket.sendData("/getLoanPoints", value);
* 获取当日借贷信息
var getLoanFunc = function () {
$.getJSON('getLoanInfo').done(function (data) {
if (data.success) {
loanDataValues = data.loanInfos.
repayDataValues = data.repayInfos.
showChartFunc();
alert(data.message);
getLoan: getLoanFunc,
connect: connectFunc
而页面所需要做的就是在加载页面元素完毕之后,调用demo.connect(),去创建WebSocket链接,等待数据的推送,然后绘制图表。至此一个简单的实时动态图表的绘制就完成了,如有任何问题欢迎随时留言提问。O(∩_∩)O
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致}

我要回帖

更多关于 i5 6300hq gtx960m 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信