深入浅出SpringBoot WebSocket构建实时应用全面指南

本文主要是介绍深入浅出SpringBoot WebSocket构建实时应用全面指南,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《深入浅出SpringBootWebSocket构建实时应用全面指南》WebSocket是一种在单个TCP连接上进行全双工通信的协议,这篇文章主要为大家详细介绍了SpringBoot如何集成WebS...

前言

为什么需要 WebSocket

在传统的 Web 应用中,通信模式主要是 HTTP 请求-响应客户端(通常是浏览器)发起一个请求,服务器处理后返回一个响应,然后连接关闭。这种模式对于获取网页内容、提交表单等操作非常有效。

然而,随着 Web 应用的复杂化,我们越来越多地需要实时、双向、持续的通信能力。例如:

  • 在线聊天室: 用户发送消息,所有在线用户能立即看到。
  • 实时通知: 新邮件、好友请求、系统告警需要即时推送给用户。
  • 股票行情/数据仪表盘: 价格、状态需要秒级甚至毫秒级更新。
  • 在线游戏 玩家状态、游戏事件需要实时同步。
  • 协作编辑: 多人同时编辑文档,彼此的修改需要实时可见。

如果使用传统的 HTTP 轮询(Polling)或长轮询(Long Polling)来实现这些功能,会带来巨大的服务器压力、延迟高、效率低下。WebSocket 协议的出现,正是为了解决这些问题。

WebSocket 是什么

WebSocket 是一种在单个 TCP 连接上进行全双工(full-duplex)通信的协议。它允许服务器主动向客户端推送数据,而无需客户端先发起请求。一旦建立连接,客户端和服务器就可以像打电话一样,随时向对方发送消息,实现真正的实时双向通信。

Spring Boot 如何简化 WebSocket 开发

Spring Boot 提供了强大的 spring-boot-starter-websocket 模块,它基于 Spring Framework 的 WebSocket 支持,极大地简化了在 Spring 应用中集成 WebSocket 的过程。它不仅支持原始的 WebSocket API,还集成了 STOMP(Simple Text Oriented Messaging Protocol)协议,使得消息的发布/订阅、点对点通信、用户特定消息等复杂场景变得异常简单。

第一部分:准备工作

1.创建 Spring Boot 项目

使用 Spring Initializr (https://start.spring.io/) 创建一个新的项目。确保添加以下依赖:

pom.XML (Maven) 相关依赖示例:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-websocket</artifactId>
    </dependency>
    <!-- 可选:用于模板渲染 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <!-- 可选:简化代码 -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <scope>provided</scope>
    </dependency>
</dependencies>
  • Spring Web (spring-boot-starter-web)
  • Spring WebSocket (spring-boot-starter-websocket)
  • (可选) Thymeleaf (spring-boot-starter-thymeleaf) - 用于创建简单的 HTML 前端页面进行演示。
  • (可选) Lombok - 简化 Java 代码(如 @Data, @AllArgsConstructor)。

2.项目结构

一个典型的结构可能如下:

src/
├── main/
│   ├── java/
│   │   └── com/example/websocketdemo/
│   │       ├── WebSocketConfig.java
│   │       ├── WebSocketController.java
│   │       ├── model/
│   │       │   └── Message.java
│   │       └── WebSocketDemoApplication.java
│   └── resources/
│       ├── static/
│       │   └── js/
│       │       └── app.js
│       └── templates/
│           └── index.html
└── test/
    └── ...

第二部分:配置 WebSocket (WebSocketConfig)

这是启用和配置 WebSocket 功能的核心步骤。我们需要创建一个配置类。

package com.example.websocketdemo;

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;

/**
 * WebSocket 配置类
 * @EnableWebSocketMessageBroker 注解启用 STOMP 消息代理功能。
 */
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    /**
     * 配置消息代理(Message Broker)
     * 消息代理负责处理来自客户端的消息,并将消息广播给订阅了特定目的地的客户端。
     *
     * @param config MessageBrokerRegistry
     */
    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        // 1. 启用一个简单的内存消息代理,用于处理以 "/topic" 或 "/queue" 开头的消息。
        //    - "/topic" 通常用于**发布/订阅**模式(一对多广播)。
        //    - "/queue" 通常用于**点对点**模式(一对一,但多个订阅者时会负载均衡)。
        config.enableSimpleBroker("/topic", "/queue");

        // 2. 定义应用目的地前缀。
        //    所有以 "/app" 开头的 STOMP 消息都会被路由到带有 @MessageMapping 注解的控制器方法中。
        //    例如:客户端发送到 "/app/hello" 的消息会被 @MessageMapping("/hello") 的方法处理。
        config.setApplicationDestinationPrefixes("/app");

        // (可选) 设置用户目的地前缀 (用于用户特定消息)
        // config.setUserDestinationPrefix("/user");
    }

    /**
     * 注册 STOMP 协议的 WebSocket 端点。
     * 客户端通过这些端点与服务器建立 WebSocket 连接。
     *
     * @param registry StompEndpointRegistry
     */
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        // 1. 注册一个名为 "/ws" 的端点。
        //    客户端将连接到 "ws://<server>:<port>/ws" (HTTP) 或 "wss://<server>:<port>/ws" (HTTPS)。
        registry.addEndpoint("/ws")

                // 2. 启用 SockJS 作为后备机制。
                //    SockJS 是一个 JavaScript 库,它在浏览器不支持原生 WebSocket 时,
                //    会尝试使用其他技术(如轮询)来模拟 WebSocket 行为,提高兼容性。
                //    客户端连接时,如果使用 SockJS,URL 会是 "/ws/sockjs/info" 等。
                .withSockJS();

        // (可选) 可以注册多个端点
        // registry.addEndpoint("/another-endpoint").withSockJS();
    }
}

关键点解析:

@EnableWebSocketMessageBroker: 这个注解是开启 Spring WebSocket 支持的关键,它启用了 STOMP 消息代理。

configureMessageBroker:

  • enableSimpleBroker(...): 启用一个简单的内存消息代理。对于生产环境,你可能需要集成更强大的消息代理,如 RabbitMQRedis(通过 @EnableStompBrokerRelay 配置),以实现集群部署和消息持久化。
  • setApplicationDestinationPrefixes(...): 定义了应用处理消息的前缀。/app 是约定俗成的前缀。

registerStompEndpoints:

  • addEndpoint("/ws"): 定义了 WebSocket 连接的实际路径。
  • .withSockJS(): 强烈建议启用,以确保在老旧浏览器或网络环境下的兼容性。

第三部分:定义消息模型 (Message.java)

创建一个简单的 POJO 类来表示我们要发送和接收的消息。

package com.example.websocketdemo.model;

import lombok.Data;
import lombok.AllArgsConstructor;

/**
 * 消息实体类
 */
@Data
@AllArgsConstructor
public class Message {
    private String content; // 消息内容
    private String sender;  // 发送者
    private long timestamp; // 时间戳

    // 无参构造函数(JSON 反序列化需要)
    public Message() {}

    // (可选) 可以添加更多字段,如消息类型、接收者等
}

第四部分:创建 WebSocket 控制器 (WebSocketController.java)

这个控制器负责处理来自客户端的消息(通过 @MessageMapping)以及向客户端发送消息(通过 SimpMessagingTemplate)。

package com.example.websocketdemo;

import com.example.websocketdemo.model.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.util.HtmlUtils;

import java.time.Instant;

/**
 * WebSocket 消息处理控制器
 */
@Controller // 使用 @Controller 而不是 @RestController,因为通常不直接返回 HTTP 响应
public class WebSocketController {

    // SimpMessagingTemplate 用于从服务器端任意位置向客户端发送消息
    @Autowired
    private SimpMessagingTemplate messagingTemplate;

    /**
     * 处理客户端发送到 "/app/hello" 的消息。
     * 此方法将处理消息,并将处理后的结果广播给所有订阅了 "/topic/greetings" 的客户端。
     *
     * @param message 客户端发送的原始消息 (Message 对象)
     * @return 处理后的消息 (Message 对象) - 这个返回值会被 @SendTo 指定的目的地接收
     * @throws Exception
     */
    @MessageMapping("/hello") // 监听目的地 "/app/hello"
    @SendTo("/topic/greetings") // 将方法返回值发送到 "/topic/greetings"
    public Message greeting(@Payload Message message) throws Exception {
        // 模拟一些处理延迟
        Thread.sleep(1000);

        // 返回一个处理后的消息,包含原内容、发送者和当前时间戳
        return new Message(
   http://www.chinasem.cn             "Hello, " + HtmlUtils.htmlEscape(message.getSender()) + "!",
                "Server",
                Instant.now().toEpochMilli()
        );
    }

    /**
     * 处理客户端发送到 "/app/chat" 的消息。
     * 这个方法展示了如何使用 SimpMessagingTemplate 进行更灵活的消息发送。
     * 它不会返回值给 @SendTo,而是直接使用 messagingTemplate 发送消息。
     *
     * @param message 客户端发送的聊天消息
     */
    @MessageMapping("/chat")
    public void handleChatMessage(@Payload Message message) {
        // 可以在这里进行消息验证、存储到数据库等操作
        // ...

        // 使用 SimpMessagingTemplate 将消息广播给所有订阅了 "/topic/chat" 的客户端
        messagingTemplate.convertAndSend("/topic/chat", message);

        // (示例) 向特定用户发送消息 (需要配置用户目的地前缀)
        // messagingTemplate.convertAndSendToUser("username", "/queue/private", privateMessage);
    }

    /**
     * (可选) 示例:从服务器内部其他地方(如定时任务、服务)触发消息发送
     */
    // @Scheduled(fixedRate = 5000)
    // public void sendServerTime() {
    //     Message timeMessage = new Message("Server Time: " + Instant.now(), "System", Instant.now().toEpochMilli());
    //     messagingTemplate.convertAndSend("/topic/greetings", timeMessage);
    // }
}

关键点解析:

  • @Controller: 标记为控制器。

@MessageMapping("/hello"): 将方法映射到 STOMP 消息的目的地 /app/hello。客户端发送到 /app/hello 的消息会触发此方法。

@Payload: 明确指定参数是从消息体(Payload)中提取并反序列化为 Message 对象的。

@SendTo("/topic/greetings"): 指定该方法的返回值应该发送到 /topic/greetings 这个目的地。所有订阅了此目的地的客户端都会收到此消息。

SimpMessagingTemplate: 这是一个强大的工具,允许你在代码的任何地方(而不仅限于 @MessageMapping 方法)发送消息。

  • convertAndSend(destination, payload) 方法会将 payload 对象序列化(通常是 JSON)并发送到指定的 destination
  • convertAndSendToUser(user, destination, payload) 用于向特定用户发送消息(需要配置用户目的地前缀和用户识别机制)。

第五部分:创建前端页面 (index.html)

使用 Thymeleaf 创建一个简单的 HTML 页面来测试我们的 WebSocket 功能。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
  <head>
    <meta charset="UTF-8" />
    <title>Spring Boot WebSocket Demo</title>
    <!-- 引入 SockJS 客户端库 (如果配置了 withSockJS) -->
    <script src="https://cdn.jsdelivr.nepythont/npm/sockjs-client@1/dist/sockjs.min.js"></script>
    <!-- 引入 STOMP 客户端库 -->
    <script src="https://cdn.jsdelivr.net/npm/@stomp/stompjs@6.1.0/bundles/stomp.umd.min.js"></script>
    <!-- (可选) Bootstrap 用于美化 -->
    <link
      href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="external nofollow" 
      rel="stylesheet"
    />
  </head>
  <body>
    <div class="container mt-5">
      <h1>WebSocket Chat & Greeting Demo</h1>

      <div class="row">
        <div class="col-md-6">
          <h3>Send Greeting</h3>
          <form id="greetingForm">
            <div class="mb-3">
              <label for="greetingSender" class="form-label">Your Name:</label>
              <input
                type="text"
                class="form-control"
                id="greetingSender"
                placeholder="Enter your name"
                required
              />
            </div>
            <button type="submit" class="btn btn-primary">Send Greeting</button>
          </form>
        </div>

        <div class="col-md-6">
          <h3>Chat Room</h3>
          <form id="chatForm">
            <div class="mb-3">
              <label for="chatSender" class="form-label">Nickname:</label>
              <input
                type="text"
                class="form-control"
                id="chatSender"
                placeholder="Enter nickname"
                required
              />
            </div>
            <div class="mb-3">
              <label for="chatMessage" class="form-lpythonabel">Message:</label>
              <textarea
                class="form-control"
                id="chatMessage"
                rows="3"
                placeholder="Type your message..."
                required
              ></textarea>
            </div>
            <button type="submit" class="btn btn-success">Send Message</button>
          </form>
        </div>
      </div>

      <dwww.chinasem.cniv class="row mt-4">
        <div class="col-md-6">
          <h3>Greetings Received</h3>
          <ul id="greetingList" class="list-group"></ul>
        </div>
        <div class="col-md-6">
          <h3>Chat Messages</h3>
          <ul id="chatList" class="list-group"></ul>
        </div>
      </div>
    </div>

    <!-- 引入自定义 JavaScript -->
    <script th:src="@{/js/app.js}"></script>
  </body>
</html>

第六部分:编写前端 JavaScript (app.js)

这是前端与 WebSocket 交互的核心逻辑。

// 定义全局变量
let jsstompClient = null
let connected = false

// 页面加载完成后执行
document.addEventListener("DOMContentLoaded", function () {
  connect()
})

// 连接到 WebSocket 服务器
function connect() {
  // 1. 创建 SockJS 实例,连接到后端配置的端点 "/ws"
  //    如果后端没有配置 withSockJS,则使用 new WebSocket("ws://localhost:8080/ws");
  const socket = new SockJS("/ws") // 注意:路径是相对于当前页面的,这里假设在根路径

  // 2. 使用 SockJS 实例创建 STOMP 客户端
  stompClient = Stomp.over(socket)

  // 3. 连接到 STOMP 代理
  stompClient.connect(
    {},
    function (frame) {
      console.log("Connected: " + frame)
      connected = true
      // 更新 UI 状态 (可选)
      // document.getElementById('connectionStatus').innerHTML = 'Connected';

      // 4. 订阅目的地 "/topic/greetings"
      //    当服务器向 "/topic/greetings" 发送消息时,onGreetingReceived 函数会被调用
      stompClient.subscribe("/topic/greetings", onGreetingReceived)

      // 5. 订阅目的地 "/topic/chat"
      stompClient.subscribe("/topic/chat", onChatMessageReceived)
    },
    function (error) {
      console.error("Connection error: " + error)
      connected = false
      // 重连逻辑 (可选)
      // setTimeout(function() { connect(); }, 5000);
    }
  )
}

// 处理从 "/topic/greetings" 接收到的消息
function onGreetingReceived(payload) {
  const message = JSON.parse(payload.body)
  const greetingList = document.getElementById("greetingList")
  const item = document.createElement("li")
  item.textContent = `[${new Date(message.timestamp).toLocaleTimeString()}] ${
    message.sender
  }: ${message.content}`
  item.className = "list-group-item list-group-item-info"
  greetingList.appendChild(item)
  // 自动滚动到底部
  greetingList.scrollTop = greetingList.scrollHeight
}

// 处理从 "/topic/chat" 接收到的消息
function onChatMessageReceived(payload) {
  const message = JSON.parse(payload.body)
  const chatList = document.getElementById("chatList")
  const item = document.createElement("li")
  item.textContent = `[${new Date(message.timestamp).toLocaleTimeString()}] ${
    message.sender
  }: ${message.content}`
  item.className = "list-group-item"
  chatList.appendChild(item)
  chatList.scrollTop = chatList.scrollHeight
}

// 处理 "Send Greeting" 表单提交
document
  .getElementById("greetingForm")
  .addEventListener("submit", function (event) {
    event.preventDefault() // 阻止表单默认提交行为
    const senderInput = document.getElementById("greetingSender")
    const sender = senderInput.value.trim()
    if (sender && connected) {
      // 发送消息到目的地 "/app/hello"
      // 消息体是一个 JSON 字符串
      stompClient.send(
        "/app/hello",
        {},
        JSON.stringify({ sender: sender, content: "Greeting Request" })
      )
      senderInput.value = "" // 清空输入框
    } else if (!connected) {
      alert("WebSocket not connected!")
    }
  })

// 处理 "Send Message" 表单提交
document
  .getElementById("chatForm")
  .addEventListener("submit", function (event) {
    event.preventDefault()
    const senderInput = document.getElementById("chatSender")
    const messageInput = document.getElementById("chatMessage")
    const sender = senderInput.value.trim()
    const content = messageInput.value.trim()
    if (sender && content && connected) {
      // 发送消息到目的地 "/app/chat"
      const chatMessage = {
        sender: sender,
        content: content,
        timestamp: new Date().getTime(), // 客户端时间戳,服务器会用自己的
      }
      stompClient.send("/app/chat", {}, JSON.stringify(chatMessage))
      // 清空输入框
      messageInput.value = ""
      // (可选) 立即将消息显示在本地聊天列表(回显),服务器广播后会再次收到
      // onChatMessageReceived({body: JSON.stringify(chatMessage)});
    } else if (!connected) {
      alert("WebSocket not connected!")
    }
  })

// (可选) 断开连接函数
function disconnect() {
  if (stompClient) {
    stompClient.disconnect()
    connected = false
    console.log("Disconnected")
    // 更新 UI 状态
    // document.getElementById('connectionStatus').innerHTML = 'Disconnected';
  }
}

// 页面卸载时断开连接
window.addEventListener("beforeunload", function () {
  disconnect()
})

关键点解析:

  • SockJS('/ws'): 创建 SockJS 连接,路径必须与后端 WebSocketConfigaddEndpoint("/ws") 一致。
  • Stomp.over(socket): 使用 SockJS 连接创建 STOMP 客户端。
  • stompClient.connect(headers, connectCallback, errorCallback): 连接到 STOMP 代理。headers 通常为空对象 {}
  • stompClient.subscribe(destination, callback): 订阅一个目的地。callback 函数接收一个 payload 参数,其 body 属性是服务器发送的原始消息字符串(通常是 JSON)。
  • stompClient.send(destination, headers, body): 向指定目的地发送消息。body 是消息内容(字符串)。
  • JSON.parse(payload.body): 将接收到的 JSON 字符串解析成 JavaScript 对象。
  • JSON.stringify(object): 将 JavaScript 对象序列化成 JSON 字符串发送。

第七部分:运行与测试

启动应用: 运行 WebSocketDemoApplication.javamain 方法。

访问页面: 打开浏览器,访问 http://localhost:8080 (或你配置的端口和路径)。

观察控制台: 打开浏览器的开发者工具(F12),查看 Network 和 Console 标签页。你应该能看到 SockJS 或 WebSocket 连接建立成功 (CONNECTED 帧)。

测试功能:

  • 在 “Send Greeting” 区域输入名字并点击 “Send Greeting”。稍等 1 秒,你会在 “Greetings Received” 列表中看到服务器返回的 “Hello, [你的名字]!” 消息。
  • 在 “Chat Room” 区域输入昵称和消息,点击 “Send Message”。消息会立即出现在 “Chat Messages” 列表中(因为服务器广播回所有客户端,包括发送者)。
  • 打开多个浏览器标签页或窗口访问同一个页面。在一个窗口发送消息,其他所有窗口都会实时收到更新!这就是 WebSocket 的魔力。

第八部分:高级主题与最佳实践

1.用户认证与授权 (Security):

  • 通常需要将 WebSocket 连接与用户的登录会话关联。可以在 WebSocketConfigregisterStompEndpoints 中添加拦截器,或者在 HttpSessionHandshakeInterceptor 中将用户信息存入 WebSocketSession 的属性。
  • 使用 Spring Security 保护 /ws 端点,确保只有认证用户才能连接。
  • @MessageMapping 方法上使用 @PreAuthorize 进行细粒度权限控制。
  • 使用 messagingTemplate.convertAndSendToUser(username, destination, payload) 向特定用户发送私有消息。需要配置 setUserDestinationPrefix("/user")

2.消息代理 (Message Broker):

Simple Broker: 适用于单机部署的简单应用。在集群环境下,不同实例间的客户端无法互相通信。

STOMP Broker Relay (推荐生产环境): 配置 Spring Boot 应用连接到外部的、功能更强大的 STOMP 消息代理(如 RabbitMQ, ActiveMQ, Redis)。

// 在 WebSocketConfig 中
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
    // 配置应用目的地前缀
    config.setApplicationDestinationPrefixes("/app");
    // 配置用户目的地前缀
    config.setUserDestinationPrefix("/user");

    // 启用 STOMP 代理中继,连接到外部的 Broker
    config.enableStompBrokerRelay("/topic", "/queue")
          .setRelayHost("localhost") // 外部 Broker 的主机
          .setRelayPort(61613)      // STOMP 端口 (RabbitMQ 默认 61613)
          .setClientLogin("guest")  // Broker 用户名
          .setClientPasscode("guest"); // Broker 密码
}

优势: 支持集群、消息持久化、更复杂的消息路由、高可用性。

3.异常处理:

  • 可以使用 @ControllerAdvice@MessageExceptionHandler 注解来处理 @MessageMapping 方法中抛出的异常,并向客户端发送错误消息。
  • 处理连接断开 (WebSocketSession 关闭) 的逻辑。

4.性能与监控:

  • 监控连接数、消息吞吐量。
  • 考虑消息大小和频率,避免网络拥塞。
  • 对于高并发场景,优化线程池配置。

5.前端库选择:

  • @stomp/stompjs 是目前最流行和维护良好的 STOMP 客户端库。
  • sockjs-client 是 SockJS 的官方库。

第九部分:总结

通过本文的详细步骤,我们成功地在 Spring Boot 应用中集成并实现了 WebSocket 功能。我们学习了:

  • 核心概念: WebSocket 协议、STOMP、消息代理、发布/订阅模式。
  • 配置: 使用 @EnableWebSocketMessageBrokerWebSocketMessageBrokerConfigurer 进行配置。
  • 后端开发: 使用 @MessageMapping, @SendTo, SimpMessagingTemplate 处理消息和发送消息。
  • 前端开发: 使用 sockjs-client@stomp/stompjs 库建立连接、订阅、发送消息。
  • 高级主题: 安全、消息代理、异常处理。

Spring Boot 的 WebSocket 支持使得构建实时 Web 应用变得相对简单和高效。掌握这些知识,你就可以为你的应用添加强大的实时交互能力了。

下一步:

  • 尝试集成 Spring Security 进行用户认证。
  • 将简单消息代理替换为 RabbitMQ 或 Redis。
  • 实现更复杂的聊天功能,如群组、在线状态、消息历史记录。
  • 探索 WebSocket 在游戏、协作工具等领域的应用。

以上就是深入浅出SpringBoot WebSocket构建实时应用全面指南的详细内容,更多关于SpringBoot WebSocket构建实时应用的资料请关注China编程(www.chinasem.cn)其它相关文章!

这篇关于深入浅出SpringBoot WebSocket构建实时应用全面指南的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1155528

相关文章

Java中流式并行操作parallelStream的原理和使用方法

《Java中流式并行操作parallelStream的原理和使用方法》本文详细介绍了Java中的并行流(parallelStream)的原理、正确使用方法以及在实际业务中的应用案例,并指出在使用并行流... 目录Java中流式并行操作parallelStream0. 问题的产生1. 什么是parallelS

Java中Redisson 的原理深度解析

《Java中Redisson的原理深度解析》Redisson是一个高性能的Redis客户端,它通过将Redis数据结构映射为Java对象和分布式对象,实现了在Java应用中方便地使用Redis,本文... 目录前言一、核心设计理念二、核心架构与通信层1. 基于 Netty 的异步非阻塞通信2. 编解码器三、

SpringBoot基于注解实现数据库字段回填的完整方案

《SpringBoot基于注解实现数据库字段回填的完整方案》这篇文章主要为大家详细介绍了SpringBoot如何基于注解实现数据库字段回填的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解... 目录数据库表pom.XMLRelationFieldRelationFieldMapping基础的一些代

一篇文章彻底搞懂macOS如何决定java环境

《一篇文章彻底搞懂macOS如何决定java环境》MacOS作为一个功能强大的操作系统,为开发者提供了丰富的开发工具和框架,下面:本文主要介绍macOS如何决定java环境的相关资料,文中通过代码... 目录方法一:使用 which命令方法二:使用 Java_home工具(Apple 官方推荐)那问题来了,

JDK21对虚拟线程的几种用法实践指南

《JDK21对虚拟线程的几种用法实践指南》虚拟线程是Java中的一种轻量级线程,由JVM管理,特别适合于I/O密集型任务,:本文主要介绍JDK21对虚拟线程的几种用法,文中通过代码介绍的非常详细,... 目录一、参考官方文档二、什么是虚拟线程三、几种用法1、Thread.ofVirtual().start(

Java HashMap的底层实现原理深度解析

《JavaHashMap的底层实现原理深度解析》HashMap基于数组+链表+红黑树结构,通过哈希算法和扩容机制优化性能,负载因子与树化阈值平衡效率,是Java开发必备的高效数据结构,本文给大家介绍... 目录一、概述:HashMap的宏观结构二、核心数据结构解析1. 数组(桶数组)2. 链表节点(Node

Java AOP面向切面编程的概念和实现方式

《JavaAOP面向切面编程的概念和实现方式》AOP是面向切面编程,通过动态代理将横切关注点(如日志、事务)与核心业务逻辑分离,提升代码复用性和可维护性,本文给大家介绍JavaAOP面向切面编程的概... 目录一、AOP 是什么?二、AOP 的核心概念与实现方式核心概念实现方式三、Spring AOP 的关

详解SpringBoot+Ehcache使用示例

《详解SpringBoot+Ehcache使用示例》本文介绍了SpringBoot中配置Ehcache、自定义get/set方式,并实际使用缓存的过程,文中通过示例代码介绍的非常详细,对大家的学习或者... 目录摘要概念内存与磁盘持久化存储:配置灵活性:编码示例引入依赖:配置ehcache.XML文件:配置

Java 虚拟线程的创建与使用深度解析

《Java虚拟线程的创建与使用深度解析》虚拟线程是Java19中以预览特性形式引入,Java21起正式发布的轻量级线程,本文给大家介绍Java虚拟线程的创建与使用,感兴趣的朋友一起看看吧... 目录一、虚拟线程简介1.1 什么是虚拟线程?1.2 为什么需要虚拟线程?二、虚拟线程与平台线程对比代码对比示例:三

从基础到高级详解Go语言中错误处理的实践指南

《从基础到高级详解Go语言中错误处理的实践指南》Go语言采用了一种独特而明确的错误处理哲学,与其他主流编程语言形成鲜明对比,本文将为大家详细介绍Go语言中错误处理详细方法,希望对大家有所帮助... 目录1 Go 错误处理哲学与核心机制1.1 错误接口设计1.2 错误与异常的区别2 错误创建与检查2.1 基础