websocket介绍
WebSocket协议是一种双向通信协议,它建立在TCP之上,同http一样通过TCP来传输数据,但是它和http最大的不同有两点:1.WebSocket是一种双向通信协议,在建立连接后,WebSocket服务器和客户端都能主动的向对方发送或接收数据,就像Socket一样,不同的是WebSocket是一种建立在Web基础上的一种简单模拟Socket的协议;2.WebSocket需要通过握手连接,类似于TCP它也需要客户端和服务器端进行握手连接,连接成功后才能相互通信。
websocket的springboot实现
创建一个maven工程,pom中加入依赖
如果是运行在tomcat下,主要引入javaee-api,不过使用springboot的内置tomcat就不需要了
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
<version>1.3.5.RELEASE</version>
</dependency>
</dependencies>
配置端口和静态资源
创建application.properties文件,添加server端口和静态资源路径
server.port=8080
spring.resources.static-locations=classpath:/webapp/html/
websocket服务端的实现
首先是springboot的入口
package com.web;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
@EnableAutoConfiguration
@ComponentScan
public class Application
{
public static void main(String[] args)
{
SpringApplication.run(Application.class, args);
}
}
注入ServerEndpointExporter的bean
package com.web;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
websocket的具体实现
package com.web;
import java.io.IOException;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.springframework.stereotype.Component;
@ServerEndpoint("/websocket")
@Component
public class MyWebSocket {
@OnMessage
public void onMessage(String message, Session session)
throws IOException, InterruptedException {
// Print the client message for testing purposes
System.out.println("Received: " + message);
// Send the first message to the client
session.getBasicRemote().sendText("This is the first server message");
// Send 3 messages to the client every 5 seconds
int sentMessages = 0;
while(sentMessages < 3){
Thread.sleep(5000);
session.getBasicRemote().
sendText("This is an intermediate server message. Count: "
+ sentMessages);
sentMessages++;
}
// Send a final message to the client
session.getBasicRemote().sendText("This is the last server message");
}
@OnOpen
public void onOpen () {
System.out.println("Client connected");
}
@OnClose
public void onClose () {
System.out.println("Connection closed");
}
}
一个简单的demo,websocket一共有四种事件
- onopen websocket建立连接完成
- onclose websocket连接关闭
- onmessage websocket接收到数据,发送数据调用socket.send方法
- onerror websocket发生错误
websocket的客户端的实现
websocket两种实现方法,一种是sockjs,一种是HTML5,这里使用HTML5实现,创建一个index.html
<!DOCTYPE HTML>
<html>
<head>
<title>My WebSocket</title>
</head>
<body>
Welcome<br/>
<input id="text" type="text" /><button onclick="send()">Send</button> <button onclick="closeWebSocket()">Close</button>
<div id="message">
</div>
</body>
<script type="text/javascript">
var websocket = null;
//判断当前浏览器是否支持WebSocket
if('WebSocket' in window){
websocket = new WebSocket("ws://localhost:8080/websocket");
}
else{
alert('Not support websocket')
}
//连接发生错误的回调方法
websocket.onerror = function(){
setMessageInnerHTML("error");
};
//连接成功建立的回调方法
websocket.onopen = function(event){
setMessageInnerHTML("open");
}
//接收到消息的回调方法
websocket.onmessage = function(event){
setMessageInnerHTML(event.data);
}
//连接关闭的回调方法
websocket.onclose = function(){
setMessageInnerHTML("close");
}
//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function(){
websocket.close();
}
//将消息显示在网页上
function setMessageInnerHTML(innerHTML){
document.getElementById('message').innerHTML += innerHTML + '<br/>';
}
//关闭连接
function closeWebSocket(){
websocket.close();
}
//发送消息
function send(){
var message = document.getElementById('text').value;
websocket.send(message);
}
</script>
</html>
运行Application.java,页面访问http://127.0.0.1:8080/index.html,可以通过客户端发送消息,也可以接受服务端返回的消息
这样基本实现了简单的websocket通讯,接下来websocket的客户端接入echars的接口,实现日志系统的前端展示
websokcet安全模式
websocket的安全模式需要创建wss实例,wss是基于https握手协议的,我们的cf平台统一配置了https协议,所以不用再配置ssl,直接创建wss实例即可
if(window.location.protocol == 'http:'){
websocket = new WebSocket("ws://localhost:8080/websocket");
}else{
websocket = new WebSocket("wss://localhost:8080/websocket");
}
websocket的token验证
websocket的数据传输安全模式通过wss,客户端和服务端握手的时候采用https协议,这时的安全需要token验证
websocket = new WebSocket(“wss://localhost:8080/websocket?token=*“)
用户登入平台的时候获取token,服务端拿到token去平台验证
private static void tokenAuth(String token) {
//发送 GET 请求
String s=HttpPost.sendGet("http://&&&&&", "token");
}
public static String sendGet(String url, String param) {
String result = "";
BufferedReader in = null;
try {
String urlNameString = url + "?" + param;
URL realUrl = new URL(urlNameString);
// 打开和URL之间的连接
URLConnection connection = realUrl.openConnection();
// 设置通用的请求属性
connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 建立实际的连接
connection.connect();
// 获取所有响应头字段
Map<String, List<String>> map = connection.getHeaderFields();
// 遍历所有的响应头字段
for (String key : map.keySet()) {
System.out.println(key + "--->" + map.get(key));
}
// 定义 BufferedReader输入流来读取URL的响应
in = new BufferedReader(new InputStreamReader(
connection.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("发送GET请求出现异常!" + e);
e.printStackTrace();
}
// 使用finally块来关闭输入流
finally {
try {
if (in != null) {
in.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
return result;
}