Servlet containers, clients
Servlet containers
Jetty
✅ Yes
✅ Yes (via async I/O)
✅ Yes
✅ Yes (with Coroutine-based APIs)
Tomcat
✅ Yes
✅ Yes (via async servlets)
✅ Yes
⚠️ Limited (needs adapters like ktor-server-tomcat
)
Undertow
✅ Yes
✅ Yes (reactive streams)
✅ Yes
✅ Yes (used in ktor-server-undertow
)
Netty (is not a servlet container—it's an event-driven network application framework that can be used to build non-blocking servers and clients)
⚠️ Not its primary model
✅ Yes (fully event-driven)
✅ Yes
✅ Yes (integrates well with Ktor and coroutines)
Clients
RestTemplate
✅ Yes
❌ No
⚠️ Limited
Synchronous API, designed for Spring MVC.
WebClient (Reactor Netty (default in Spring Boot))
⚠️ Limited
✅ Yes
✅ Yes
Non-blocking, reactive web client from Spring WebFlux.
Ktor
✅ Yes
✅ Yes
✅ Yes
Designed for Kotlin; supports both blocking and non-blocking calls.
OkHttp
✅ Yes
✅ Yes
⚠️ Limited
Primarily synchronous but supports asynchronous requests; good for Kotlin coroutines.
Apache HttpClient
✅ Yes
⚠️ Limited
⚠️ Limited
Synchronous by default; can use Future
for async.
Retrofit
✅ Yes
✅ Yes
✅ Yes
Works with OkHttp, designed for REST APIs; supports coroutines via extensions.
Vert.x Web Client
❌ No
✅ Yes
✅ Yes
Fully non-blocking and designed for asynchronous programming.
Spring’s WebClient
is a non-blocking HTTP client, but it can use different underlying engines for handling HTTP requests.
What determines WebClient's underlying engine?
It depends on which Spring Boot starter you include:
If using
spring-boot-starter-webflux
(Reactive)WebClient defaults to Netty (via
Reactor Netty
).Netty handles HTTP connections asynchronously.
If using
spring-boot-starter-web
(Blocking, Tomcat)WebClient uses Apache HttpClient or Java’s
HttpURLConnection
.It can still be non-blocking at the application level, but the underlying client might not be fully asynchronous.
If you’re making a few HTTP requests per second → You can use a blocking client inside coroutines with
Dispatchers.IO
Last updated
Was this helpful?