You want to ship an API. You don’t want to hand-configure Tomcat, write a web.xml, or fight a servlet container. A Spring Boot REST controller gets you from zero to a working HTTP endpoint in about five minutes — and this guide is the copy-paste-run version, plus just enough explanation that you actually understand what you pasted.

What you need first

One dependency: spring-boot-starter-web. Add it to your pom.xml (or build.gradle) and Spring Boot pulls in Spring MVC, Jackson (for JSON), and an embedded Tomcat. That last part is the magic — there’s no external server to install or deploy to. Your app is the server. Generate a skeleton at start.spring.io if you don’t have one (more on that in Surviving Day 1 with Spring Boot 3).

1. The main class

Nothing fancy. Just a class with main and @SpringBootApplication:

package com.coderboi.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

@SpringBootApplication is three annotations in one: @Configuration, @EnableAutoConfiguration, and @ComponentScan. That last one means Spring scans this package (and below) for components — which is why your controller gets picked up automatically as long as it lives under com.coderboi.demo.

2. The controller

One annotation, one method, one endpoint. That’s it:

package com.coderboi.demo.web;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @GetMapping("/hello")
    public String hello(@RequestParam(defaultValue = "coderboi") String name) {
        return "Hey %s, the API is alive.".formatted(name);
    }
}

Hit http://localhost:8080/hello and you get plain text back. Hit http://localhost:8080/hello?name=world and you get “Hey world, the API is alive.” No XML, no web.xml, no tears.

The annotations that matter

  • @RestController — marks the class as a web controller and tells Spring every method returns the response body directly (it’s @Controller + @ResponseBody). Without the @ResponseBody half, Spring would try to resolve your return value to a view template.
  • @GetMapping("/hello") — maps HTTP GET /hello to this method. There’s a sibling for each verb: @PostMapping, @PutMapping, @DeleteMapping, @PatchMapping.
  • @RequestParam — binds a query-string parameter. defaultValue makes it optional; drop that and the param becomes required (a missing one returns 400).

Returning JSON instead of text

Real APIs return JSON. Return an object (or a record) and Jackson serializes it automatically — no extra config:

public record Greeting(String message, long timestamp) {}

@GetMapping("/greeting")
public Greeting greeting(@RequestParam(defaultValue = "coderboi") String name) {
    return new Greeting("Hey %s 👋".formatted(name), System.currentTimeMillis());
}

GET /greeting?name=world now returns {"message":"Hey world 👋","timestamp":...}. To grab a value from the URL path instead of the query string, use @PathVariable:

@GetMapping("/users/{id}")
public Greeting user(@PathVariable Long id) { ... }

And to accept a JSON request body on a POST, take a @RequestBody parameter — Jackson deserializes the incoming JSON into your object.

Common gotchas

  • Controller not found (404 on everything). It’s almost always component scanning — your controller lives outside the package of the @SpringBootApplication class. Move it under that package tree.
  • Required param missing → 400. Add a defaultValue or required = false if the param is optional.
  • Returning a String when you meant JSON. A raw String return is sent as text/plain. Return an object/record for JSON.
  • Port 8080 already in use. Set server.port in application.properties, or stop whatever’s squatting on the port.

FAQ

@RestController vs @Controller — which do I use?
Use @RestController for APIs that return data (JSON/text). @Controller is for server-rendered views (Thymeleaf, etc.) and needs @ResponseBody on methods that should return data instead of a view name.
Do I need to install Tomcat?
No. spring-boot-starter-web bundles an embedded Tomcat, so java -jar yourapp.jar (or running the main class) starts the server. There’s nothing separate to install or deploy to.
How do I read the request body?
Add a @RequestBody parameter of your DTO/record type to a @PostMapping method. Jackson deserializes the JSON automatically.
How do I change the port?
Set server.port=9090 in application.properties (or application.yml), or pass --server.port=9090 on startup.

Key takeaway: A Spring Boot REST controller is one @RestController class with @GetMapping/@PostMapping methods; add spring-boot-starter-web, keep the controller under your main package, and return objects to get JSON for free. Five minutes, no servlet config.

Next steps: handle errors cleanly with a global exception handler, then lock it down with JWT authentication.