易登官网在前期为了快速为开发者提供服务,登录认证的时候使用轮询的方式,一遍遍调用后端接口判断用户是否已经登录。轮询的优点就是技术门槛低、开发方便,但是缺点也显而易见:频繁请求后端接口会占用大量服务器资源,也会让其他开发者看起来太不专业。
org.springframework.boot
spring-boot-starter-websocket
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
@Slf4j
@ServerEndpoint(value = "/websocket/{userId}")
@Component
public class MyWebSocket {
/**
* 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
*/
private static int onlineCount = 0;
// 用来存放用户与会话的关系
private static ConcurrentHashMap socketMap = new ConcurrentHashMap<>();
/**
* 与某个客户端的连接会话,需要通过它来给客户端发送数据
*/
private Session session;
/**
* 连接建立成功调用的方法
*/
@OnOpen
public void onOpen(Session session, @PathParam("userId") String userId) {
this.session = session;
if (socketMap.containsKey(userId)) {
socketMap.remove(userId);
socketMap.put(userId, this);
} else {
socketMap.put(userId, this);
//在线数加1
addOnlineCount();
}
log.info("有新连接加入!userId={}, 当前在线人数为:{}", userId, getOnlineCount());
try {
sendMessage("success");
log.info("新建链接成功");
} catch (IOException e) {
log.error(e.getMessage(), e);
}
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose(@PathParam("userId") String userId) {
socketMap.remove(userId);
subOnlineCount(); //在线数减1
log.info("有一连接关闭!当前在线人数为:{}", getOnlineCount());
}
/**
* 收到客户端消息后调用的方法
*
* @param message 客户端发送过来的消息
*/
@OnMessage
public void onMessage(String message, Session session) throws IOException {
log.info("收到客户端消息:{}", message);
}
// 给指定人发送消息
public static void sendMessage(@PathParam("userId") String userId, String message) {
MyWebSocket myWebSocket = socketMap.get(userId);
if (myWebSocket != null) {
try {
myWebSocket.session.getBasicRemote().sendText(message);
} catch (IOException e) {
log.error("给用户:{}发送消息{}失败!", userId, message, e);
}
} else {
log.warn("用户{}还未建立连接", userId);
}
}
/**
* 发生错误时调用
*/
@OnError
public void onError(Session session, Throwable error) {
log.error("发送消息失败!", error);
}
public void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
//this.session.getAsyncRemote().sendText(message);
}
public static synchronized int getOnlineCount() {
return onlineCount;
}
public static synchronized void addOnlineCount() {
MyWebSocket.onlineCount++;
}
public static synchronized void subOnlineCount() {
MyWebSocket.onlineCount--;
}
}
let ws = new WebSocket("ws://www.test.com/api/websocket/" + this.tempUserId);
// 创建连接成功回调
ws.onopen = () => {
ws.send("连接成功");
}
// 关闭连接回调
ws.onclose = () => {
}
// 接收到服务端消息回调
ws.onmessage = (evt) => {
let message = evt.data;
console.log("收到ws消息:", message);
}
# webSocket变量定义
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
server_name www.test.com;
location / {
root /var/html; # 前端静态页面路径
index index.html;
}
location /api {
proxy_pass http://localhost:8888;
# 以下三行代码是升级请求协议,使之支持webSocket
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade; # 主要配置
proxy_set_header Connection $connection_upgrade; #主要配置
}
}
用户在点击易登登录按钮后,前端与服务端建立ws连接
用户在登录之后,服务端会给前端发送用户已经登录的消息,并将用户信息通过消息发送给前端页面
原文链接:记忆旅途
留言与评论(共有 0 条评论) “” |