Careeroza
How a Request Reaches Your Controller
The Request Flow
Spring MVC is built around one central servlet, the DispatcherServlet (the "front controller"). Every request goes through it.
curl GET /api/products
|
v
Embedded Tomcat (port 8080) -- reads the HTTP text, makes a request object
|
v
DispatcherServlet -- the front controller
| 1. HandlerMapping: which method handles GET /api/products ?
v
ProductController.all() -- your code runs, returns List<Product>
|
v
HttpMessageConverter (Jackson) -- List<Product> -> JSON text
|
v
Response: 200 OK, Content-Type: application/json, body [...]A Mini Dispatcher in Plain Java
Example
The core of handler mapping is a lookup from "method + path" to a handler function. A tiny version, including the 404 and 405 cases Spring returns:
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
public class Main {
static final Map<String, Supplier<Object>> handlers = new LinkedHashMap<>();
static final List<String> catalogue = List.of("Boat Rockerz 450", "Clean Code");
static String dispatch(String method, String path) {
Supplier<Object> handler = handlers.get(method + " " + path);
if (handler != null) return "200 OK " + handler.get();
boolean pathExists = handlers.keySet().stream().anyMatch(k -> k.endsWith(" " + path));
return pathExists ? "405 Method Not Allowed" : "404 Not Found";
}
public static void main(String[] args) {
// what @GetMapping registers at startup
handlers.put("GET /api/products", () -> catalogue);
handlers.put("GET /api/products/count", () -> catalogue.size());
handlers.put("GET /ping", () -> Map.of("status", "UP"));
System.out.println("GET /api/products -> " + dispatch("GET", "/api/products"));
System.out.println("GET /api/products/count -> " + dispatch("GET", "/api/products/count"));
System.out.println("GET /ping -> " + dispatch("GET", "/ping"));
System.out.println("DELETE /api/products -> " + dispatch("DELETE", "/api/products"));
System.out.println("GET /api/orders -> " + dispatch("GET", "/api/orders"));
}
}Output
GET /api/products -> 200 OK [Boat Rockerz 450, Clean Code]
GET /api/products/count -> 200 OK 2
GET /ping -> 200 OK {status=UP}
DELETE /api/products -> 405 Method Not Allowed
GET /api/orders -> 404 Not FoundMappings in the Log
Set logging.level.org.springframework.web=DEBUG to see which handler each request goes to. Very useful when you get an unexpected 404.
Example
curl http://localhost:8080/api/productsExample output
... DEBUG ... o.s.web.servlet.DispatcherServlet : GET "/api/products", parameters={}
... DEBUG ... s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to com.shopease.product.ProductController#all()
... DEBUG ... m.m.a.RequestResponseBodyMethodProcessor : Using 'application/json', given [*/*] and supported [application/json, ...]
... DEBUG ... o.s.web.servlet.DispatcherServlet : Completed 200 OK