A controller is the class that receives HTTP requests from clients, decides what to do with them, and returns a response. Spring maps each URL and HTTP method (GET, POST, PUT, DELETE) to a controller method using annotations like @GetMapping and @PostMapping. It is used to keep the web layer separate: the controller only handles request and response, and passes the real work to a service. Using one controller per resource (Student, Course) keeps each URL group and its responsibility clear.
Types
@Controller: returns view names for HTML pages (Spring MVC with Thymeleaf).@RestController: returns JSON directly (@Controller+@ResponseBody), used in this example.- Mapping annotations:
@RequestMapping(class level),@GetMapping,@PostMapping,@PutMapping,@DeleteMapping,@PatchMapping. - Input annotations:
@PathVariable(/students/1),@RequestParam(?name=ravi),@RequestBody(JSON body). - Response control:
ResponseEntityfor status codes such as 201, 204, and 404.
Hands-on Experiment: Creating a spring boot application along with different controllers
The following steps are involved in developing this hands-on experiment.
Step 1: Generate the Project
Step 2: Project Structure
Step 3: pom.xml
Step 4: application.properties
Step 5: Create Entity Class
Step 6: Create Repository Interface
Step 7: Create Service Class
Step 8: Create Controller Class
Step 9: Main Application Class
Step 10: Run the Main Application Class
Step 1: Configure the Project on Spring Initializr
Go to start.spring.io and set:
- Project: Maven
- Language: Java
- Spring Boot version: 3.2.x
- Group: com.example
- Artifact: controllers
- Name: controllers
- Package name: com.example.controllers
- Packaging: Jar
- Java: 17
- Dependencies: Spring Web, Spring Data JPA, MySQL Driver
Click Generate to download the ZIP, then extract and import it into your IDE as a Maven project.
Step 2: Generated Project Structure

Step 3: Explore pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>student-controllers-demo</artifactId>
<version>1.0.0</version>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Step 4: application.yml
spring:
datasource:
url: jdbc:mysql://localhost:3306/student_controllers_db?createDatabaseIfNotExist=true&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
username: root
password: password
jpa:
hibernate:
ddl-auto: update
show-sql: true
server:
port: 8082Code language: JavaScript (javascript)
Step 5: Create Entity classes
package com.example.controllers.entity;
import jakarta.persistence.*;
@Entity
public class Course {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
private int durationInWeeks;
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
public int getDurationInWeeks() { return durationInWeeks; }
public void setDurationInWeeks(int durationInWeeks) { this.durationInWeeks = durationInWeeks; }
}
package com.example.controllers.entity;
import jakarta.persistence.*;
@Entity
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String email;
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 String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
}
Step 6: Create Repository interfaces
package com.example.controllers.repository;
import com.example.controllers.entity.Course;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface CourseRepository extends JpaRepository<Course, Long> {
List<Course> findByTitleContainingIgnoreCase(String title);
}
package com.example.controllers.repository;
import com.example.controllers.entity.Student;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface StudentRepository extends JpaRepository<Student, Long> {
List<Student> findByNameContainingIgnoreCase(String name);
}
Step 7: Create Service classes
package com.example.controllers.service;
import com.example.controllers.entity.Course;
import com.example.controllers.repository.CourseRepository;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
public class CourseService {
private final CourseRepository repository;
public CourseService(CourseRepository repository) {
this.repository = repository;
}
public Course save(Course course) {
return repository.save(course);
}
public List<Course> findAll(String title) {
return (title == null) ? repository.findAll() : repository.findByTitleContainingIgnoreCase(title);
}
public Optional<Course> findById(Long id) {
return repository.findById(id);
}
public boolean delete(Long id) {
if (!repository.existsById(id)) return false;
repository.deleteById(id);
return true;
}
}
package com.example.controllers.service;
import com.example.controllers.entity.Student;
import com.example.controllers.repository.StudentRepository;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
public class StudentService {
private final StudentRepository repository;
public StudentService(StudentRepository repository) {
this.repository = repository;
}
public Student save(Student student) {
return repository.save(student);
}
public List<Student> findAll(String name) {
return (name == null) ? repository.findAll() : repository.findByNameContainingIgnoreCase(name);
}
public Optional<Student> findById(Long id) {
return repository.findById(id);
}
public Optional<Student> update(Long id, Student updated) {
return repository.findById(id).map(existing -> {
existing.setName(updated.getName());
existing.setEmail(updated.getEmail());
return repository.save(existing);
});
}
public boolean delete(Long id) {
if (!repository.existsById(id)) return false;
repository.deleteById(id);
return true;
}
}
Step 8: Create Controller classes
package com.example.controllers.controller;
import com.example.controllers.entity.Course;
import com.example.controllers.service.CourseService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
// Controller 2: everything about COURSES lives under /api/courses
// Same annotations, different responsibility -> one controller per resource
@RestController
@RequestMapping("/api/courses")
public class CourseController {
private final CourseService service;
public CourseController(CourseService service) {
this.service = service;
}
@PostMapping
public ResponseEntity<Course> add(@RequestBody Course course) {
return ResponseEntity.status(HttpStatus.CREATED).body(service.save(course));
}
// GET /api/courses or GET /api/courses?title=java
@GetMapping
public List<Course> list(@RequestParam(required = false) String title) {
return service.findAll(title);
}
@GetMapping("/{id}")
public ResponseEntity<Course> get(@PathVariable Long id) {
return service.findById(id)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(@PathVariable Long id) {
return service.delete(id) ? ResponseEntity.noContent().build()
: ResponseEntity.notFound().build();
}
}
package com.example.controllers.controller;
import com.example.controllers.entity.Student;
import com.example.controllers.service.StudentService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
// Controller 1: everything about STUDENTS lives under /api/students
@RestController
@RequestMapping("/api/students")
public class StudentController {
private final StudentService service;
public StudentController(StudentService service) {
this.service = service;
}
// POST /api/students -> body (JSON) becomes a Student; reply 201 Created
@PostMapping
public ResponseEntity<Student> register(@RequestBody Student student) {
return ResponseEntity.status(HttpStatus.CREATED).body(service.save(student));
}
// GET /api/students or GET /api/students?name=ravi (@RequestParam is optional)
@GetMapping
public List<Student> list(@RequestParam(required = false) String name) {
return service.findAll(name);
}
// GET /api/students/1 -> 200 with student, or 404
@GetMapping("/{id}")
public ResponseEntity<Student> get(@PathVariable Long id) {
return service.findById(id)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
// PUT /api/students/1
@PutMapping("/{id}")
public ResponseEntity<Student> update(@PathVariable Long id, @RequestBody Student student) {
return service.update(id, student)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
// DELETE /api/students/1 -> 204 No Content, or 404
@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(@PathVariable Long id) {
return service.delete(id) ? ResponseEntity.noContent().build()
: ResponseEntity.notFound().build();
}
}
Step 9: Main Application
package com.example.controllers;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ControllersApplication {
public static void main(String[] args) {
SpringApplication.run(ControllersApplication.class, args);
}
}
Step 10: Run ControllerApplication


