Understand controllers, dependency injection, and auto-configuration with a minimal runnable project structure. Run your first JSON-returning API endpoint.
Key Takeaways
- Layered architecture: controllers, services, and repositories each handle their specific responsibilities.
- Expose the endpoint using @RestController and @GetMapping
- Distinguish between development and production environments via configuration files
- Use a unified response structure to standardize API output
Many beginners get discouraged by the abundance of annotations and configurations when learning Spring Boot. In reality, a runnable API service requires very little code. This guide aims to help you build your first JSON-returning endpoint in under 30 minutes while understanding the purpose of every line of code.
Understand the layers first, then write the code.
A maintainable backend project typically separates "request handling," "business logic," and "data access." Controllers handle only parameter parsing and response formatting. Business logic resides in the service layer, while data access is delegated to the repository layer. This separation ensures that changes in one layer do not impact others.
- Controller: parse request parameters, invoke services, and assemble responses
- Service: Orchestrates business workflows without handling HTTP details.
- Repository: Encapsulates data access and abstracts database differences.
Write the first API endpoint
Here's a minimal controller example. After starting the app, visit /api/health to see the JSON response from the service. Note that annotations are just declarations; the container handles actual object creation. This is the value of dependency injection.
1import org.Spring Framework.web.bind.annotation.*;23@REST Controller4@Request Mapping("/api")5public class HealthController {67 private final Health Service healthService;89 public HealthController(Health Service healthService) {10 this.healthService = healthService;11 }1213 @GetMapping("/health")14 public API Response health() {15 return API Response.ok(healthService.status());16 }17}Unified Response Structure
Standardizing API response formats simplifies error handling on the frontend. We recommend using a consistent structure with `code`, `message`, and `data` fields for both success and failure responses, avoiding inconsistent implementations across different endpoints.
- On success, the code is 0 and data contains business information.
- On failure, the code must not be 0; provide a readable message.
- Do not return exception stack traces directly to the frontend.
What's next
After getting the API working, we recommend adding parameter validation, global exception handling, and API documentation. These steps will transform your service from "functional" to "production-ready." Once complete, return to the advanced section of the learning path to explore data access and transactions.