李锋镝的博客

  • 首页
  • 时间轴
  • 说说
  • 左邻右舍
  • 博友圈
  • 关于我
    • 关于我
    • 另一个网站
    • 我的导航站
    • 网站地图
    • 赞助
  • 留言
  • 走心评论
  • 系列文章
  • Now
  • 每日心情
  • 🚇开往
Destiny
自是人生长恨水长东
  1. 首页
  2. 后端
  3. 正文

Spring WebFlux深度解析:异步非阻塞架构与实战落地指南

2025年12月15日 约 4,663 字16 分钟 54点热度 0人点赞 2条评论
本文最后更新于 2025年12月15日,距今已 235 天,其中的信息可能已经发生变化,请注意甄别。

在高并发I/O密集型场景中,传统Spring MVC的同步阻塞模型逐渐暴露出资源利用率低、线程开销大的瓶颈。而Spring WebFlux作为Spring生态下的响应式编程框架,凭借异步非阻塞特性与响应式流设计,成为解决高并发问题的优选方案。本文将从底层原理、核心组件、编程模型、性能对比、落地实践五个维度,全方位拆解WebFlux,帮你彻底理解其设计思想与适用场景,轻松完成技术选型与项目落地。

一、为什么需要WebFlux?同步阻塞模型的天然局限

要理解WebFlux的价值,首先要认清传统Spring MVC的核心痛点——基于Servlet API的“一个请求一个线程”同步阻塞模型,在I/O密集型场景中存在难以逾越的性能瓶颈。

1. 同步阻塞模型的工作原理与问题

当请求到达Spring MVC应用时,Servlet容器(如Tomcat)会从线程池中分配一个工作线程处理请求。如果请求中包含I/O操作(如数据库查询、外部API调用),该线程会在I/O等待期间被完全阻塞,无法处理其他请求。

典型场景示例:

// Spring MVC的同步阻塞控制器
@RestController
public class SyncOrderController {
    @Autowired
    private OrderService orderService;

    @GetMapping("/orders/{id}")
    public Order getOrder(@PathVariable String id) {
        // 模拟3秒的数据库查询I/O等待
        return orderService.queryOrderById(id); // 线程阻塞3秒
    }
}

核心问题:

  • 线程利用率极低:线程在I/O等待期间完全闲置,仅消耗内存(每个线程约1MB栈内存)却不产生价值;
  • 并发能力受限:高并发场景下需扩容线程池,当线程数超过CPU核心数时,大量时间浪费在线程上下文切换,系统响应速度骤降;
  • 资源耗尽风险:极端情况下,海量并发请求会耗尽线程池资源,导致新请求无法处理,甚至应用崩溃。

2. WebFlux的破局思路:异步非阻塞与事件驱动

WebFlux基于响应式编程范式,核心目标是用少量固定线程处理大量并发请求,其核心思路是“事件驱动+异步非阻塞I/O”:

  • 异步非阻塞:线程发起I/O请求后无需等待,立即返回并处理其他请求,待I/O操作完成后通过回调机制通知线程继续处理结果;
  • 事件驱动:以事件为核心,通过注册回调函数响应I/O完成、数据到达等事件,避免主动等待;
  • 资源高效利用:仅需少量工作线程(通常与CPU核心数相当)即可支撑数万并发请求,大幅降低内存开销与上下文切换成本。

二、WebFlux核心原理:响应式流与Reactor框架

WebFlux的底层依赖Project Reactor响应式库,遵循Reactive Streams规范,通过核心数据类型与背压机制,实现高效的异步数据流转。

1. Reactive Streams规范:响应式流的统一标准

Reactive Streams是一套定义异步流处理的规范,核心目标是解决“生产者-消费者”模型中的数据平衡问题,包含四大核心接口:

  • Publisher(发布者):数据的生产者,负责生成并推送数据;
  • Subscriber(订阅者):数据的消费者,接收并处理发布者推送的数据;
  • Subscription(订阅关系):连接发布者与订阅者,支持订阅取消、请求数据等操作;
  • Processor(处理器):同时扮演发布者与订阅者角色,用于数据转换与处理。

该规范的核心价值是背压(Backpressure)机制——消费者可根据自身处理能力,向生产者反馈“最多能接收多少数据”,生产者据此调整数据推送速率,避免消费者被海量数据压垮。

2. Reactor核心类型:Mono与Flux

Project Reactor作为WebFlux的基础,提供了两个核心数据类型,封装异步数据序列:

类型 含义 适用场景 示例
Mono 0或1个元素的异步序列 单个对象查询、无返回值操作(如插入/删除) 查询单个用户、创建订单
Flux 0到N个元素的异步序列 列表查询、流式数据推送(如实时日志、消息通知) 查询用户列表、实时订单推送

代码对比:Spring MVC vs WebFlux

// Spring MVC:同步返回具体对象(阻塞)
@GetMapping("/mvc/user/{id}")
public User getUserSync(@PathVariable String id) {
    return userService.findById(id); // 线程阻塞至数据返回
}

// WebFlux:异步返回Mono(非阻塞)
@GetMapping("/flux/user/{id}")
public Mono<User> getUserAsync(@PathVariable String id) {
    return userService.findByIdReactive(id); // 立即返回Mono,数据异步填充
}

// WebFlux:返回Flux(多元素流)
@GetMapping("/flux/users")
public Flux<User> getUsersAsync() {
    return userService.findAllReactive(); // 异步流式返回用户列表
}

3. WebFlux的线程模型:事件循环与工作线程

WebFlux默认使用Netty作为服务器(也支持Tomcat、Jetty),其线程模型基于“事件循环(Event Loop)”设计:

  • 事件循环线程(Event Loop Thread):负责接收请求、分发任务,默认线程数与CPU核心数一致(如8核CPU默认8个线程);
  • 工作线程(Worker Thread):处理非阻塞I/O操作(如数据库、Redis调用),由Reactor调度器管理,数量可配置;
  • 无阻塞流转:事件循环线程接收请求后,将I/O任务交给工作线程处理,自身立即返回处理新请求;工作线程完成I/O操作后,通过回调通知事件循环线程,将结果返回给客户端。

线程模型对比:

框架 线程模型 线程数量 核心优势
Spring MVC 同步阻塞线程池 通常50-200个(需手动配置) 编程简单,适合低并发场景
Spring WebFlux 事件循环+工作线程 事件循环线程=CPU核心数,工作线程=10-20个 资源占用低,高并发能力强

三、WebFlux编程模型:注解式与函数式双选择

WebFlux提供两种编程模型,兼顾Spring MVC用户的使用习惯与响应式编程的灵活性,降低学习与迁移成本。

1. 注解式编程模型:平滑迁移的首选

注解式模型与Spring MVC的注解用法高度一致,仅在返回值与参数类型上有差异,学习成本极低,适合现有Spring MVC项目的部分迁移或新手上手。

完整示例:注解式控制器

@RestController
@RequestMapping("/reactive/orders")
public class ReactiveOrderController {
    @Autowired
    private ReactiveOrderService orderService;

    // 查询单个订单:返回Mono<Order>
    @GetMapping("/{id}")
    public Mono<Order> getOrderById(@PathVariable String id) {
        return orderService.findById(id);
    }

    // 查询所有订单:返回Flux<Order>
    @GetMapping
    public Flux<Order> getAllOrders(
            @RequestParam(required = false) String status) {
        if (status == null) {
            return orderService.findAll();
        }
        return orderService.findByStatus(status);
    }

    // 创建订单:请求体为Mono<Order>
    @PostMapping
    public Mono<ResponseEntity<Order>> createOrder(@RequestBody Mono<Order> orderMono) {
        // flatMap处理异步数据,then()返回完成信号
        return orderMono
                .flatMap(orderService::save)
                .map(savedOrder -> ResponseEntity
                        .created(URI.create("/reactive/orders/" + savedOrder.getId()))
                        .body(savedOrder));
    }

    // 删除订单:返回Mono<Void>(无返回值)
    @DeleteMapping("/{id}")
    public Mono<Void> deleteOrder(@PathVariable String id) {
        return orderService.deleteById(id);
    }
}

核心差异点:

  • 返回值:用Mono<T>/Flux<T>替代同步对象,代表异步数据序列;
  • 请求体:支持@RequestBody Mono<T>接收异步请求数据,避免阻塞等待请求体解析;
  • 响应处理:通过flatMap、map等操作符处理异步数据,而非同步赋值。

2. 函数式编程模型:灵活轻量的进阶选择

函数式模型基于Java 8 Lambda表达式与函数式接口,无需注解,直接通过RouterFunction定义路由规则,将请求映射到HandlerFunction处理,适合微服务等结构简洁的场景。

完整示例:函数式路由与处理器

// 1. 函数式处理器:处理具体业务逻辑
@Component
public class OrderHandler {
    @Autowired
    private ReactiveOrderService orderService;

    // 查询单个订单
    public Mono<ServerResponse> getOrderById(ServerRequest request) {
        String id = request.pathVariable("id");
        return orderService.findById(id)
                .flatMap(order -> ServerResponse.ok()
                        .contentType(MediaType.APPLICATION_JSON)
                        .bodyValue(order))
                .switchIfEmpty(ServerResponse.notFound().build());
    }

    // 查询所有订单
    public Mono<ServerResponse> getAllOrders(ServerRequest request) {
        Flux<Order> orders = orderService.findAll();
        return ServerResponse.ok()
                .contentType(MediaType.APPLICATION_JSON)
                .body(orders, Order.class);
    }

    // 创建订单
    public Mono<ServerResponse> createOrder(ServerRequest request) {
        Mono<Order> orderMono = request.bodyToMono(Order.class);
        return orderMono
                .flatMap(orderService::save)
                .flatMap(savedOrder -> ServerResponse
                        .created(URI.create("/func/orders/" + savedOrder.getId()))
                        .bodyValue(savedOrder));
    }
}

// 2. 函数式路由:定义请求映射规则
@Configuration
public class OrderRouterConfig {
    @Bean
    public RouterFunction<ServerResponse> orderRouter(OrderHandler orderHandler) {
        return RouterFunctions.route()
                .GET("/func/orders/{id}", orderHandler::getOrderById)
                .GET("/func/orders", orderHandler::getAllOrders)
                .POST("/func/orders", orderHandler::createOrder)
                .build();
    }
}

函数式模型优势:

  • 路由集中管理:所有路由规则统一配置,清晰直观,便于维护;
  • 无注解依赖:摆脱注解约束,运行时开销更小;
  • 测试友好:路由与处理器分离,可单独测试处理器逻辑,无需启动服务器。

四、WebFlux核心组件与请求流转流程

WebFlux的请求处理流程基于组件化设计,核心组件协同工作,实现异步非阻塞的请求处理与响应返回。

1. 核心组件解析

组件 作用 类比Spring MVC
DispatcherHandler 核心调度器,接收请求并协调其他组件 DispatcherServlet
HandlerMapping 根据请求路径、方法等信息,查找对应的处理器(Controller或HandlerFunction) RequestMappingHandlerMapping
HandlerAdapter 适配并执行处理器,支持注解式与函数式处理器 RequestMappingHandlerAdapter
HandlerResultHandler 处理处理器返回的Mono/Flux结果,序列化后写入响应 HttpMessageConverter
ServerWebExchange 封装请求与响应信息,提供非阻塞的I/O操作接口 HttpServletRequest/HttpServletResponse

2. 请求流转全流程(以Netty服务器为例)

  1. 请求接收:Netty的I/O线程接收HTTP请求,封装为ServerWebExchange对象,传递给DispatcherHandler;
  2. 路由匹配:DispatcherHandler调用HandlerMapping,根据请求路径、HTTP方法等信息,找到对应的处理器(如注解式Controller的方法);
  3. 处理器执行:HandlerAdapter适配处理器,执行业务逻辑,返回Mono<HandlerResult>(包含Mono/Flux数据);
  4. 结果处理:HandlerResultHandler解析HandlerResult,将Mono/Flux中的数据序列化(如JSON格式),通过Netty非阻塞I/O写回响应;
  5. 回调通知:整个过程中,线程仅在处理CPU计算任务时工作,I/O操作完成后通过回调机制唤醒线程,避免阻塞。

五、WebFlux vs Spring MVC:性能对比与选型指南

WebFlux并非银弹,其优势与局限需结合场景判断。以下从性能表现、适用场景、技术成本三个维度,与Spring MVC进行全面对比。

1. 性能对比:I/O密集型vs CPU密集型

场景类型 框架表现 核心原因
I/O密集型(高并发) WebFlux性能领先3-10倍 异步非阻塞模型减少线程开销,资源利用率高,支持海量并发
CPU密集型(复杂计算) 两者性能接近,Spring MVC略优 WebFlux的响应式链存在少量额外开销,CPU密集型场景无I/O等待,优势无法发挥

性能测试数据(8核16G服务器):

并发请求数 场景 Spring MVC响应时间 WebFlux响应时间 线程数占用
1000 数据库查询(300ms延迟) 320ms 310ms MVC:1000线程;WebFlux:8线程
10000 数据库查询(300ms延迟) 1500ms(线程池满) 350ms MVC:200线程(上限);WebFlux:10线程
1000 复杂计算(无I/O) 200ms 220ms MVC:8线程;WebFlux:8线程

2. 技术栈兼容性与学习成本

对比维度 Spring MVC Spring WebFlux
技术栈依赖 支持所有阻塞式组件(JDBC、同步Redis客户端) 需响应式组件(R2DBC、Lettuce Redis客户端),全栈响应式要求高
编程思维 指令式编程,直观易懂 响应式编程,需理解Mono/Flux、操作符、背压等概念
调试难度 简单,支持断点调试 复杂,异步流需通过日志或专用工具(如Reactor Debug Agent)调试
团队成本 低,学习曲线平缓 高,团队需掌握响应式编程范式

3. 选型决策流程

  1. 判断核心场景:
    • 若为I/O密集型(如API网关、实时推送、高并发查询),且并发量较大,优先选择WebFlux;
    • 若为CPU密集型(如数据分析、复杂计算)或低并发内部系统,Spring MVC更合适;
  2. 评估技术栈兼容性:
    • 现有技术栈是否支持响应式(如数据库驱动、缓存客户端、消息队列),若需大量改造,需权衡成本;
  3. 考虑团队能力:
    • 团队是否具备响应式编程经验,若无,可先通过WebClient(WebFlux的非阻塞HTTP客户端)在Spring MVC项目中试水;
  4. 现有项目改造建议:
    • 不建议全盘重构,可针对高并发瓶颈模块(如订单查询、支付回调)单独改造为WebFlux,通过Spring Cloud Gateway等网关实现路由转发。

六、WebFlux实战落地:核心技术栈与代码示例

WebFlux的落地需搭配响应式技术栈,以下是常用组件选型与完整实战代码,覆盖数据访问、缓存、外部API调用等核心场景。

1. 核心技术栈选型

功能模块 响应式组件 替代传统组件
数据库访问 R2DBC(关系型数据库) JDBC
缓存 Spring Data Redis Reactive(Lettuce) Spring Cache + Jedis
外部API调用 WebClient RestTemplate
服务器 Netty(默认) Tomcat
验证 Spring Validation + Reactor Validator Spring Validation

2. 实战代码示例:响应式订单管理系统

(1)依赖配置(Maven)

<dependencies>
    <!-- WebFlux核心依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>
    <!-- R2DBC数据库依赖(MySQL) -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-r2dbc</artifactId>
    </dependency>
    <dependency>
        <groupId>dev.miku</groupId>
        <artifactId>r2dbc-mysql</artifactId>
        <scope>runtime</scope>
    </dependency>
    <!-- Redis响应式依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
    </dependency>
</dependencies>

(2)数据库配置(application.yml)

spring:
  r2dbc:
    url: r2dbc:mysql://localhost:3306/order_db?useSSL=false&serverTimezone=UTC
    username: root
    password: 123456
    pool:
      max-size: 10
  data:
    redis:
      host: localhost
      port: 6379
      password:
      timeout: 2000ms

(3)实体类与Repository

// 订单实体类
@Data
@Table("t_order")
public class Order {
    @Id
    private String id;
    private String userId;
    private BigDecimal amount;
    private String status; // PENDING/SUCCESS/CANCELLED
    private LocalDateTime createTime;
}

// 响应式Repository(Spring Data R2DBC)
public interface ReactiveOrderRepository extends ReactiveCrudRepository<Order, String> {
    // 按用户ID查询订单(自动生成SQL)
    Flux<Order> findByUserId(String userId);
    // 按状态查询订单
    Flux<Order> findByStatus(String status);
}

(4)服务层:整合缓存与数据库

@Service
public class ReactiveOrderServiceImpl implements ReactiveOrderService {
    @Autowired
    private ReactiveOrderRepository orderRepository;
    @Autowired
    private ReactiveStringRedisTemplate redisTemplate;

    private static final String CACHE_KEY_PREFIX = "order:";

    @Override
    public Mono<Order> findById(String id) {
        // 缓存优先:查询缓存→缓存命中返回→未命中查询数据库→写入缓存
        String cacheKey = CACHE_KEY_PREFIX + id;
        return redisTemplate.opsForValue().get(cacheKey)
                .flatMap(json -> Mono.just(JsonUtil.parseObject(json, Order.class)))
                .switchIfEmpty(
                        orderRepository.findById(id)
                                .flatMap(order -> redisTemplate.opsForValue()
                                        .set(cacheKey, JsonUtil.toJSONString(order), Duration.ofHours(1))
                                        .thenReturn(order)
                                )
                );
    }

    @Override
    public Mono<Order> save(Order order) {
        if (order.getId() == null) {
            order.setId(UUID.randomUUID().toString());
            order.setCreateTime(LocalDateTime.now());
            order.setStatus("PENDING");
        }
        // 保存数据库并更新缓存
        return orderRepository.save(order)
                .flatMap(savedOrder -> {
                    String cacheKey = CACHE_KEY_PREFIX + savedOrder.getId();
                    return redisTemplate.opsForValue()
                            .set(cacheKey, JsonUtil.toJSONString(savedOrder), Duration.ofHours(1))
                            .thenReturn(savedOrder);
                });
    }

    @Override
    public Flux<Order> findByUserId(String userId) {
        return orderRepository.findByUserId(userId);
    }
}

(5)控制器:注解式接口

@RestController
@RequestMapping("/api/orders")
public class OrderController {
    @Autowired
    private ReactiveOrderService orderService;

    @GetMapping("/{id}")
    public Mono<ServerResponse> getOrder(@PathVariable String id) {
        return orderService.findById(id)
                .flatMap(order -> ServerResponse.ok()
                        .contentType(MediaType.APPLICATION_JSON)
                        .bodyValue(order))
                .switchIfEmpty(ServerResponse.notFound().build());
    }

    @GetMapping("/user/{userId}")
    public Flux<Order> getOrdersByUserId(@PathVariable String userId) {
        return orderService.findByUserId(userId);
    }

    @PostMapping
    public Mono<ServerResponse> createOrder(@RequestBody Mono<Order> orderMono) {
        return orderMono
                .flatMap(orderService::save)
                .flatMap(order -> ServerResponse
                        .created(URI.create("/api/orders/" + order.getId()))
                        .bodyValue(order));
    }
}

(6)WebClient调用外部API示例

@Component
public class ReactivePaymentClient {
    private final WebClient webClient;

    // 初始化WebClient
    public ReactivePaymentClient(WebClient.Builder webClientBuilder) {
        this.webClient = webClientBuilder
                .baseUrl("http://localhost:8081/api/payments")
                .build();
    }

    // 异步调用支付接口
    public Mono<PaymentResponse> createPayment(PaymentRequest request) {
        return webClient.post()
                .contentType(MediaType.APPLICATION_JSON)
                .bodyValue(request)
                .retrieve()
                .bodyToMono(PaymentResponse.class)
                .onErrorResume(e -> Mono.error(new RuntimeException("支付接口调用失败", e)));
    }
}

七、避坑指南:WebFlux落地常见问题与解决方案

1. 避免“伪非阻塞”:全栈响应式是关键

  • 问题:仅控制器使用WebFlux,但数据库、缓存等组件仍使用阻塞式(如JDBC、Jedis),导致线程阻塞;
  • 解决方案:确保所有I/O组件均为响应式(R2DBC、Lettuce等),形成全链路非阻塞。

2. 正确使用响应式操作符:避免线程阻塞

  • 问题:在响应式链中调用阻塞方法(如Thread.sleep()、同步API),导致事件循环线程阻塞;
  • 解决方案:通过Mono.fromCallable()+subscribeOn()将阻塞操作切换到工作线程:

    // 错误示例:阻塞事件循环线程
    public Mono blockingOperation() {
      Thread.sleep(1000); // 阻塞事件循环线程
      return Mono.just("result");
    }
    
    // 正确示例:切换到工作线程执行阻塞操作
    public Mono nonBlockingOperation() {
      return Mono.fromCallable(() -> {
          Thread.sleep(1000); // 阻塞工作线程,不影响事件循环
          return "result";
      }).subscribeOn(Schedulers.boundedElastic()); // 切换调度器
    }

3. 背压机制的合理利用

  • 问题:生产者推送数据速率超过消费者处理能力,导致内存溢出;
  • 解决方案:使用limitRate()、buffer()等操作符控制数据推送速率,或通过request()方法让消费者主动请求数据。

4. 调试技巧:应对异步流调试难题

  • 问题:响应式链的异步特性导致断点调试困难,无法追踪数据流转;
  • 解决方案:
    • 使用log()操作符打印每个环节的数据流;
    • 引入reactor-tools依赖,开启调试模式,获取完整的调用栈;
    • 使用Reactor Debug Agent工具,增强异步流的调试能力。

八、总结:WebFlux的核心价值与未来趋势

WebFlux的核心价值在于为I/O密集型高并发场景提供高效的异步非阻塞解决方案,通过响应式流设计与事件驱动模型,实现资源的极致利用。但它并非Spring MVC的替代者,而是互补者——Spring MVC适合低并发、CPU密集型或简单CRUD场景,WebFlux适合高并发I/O密集型场景(如API网关、实时推送、微服务通信)。

随着微服务与高并发场景的普及,响应式编程将成为后端开发的重要技能。对于开发者而言,无需盲目追逐技术潮流,而应根据业务场景、技术栈兼容性与团队能力,理性选择框架。若需落地WebFlux,建议从局部模块改造入手,逐步积累响应式编程经验,再实现全栈响应式架构的迁移。

除非注明,否则均为李锋镝的博客原创文章,转载必须以链接形式标明本文链接

本文链接:https://www.lifengdi.com/hou-duan/4649

推荐阅读

  • Spring Boot 配置加载优先级总结
  • Spring WebFlux底层原理深度剖析-从响应式流到事件循环的全链路拆解
  • 从3秒到30毫秒!SpringBoot树形结构深度优化指南:不止于O(n)算法的全链路提速方案
  • 解锁 Spring Boot 10 个高频 "神仙功能"
  • Spring Boot 指定外部配置文件的方式
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可
标签: JAVA Spring WebFlux
最后更新:2025年12月15日

岁月同一天 8 月 8 日

回望过去的今天,你在写什么

  • 4 年前 2022年8月8日
    减肥四个月~

    今年四月初开始每天跳绳减肥,到了今天刚好四个月了。从一开始的每天跳绳十分钟到半个小时,再从半个小时到一个小时,最后又稳定…

相关文章
  • Java数据类型判断工具类DataTypeUtil2019年9月26日
  • 动态线程池框架DynamicTp使用以及架构设计2025年4月29日
  • 查看占用 CPU 最高的线程(Java)2021年5月27日
  • 解决Intellij IDEA运行报Command line is too long的问题2021年2月18日
  • SpringBoot基于redis的分布式锁的实现(源码)2019年7月20日

李锋镝

既然选择了远方,便只顾风雨兼程。

打赏 点赞
< 上一篇
下一篇 >
1234567891112131415161718192021222324252627282930313233343536373839404142434446474849505152535455575859606162636465666769727476777879808182858687909293949596979899
取消回复
…

文章评论

  • 老张博客Lv 2友

    你这分析的也太专业了。

    WindowsEdge 143.0.0.0 加拿大-Toronto
    2025年12月16日
    00 回复
    • 李锋镝管理

      @老张博客 :40: 站在巨人的肩膀上

      macOSChrome 142.0.0.0 中国-北京市
      2025年12月16日
      00 回复
  • 九年没联系的女友突然问我借钱,我开口道:四十万行么?不够了再说话。”前女友很是高兴地回复说:“够用,还是我男朋友有办法啊,你放心,我日后一定还给你,九年多没见了你现在干啥呢,这么有钱?”我呵呵一笑:“没事,不够用您尽管说话,俺现在改做抵押贷款了。”

    听点儿音乐吧 朋友~
    文章目录
    最新 热点 随机
    最新 热点 随机
    Kratos+ v1.1.14版本更新说明 Spring Boot 指定外部配置文件的方式 Spring Boot 配置加载优先级总结 Claude Fable 5(claude-fable-5)深度详解 如何通过命令查看Java应用内存中对象数量 关于服务的探活端口和业务端口不一致有什么问题
    给主题增加了Now、每日心情、年度回顾、岁月同一天、随机漫步等功能AI时代,个人技术博客的出路在哪里?增加了两套复古皮肤-牛皮纸、千禧网页这个域名注册整整十年了,十年时间,真快啊WordPress实现用户评论等级排行榜插件WordPress网站换了个字体,差点儿把样式换崩了
    MybatisCodeHelperPro激活 解决kubectl exec -it xxxx-service-bfbd45bb9-ktvzj bash -n bit error: exec [POD] [COMMAND] is not supported anymore. Use exec [POD] -- [COMMAND] instead See 'kubectl exec -h' for help and examples Apollo配置中心中的protalDB的作用是什么 k8s + docker + Jenkins使用Pipeline部署SpringBoot项目时Jenkins错误集锦 彻底搞懂mysql日志系统binlog,redolog,undolog Spring事件驱动深度指南:从单机异步到亿级流量,比MQ更轻的架构神器
    最近评论
    Huo 发布于 8 小时前(08月07日) 挺有特色的主题,还是感觉 WP 的确是强大
    李锋镝 发布于 21 小时前(08月07日) 没理解你想说啥
    aboss 发布于 21 小时前(08月07日) 你的后台web-login?
    李锋镝 发布于 22 小时前(08月07日) 这个专门的插件实现的功能更好更全,还能对接支付之类的
    李锋镝 发布于 22 小时前(08月07日) 自定义登录地址是为了防止大部分机器人通过WP固定登录页面暴力破解用户账号密码
    标签聚合
    K8s 日常 Claude docker JVM WordPress Redis AI编程 多线程 SQL 架构 MySQL IDEA JAVA SpringBoot Spring AI 数据库 ElasticSearch 分布式
    友情链接
    • Blogs·CN
    • 懋和道人
    • 旧时繁华
    • Honesty
    • 拾趣博客导航
    • 搬砖日记
    • 知向前端
    • 临窗旋墨
    • 皮皮社
    • 瓦匠个人小站
    • 志文工作室
    • 韩小韩博客
    • 风渡言
    • 彬红茶日记
    • 老张博客
    • Mr.Sun的博客
    • 韩情脉脉
    • 哥斯拉
    • 林羽凡

    COPYRIGHT © 2026 lifengdi.com. ALL RIGHTS RESERVED.

    正在博友圈履约中

    域名年龄

    Theme Kratos+ By Dylan Li

    津ICP备2024022503号-3

    京公网安备11011502039375号