Spring RestTemplate 发起 GET 请求时正确塞入 Headers 的完整实例
记录一次用 RestTemplate 调接口需要带自定义请求头的经历,把整个实现和依赖都贴出来,避免后来人绕路。
支持通配符SSL证书、多域名证书、IP证书。适配ACME接口, 支持Zerossl、Let's Encrypt和Google等渠道。登录已有账号
2026-08-01 10:15:34 Spring WebFlux Reactor Netty 响应式编程 Java
WebFlux 默认跑在 Netty 上,异步非阻塞那套东西,跟传统的 Servlet 容器区别挺大。这里把涉及到的 Reactor 编程、Netty 集成和一些实际写法梳理一下。
Reactor 提供了 Mono 和 Flux 两种基础类型,一个处理 0 到 1 个元素,一个处理 0 到 N 个。创建很简单:
Mono<String> mono = Mono.just("Hello");
Flux<Integer> flux = Flux.range(1, 5);
有了数据流,就可以链式调用操作符,比如把 1 到 5 每个数乘 2,只留大于 5 的,最后订阅输出。终端操作 subscribe 之前整个流是惰性的,不发数据。
Flux.range(1, 5)
.map(i -> i * 2)
.filter(i -> i > 5)
.subscribe(System.out::println);
响应式宣言里提到的灵敏性、可恢复性、可伸缩性、消息驱动,在 Reactor 里都有对应的实现:异步非阻塞保证快速响应,错误信号单独走 onError 通道方便恢复和降级,背压让消费者控制生产速率来伸缩,底层事件循环驱动消息传递,整体很轻量。
服务器这块,引入 spring-boot-starter-webflux 后默认带的就是 Reactor Netty,启动日志里能直接看到 Netty 监听的端口。
2025-09-05 14:30:22.123 INFO 12345 --- [ main] o.s.b.web.embedded.netty.NettyWebServer : Netty started on port 8080
想换成 Undertow 的话,排除掉 reactor-netty,再加 undertow 的 starter 就行。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-reactor-netty</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
跟 Vert.x 配合有两种路子。最直接的就是用 WebClient 去调 Vert.x 的 HTTP 服务,把响应包成 Mono。
WebClient client = WebClient.create("http://vertx-service:8081");
Mono<String> result = client.get()
.uri("/api/data")
.retrieve()
.bodyToMono(String.class);
另一种是自己写适配器,实现 Vert.x 的响应式接口和 WebHandler 的对接,相对复杂一些,不过能做到更深度集成。
实际写代码时,WebFlux 支持函数式和注解两种风格。函数式定义路由比较灵活:
@Bean
public RouterFunction<ServerResponse> routerFunction() {
return RouterFunctions.route()
.GET("/hello", request -> ServerResponse.ok().body(Mono.just("Hello, WebFlux!"), String.class))
.build();
}
注解方式跟 Spring MVC 很像,用 @RestController 和 @GetMapping,返回值包成 Mono 或 Flux。
@RestController
public class UserController {
@GetMapping("/user/{id}")
public Mono<User> getUser(@PathVariable String id) {
return userService.getUserById(id);
}
@PostMapping("/user")
public Mono<Void> saveUser(@RequestBody User user) {
return userService.saveUser(Mono.just(user));
}
}
Netty 和 Vert.x 的定位不太一样。
Netty 就是个高性能 NIO 框架,事件循环单线程处理 I/O,WebFlux 开箱即用。Vert.x 更像全栈响应式工具集,默认用 Worker 线程池(也能配),集成到 WebFlux 得手动适配。一般项目用 Netty 足够了,除非你重度依赖 Vert.x 生态或者有特殊线程模型需求。
这套组合在小规模或 I/O 密集型场景下跑起来挺稳的,函数式路由适合复杂规则,注解方式直来直去。
线上如果遇到高并发,背压的调整往往是关键。
上一篇: Java类初始化失败:NoClassDefFoundError排查与解决
下一篇: 微信自定义分享卡片样式实现方案
记录一次用 RestTemplate 调接口需要带自定义请求头的经历,把整个实现和依赖都贴出来,避免后来人绕路。
记录一次排序 NPE 的排查和解决,顺便说下 IDEA 调试集合时 null 元素不显示的问题怎么调整。
跑单测突然报 Command line is too long,大多数情况在 Run Configuration 里勾一个选项就完事。这里把原因和几种方案一起记一下。
面对Java解析XML,DOM与DOM4J是两大主流选择。本文详尽分析标准DOM的内置优势与DOM4J在API简洁性、性能及XPath支持上的卓越表现。无论小型配置还是大型数据处理,助你理解两者差异,做出明智的技术选型。
拥抱Java 8及更高版本带来的日期处理革新!本文聚焦于yyyy-MM-dd格式化,详细对比传统SimpleDateFormat与现代DateTimeFormatter。深入探讨DateTimeFormatter为何成为未来主流,其不可变性、线程安全等核心优势如何助你构建更健壮、高效的应用。是时候升级你的日期格式化方式了!