Why this matters
- Spring Boot builds on the Servlet API — understanding the container explains why annotations like
@GetMappingwork and where request threads come from. - Production issues such as thread pool exhaustion and slow responses often trace back to servlet container behaviour, not your business logic.
- Interviewers frequently ask how an HTTP request reaches a Java method; a clear servlet mental model separates confident answers from vague ones.
The servlet contract
Before Spring existed, Java web apps implemented jakarta.servlet.http.HttpServlet. The container calls doGet, doPost, or similar methods for each request. Your BookStore health check could have looked like this:
public class HealthServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
resp.setContentType("application/json");
resp.getWriter().write("{\"status\":\"UP\"}");
}
}
Spring MVC replaces hand-written servlets with @RestController classes, but underneath Tomcat still dispatches to a DispatcherServlet — a servlet that delegates to your controllers.
Key servlet types
- Servlet container — Embedded Tomcat in Boot; manages threads, parses HTTP, and invokes servlets.
- HttpServletRequest — Read-only view of headers, path, query params, and body.
- HttpServletResponse — Where you set status codes, headers, and write the response body.
- Filter — Runs before the servlet; used for logging, compression, and security (covered later).
From URL to handler method
When a client calls GET /api/books/42, the container:
Request handling steps
- Accepts the TCP connection on port 8080.
- Parses the HTTP request line and headers.
- Matches the path against registered servlet mappings.
- Invokes
DispatcherServlet.service(), which finds@GetMapping("/api/books/{id}")onBookController. - Serialises the returned
BookResponseto JSON and flushes the response.
The entire round trip happens on one container thread unless you explicitly go async.
Embedded Tomcat in Spring Boot
Boot ships with an embedded servlet container so you never deploy a WAR to a standalone Tomcat. Running BookStoreApplication starts Tomcat on the classpath:
server:
port: 8080
servlet:
context-path: /bookstore
With context-path set, every endpoint moves under /bookstore — useful when multiple services share a gateway.
Request and response headers
Headers carry metadata the container does not interpret for routing:
@GetMapping("/api/books")
public List<BookSummary> listBooks(
@RequestHeader(value = "Accept-Language", defaultValue = "en") String locale) {
return bookService.findAll(locale);
}
Content-Type: application/json tells the client how to parse the body. Accept tells the server what format the client prefers. Spring's HttpMessageConverter handles the conversion automatically.
Thread-per-request model
Tomcat maintains a thread pool (default max 200). Each request occupies one thread for its full duration. A slow database query in BookService blocks that thread until the query completes. This is why connection pool sizing and query performance matter at the web layer.
Servlet spec vs Spring abstractions
| Aspect | Servlet layer | Spring Boot equivalent |
|---|---|---|
| URL mapping | web.xml servlet mapping | @GetMapping, @PostMapping |
| Request filtering | Filter | Filter bean or Spring Security chain |
| Request data | HttpServletRequest | @PathVariable, @RequestBody |
| Response body | Manual JSON writing | HttpMessageConverter + Jackson |
URL mapping
Servlet layerweb.xml servlet mappingSpring Boot equivalent@GetMapping, @PostMappingRequest filtering
Servlet layerFilterSpring Boot equivalentFilter bean or Spring Security chainRequest data
Servlet layerHttpServletRequestSpring Boot equivalent@PathVariable, @RequestBodyResponse body
Servlet layerManual JSON writingSpring Boot equivalentHttpMessageConverter + Jackson
You rarely touch servlets directly in Boot, but knowing they exist explains stack traces that mention DispatcherServlet and StandardWrapperValve.
Observing the flow locally
Start the BookStore app and watch Tomcat log the port:
./mvnw spring-boot:run
curl -v http://127.0.0.1:8080/api/books
The -v flag prints request and response headers — the same bytes Tomcat parsed before your controller ran.
Quick recall
Everything you need if you only revisit this box.
- A servlet container (Tomcat) parses HTTP and invokes servlet code on a thread-per-request model.
- Spring MVC's
DispatcherServletis a servlet that maps URLs to@RestControllermethods. - Boot embeds Tomcat — no external server install or WAR deployment required.
HttpServletRequestandHttpServletResponseare the low-level API; Spring wraps them with annotations.- Thread pool exhaustion is a container-level problem caused by blocking I/O in handlers.
- Filters run before servlets and form the basis of Spring Security's filter chain.
Test yourself
Answer these before moving on — recall is what makes it stick.