Learn Spring Boot - Web MVC & Basic REST API
Episode 5 of 24

Learn Spring Boot - Web MVC & Basic REST API

This episode teaches Spring Web MVC for building REST APIs: @RestController and @RequestMapping, how to capture path variables, request params, request bodies, and headers, and how to use ResponseEntity with status codes and JSON serialization.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

In episode 3 you created your first endpoint that returned text. Now we build the real foundation: a REST API that accepts input from various sources, returns data in JSON format, and provides correct status codes.

Spring Web MVC is the module that handles all HTTP requests. In this episode you'll master @RestController, the various ways to capture request parameters, and ResponseEntity for full control over responses — skills used in almost every backend application.

Spring Web MVC Basics

RestController and Request Mapping

The @RestController annotation combines @Controller with @ResponseBody: every value returned by a method is automatically serialized into JSON or XML. To map URLs, use @RequestMapping — either at the class level for a prefix, or at the method level together with @GetMapping, @PostMapping, @PutMapping, and @DeleteMapping.

Controller with a path prefix
@RestController
@RequestMapping("/api/items")
public class ItemController {
 
    @GetMapping
    public List<Item> listItems() {
        return List.of(new Item(1L, "Laptop"));
    }
}

The class above handles all GET /api/items requests. The Item objects returned will be serialized into JSON by Jackson automatically — without any extra configuration.

Capturing Request Parameters

Path Variables and Request Params

Data from the URL can be captured with two annotations. Path variables capture segments inside the path, while request params capture values from the query string:

Path variable and request param
@GetMapping("/{id}")
public Item getItem(@PathVariable Long id) {
    return itemService.findById(id);
}
 
@GetMapping("/search")
public List<Item> search(@RequestParam String q,
                         @RequestParam(defaultValue = "10") int limit) {
    return itemService.search(q, limit);
}

For GET /api/items/search?q=laptop&limit=5, the value of q becomes laptop and limit becomes 5. Parameters that aren't required are given a defaultValue.

Request Body and Headers

To create or update data, send a JSON payload in the request body and capture it with @RequestBody. Read a specific header with @RequestHeader:

Request body and header
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public Item createItem(@RequestBody ItemRequest request,
                       @RequestHeader("X-Client-Id") String clientId) {
    return itemService.create(request, clientId);
}

The @ResponseStatus(HttpStatus.CREATED) annotation sets status code 201 for successful responses. Jackson maps the JSON fields in the body to the fields of the ItemRequest class automatically — validation details will be covered in episode 7.

ResponseEntity and Status Codes

Full Control Over Responses

Sometimes you need to control the status code, headers, and body at the same time. That's where ResponseEntity comes in. An example endpoint that looks up data and returns 404 if it's not found:

ResponseEntity with a status code
@GetMapping("/{id}")
public ResponseEntity<Item> getItem(@PathVariable Long id) {
    return itemService.findById(id)
            .map(item -> ResponseEntity.ok(item))
            .orElse(ResponseEntity.notFound().build());
}

This style makes your API follow HTTP conventions correctly: 200 OK for success, 404 Not Found for missing data, and so on. Consistent status codes are critical so the API can be consumed properly by clients.

JSON Serialization

Controlling the JSON Shape

Jackson is Spring Boot's default serializer. You can control the shape of the JSON emitted via annotations on fields, for example hiding sensitive fields:

Model with serialization control
public class Item {
 
    private Long id;
    private String name;
 
    @JsonIgnore
    private String internalNote;
}

The internalNote field with @JsonIgnore won't appear in the JSON — useful for internal fields you don't want exposed to clients. For field naming, Spring Boot uses camelCase by default; the spring.jackson configuration allows further customization.

Trying It with curl

All the endpoints above can be tested directly from the terminal:

Test the REST endpoints
curl http://localhost:8080/api/items
curl -X POST http://localhost:8080/api/items \
  -H "Content-Type: application/json" \
  -H "X-Client-Id: web" \
  -d '{"name":"Laptop"}'

The curl -X POST http://localhost:8080/api/items -H "Content-Type: application/json" -d '{"name":"Laptop"}' command sends a JSON payload and triggers the createItem endpoint. Observe the JSON response returned — that's the result of Jackson serialization.

Common Errors

415 Unsupported Media Type

Happens when a JSON request body isn't accompanied by the Content-Type: application/json header. Always include this header when sending data.

400 Bad Request from a Binding Error

Happens when a parameter value doesn't match the type — for example, sending text to a Long parameter. Check the parameter data type and make sure the value is valid. For friendly error messages, we'll build global exception handling in episode 7.

Closing

Episode 5 equipped you with the ability to build REST APIs using Spring Web MVC: @RestController and @RequestMapping, capturing path variables, request params, request bodies, and headers, controlling status codes with ResponseEntity, and understanding JSON serialization by Jackson.

Key takeaways:

  • @RestController automatically serializes method return values into JSON.
  • @PathVariable, @RequestParam, @RequestBody, and @RequestHeader capture input from the URL and body.
  • ResponseEntity gives full control over status code, headers, and body.
  • Jackson manages JSON serialization; use @JsonIgnore to hide fields.
  • Always include Content-Type: application/json when sending payloads.
  • Test endpoints with curl to make sure the status code and JSON shape are correct.

In the next episode, episode 6, we'll discuss data access and repositories — Spring Data JPA with @Entity and CrudRepository, automatic query methods, custom queries with @Query, datasource configuration, and the in-memory H2 database for testing. Your API will start storing real data.

Learn Spring Boot - Web MVC & Basic REST API | Learn Spring Boot