uni-app的API一部分是基于ECMA的还有一部分是由uniapp自己扩展的api,
其中websocket就是由uniapp自己扩展的api。
从创建一个 WebSocket (opens new window)连接,监听,发送等都跟传统的websocket有点不同。
这里跟大家分享的是web端进行通信的样例,其中小程序端通信需要按照官网的协议样例进行wss://www.example.com/socket,而web端则是ws://www.example.com/socket。
uni.connectSocket({
url: 'wss://www.example.com/socket',
data() {
return {
x: '',
y: ''
};
},
header: {
'content-type': 'application/json'
},
protocols: ['protocol1'],
method: 'GET'
});
uni.onSocketOpen(function (res) {
console.log('WebSocket连接已打开!');
});
uni.sendSocketMessage({
data: msg
});
发送时特别注意数据格式,记得要转换数据格式
我贴一下发送的样例,这是一个方法,我是从真实项目中直接拉出来的
send() {
if (!this.text) {
return uni.showToast({
title: "请输入内容"
})
} else {
if (typeof(WebSocket) == "undefined") {
console.log("您的浏览器不支持WebSocket");
} else {
console.log("您的浏览器支持WebSocket");
// 组装待发送的消息 json
// {"from": "zhang", "to": "admin", "text": "聊天文本"}
let message = {
from: this.user.username,
to: this.userText,
text: this.text
}
uni.sendSocketMessage(JSON.stringify(message)); // 将组装好的json发送给服务端,由服务端进行转发
this.messages.push({
user: this.user.username,
text: this.text
})
// 构建消息内容,本人消息
this.createContent(null, this.user.username, this.text)
this.text = '';
}
}
},
uni.onSocketMessage(function (res) {
console.log('收到服务器内容:' + res.data);
});
uni.onSocketClose(function() {
console.log("websocket已关闭");
});
将websocket五大步骤抽离成函数形式,下面是样例代码
init() { //将连接的操作和判断浏览器是否支持websocket抽离成函数
// this.user = sessionStorage.getItem("user") ? JSON.parse(sessionStorage.getItem("user")) : {}
// let username = this.user.username;
let username = uni.getStorageSync("username");
let _this = this;
_this.text1 = "用户" + username + "已进入聊天"
if (typeof(WebSocket) == "undefined") { //WebSocket是浏览器自定义的无需多管,记住这个方法即可
console.log("您的浏览器不支持WebSocket");
} else {
console.log("您的浏览器支持WebSocket");
let socketUrl = "ws://localhost:8080/imserver/" + username;
if (SocketTask != null) {
SocketTask.close();
SocketTask = null;
}
// 开启一个websocket服务
console.log(socketUrl)
uni.connectSocket({
url: "ws://localhost:8080/imserver/" + username, //仅为示例,并非真实接口地址。
complete: () => {
},
success(res) {
console.log(res)
},
fail(err) {
console.log(err)
}
});
// console.log(SocketTask)
// SocketTask.onOpen(function(res){
// console.log("websockrt已打开")
// });
uni.onSocketOpen(function(res) {
console.log("websockrt已打开")
})
// 浏览器端收消息,获得从服务端发送过来的文本消息
uni.onSocketMessage(function(msg) {
console.log("收到数据====" + msg.data)
let data = JSON.parse(msg
.data
) // 对收到的json数据进行解析, 类似这样的: {"users": [{"username": "zhang"},{ "username": "admin"}]}
if (data.users) { // 获取在线人员信息
_this.users = data.users.filter(user => user.username !==
username) // 获取当前连接的所有用户信息,并且排除自身,自己不会出现在自己的聊天列表里
} else {
// 如果服务器端发送过来的json数据 不包含 users 这个key,那么发送过来的就是聊天文本json数据
// // {"from": "zhang", "text": "hello"}
if (data.from === _this.chatUser) {
_this.messages.push(data)
// 构建消息内容
_this.createContent(data.from, null, data.text)
}
}
});
//关闭事件
uni.onSocketClose(function() {
console.log("websocket已关闭");
});
//发生了错误事件
uni.onSocketError(function() {
console.log("websocket发生了错误");
});
}
}
配置WebSocketStompConfig,建立config包,在config文件夹新建WebSocketStompConfig类
package com.gpnu.cn.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
* 开启WebSocket支持
* @author zhengkai
*/
@Configuration
public class WebSocketStompConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter()
{
return new ServerEndpointExporter();
}
}
新建utils包,在utils包下新建WebSocket类
package com.gpnu.cn.utils;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
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 com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
;
import lombok.extern.log4j.Log4j2;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
/**
* WebSocketServer
*
* @author zhengkai.blog.csdn.net
*/
@Component
@ServerEndpoint("/websocket/{username}")
@Log4j2
public class WebSocket {
private Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* 在线人数
*/
public static int onlineNumber = 0;
/**
* 以用户的姓名为key,WebSocket为对象保存起来
*/
private static Map<String, WebSocket> clients = new ConcurrentHashMap<String, WebSocket>();
/**
* 会话
*/
private Session session;
/**
* 用户名称
*/
private String username;
/**
* 建立连接
*
* @param session
*/
@OnOpen
public void onOpen(@PathParam("username") String username, Session session) {
onlineNumber++;
logger.info("现在来连接的客户id:" + session.getId() + "用户名:" + username);
this.username = username;
this.session = session;
logger.info("有新连接加入! 当前在线人数" + onlineNumber);
try {
//messageType 1代表上线 2代表下线 3代表在线名单 4代表普通消息
//先给所有人发送通知,说我上线了
Map<String, Object> map1 = new HashMap<>();
map1.put("messageType", 1);
map1.put("username", username);
sendMessageAll(JSON.toJSONString(map1), username);
//把自己的信息加入到map当中去
clients.put(username, this);
//给自己发一条消息:告诉自己现在都有谁在线
Map<String, Object> map2 =new HashMap<>();
map2.put("messageType", 3);
//移除掉自己
Set<String> set = clients.keySet();
map2.put("onlineUsers", set);
sendMessageTo(JSON.toJSONString(map2), username);
} catch (IOException e) {
logger.info(username + "上线的时候通知所有人发生了错误");
}
}
@OnError
public void onError(Session session, Throwable error) {
logger.info("服务端发生了错误" + error.getMessage());
//error.printStackTrace();
}
/**
* 连接关闭
*/
@OnClose
public void onClose() {
onlineNumber--;
//webSockets.remove(this);
clients.remove(username);
try {
//messageType 1代表上线 2代表下线 3代表在线名单 4代表普通消息
Map<String, Object> map1 = new HashMap<>();
map1.put("messageType", 2);
map1.put("onlineUsers", clients.keySet());
map1.put("username", username);
sendMessageAll(JSON.toJSONString(map1), username);
} catch (IOException e) {
logger.info(username + "下线的时候通知所有人发生了错误");
}
logger.info("有连接关闭! 当前在线人数" + onlineNumber);
}
/**
* 收到客户端的消息
*
* @param message 消息
* @param session 会话
*/
@OnMessage
public void onMessage(String message, Session session) {
try {
logger.info("来自客户端消息:" + message + "客户端的id是:" + session.getId());
JSONObject jsonObject = JSON.parseObject(message);
String textMessage = jsonObject.getString("message");
String fromusername = jsonObject.getString("username");
String tousername = jsonObject.getString("to");
//如果不是发给所有,那么就发给某一个人
//messageType 1代表上线 2代表下线 3代表在线名单 4代表普通消息
Map<String, Object> map1 = new HashMap<>();
map1.put("messageType", 4);
map1.put("textMessage", textMessage);
map1.put("fromusername", fromusername);
if (tousername.equals("All")) {
map1.put("tousername", "所有人");
sendMessageAll(JSON.toJSONString(map1), fromusername);
} else {
map1.put("tousername", tousername);
sendMessageTo(JSON.toJSONString(map1), tousername);
}
} catch (Exception e) {
logger.info("发生了错误了");
}
}
public void sendMessageTo(String message, String ToUserName) throws IOException {
for (WebSocket item : clients.values()) {
if (item.username.equals(ToUserName)) {
item.session.getAsyncRemote().sendText(message);
break;
}
}
}
public void sendMessageAll(String message, String FromUserName) throws IOException {
for (WebSocket item : clients.values()) {
item.session.getAsyncRemote().sendText(message);
}
}
public static synchronized int getOnlineCount() {
return onlineNumber;
}
}