webSocket快速入门

作者:一只游鱼日期:2025/10/13

webSocket快速入门

一、WebSocket 是什么?

WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议。
简单说,它能让客户端(浏览器)和服务器之间实时双向通信。

对比传统 HTTP

特性HTTPWebSocket
连接方式请求-响应持久连接
通信方向客户端 → 服务端双向
实时性差,需要轮询极好
传输协议HTTP/1.1ws:// 或 wss://
应用场景普通网页请求实时聊天、通知、监控数据推送等

二、Vue + Spring Boot 实现 WebSocket (基础)

1 springboot

依赖

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-websocket</artifactId>

</dependency>

编写 WebSocket 配置类

1@Configuration
2@EnableWebSocket  // 开启websocket
3public class WebSocketConfig implements WebSocketConfigurer {
4// 注册websocket处理器
5    @Override
6    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
7        registry.addHandler(new MyWebSocketHandler(), "/ws")
8                .setAllowedOrigins("*"); // 允许跨域
9    }
10}

编写处理器

1// 自定义websocket处理器
2public class MyWebSocketHandler extends TextWebSocketHandler {
3    // 保存所有连接的session
4    private static final CopyOnWriteArraySet<WebSocketSession> sessions = new CopyOnWriteArraySet<>();
5    // 当有新的连接时,将session添加到sessions中
6    @Override
7    public void afterConnectionEstablished(WebSocketSession session) {
8        sessions.add(session);
9        System.out.println("新连接:" + session.getId());
10    }
11    // 处理消息
12    @Override
13    public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
14        String msg = message.getPayload();
15        System.out.println("收到消息:" + msg);
16        // 回复客户端
17        session.sendMessage(new TextMessage("服务器收到:" + msg));
18    }
19    // 连接关闭时
20    @Override
21    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
22        sessions.remove(session);
23        System.out.println("连接关闭:" + session.getId());
24    }
25
26    // 向所有连接推送消息
27    public static void broadcast(String message) throws Exception {
28        for (WebSocketSession session : sessions) {
29            if (session.isOpen()) {
30                session.sendMessage(new TextMessage(message));
31            }
32        }
33    }
34}

创建控制类

1@RestController
2@RequestMapping("/api/test")
3public class TestController {
4
5    @GetMapping("/push")
6    public String pushMessage(@RequestParam String msg) throws Exception {
7        MyWebSocketHandler.broadcast("服务端推送:" + msg);
8        return "ok";
9    }
10}

2 vue

创建工具类

1let ws = null;
2let reconnectTimer = null;
3let url = "ws://localhost:8081/ws";
4
5function createWebSocket(onMessage) {
6    if (ws) return; // 防止重复创建
7    // 创建 WebSocket 连接
8    ws = new WebSocket(url);
9
10    ws.onopen = () => {
11        console.log("WebSocket 已连接");
12    };
13    // 接收服务器消息
14    ws.onmessage = (event) => {
15        if (onMessage) onMessage(event.data);
16    };
17
18    ws.onclose = () => {
19        console.log(" WebSocket 已关闭,尝试重连...");
20        ws = null;
21        reconnect(); // 自动重连
22    };
23
24    ws.onerror = (err) => {
25        console.error("WebSocket 出错:", err);
26        ws.close();
27    };
28}
29// 自动重连
30function reconnect() {
31    if (reconnectTimer) return;
32    reconnectTimer = setTimeout(() => {
33        createWebSocket();
34        reconnectTimer = null;
35    }, 3000);
36}
37// 发送消息
38function sendMsg(msg) {
39    if (ws && ws.readyState === WebSocket.OPEN) {
40        ws.send(msg);
41    } else {
42        console.warn("WebSocket 未连接,消息未发送");
43    }
44}
45// 关闭 WebSocket 连接
46function closeWebSocket() {
47    if (ws) {
48        ws.close();
49        ws = null;
50    }
51}
52
53export default {
54    createWebSocket,
55    sendMsg,
56    closeWebSocket
57};

写一个简单的页面来调用

1<template>
2  <div>
3    <h2>WebSocket 测试</h2>
4    <p>收到消息:{{ message }}</p>
5    <input v-model="input" />
6    <button @click="send">发送</button>
7  </div>
8</template>
9
10<script>
11import wsService from "@/utils/websocket";
12
13export default {
14  data() {
15    return {
16      message: "",
17      input: ""
18    };
19  },
20  mounted() {
21    wsService.createWebSocket((msg) => {
22      this.message = msg;
23    });
24  },
25  beforeUnmount() {
26    wsService.closeWebSocket();
27  },
28  methods: {
29    send() {
30      wsService.sendMsg(this.input);
31      this.input = "";
32    }
33  }
34};
35</script>

注意:运行后, WebSocket 服务地址为:
ws://localhost:8081/ws

我们可以测试一下,启动vue、springboot项目:

可以看到前后端控制台都打印出了websocket连接成功的日志。

发送消息后后端也能及时的收到消息:

三、websocket 高级封装

在一般的项目中通常会:

  1. 使用 Pinia/Vuex 管理 WebSocket 状态(是否在线、消息队列等);
  2. 支持 心跳检测
  3. 支持 断线重连 + 消息缓存
  4. 区分不同业务消息类型(如 chat, notice, system)。

这里我们为了直接支持

a.自动重连
b.心跳检测
c.区分业务消息类型(如 chat, notice, system)
d.统一管理连接状态

来修改一下websocket的工具类封装:

1let ws = null;
2let heartbeatTimer = null;
3let reconnectTimer = null;
4let reconnectAttempts = 0;
5
6const HEARTBEAT_INTERVAL = 5000; // 心跳间隔 5s
7const MAX_RECONNECT_ATTEMPTS = 10;
8const WS_URL = "ws://localhost:8081/ws"; // 后端地址
9
10// === 初始化 WebSocket 连接 ===
11function createWebSocket(onMessageCallback) {
12    if (ws && ws.readyState === WebSocket.OPEN) return;
13
14    ws = new WebSocket(WS_URL);
15
16    ws.onopen = () => {
17        console.log("WebSocket 连接成功");
18        reconnectAttempts = 0;
19        startHeartbeat();
20    };
21
22    ws.onmessage = (event) => {
23        try {
24            const data = JSON.parse(event.data);
25            handleMessage(data, onMessageCallback);
26        } catch (e) {
27            console.warn("收到非JSON消息:", event.data);
28        }
29    };
30
31    ws.onclose = () => {
32        console.warn("WebSocket 已关闭,尝试重连...");
33        stopHeartbeat();
34        reconnect();
35    };
36
37    ws.onerror = (err) => {
38        console.error("WebSocket 出错:", err);
39        ws.close();
40    };
41}
42
43// === 心跳机制 ===
44function startHeartbeat() {
45    stopHeartbeat();
46    heartbeatTimer = setInterval(() => {
47        send({ type: "ping" });
48    }, HEARTBEAT_INTERVAL);
49}
50
51function stopHeartbeat() {
52    if (heartbeatTimer) {
53        clearInterval(heartbeatTimer);
54        heartbeatTimer = null;
55    }
56}
57
58// === 重连机制 ===
59function reconnect() {
60    if (reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
61        console.error("重连次数过多,停止尝试");
62        return;
63    }
64
65    reconnectAttempts++;
66    const delay = reconnectAttempts * 2000; // 递增延迟
67    console.log([`${delay / 1000}s 后重连第 ${reconnectAttempts} 次...`](https://xplanc.org/primers/document/zh/03.HTML/EX.HTML%20%E5%85%83%E7%B4%A0/EX.s.md));
68
69    reconnectTimer = setTimeout(() => {
70        createWebSocket();
71    }, delay);
72}
73
74// === 消息分发 ===
75function handleMessage(data, callback) {
76    if (!data.type) {
77        console.warn("未知消息类型:", data);
78        return;
79    }
80
81    switch (data.type) {
82        case "chat":
83            console.log("聊天消息:", data.content);
84            break;
85        case "notice":
86            console.log("通知:", data.content);
87            break;
88        case "system":
89            console.log("系统消息:", data.content);
90            break;
91        case "pong":
92            console.log("心跳响应");
93            break;
94        default:
95            console.log("其他类型消息:", data);
96    }
97
98    if (callback) callback(data);
99}
100
101// === 发送消息 ===
102function send(msg) {
103    if (!ws || ws.readyState !== WebSocket.OPEN) {
104        console.warn("WebSocket 未连接,发送失败:", msg);
105        return;
106    }
107    ws.send(JSON.stringify(msg));
108}
109
110// === 主动关闭 ===
111function close() {
112    stopHeartbeat();
113    if (ws) {
114        ws.close();
115        ws = null;
116    }
117}
118
119export default {
120    createWebSocket,
121    send,
122    close
123};

创建一个新的页面:

1<template>
2  <div class="p-4">
3    <h2>💬 WebSocket 聊天示例</h2>
4    <p>收到的消息:{{ lastMessage }}</p>
5
6    <div class="mt-4">
7      <input v-model="message" placeholder="输入消息..." />
8      <select v-model="type">
9        <option value="chat">聊天</option>
10        <option value="notice">通知</option>
11        <option value="system">系统</option>
12      </select>
13      <button @click="sendMsg">发送</button>
14    </div>
15  </div>
16</template>
17
18<script>
19import wsService from "@/utils/websocket";
20
21export default {
22  data() {
23    return {
24      message: "",
25      type: "chat",
26      lastMessage: ""
27    };
28  },
29  mounted() {
30    wsService.createWebSocket((msg) => {
31      this.lastMessage = [`${msg.type}: ${msg.content}`](https://xplanc.org/primers/document/zh/10.Bash/90.%E5%B8%AE%E5%8A%A9%E6%89%8B%E5%86%8C/EX.type.md);
32    });
33  },
34  beforeUnmount() {
35    wsService.close();
36  },
37  methods: {
38    sendMsg() {
39      wsService.send({
40        type: this.type,
41        content: this.message,
42        from: "前端用户"
43      });
44      this.message = "";
45    }
46  }
47};
48</script>

修改后端的处理数据方式:

1    // 处理消息
2    @Override
3    public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
4        String msg = message.getPayload();
5        System.out.println("收到消息:" + msg);
6/**
7 *websocket高级封装
8 *区分不同业务消息类型
9 *支持 心跳检测
10 */
11        // 解析前端JOSN
12        JSONObject json = new JSONObject(msg);
13        String type = json.optString("type");
14        // 构造回复数据
15        JSONObject data = new JSONObject();
16        data.put("type", type);
17        data.put("content","服务器已收到:"+ json.optString("content"));
18
19        //模拟心跳回应
20        if ("ping".equals(type)) {
21            data.put("type", "pong");
22        }
23
24
25        // 回复客户端
26        session.sendMessage(new TextMessage(json.toString()));
27    }

发送后可以看到:

四、广播(全员发)和私聊(发给指定userId )功能

那么问题来了,广播和私聊功能是如何在websocket中实现的?

这里,我们可通过记录连接成功的用户(也就是在线的用户)来进行,在前端拼接websocket url时,可以加上用户唯一的/id 来分辨不同的用户。。

如:

ws://localhost:8080/ws/1

这时在后端截取id来获取在线用户。

后端修改config

1@Configuration
2@EnableWebSocket  // 开启websocket
3public class WebSocketConfig implements WebSocketConfigurer {
4// 注册websocket处理器
5    @Override
6    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
7        registry.addHandler(new MyWebSocketHandler(), "/ws/{userId}")
8                .setAllowedOrigins("*"); // 允许跨域
9    }
10}
11
12
13public class MyWebSocketHandler extends TextWebSocketHandler {
14
15    // 保存所有连接:userId -> session
16    private static final ConcurrentHashMap<String, WebSocketSession> sessions = new ConcurrentHashMap<>();
17    // 当有新的连接时,将session添加到sessions中
18    @Override
19    public void afterConnectionEstablished(WebSocketSession session) {
20        // 获取用户ID  ws://localhost:8081/ws/1
21        String path = session.getUri().getPath();
22        System.out.println("新连接:" + path);
23        String userId = path.substring(path.lastIndexOf("/") + 1);
24        sessions.put(userId, session);
25        System.out.println("新连接:" + userId + " (sessionId=" + session.getId() + ")");
26    }
27    // 处理消息
28    @Override
29    public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
30        String msg = message.getPayload();
31        System.out.println("收到消息:" + msg);
32
33        // 默认逻辑:回复收到的内容
34//        JSONObject json = new JSONObject(msg);
35//        String content = json.optString("content");
36//
37//        JSONObject reply = new JSONObject();
38//        reply.put("content", "服务器已收到:" + content);
39//        reply.put("type", "system");
40//        session.sendMessage(new TextMessage(reply.toString()));
41    }
42    // 连接关闭时
43    @Override
44    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
45        sessions.entrySet().removeIf(entry -> entry.getValue().equals(session));
46        System.out.println("连接关闭:" + session.getId());
47    }
48
49
50    // 专用方法分发
51
52
53    /**
54     * 广播
55     */
56    public static void broadcast(String from, String message,String type) throws Exception {
57        JSONObject data = new JSONObject();
58        data.put("from", from);
59        data.put("type", type);
60        data.put("content", message);
61        // 发送给所有连接
62        for (WebSocketSession session : sessions.values()) {
63            if (session.isOpen()) {
64                session.sendMessage(new TextMessage(data.toString()));
65            }
66        }
67        System.out.println("广播消息:" + message);
68    }
69
70    /**
71     * 私聊
72     */
73    public static void sendToUser(String from, String to, String message, String type) throws Exception {
74        WebSocketSession target = sessions.get(to);
75        if (target != null && target.isOpen()) {
76            JSONObject data = new JSONObject();
77            data.put("from", from);
78            data.put("type", type);
79            data.put("to", to);
80            data.put("content", message);
81            // 发送给指定连接
82            target.sendMessage(new TextMessage(data.toString()));
83            System.out.println("私聊消息:" + from + " → " + to + ":" + message);
84        } else {
85            System.out.println("用户 " + to + " 不在线或不存在");
86        }
87    }
88}

控制器区分不同业务:

1@RestController
2@RequestMapping("/api/test")
3public class TestController {
4
5//    @GetMapping("/push")
6//    public String pushMessage(@RequestParam String msg) throws Exception {
7//        MyWebSocketHandler.broadcast("服务端推送:" + msg);
8//        return "ok";
9//    }
10
11
12    // 广播
13    @PostMapping("/broadcast")
14    public void broadcast(@RequestBody Map<String, String> body) throws Exception {
15        MyWebSocketHandler.broadcast(body.get("from"), body.get("content"), body.get("type"));
16    }
17    // 私聊
18    @PostMapping("/private")
19    public void privateMsg(@RequestBody Map<String, String> body) throws Exception {
20        MyWebSocketHandler.sendToUser(body.get("from"), body.get("to"), body.get("content"), body.get("type"));
21    }
22}

前端封装websocket 时,获取id并拼接:

创建广播和私聊方法:

1// WebSocket 工具模块
2let ws = null; // WebSocket 实例
3let heartbeatTimer = null;  // 心跳定时器
4let reconnectTimer = null;  // 重连定时器
5let reconnectAttempts = 0;  // 重连尝试次数
6
7const HEARTBEAT_INTERVAL = 10000; // 心跳间隔 10s
8const MAX_RECONNECT_ATTEMPTS = 10;
9const WS_URL = "ws://localhost:8081/ws"; // 后端地址
10
11// === 初始化 WebSocket 连接 ===
12function createWebSocket(onMessageCallback, uid) {
13    return new Promise((resolve, reject) => {
14        if (!uid) {
15            console.error("缺少用户ID,WebSocket无法建立连接");
16            reject("缺少用户ID");
17            return;
18        }
19
20        // 如果已存在连接则直接返回
21        if (ws && ws.readyState === WebSocket.OPEN) {
22            console.log("WebSocket 已连接");
23            resolve();
24            return;
25        }
26
27        // 拼装 URL
28        const id = `${WS_URL}/${uid}`;
29        ws = new WebSocket(id);
30
31        ws.onopen = () => {
32            console.log(`用户 ${uid} WebSocket 连接成功`);
33            reconnectAttempts = 0;
34            startHeartbeat();
35            resolve(); // 通知外部连接成功
36        };
37
38        ws.onmessage = (event) => {
39            console.log("收到消息:", event.data);
40            try {
41                const data = JSON.parse(event.data);
42                handleMessage(data, onMessageCallback);
43            } catch (e) {
44                console.warn("收到非JSON消息:", event.data);
45            }
46        };
47
48        ws.onclose = () => {
49            console.warn("WebSocket 已关闭,尝试重连...");
50            stopHeartbeat();
51            reconnect(() => createWebSocket(onMessageCallback, uid));
52        };
53
54        ws.onerror = (err) => {
55            console.error("WebSocket 出错:", err);
56            ws.close();
57            reject(err); // 通知外部连接失败
58        };
59    });
60}
61
62// === 心跳机制 ===
63function startHeartbeat() {
64    stopHeartbeat();
65    heartbeatTimer = setInterval(() => {
66        send({ type: "ping" });
67    }, HEARTBEAT_INTERVAL);
68}
69
70// === 停止心跳 ===
71function stopHeartbeat() {
72    if (heartbeatTimer) {
73        clearInterval(heartbeatTimer);
74        heartbeatTimer = null;
75    }
76}
77
78// === 重连机制 ===
79function reconnect(reconnectAction) {
80    if (reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
81        console.error("重连次数过多,停止尝试");
82        return;
83    }
84
85    reconnectAttempts++;
86    const delay = reconnectAttempts * 2000; // 递增延迟
87    console.log([`${delay / 1000}s 后重连第 ${reconnectAttempts} 次...`](https://xplanc.org/primers/document/zh/03.HTML/EX.HTML%20%E5%85%83%E7%B4%A0/EX.s.md));
88
89    reconnectTimer = setTimeout(() => {
90        if (typeof reconnectAction === "function") {
91            reconnectAction();
92        }
93    }, delay);
94}
95
96// === 消息分发 ===
97function handleMessage(data, callback) {
98    if (!data.type) {
99        console.warn("未知消息类型:", data);
100        return;
101    }
102
103    switch (data.type) {
104        case "chat":
105            console.log("聊天消息:", data.content);
106            break;
107        case "notice":
108            console.log("通知:", data.content);
109            break;
110        case "system":
111            console.log("系统消息:", data.content);
112            break;
113        case "private":
114            console.log("私聊消息:", data);
115            break;
116        case "broadcast":
117            console.log("广播消息:", data);
118            break;
119        case "ping":
120            console.log("心跳响应");
121            break;
122        default:
123            console.log("其他类型消息:", data);
124    }
125
126    // 回调交给 Vue 层处理
127    if (callback) callback(data);
128}
129
130// === 发送消息 ===
131function send(msg) {
132    if (!ws || ws.readyState !== WebSocket.OPEN) {
133        console.warn("WebSocket 未连接,发送失败:", msg);
134        return;
135    }
136    ws.send(JSON.stringify(msg));
137}
138
139// === 广播 ===
140function broadcast(from, msg) {
141    send({ type: "broadcast", from, content: msg });
142}
143
144// === 私聊 ===
145function privateChat(from, to, msg) {
146    send({ type: "private", from, to, content: msg });
147}
148
149// === 主动关闭 ===
150function close() {
151    stopHeartbeat();
152    if (ws) {
153        ws.close();
154        ws = null;
155    }
156}
157
158// === 导出 ===
159export default {
160    createWebSocket,
161    send,
162    close,
163    broadcast,
164    privateChat
165};

创建聊天/接收页面:

1<template>
2  <div class="p-4">
3    <h2 class="text-xl font-bold mb-4">💬 WebSocket 聊天示例</h2>
4
5    <div class="mb-4">
6      <p>当前用户ID:<strong>{{ from }}</strong></p>
7      <p>WebSocket状态:<span>{{ wsConnected ? "✅ 已连接" : "❌ 未连接" }}</span></p>
8    </div>
9
10    <!-- 消息显示区 -->
11    <div class="border rounded p-4 h-64 overflow-y-auto bg-gray-50 mb-4">
12      <div
13          v-for="(msg, index) in messages"
14          :key="index"
15          :class="[
16        'mb-2 p-2 rounded',
17        msg.type === 'broadcast'
18          ? 'bg-green-100'
19          : msg.from === from
20          ? 'bg-blue-100 text-right'
21          : 'bg-white'
22      ]"
23      >
24        <p class="text-sm">
25          <strong>{{ msg.from === from ? "我" : msg.from }}</strong>:
26          {{ msg.content }}
27        </p>
28      </div>
29    </div>
30
31    <!-- 私聊输入区 -->
32    <div class="space-y-2 mb-4">
33      <h3 class="font-semibold">📨 私聊消息</h3>
34      <input
35          v-model="to"
36          placeholder="输入对方用户ID"
37          class="border p-2 w-full"
38      />
39      <input
40          v-model="privateMsg"
41          placeholder="输入要发送的私聊内容"
42          class="border p-2 w-full"
43      />
44      <button
45          @click="sendPrivate"
46          class="bg-blue-500 text-white px-4 py-1 rounded"
47      >
48        发送私聊
49      </button>
50    </div>
51
52    <!-- 广播输入区 -->
53    <div class="space-y-2">
54      <h3 class="font-semibold">📢 广播消息</h3>
55      <input
56          v-model="broadcastMsg"
57          placeholder="输入要广播的内容"
58          class="border p-2 w-full"
59      />
60      <button
61          @click="sendBroadcast"
62          class="bg-green-500 text-white px-4 py-1 rounded"
63      >
64        发送广播
65      </button>
66    </div>
67  </div>
68</template>
69
70<script>
71  import wsService from "@/utils/websocket";
72  import axios from "axios";
73
74  export default {
75    data() {
76      return {
77        from: "1", // 当前用户ID(测试用)
78        to: "",
79        privateMsg: "",
80        broadcastMsg: "",
81        messages: [],
82        wsConnected: false
83      };
84    },
85    mounted() {
86      // 创建 WebSocket 连接(如 ws://localhost:8081/ws/1)
87      wsService.createWebSocket(
88          // 接收消息时的回调
89          (msg) => {
90            this.messages.push(msg);
91          },
92          // 当前用户 ID
93          this.from,
94      )
95      .then(() => {
96        this.wsConnected = true;
97      })
98    },
99
100    beforeUnmount() {
101      wsService.close();
102    },
103    methods: {
104      // 发送私聊消息
105      async sendPrivate() {
106        if (!this.to || !this.privateMsg) {
107          alert("请填写对方ID和消息内容");
108          return;
109        }
110        await axios.post("/api/api/test/private", {
111          from: this.from,
112          to: this.to,
113          type: "chat",
114          content: this.privateMsg
115        });
116        this.privateMsg = "";
117      },
118
119      // 发送广播消息
120      async sendBroadcast() {
121        if (!this.broadcastMsg) {
122          alert("请输入广播内容");
123          return;
124        }
125        await axios.post("/api/api/test/broadcast", {
126          from: this.from,
127          type: "chat",
128          content: this.broadcastMsg
129        });
130        this.broadcastMsg = "";
131      }
132    }
133  };
134</script>
135
136<style scoped>
137  input {
138    border-radius: 6px;
139  }
140</style>

效果:

这时我们可以用几个页面模拟几个用户:

写两个页面,修改from

1data() {
2  return {
3    from: "2", // 当前用户ID(测试用)
4    to: "",
5    privateMsg: "",
6    broadcastMsg: "",
7    messages: [],
8    wsConnected: false
9  };
10},

打开页面后,查看后端日志:发现有两个设备在线:

用户2给用户1发送信息:

用户1广播信息:


webSocket快速入门》 是转载文章,点击查看原文


相关推荐


推荐 12 款开源美观、简单易用的 WPF UI 控件库,让 WPF 应用界面焕然一新!
追逐时光者2025/10/12

前言 今天大姚给大家分享 12 款开源美观、简单易用、主题控件齐全的 WPF UI 控件库,帮助大家轻松打造现代化 WPF 桌面应用,提升开发效率与视觉体验! WPF 介绍 WPF 是一个强大的桌面应用程序框架,用于构建具有丰富用户界面的 Windows 应用。它提供了灵活的布局、数据绑定、样式和模板、动画效果等功能,让开发者可以创建出吸引人且交互性强的应用程序。 HandyControl HandyControl是一套WPF控件库,它几乎重写了所有原生样式,同时包含80余款自定义控件。使用Ha


微硕WSD2018DN22 N沟MOSFET,汽车副驾桌板LED照明负载开关
MOS管-冠华伟业2025/10/10

随着“办公座舱”概念升温,副驾折叠桌板需集成5V/9V USB、LED照明、触控按键等模块,空间被压缩至“毫米级”,却必须满足“零继电器噪音+零待机功耗+1mm高度”三重要求。微硕WINSOK推出DFN2×2-6S N沟MOSFET WSD2018DN22,凭10mΩ低导通电阻与12A峰值电流,为12V平台桌板LED照明提供“芯片级”静音负载开关方案,一键实现“无感”点亮与μA级待机。 一、市场趋势催生器件需求 2025年中国副驾桌板渗透率预计达28%,单车灯节点由1路增至4路,核心痛点:


程序员副业 | 2025年9月复盘
嘟嘟MD2025/10/9

本文首发于公众号:嘟爷创业日记 。 我已经坚持日更600天+,欢迎过来追剧~ 大家好,我是嘟嘟MD,一个10年程序员,现在离职创业,有700天了,我每个月都会写一篇总结复盘,让大家可以近距离看看一个离职程序员都在干什么,今天这篇是九月份的总结,大概2000字,略长,有空的可以翻翻,希望对大家有一丢丢的借鉴作用! 一、月度大事 大家好,九月结束了,忙碌的一个月又结束了,这个月有些事情变化挺大,需要做出取舍。 1:公众号运营+B站视频运营 公众号和B站视频运营还是我的最高优先级,算是我的主业


【Ubuntu 20.04升级python3.9后终端打不开的bug】
woshihonghonga2025/10/7

3. 把Python3.9改为Python3首选项     sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.9 1     sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.8 2     sudo update-alternatives --config python3     


HBase的自动负载均衡,提升大数据存储性能
AI量化价值投资入门到精通2025/10/6

HBase自动负载均衡:让大数据存储像排队买奶茶一样高效 关键词 HBase、自动负载均衡、Region分布、大数据存储、性能优化、RegionServer、Master 摘要 在大数据存储领域,HBase凭借高可靠性、强一致性和可线性扩展的特性,成为电商订单、用户行为日志、物联网传感器数据等场景的首选。但随着数据量爆炸式增长,一个隐形的“性能杀手”会逐渐浮现——Region分布不均:有的RegionServer(数据节点)扛着100个Region(数据分片)忙得“喘不过气”,有的却只拿


Python 的内置函数 all
IMPYLH2025/10/4

Python 内建函数列表 > Python 的内置函数 all all() 是 Python 提供的一个高效工具,它可以快速判断可迭代对象中的所有元素是否都为真值(Truthy)。它的使用非常简单,但结合不同的场景,可以写出非常优雅的代码。 all 的函数原型如下: def all(iterable): ''' 判断可迭代对象内容是否全部为真值 :param iterable: 一个可迭代对象 :return: 如果 iterable 的所有元素均为真值


什么是Fork/Join?
karry_k2025/10/3

ForkJoin Fork/Join 是什么? 它是Java7 引入的一个 并行计算框架, 位于 java.util.concurrent 包下 。 主要解决的问题是:把大任务拆分成多个小任务并行执行,然后合并结果。 核心思想:分治法+工作窃取 核心类 ForkJoinPool 一个特殊的线程池,支持“工作窃取”算法。 每个线程都有自己的任务队列,如果某个线程空闲,会去偷别人的任务执行。 RecursiveTask<V> 代表有返回值的任务。 必须重写 prote


《探索C语言中数组的奥秘(下)》
小龙报2025/10/2

《探索C语言中数组的奥秘(下)》 前言 学习了二维数组,我们已经基本了解了C语言中数组的使用方式,接下来就让我们进入二维数组的学习吧! 一、二维数组的创建 1.1⼆维数组的概念 ⼀维数组的数组的元素都是内置类型的,如果我们把⼀维数组做为数组的元素这时候就是⼆维数组,⼆维数组作为数组元素的数组被称为三维数组,⼆维数组以上的数组统称为多维数组。 1.2二维数组的创建 语法规则: type arr_name[常量值1][常量值2]; 例如: int arr[3][5]; double data[


【展厅多媒体】解析VR虚拟驾驶实现多场景自由切换
bmcyzs2025/10/2

VR虚拟驾驶技术的场景切换能力,彻底打破了物理展厅的空间局限,为体验者带来前所未有的自由探索感。系统内置丰富的数字场景资源库,涵盖多种精心设计的驾驶情境——从晨光映照的海岸公路,到霓虹流转的未来都市,用户只需通过直观的选单界面,便能轻松切换不同驾驶世界。 为实现流畅自然的体验过渡,模拟驾驶平台着重优化场景加载效率,通过预加载与渲染技术,极大缩短场景切换等待时间,保障体验过程的连贯性与沉浸感。在汽车展厅中,这项功能被灵活运用于展示车辆性能:切换到山地模式可突显SUV的爬坡能力,选用雨天场景则能清晰


AI 赋能 EMS 微电网能效管理平台:构建分布式能源的智能调控中枢
DDC楼宇自控与IBMS集成系统解读10/2/2025

微电网作为分布式能源(光伏、风电、储能)与负荷的局部能源网络,是实现 “双碳” 目标、提升能源利用效率的关键载体。传统能源管理系统(EMS)虽能完成微电网内数据采集、简单调度与监控,但面对微电网 “新能源出力波动大(如光伏受光照影响)、负荷需求动态变化(如工业用电峰谷差)、多能源协同复杂(如光 - 储 - 充联动)” 等特性,逐渐暴露出调度精度低、能效优化不足、故障响应滞后等短板。随着人工智能(AI)技术的深度融入,EMS 微电网能效管理平台正从 “被动监控” 向 “主动预测、智能优化、协同调度” 升级,形

首页编辑器站点地图

Copyright © 2025 聚合阅读

License: CC BY-SA 4.0