@RestController & @RequestMapping in Spring Boot: HTTP Verbs, Path Variables

Master Spring Boot REST endpoint mapping: @RestController, @RequestMapping, @GetMapping, path variables, query params, and handler method signatures.

published: reading time: 23 min read author: GeekWorkBench
Quick Summary

Master Spring Boot REST endpoint mapping: @RestController, @RequestMapping, @GetMapping, path variables, query params, and handler method signatures. The guide uses practical examples to explain @restcontroller vs @controller, @requestmapping basics and shows how to apply the ideas in a Spring Boot project. It closes with common pitfalls and production checks so you can apply the pattern with fewer surprises.

@RestController and @RequestMapping in Spring Boot

Introduction

@RestController vs @Controller

Before mapping URLs, you need to understand what @RestController actually is.

@RestController is a composed annotation that combines @Controller and @ResponseBody. This means two things: the class is a Spring bean eligible for component scanning, and every method return value is written directly to the HTTP response body rather than being resolved through a view template.

// This
@RestController
public class UserController { }

// Is equivalent to this
@Controller
@ResponseBody
public class UserController { }

If you need to serve HTML pages (Thymeleaf, FreeMarker), use plain @Controller. If you are building a REST API where the response is JSON or XML, use @RestController. Mixing both in one class is possible by annotating specific methods with @ResponseBody, but it is cleaner to keep them separate.

@RequestMapping Basics

@RequestMapping on a class sets a base path. All methods in the class inherit it and append their own paths.

@RestController
@RequestMapping("/api/users")
public class UserController {

    @RequestMapping(method = RequestMethod.GET)
    public List<User> listUsers() {
        return userService.findAll();
    }

    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public User getUser(@PathVariable Long id) {
        return userService.findById(id);
    }
}

The URL resolves to /api/users for listUsers() and /api/users/{id} for getUser(), where {id} is a path variable.

HTTP Method Shortcuts

Writing method = RequestMethod.GET every time is tedious. Spring provides shortcut annotations for each HTTP method:

@RestController
@RequestMapping("/api/users")
public class UserController {

    @GetMapping             // equivalent to @RequestMapping(method = RequestMethod.GET)
    public List<User> listUsers() { ... }

    @GetMapping("/{id}")    // /api/users/{id} — GET
    public User getUser(@PathVariable Long id) { ... }

    @PostMapping           // /api/users — POST
    public User createUser(@RequestBody @Valid UserInput input) { ... }

    @PutMapping("/{id}")   // /api/users/{id} — PUT
    public User updateUser(@PathVariable Long id, @RequestBody @Valid UserInput input) { ... }

    @DeleteMapping("/{id}") // /api/users/{id} — DELETE
    public void deleteUser(@PathVariable Long id) { ... }

    @PatchMapping("/{id}")  // /api/users/{id} — PATCH
    public User patchUser(@PathVariable Long id, @RequestBody Map<String, Object> updates) { ... }
}

All six shortcut annotations (@GetMapping, @PostMapping, @PutMapping, @DeleteMapping, @PatchMapping, @OptionsMapping) accept the same parameters as @RequestMapping: value, path, method, params, headers, consumes, produces.

Path Variables

Use @PathVariable to extract dynamic segments from the URL path.

@GetMapping("/users/{id}/orders/{orderId}")
public Order getUserOrder(
        @PathVariable Long id,
        @PathVariable Long orderId) {
    return orderService.findForUser(id, orderId);
}

Spring matches {id} and {orderId} to the method parameters by name. You can also specify the variable name explicitly if your parameter name has been erased by the Java compiler (due to -parameters flag not being set):

@PathVariable("id") Long userId  // explicit name when compiler strips parameter names

Multiple path variables in a single URL are fine—each maps to its own parameter. Just make sure the parameter types are compatible with what appears in the URL. If a user sends /users/abc/orders/123, Spring throws a type mismatch exception and returns a 400 Bad Request.

Regex Constraints on Path Variables

You can constrain what a path variable matches using regex syntax:

@GetMapping("/users/{id:^[0-9]{1,10}$}")
public User getUserByNumericId(@PathVariable Long id) { ... }

This endpoint only matches when id is a numeric string of 1 to 10 digits. Anything else returns 404. This is useful when you have multiple endpoints with overlapping patterns and need to disambiguate.

Query Parameters

Use @RequestParam for URL query strings and form data.

@GetMapping("/users/search")
public List<User> searchUsers(
        @RequestParam String name,
        @RequestParam(required = false) String email,
        @RequestParam(defaultValue = "0") int page,
        @RequestParam(defaultValue = "20") int size) {
    return userService.search(name, email, page, size);
}

Called with: /api/users/search?name=alice&email=alice@example.com&page=2&size=10

Key points about @RequestParam:

  • required = false makes the parameter optional—method must handle null
  • defaultValue = “0” provides a value when the parameter is absent
  • You cannot combine required = false with a primitive (int, boolean) because primitives cannot be null—use their wrapper types (Integer, Boolean) instead
  • The parameter name in the method must match the query string key, or use @RequestParam(“name”) to map explicitly

Request Body

Use @RequestBody to deserialize the request body into a Java object. Spring uses the Content-Type header to select the appropriate HttpMessageConverter.

@PostMapping("/users")
public User createUser(@RequestBody @Valid UserInput input) {
    return userService.create(input);
}

@Valid (from Bean Validation, JSR-380) triggers validation on the input object before the method runs. If validation fails, Spring throws a MethodArgumentNotValidException and returns a 422 Unprocessable Entity with details.

For JSON, Spring uses MappingJackson2HttpMessageConverter by default. For XML, you need jaxb2-root-http-message-converter on the classpath. For plain text, StringHttpMessageConverter handles it.

Response Handling

@RestController methods can return:

Plain objects — serialized via HttpMessageConverter:

@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) {
    return userService.findById(id);  // serialized to JSON automatically
}

ResponseEntity<T> — full control over status code, headers, and body:

@PostMapping("/users")
public ResponseEntity<User> createUser(@RequestBody @Valid UserInput input) {
    User created = userService.create(input);
    return ResponseEntity.created(URI.create("/api/users/" + created.getId()))
            .body(created);
}

void — suitable for responses where the status is set via ServletResponse or when you handle the response directly:

@DeleteMapping("/users/{id}")
public void deleteUser(@PathVariable Long id) {
    userService.delete(id);
    // Returns 200 OK with empty body
}

Content Negotiation

Spring MVC uses the Accept header to determine the response format. If a client sends Accept: application/json, it gets JSON. If it sends Accept: application/xml, it gets XML (if an XML converter is configured).

You can also force a format via the produces attribute on the mapping:

@GetMapping(value = "/users/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
public User getUserAsJson(@PathVariable Long id) { ... }

@GetMapping(value = "/users/{id}", produces = MediaType.APPLICATION_XML_VALUE)
public User getUserAsXml(@PathVariable Long id) { ... }

This creates two distinct endpoints differentiated by the Accept header. Spring matches based on the Accept header, not the URL.

Similarly, consumes restricts what request content types are accepted:

@PostMapping(value = "/users", consumes = MediaType.APPLICATION_JSON_VALUE)
public User createUser(@RequestBody @Valid UserInput input) { ... }

A request with Content-Type: text/plain to this endpoint returns 415 Unsupported Media Type.

Request Flow

graph TD
    A[HTTP Request] --> B[DispatcherServlet]
    B --> C[HandlerMapping<br/>matches URL + HTTP method]
    C --> D[HandlerAdapter<br/>calls controller method]
    D --> E[Method executes<br/>@PathVariable, @RequestParam, @RequestBody resolved]
    E --> F[Return value processed<br/>via HttpMessageConverter]
    F --> G[HTTP Response sent]

DispatcherServlet is the front controller that routes all requests. HandlerMapping implementations (usually RequestMappingHandlerMapping) scan for @RequestMapping annotations and build a map of URL patterns to handler methods. HandlerAdapter (usually RequestMappingHandlerAdapter) invokes the actual method, resolving parameters along the way.

When to Use @RestController vs @ControllerAdvice

@ControllerAdvice (or @RestControllerAdvice which combines both) lets you apply cross-cutting behavior to all controllers—like global exception handling, binding result normalization, or adding common response headers.

Use @RestControllerAdvice when all your responses are bodies (REST APIs). Use @ControllerAdvice when you have template-based controllers mixed in.

Failure Scenarios

405 Method Not Allowed

  • Cause: The URL exists but the HTTP method has no handler. For example, sending POST to /api/users/123 when only @GetMapping(“/{id}”) is defined.
  • Fix: Add the missing mapping method or use @RequestMapping(method = RequestMethod.ALL) to catch all methods on a given path.

404 Not Found

  • Cause: No handler matches the URL pattern. Check for typos, missing leading slashes, or mismatched path variable names.
  • Fix: Verify the @GetMapping(“/users/{id}”) annotation matches the URL being requested.

400 Bad Request from path variable type mismatch

  • Cause: Sending /users/abc when the parameter is declared as Long id. Spring cannot convert “abc” to a Long.
  • Fix: Validate the input format on the client side, or use a regex constraint on the path variable.

415 Unsupported Media Type

  • Cause: Sending a request with a Content-Type your endpoint does not consume. The @PostMapping defaults to consuming nothing unless you specify consumes.
  • Fix: Add consumes = MediaType.APPLICATION_JSON_VALUE if your endpoint expects JSON.

Null @RequestParam when parameter is missing

  • Cause: @RequestParam without required = false on an optional parameter, or using a primitive type.
  • Fix: Use required = false with a wrapper type (Integer not int).

When to Use / When NOT to Use

When to Use @RestController

@RestController is the right choice when every method in your class returns data to be serialized directly into the HTTP response body — JSON, XML, plain text. If you are building a REST API, a microservice, or any endpoint-oriented service where views and templates are not involved, @RestController eliminates the boilerplate of annotating every method with @ResponseBody.

When NOT to Use @RestController

If you need to serve HTML pages through a template engine like Thymeleaf or FreeMarker, use plain @Controller. Mixing template rendering and REST endpoints in the same class is technically possible but creates confusion. If you find yourself adding @ResponseBody to most methods in a @Controller class, just switch to @RestController instead.

When to Use @GetMapping / @PostMapping etc

Use the specific HTTP method annotations whenever the method only handles one HTTP verb. They reduce noise in your code and make the intent of each endpoint immediately obvious when reading the class. These annotations also set up the correct consumes and produces defaults automatically.

When to Use @RequestMapping with Explicit Method

Use @RequestMapping(method = RequestMethod.GET) (or the equivalent) when you need to handle multiple HTTP methods on the same path, or when you are building a less common endpoint (like OPTIONS or TRACE) that does not have its own shortcut annotation.

When to Use Path Variables

Use @PathVariable when a piece of data is inherently part of the URL structure — a resource ID, a username, an order number. The URL /users/42 makes sense as a bookmarkable, shareable resource address. Do not cram everything into path variables though; if the parameter is an optional filter rather than a resource identifier, @RequestParam is more appropriate.

When to Use @RequestParam

Use @RequestParam for query parameters that represent optional filters, sorting, pagination, or any data that is not intrinsic to the resource identity. If you find yourself building queries like /search?name=alice&status=active, those are query parameters.

Trade-Off Table

Annotation Best Used For Avoid When
@RestController REST APIs returning JSON/XML Template-based HTML rendering
@Controller View templates (Thymeleaf, JSP) Pure API endpoints
@GetMapping Read-only endpoint retrieval Mutations (use POST/PUT/DELETE)
@PostMapping Creating resources Read operations (misleading semantics)
@PathVariable Resource identifiers in URL path Optional filters or search parameters
@RequestParam Query parameters, optional filters Core resource identity (use path var)
@RequestBody JSON/XML payloads deserialized to object Form fields (use @ModelAttribute)
ResponseEntity<T> Full control over status, headers, body Simple returns where 200 is assumed

Common Pitfalls / Anti-Patterns

  1. Forgetting the leading slash on paths: @GetMapping(“users”) maps to /users relative to the servlet context, not /users relative to the class-level @RequestMapping. Be explicit: @GetMapping(“/users”).
  2. Path variable name mismatch after compilation: If you compile without the -parameters flag, Java erases parameter names. Use @PathVariable(“id”) explicitly rather than relying on the compiler.
  3. Combining @PathVariable and @RequestParam with the same name: They are independent; you can have /users/{id}?name=alice where both resolve to different values.
  4. Returning null from a @GetMapping: This returns an empty JSON null or 204 No Content depending on your configuration. If null is a valid business response, return Optional<User> instead.
  5. Missing @Valid on @RequestBody: Without it, invalid input passes through without validation errors. Always add @Valid for user input.

Security Notes

  • Validate all path variables and request parameters: They are user-controlled. A Long id path variable that queries a database should check ownership before returning data.
  • Limit request body size: Prevent large payload attacks by setting server.tomcat.max-http-form-post-size or equivalent for your server.
  • Sensitive data in query strings: Query parameters appear in logs and browser history. Do not pass tokens, passwords, or PII as query parameters—use headers or request bodies instead.
  • CORS configuration: If your API is called from browsers, configure CORS via @CrossOrigin on the controller or a global WebMvcConfigurer—do not allow arbitrary origins in production.

Observability Checklist

  • Verify all endpoints are reachable via a contracts test or API integration test
  • Confirm 405 is returned when an HTTP method is not allowed on a valid URL
  • Check that path variable regex constraints are tested
  • Confirm @Valid on @RequestBody methods catches invalid input and returns 422
  • Verify CORS is configured correctly for all origins that need access
  • Log request paths at INFO or DEBUG level to track which endpoints are hit
  • Confirm sensitive data is not logged in query strings

Quick Recap Checklist

  • @RestController = @Controller + @ResponseBody (all return values go to response body)
  • @RequestMapping on a class sets the base path; methods append to it
  • Use @GetMapping / @PostMapping / @PutMapping / @DeleteMapping / @PatchMapping as shortcuts for common verbs
  • @PathVariable extracts dynamic URL segments; use explicit names if compiling without -parameters
  • @RequestParam extracts query string parameters; use required = false for optional ones
  • @RequestBody deserializes the request body; add @Valid to trigger Bean Validation
  • ResponseEntity<T> gives full control over status, headers, and body
  • Use produces and consumes to restrict media types for content negotiation
  • @ControllerAdvice / @RestControllerAdvice for global exception handling across all controllers
  • Never pass sensitive data in query string parameters

Interview Questions

1. What is the difference between @RestController and @Controller?

@RestController is a composed annotation that combines @Controller and @ResponseBody. In a plain @Controller, method return values are passed to a view resolver for template rendering. In a @RestController, every return value is serialized directly to the response body via an HttpMessageConverter. If you need both view rendering and REST endpoints in the same class, use @Controller and annotate specific methods with @ResponseBody.

2. How do you handle optional query parameters in a Spring MVC endpoint?

Use @RequestParam(required = false) on a method parameter of type Integer, Boolean, or another wrapper type—primitives cannot be null. You can also provide a defaultValue to use when the parameter is absent. If the parameter is missing and required is not set to false, Spring returns a 400 Bad Request. For multiple optional parameters, each needs its own @RequestParam annotation.

3. What causes a 405 Method Not Allowed response in a Spring Boot application?

A 405 means the URL pattern matches a handler but that HTTP method has no mapped method. For example, sending a POST to /api/users/123 when only @GetMapping("/{id}") is defined. The fix is to add the missing HTTP method handler. Spring's DispatcherServlet matches the incoming request against all registered @RequestMapping patterns and returns 405 if the method is not among them. You can also use @RequestMapping(method = RequestMethod.ALL) to catch unimplemented methods, though returning 405 is usually the correct behavior.

4. How does Spring MVC resolve @PathVariable and @RequestParam annotations at runtime?

RequestMappingHandlerAdapter invokes each controller method via HandlerMethodArgumentResolver implementations. When a request arrives, the adapter iterates through the method parameters and finds the corresponding resolver for each one—PathVariableMethodArgumentResolver for @PathVariable, RequestParamMethodArgumentResolver for @RequestParam, and so on. Each resolver reads from the HTTP request (URL path, query string, headers, body) and converts the value to the parameter type. If conversion fails, a type mismatch triggers a 400 Bad Request before your method ever executes.

5. When would you use @ControllerAdvice instead of simple try-catch blocks inside a controller method?

@ControllerAdvice (or @RestControllerAdvice) applies global behavior across all controllers without repeating code. It is the right tool for centralized exception handling, normalizing binding errors into a consistent response format, adding headers to every response, or applying request-wide data binding. A try-catch inside one method only affects that method. As soon as you find yourself catching the same exception type in multiple controllers, that is the signal to move the logic to a @RestControllerAdvice.

6. How does content negotiation work in Spring MVC, and when would you use the produces attribute?

Content negotiation selects the response format based on the Accept header. If a client sends Accept: application/json, Spring uses an JSON serializer; Accept: application/xml triggers XML serialization. The produces attribute on a mapping annotation forces a specific content type, effectively creating separate endpoints for different formats at the same URL. Use produces when you need to serve different representations (JSON vs XML) from the same URL based on client preference. The consumes attribute mirrors this for request body formats.

7. What is the role of HttpMessageConverter in a Spring REST endpoint?

HttpMessageConverter bridges between Java objects and HTTP request/response bodies. On the way in, MappingJackson2HttpMessageConverter (for JSON) deserializes the request body into a Java object. On the way out, it serializes the return value to the response body. Spring Boot auto-configures a set of converters including JSON, XML, and plain text. You can register custom converters or override defaults via WebMvcConfigurer. The converter selected depends on the Content-Type header for requests and the Accept header or produces attribute for responses.

8. What is the difference between @PathVariable and @RequestParam? When would you choose one over the other?

@PathVariable extracts dynamic segments from the URL path itself—part of the resource address, like /users/42. @RequestParam extracts query string parameters—optional modifiers like ?page=2&size=20. Choose @PathVariable when the data is a resource identifier intrinsic to the URL; choose @RequestParam when it is an optional filter, search term, or pagination control. Mixing both is valid: /users/{id}/orders?status=shipped uses both correctly.

9. How does Spring handle a type mismatch when binding a path variable, and what HTTP error does the client receive?

When a @PathVariable Long id receives a non-numeric value like /users/abc, Spring's PathVariableMethodArgumentResolver fails to convert the string to a Long and throws a TypeMismatchException. Before your controller method executes, Spring's exception handling kicks in and returns a 400 Bad Request with a descriptive error message. This is one of several parameter resolution failures that short-circuit the request before it reaches your handler method. Using regex constraints on path variables ({id:^[0-9]+$}) can prevent ambiguous matches that result in 404 instead of 400.

10. What happens if you omit @Valid on a @RequestBody parameter in a Spring REST endpoint?

Without @Valid, Spring deserializes the request body into your Java object but skips Bean Validation entirely. Invalid input—wrong types, missing required fields, constraint violations—passes silently into your method. Your service layer must then handle malformed data, or worse, bad data reaches the database. Add @Valid to trigger JSR-380 validation before the method executes. Validation failures throw MethodArgumentNotValidException, which @RestControllerAdvice can intercept to return a structured 422 Unprocessable Entity response.

11. Can a single controller method handle multiple HTTP verbs? If so, how?

Yes, by using @RequestMapping with no method specified, the mapping matches all HTTP verbs. Alternatively, list multiple methods explicitly: @RequestMapping(value = "/resource", method = {RequestMethod.GET, RequestMethod.POST}). Each shortcut annotation (@GetMapping, @PostMapping, etc.) maps to exactly one verb, so you need the generic @RequestMapping for multi-verb endpoints. Be careful: a single method handling both GET and POST is valid but can confuse API consumers and violates REST semantics where POST and GET have distinct semantics.

12. What is the difference between returning null and returning Optional from a @GetMapping method?

Returning null from a @GetMapping produces an empty JSON null or a 204 No Content depending on your Spring configuration. Either way, the client cannot tell whether the resource was not found or simply returned a null value. Returning Optional<User> makes the intent explicit: an empty Optional means no resource, which you can handle explicitly to return 404 Not Found. Spring's Optional handling via RequestMappingHandlerAdapter converts an empty Optional to a proper 404 response automatically.

13. How does the request flow from DispatcherServlet to your controller method?

The flow: DispatcherServlet receives the HTTP request, then delegates to HandlerMapping (typically RequestMappingHandlerMapping) which finds the matching controller method by URL and HTTP method. HandlerAdapter (RequestMappingHandlerAdapter) invokes the method, during which HandlerMethodArgumentResolver implementations resolve each parameter (@PathVariable, @RequestParam, @RequestBody, etc.). After the method executes, HandlerMethodReturnValueHandler processes the return value—serializing via HttpMessageConverter if it is a body response. The final HTTP response is sent back through DispatcherServlet.

14. What are the advantages of using @GetMapping, @PostMapping etc. over the generic @RequestMapping?

The specific annotations are not just syntactic sugar. Each sets correct defaults: @GetMapping implies produces = MediaType.APPLICATION_JSON_VALUE and rejects a request body, making it semantically correct and harder to misuse. They improve readability—a developer scanning the class immediately knows which HTTP verb each method handles. IDE autocomplete works better with the specific annotations. Under the hood, they all delegate to @RequestMapping, so there is no runtime performance difference.

15. How would you handle file uploads in a Spring REST controller?

Use @RequestParam("file") MultipartFile file on a @PostMapping method. Spring Boot auto-configures MultipartAutoConfiguration and sets a file size limit via spring.servlet.multipart.max-file-size and spring.servlet.multipart.max-request-size. For multiple files, use @RequestParam("files") MultipartFile[] files. Always validate the file type, scan for malicious content, and store files outside the application root—typically on disk or cloud storage like S3. Never trust the MultipartFile.getOriginalFilename() as it comes from the client and could contain path traversal characters.

16. What is the purpose of the params attribute on @RequestMapping?

The params attribute narrows a mapping based on the presence or value of request parameters. For example, @GetMapping(value = "/users", params = "role=admin") only matches requests to /users?role=admin. You can also require a parameter to simply exist: params = "debug" matches any request with a debug parameter. This is useful for creating multiple endpoints at the same URL that respond differently depending on query parameters without requiring a separate path segment or header inspection.

17. How does Spring handle CORS in a REST API, and what are the main approaches to configure it?

Cross-Origin Resource Sharing (CORS) is handled via the Access-Control-Allow-Origin and related headers. In Spring MVC you can annotate a controller or method with @CrossOrigin(origins = "https://example.com") to allow specific origins. For global configuration, implement WebMvcConfigurer and override addCorsMappings() to apply CORS rules to all endpoints matching a path pattern. In Spring Security, CORS configuration lives in the Security filter chain via CorsConfigurationSource. Never allow "*" for credentials-bearing requests in production.

18. What is the difference between @ModelAttribute and @RequestBody in Spring MVC?

@RequestBody deserializes the entire request body (typically JSON or XML) into a single object using an HttpMessageConverter. @ModelAttribute binds query parameters, form fields, and path variables to bean properties via the DataBinder, applying field-by-field binding and validation. Use @RequestBody for structured payloads (JSON POST bodies); use @ModelAttribute for HTML form submissions or when you want Spring to bind individual request parameters to a command object. Mixing both on the same method is valid if the request includes both a body and query parameters.

19. How would you implement pagination for a REST endpoint in Spring Boot?

Use @RequestParam parameters for page number and size, then return a Page<T> from your repository (Spring Data JPA) or manually construct a Page object. Example: @GetMapping("/users?page=0&size=20") with @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "20") int size. Spring Data's PageableHandlerMethodArgumentResolver auto-registers and converts Pageable parameters directly, making repository methods as simple as findAll(Pageable pageable). Always validate page/size bounds to prevent Pageable size attacks that query large offsets.

20. What are the trade-offs between returning ResponseEntity versus a plain object from a @RestController method?

Returning a plain object is concise and relies on Spring's defaults: 200 OK with the serialized body. ResponseEntity<T> gives you explicit control over the HTTP status code, response headers (including Location for resource creation), and the body. For simple read endpoints where 200 is always correct, a plain return is cleaner. For create endpoints that need to return 201 with a Location header, update endpoints that might return 204, or error responses that need custom headers, ResponseEntity is the right tool. Avoid returning null for error cases—use ResponseEntity.notFound().build() or throw an exception handled by @RestControllerAdvice.

Further Reading

Conclusion

@RestController and @RequestMapping form the foundation of Spring Boot’s web layer. Every endpoint in a Spring Boot REST API traces back to these two annotations—one marking the class as a web handler, the other binding URL patterns and HTTP methods to handler methods. The convenience variants (@GetMapping, @PostMapping, and their counterparts) reduce boilerplate and make the intended HTTP verb immediately visible when reading code.

The annotations that power parameter binding—@PathVariable, @RequestParam, and @RequestBody—each solve distinct binding problems: URL segments, query parameters, and request bodies respectively. Mixing these up is the most common source of 400 and 405 errors in Spring MVC applications. @PathVariable is for resource identifiers baked into the URL path. @RequestParam is for optional modifiers like pagination and search filters. @RequestBody is for structured payloads deserialized from the request body. Always pair @RequestBody with @Valid to enforce constraint validation before your method executes.

For response construction, prefer plain return values for simple read endpoints where 200 is always correct. Reach for ResponseEntity<T> when you need to set status codes, add headers, or return different status codes based on business logic. Centralize error and validation handling in a @RestControllerAdvice rather than scattering try-catch blocks across controllers. Content negotiation through the Accept header and produces/consumes attributes lets a single URL serve multiple representations (JSON, XML) to different clients, but only when the converters for those formats are on the classpath.

Category

Related Posts

Spring Boot Build Tools: Maven & Gradle

Configure Maven and Gradle for Spring Boot projects—plugins, dependency management, packaging JARs and WARs, and build automation essentials.

#spring-boot #spring-boot-roadmap #learning-path

Embedded Web Servers in Spring Boot: Tomcat, Jetty, Undertow

Configure embedded servers in Spring Boot: compare Tomcat, Jetty, and Undertow, tune thread pools, enable access logs, and switch implementations.

#spring-boot #spring-boot-roadmap #learning-path

JUnit 5 & Jupiter: Lifecycle, Nested & Parameterized Tests

Explore JUnit 5 Jupiter features: master test lifecycle annotations, organize tests with @Nested, and parameterize tests with @CsvSource and @MethodSource.

#spring-boot #spring-boot-roadmap #learning-path