ReviseAlgo Logo

Building REST APIs

@RestController, @RequestMapping, and HTTP Method Annotations

Configuring REST endpoints and mapping GET, POST, PUT, DELETE operations.

Last Updated: June 15, 2026 12 min read

Introduction

In Spring MVC, web controllers are traditionally used to return HTML templates (like Thymeleaf or JSP). For RESTful APIs, we serve structured data directly (e.g., JSON or XML). The @RestController annotation is a specialized stereotype annotation that combines @Controller and @ResponseBody, instructing Spring to serialize method return values directly into the HTTP response body.

Why It Matters

By using @RestController, you separate the concerns of data presentation (handled by the client-side single page app or mobile client) from data delivery. It streamlines web endpoint design, automatically converting Java objects to JSON via configured HttpMessageConverters, and provides clean, standard RESTful paths using @RequestMapping and method-level HTTP verb shortcuts.

Real-World Analogy

Think of a traditional @Controller like a full-service dine-in restaurant. The waiter takes your order, goes to the kitchen, prepares a beautiful, complete plate (HTML page), and serves it at your table. A @RestController, on the other hand, is like a wholesale grocery supplier window. You submit a list (HTTP request), and they hand you back a standard cardboard box of raw ingredients (JSON payload). They do not decorate it or serve it on plates; you decide how to prepare or render the data.

How It Works

When a client makes a request to your API, the DispatcherServlet acts as the Front Controller, routing the request through the following steps:

  1. HandlerMapping: Spring scans for classes marked with @RestController (which makes them eligible beans) and looks for matching path routes mapped via @RequestMapping.
  2. HandlerAdapter: Spring executes the target method. If the controller class or method is marked with @ResponseBody (which is implicit in @RestController), Spring bypasses MVC view resolvers.
  3. HttpMessageConverter: Spring inspects the return type and the request's Accept header (e.g., application/json). It iterates over registered converters and selects the matching one (usually MappingJackson2HttpMessageConverter) to serialize the Java object into JSON text returned to the client.

Practical Example

Here is a complete, standard CRUD Controller managing a Product resource using method-specific routing:

Quick Quiz

Q1: Which two annotations are combined into @RestController?

A) @Controller and @ResponseBody

B) @Controller and @RequestMapping

C) @Component and @ResponseBody

D) @Repository and @Controller

Answer: A — @RestController is a meta-annotation composed of @Controller and @ResponseBody, meaning all return values are serialized directly into the response body.

Q2: Which HTTP method mapping is typically expected to be non-idempotent?

A) GET

B) PUT

C) DELETE

D) POST

Answer: D — POST is non-idempotent because submitting multiple identical requests will result in multiple resource creations. GET, PUT, and DELETE are designed to be idempotent.

Scenario-Based Challenge

Production Scenario:

Your team needs to implement an API that updates a user profile. A junior developer proposes using a POST request to /api/users/update-profile. How would you refactor this to follow standard RESTful design guidelines?

View Solution

Avoid putting verbs/actions in the URL path (like /update-profile). Instead, represent the profile as a resource under the user, and use HTTP verbs to declare the action: Use a PUT request to /api/users/{userId}/profile for complete profile replacements (idempotent), or a PATCH request to /api/users/{userId}/profile for partial updates (e.g. updating only the bio field).

Interview Questions

1. How does Spring decide which HttpMessageConverter to use for converting returned objects into JSON?

Spring uses a process called content negotiation. It reads the incoming request's Accept header (e.g., application/json) and matches it against the supported media types of the registered converters. If Jackson is present on the classpath, the MappingJackson2HttpMessageConverter is registered automatically and selected to convert the return value to JSON.

2. Can you define @RequestMapping at both the class level and the method level? How do they merge?

Yes. Class-level @RequestMapping defines a shared base path for all endpoints in the controller. Method-level mappings (like @GetMapping("/details")) append their path to the base path (resulting in /base-path/details). Method-level mappings override class-level defaults for HTTP verbs.

Production Considerations

Keep your controllers lean and stateless. They should only handle HTTP routing, validation triggers, and parameter binding. All business logic, transaction scopes, and exception handling details should be delegated to the service layer to ensure scalability and high testability.