Intro
Building a Simple Web App with Spring MVC
Securing our Spring MVC Web App
Session Management
Finishing Up

Controllers in Spring MVC

An Intro to Controllers

  • The “C” in MVC: In the Model-View-Controller, the “Controller” serves as the orchestrator, handling user requests and ensuring appropriate responses.
  • The First Stop: After the DispatcherServlet‘s decided which of our controller’s methods the request should go to, our controller acts as the first stop (with regard to code we actually wrote), processing whatever the user may have provided in their HTTP request.
  • An Intermediary Layer: A Controller acts as the intermediary between the outside world (e.g. the user), and the rest of our application (the Model, which in our case will be the service layer, the repository layer, etc.), in order to generate an appropriate View as a response.
Illustrating an overview of the architecture of a full-stack Spring application, with focus on the Controller layer, with example classes HomeController and RestaurantController.
  • A Regular Shmegular Class: Concretely, we’re just talking about classes we make ourselves (typically ending with the “Controller” suffix) that we just annotate with the @Controller annotation and some methods and other special annotations.

Controllers in Spring MVC Illustrated

So, we know the controller classes are responsible for determining what happens when a HTTP request arrives on a particular path on our web application.

Illustration of a HTTP GET request being sent to the “/restaurants” path (e.g. www.ralphs.com/restaurants or localhost:8080/restaurants) and thus arriving to the appropriate method in RestaurantController, which makes use of the Model (in this case a service class) to fetch the necessary restaurant data, to then return a rendered View.
  • HTTP requests arrive at our doorstep and are redirected to the relevant methods we wrote in Controller classes we wrote, based on their path.
    • By “path”, we refer to the relative paths, the bit after the domain and TLD on a web address’ URL, and potentially app name (e.g. www.example.com/my-app/beer/394 or www.foo.com/contact or www.bar.com/users).
  • Methods we write in these Controller classes will describe exactly what has to happen when, for example, a user navigates to a page on our web app (e.g. the home page).
    • If necessary, user input is accepted and processed.
    • If necessary, service classes are used to process input or retrieve data.
    • The View (dynamically filled in HTML document) is returned as a response (this can also happen due to a redirect, if we want).

An Example of a Controller

To illustrate, let’s look at the most simple example of a method in a controller class possible, namely one that handles the request for the home page (i.e. an empty relative path):

@Controller
public class HomeController {
    @GetMapping("")
    public String getHomePage(){
        return "home";
    }
}
  • @Controller: A sub-annotation of @Component, it ensures an object of this class will get created at runtime and registered as a bean in the Spring context. Beyond that, the @Controller annotation lets Spring MVC know that this is a controller meant for handling incoming requests, so the DispatcherServlet knows where to redirect HTTP requests to.
  • @GetMapping(""): A sub-annotation of @RequestMapping, this tells Spring that the following method should handle HTTP GET requests for a specific URL’s relative path. In this case, it’s an empty string "", which means it’s the default URL (usually the home page – i.e. there is nothing after www.example.com/). The older way of writing this would have been @RequestMapping(method = RequestMethod.GET, path = ""), but it’s much shorter and more readable to use @GetMapping.
  • return “home” – here we’re giving the name of a View. In the next topic we’re going to make our first View, an HTML document with the name “home.html“. Spring MVC only needs the name of the View to know what HTML document to generate and return as a response.

Now, let’s understand how this code works:

  1. When a user opens a web browser and goes to the root URL (e.g., http://yourwebsite.com/), the Spring MVC framework receives the incoming request (a GET request, specifically).
  2. The @GetMapping annotation with the empty string "" specifies that this method (getHomePage()) should handle this request.
  3. Inside the getHomePage() method, there’s a single statement: return "home";. This statement means that when the method is called, it returns the string “home.”
  4. In the context of Spring MVC, this returned string “home” typically represents the name of a view or a template that should be displayed to the user. In other words, it’s saying, “Generate and show the HTML document named ‘home’ to the user.”
  5. The actual content of the “home” page (HTML, text, or whatever you want to display) would be defined in a separate HTML template file, and Spring MVC knows where to find it based on the view name.

👩‍💻 Hands-on Demo: Controllers in Spring MVC

  1. In the “hello-spring-mvc” project from a previous demo, create a controller class that will deal with requests for our home page.
    • In this class, write a method, with the proper annotation that handles GET requests to the empty relative path, making sure it returns a view with the name “home“.
  2. Run your web app and navigate to the home page in the web browser. What do you see? Why do you think that is?

Solutions

🕵️‍♂️ Click here to reveal the solutions
@Controller
public class HomeController {
    @GetMapping("")
    public String getHomePage(){
        return "home";
    }
}
  • What do you see? Why do you think that is?
    • We still see a 404 error because, even though the DispatcherServlet has found our getHomePage method, the returned view name “home” means the DispatcherServlet will now look for a “home.html” file in our src/main/resources/templates folder. Since it’s empty it won’t find it, and thus cause a 404 error.
    • We’ll look at how to create views in this folder in the next topic!

A More Realistic Example

To better understand the role of a Controller, let’s look at another example. First, let’s have another look at our diagram that represents our application’s layers and Spring MVC’s behind-the-scenes mechanisms:

If we zoom in more on the controllers, in a more concrete food delivery app, we see that the Controller layer communicates with the Service layer to, for example, retrieve data from the database:

In code, this example may look something like this:

@Controller
@RequiredArgsConstructor
public class RestaurantController {
    private final RestaurantService restaurantService;

    @GetMapping("/restaurants")
    public String getAllRestaurantsOverview(Model model){
        List<Restaurant> allMyRestaurants = restaurantService.fetchAllRestaurants();
        model.addAttribute("restos", allMyRestaurants );
        return "restaurant-list";
    }

    // Other mapping methods related to restaurants
}
  • So the Controller layer serves as a kind of first stop traffic cop, between the outside world and the rest of our back-end layers (like the Service and Repository layers).
  • Methods in our controller classes handle HTTP-requests sent to particular paths, and make use of other systems in our back end (e.g. services) to whip up a response (e.g. a prepared view).
    • Note: That first / in the mapping path doesn’t matter. If the path does not start with a “/” then Spring will add it when handling the mapping.
  • Don’t worry too much about the new stuff like (Model model) and model.addAttribute, as these will be discussed and used in examples in a later topic.

Summary

  • Controllers in Spring MVC act as traffic cops and orchestrators, handling user’s HTTP requests and generating HTTP responses.
  • Specifically, methods in Controllers are responsible for specifying what happens at specific paths in the web application for specific HTTP request methods (e.g. GET, POST, etc.).
  • The @Controller and @GetMapping annotations define controller classes and methods.
  • Controllers interact with back-end layers, like the Service and Repository layers, to process data and prepare responses.
  • The name of a View is returned to generate and show the appropriate HTML document as a response.