Spring Boot REST API Tutorial
author : Sai K
This tutorial will guide you through building a REST API using Java 21, Spring Boot 3+ and MySQL
database.,
We will use Java Records to transfer data between the client and server. This tutorial is
designed for beginners
and covers the following topics:
1.Introduction to Spring Boot
2. Introduction to REST API
3.Creating a Spring Boot Project
4.Creating a "Hello World" REST API
5.Creating a REST API that returns a Java Bean
6.Creating a REST API that returns a List as JSON
7.Creating a REST API that handles Path Parameters
8.Creating a REST API that handles Query Parameters
9.Creating CRUD REST APIs with MySQL Database
10.Creating Pagination and Sorting REST APIs
Introduction to Spring Boot
Spring Boot is an open-source
Java-based framework for creating stand-alone, production-grade Spring
applications. It simplifies
the development process by providing defaults for code and annotation configuration,
enabling you to
start coding quickly without worrying about setup details.
Key Features of Spring Boot
- Auto-Configuration: Automatically configures your Spring application based on the
dependencies you
have added to the project. - Standalone: Creates stand-alone Spring applications with embedded servers.
- Production-ready Features: Includes production-ready features such as metrics, health
checks, and
externalized configuration. - Convention over Configuration: Reduces the need for explicit configuration by following conventions.
- Spring Boot Starters: Provides a set of pre-configured dependencies for various
functionalities, making it
easy to get started.
Introduction to REST API
A REST API (Representational State Transfer Application Programming Interface) is an
architectural style for
building web services that interact over HTTP. REST APIs allow different
software systems to communicate and
exchange data efficiently. The key principles of REST include
statelessness, resource-based interactions, and
standardized HTTP methods like GET, POST, PUT, and
DELETE.
Key Principles of REST
Step 1: Creating a Spring Boot Project
Using Spring Initializr
- Go to start.spring.io
- Select
- Project: Maven Project
- Language: Java
- Spring Boot: 3.0.0 (or latest)
- Packaging: Jar
- Java: 21
- Dependencies:Spring Web,Spring Data JPA, MySQL Driver, Lombok, Spring Security
-
3.Click on "Generate" to download the project.
4.Unzip the downloaded project and open it in your favorite IDE.
Example Project Structure
spring-boot-security-rest-api/ ├── src/ │ ├── main/ │ │ ├── java/ │ │ │ └── com/example/demo/ │ │ │ └── DemoApplication.java │ │ │ └── controller/ │ │ │ └── ProductController.java │ │ │ └── OrderController.java │ │ │ └── model/ │ │ │ └── Product.java │ │ │ └── Order.java │ │ │ └── User.java │ │ │ └── Role.java │ │ │ └── repository/ │ │ │ └── ProductRepository.java │ │ │ └── OrderRepository.java │ │ │ └── UserRepository.java │ │ │ └── service/ │ │ │ └── ProductService.java │ │ │ └── OrderService.java │ │ │ └── UserService.java │ │ │ └── config/ │ │ │ └── SecurityConfig.java │ │ └── resources/ │ │ ├── application.properties │ └── test/ │ └── java/ │ └── com/example/demo/ │ └── DemoApplicationTests.java ├── mvnw ├── mvnw.cmd ├── pom.xml └── .mvn/ └── wrapper/ └── maven-wrapper.properties
Step 1: Creating a "Hello World" REST API
Step-by-Step Guide
1.Create a Java class named HelloWorldController in the src/main/java/com/example/demo/controller
package.package com.example.demo.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloWorldController { @GetMapping("/hello") public String helloWorld() { return "Hello, World!"; } }
Explanation
- @RestController: Indicates that the class is a REST controller, handling web requests
and returning
responses directly. - @GetMapping("/hello"): Maps HTTP GET requests to the /hello endpoint to the helloWorld method.
- helloWorld Method: Returns a simple "Hello, World!" message when accessed.
By running the Spring Boot application and navigating to http://localhost:8080/hello, you will see the ,
message "Hello, World!" in your browser or Postman.
Step 2: Creating a REST API that Returns a Java Bean
Step-by-Step Guide
1.Create a Java Record named Person in the src/main/java/com/example/demo/model package.
package com.example.demo.model; public record Person(String name, int age) {}
Explanation
1.Person Record: Defines a Java Record named Person with two fields: name (a String) and age (an int).
Java Records are a compact syntax for immutable data classes.2.Create a controller named PersonController in the src/main/java/com/example/demo/controller package.
package com.example.demo.controller; import com.example.demo.model.Person; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class PersonController { @GetMapping("/person") public Person getPerson() { return new Person("John Doe", 30); } }
Explanation
1.@GetMapping("/person"): Maps HTTP GET requests to the /person endpoint to the getPerson method.
2.getPerson Method: Returns a new Person object with the name "John Doe" and age 30 when accessed.
By running the Spring Boot application and navigating to http://localhost:8080/person, you will see
the JSON representation of the Person object: {"name":"John Doe","age":30}.Step 3: Creating a REST API that Returns a List as JSON
Step-by-Step Guide
1.Modify the PersonController to include a method that returns a list of Person objects.
package com.example.demo.controller; import com.example.demo.model.Person; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController public class PersonController { @GetMapping("/person") public Person getPerson() { return new Person("John Doe", 30); } @GetMapping("/persons") public List
getPersons() { return List.of( new Person("John Doe", 30), new Person("Jane Doe", 25) ); } } Explanation
1.@GetMapping("/persons"): Maps HTTP GET requests to the /persons endpoint to the getPersons
method.2.getPersons Method: Returns a list of Person objects.
By running the Spring Boot application and navigating to http://localhost:8080/persons, you will see
the JSON representation of the list of Person objects: [{"name":"John
Doe","age":30},{"name":"Jane Doe","age":25}].Step 4: Creating a REST API that Handles Path Parameters
Step-by-Step Guide
1.Modify the PersonController to include a method that handles path parameters.
package com.example.demo.controller; import com.example.demo.model.Person; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController public class PersonController { @GetMapping("/person") public Person getPerson() { return new Person("John Doe", 30); } @GetMapping("/persons") public List
getPersons() { return List.of( new Person("John Doe", 30), new Person("Jane Doe", 25) ); } @GetMapping("/person/{name}") public Person getPersonByName(@PathVariable String name) { return new Person(name, 30); // For simplicity, we are returning a static age. } } Explanation
1.@GetMapping("/person/{name}"): Maps HTTP GET requests to the /person/{name} endpoint to the
getPersonByName method.2.getPersonByName Method: Returns a new Person object with the name provided in the path parameter
and a static age of 30.By running the Spring Boot application and navigating to http://localhost:8080/person/John, you will see
the JSON representation of the Person object: {"name":"John","age":30}.Step 5: Creating a REST API that Handles Query Parameters
Modify the PersonController to include a method that handles query parameters.
Step-by-Step Guide
package com.example.demo.controller; import com.example.demo.model.Person; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController public class PersonController { @GetMapping("/person") public Person getPerson() { return new Person("John Doe", 30); } @GetMapping("/persons") public List
getPersons() { return List.of( new Person("John Doe", 30), new Person("Jane Doe", 25) ); } @GetMapping("/person/{name}") public Person getPersonByName(@PathVariable String name) { return new Person(name, 30); } @GetMapping("/person") public Person getPersonByNameAndAge(@RequestParam String name, @RequestParam int age) { return new Person(name, age); } } Explanation
1.@GetMapping("/person"): Maps HTTP GET requests to the /person endpoint to the
getPersonByNameAndAge method.2.getPersonByNameAndAge Method: Returns a new Person object with the name and age provided in the
query parameters.By running the Spring Boot application and navigating to http://localhost:8080/person?
name=John&age=30, you will see the JSON representation of the Person object: {"name":"John","age":30}.Step 6: Creating CRUD REST APIs with MySQL Database
Introductions
In this section, we will create a CRUD (Create, Read, Update, Delete) REST API using Spring Boot and
MySQL. We will use Java Records for data transfer objects (DTOs) and demonstrate how to test the APIs
using Postman.Step-by-Step Guide
Setting Up the Database
1.Create a MySQL database named spring_boot_db.
Configure Database Connection
1.Update the application.properties file to configure the MySQL database connection.
spring.datasource.url=jdbc:mysql://localhost:3306/spring_boot_db spring.datasource.username=root spring.datasource.password=root spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true
Create Entity Class
1.Create a new package named model and add the Person entity class.
package com.example.demo.model; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; @Entity public class Person { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private int age; public Person() {} public Person(String name, int age) { this.name = name; this.age = age; } // Getters and setters public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
Explanation
- @Entity: Specifies that the class is an entity and is mapped to a database table.
- @Id: Specifies the primary key of an entity.
- @GeneratedValue(strategy = GenerationType.IDENTITY): Provides the specification of
generation
strategies for the primary key values.
Create Repository Interface
1.Create a new package named repository and add the PersonRepository interface.
package com.example.demo.repository; import com.example.demo.model.Person; import org.springframework.data.jpa.repository.JpaRepository; public interface PersonRepository extends JpaRepository
{ } Explanation
- extends JpaRepository
: Indicates that the PersonRepository interface extends JpaRepository,
providing CRUD operations for the Person entity.
Create Service Class
1.Create a new package named service and add the PersonService class.
package com.example.demo.service; import com.example.demo.model.Person; import com.example.demo.repository.PersonRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; import java.util.Optional; @Service public class PersonService { private final PersonRepository personRepository; @Autowired public PersonService(PersonRepository personRepository) { this.personRepository = personRepository; } public List
getAllPersons() { return personRepository.findAll(); } public Optional getPersonById(Long id) { return personRepository.findById(id); } public Person createPerson(Person person) { return personRepository.save(person); } public Optional updatePerson(Long id, Person personDetails) { return personRepository.findById(id).map(person -> { person.setName(personDetails.getName()); person.setAge(personDetails.getAge()); return personRepository.save(person); }); } public void deletePerson(Long id) { personRepository.deleteById(id); } } Explanation
1.@Service: Indicates that the class is a service component in the Spring context.
2.public PersonService(PersonRepository personRepository): Uses constructor-based dependency
injection to inject the PersonRepository bean.Create Controller Class
Create a new package named controller and add the PersonController class.
package com.example.demo.controller; import com.example.demo.model.Person; import com.example.demo.service.PersonService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; import java.util.Optional; @RestController @RequestMapping("/api/persons") public class PersonController { private final PersonService personService; @Autowired public PersonController(PersonService personService) { this.personService = personService; } @GetMapping public List
getAllPersons() { return personService.getAllPersons(); } @GetMapping("/{id}") public Optional getPersonById(@PathVariable Long id) { return personService.getPersonById(id); } @PostMapping public Person createPerson(@RequestBody Person person) { return personService.createPerson(person); } @PutMapping("/{id}") public Optional updatePerson(@PathVariable Long id, @RequestBody Person personDetails) { return personService.updatePerson(id, personDetails); } @DeleteMapping("/{id}") public void deletePerson(@PathVariable Long id) { personService.deletePerson(id); } } Explanation
- @RestController: Indicates that the class is a REST controller.
- @RequestMapping("/api/persons"): Maps HTTP requests to the /api/persons URL.
- CRUD Methods: Implements CRUD operations for the Person entity.
Step 7: Creating Pagination and Sorting REST APIs
Introduction
In this section, we will extend the CRUD REST API project to include pagination and sorting features. This
will allow us to fetch a subset of data and sort it based on specified criteria.Step-by-Step Guide
Add Pagination and Sorting to the Service Class
1.Modify the PersonService class to include pagination and sorting.
package com.example.demo.service; import com.example.demo.model.Person; import com.example.demo.repository.PersonRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; import java.util.List; import java.util.Optional; @Service public class PersonService { private final PersonRepository personRepository; @Autowired public PersonService(PersonRepository personRepository) { this.personRepository = personRepository; } public List
getAllPersons() { return personRepository.findAll(); } public Optional getPersonById(Long id) { return personRepository.findById(id); } public Person createPerson(Person person) { return personRepository.save(person); } public Optional updatePerson(Long id, Person personDetails) { return personRepository.findById(id).map(person -> { person.setName(personDetails.getName()); person.setAge(personDetails.getAge()); return personRepository.save(person); }); } public void deletePerson(Long id) { personRepository.deleteById(id); } public Page getPersonsPage(int page, int size) { Pageable pageable = PageRequest.of(page, size); return personRepository.findAll(pageable); } public Page getPersonsPageSorted(int page, int size, String sortBy) { Pageable pageable = PageRequest.of(page, size, Sort.by(sortBy)); return personRepository.findAll(pageable); } } Explanation
- getPersonsPage Method: Fetches a page of Person data.
- getPersonsPageSorted Method: Fetches a page of Person data sorted by the specified field.
Add Pagination and Sorting Endpoints to the Controller Class
1.Modify the PersonController class to include endpoints for pagination and sorting.
package com.example.demo.controller; import com.example.demo.model.Person; import com.example.demo.service.PersonService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.web.bind.annotation.*; import java.util.List; import java.util.Optional; @RestController @RequestMapping("/api/persons") public class PersonController { private final PersonService personService; @Autowired public PersonController(PersonService personService) { this.personService = personService; } @GetMapping public List
getAllPersons() { return personService.getAllPersons(); } @GetMapping("/{id}") public Optional getPersonById(@PathVariable Long id) { return personService.getPersonById(id); } @PostMapping public Person createPerson(@RequestBody Person person) { return personService.createPerson(person); } @PutMapping("/{id}") public Optional updatePerson(@PathVariable Long id, @RequestBody Person personDetails) { return personService.updatePerson(id, personDetails); } @DeleteMapping("/{id}") public void deletePerson(@PathVariable Long id) { personService.deletePerson(id); } @GetMapping("/page") public Page getPersonsPage(@RequestParam int page, @RequestParam int size) { return personService.getPersonsPage(page, size); } @GetMapping("/page/sorted") public Page getPersonsPageSorted(@RequestParam int page, @RequestParam int size, @RequestParam String sortBy) { return personService.getPersonsPageSorted(page, size, sortBy); } } Explanation
- @GetMapping("/page"): Maps HTTP GET requests to the /page endpoint to the getPersonsPage
method. - @GetMapping("/page/sorted"): Maps HTTP GET requests to the /page/sorted endpoint to the
getPersonsPageSorted method. - getPersonsPage and getPersonsPageSorted Methods: Fetch pages of Person data, optionally sorted
by the specified field.
By running the Spring Boot application and navigating to http://localhost:8080/api/persons/page?
page=0&size=5, you can fetch the first page of Person data with 5 records per page. Similarly, by
navigating to http://localhost:8080/api/persons/page/sorted?page=0&size=5&sortBy=name, you can fetch
the first page of Person data sorted by name with 5 records per page.Conclusion
This tutorial covered the basics of creating REST APIs using Spring Boot 3.3.0 and Java 21. We started
with a "Hello World" REST API and gradually built more complex APIs, including handling path and query
parameters, and implementing CRUD operations with MySQL. We also covered how to implement
pagination and sorting in REST APIs.By following these steps, you can build robust and scalable REST APIs with Spring Boot and Java Records
for data transfer.Related Spring and Spring Boot Tutorials/Guides:
- @RestController: Indicates that the class is a REST controller, handling web requests
and returning