Correct Methods for Returning HTML Pages from RESTful Controllers in Spring Boot

Nov 23, 2025 · Programming · 16 views · 7.8

Keywords: Spring Boot | Controller | HTML Return | @RestController | @Controller

Abstract: This article provides an in-depth analysis of common issues when returning HTML pages from controllers in Spring Boot applications. It explains the fundamental differences between @RestController and @Controller annotations, presents multiple implementation solutions for returning HTML pages, including using @Controller annotation, ModelAndView objects, and configuring view resolvers. Through code examples and principle analysis, the article helps developers understand Spring MVC's view resolution mechanism and avoid common configuration errors.

Problem Background and Cause Analysis

During Spring Boot development, many developers encounter this issue: when attempting to return HTML pages from controllers, the browser only displays the filename instead of the page content. This situation typically occurs in controllers annotated with @RestController.

When using the @RestController annotation, Spring marks the controller as a RESTful controller, and all method return values automatically have the @ResponseBody annotation added. This means the returned string "login" is directly written to the HTTP response body rather than being parsed as a view name.

Essentially, the following two approaches are equivalent:

@RestController
public class HomeController {
    @RequestMapping("/")
    public String welcome() {
        return "login";
    }
}

Is equivalent to:

@Controller
public class HomeController {
    @RequestMapping("/")
    @ResponseBody
    public String welcome() {
        return "login";
    }
}

When using the @ResponseBody annotation, the return value "login" is attached as a string object directly to the HTTP response body. If a JSON converter is configured, objects are serialized into JSON format; for string types, the string content is directly output. This is why users only see login instead of the HTML page.

Solution: Using @Controller Annotation

The simplest solution to correctly return HTML pages is to replace @RestController with the @Controller annotation:

@Controller
public class HomeController {
    @RequestMapping("/")
    public String welcome() {
        return "login";
    }
}

In this configuration, Spring parses the return value "login" as a view name rather than directly writing it to the response body. Spring Boot defaults to using Thymeleaf as the template engine and automatically looks for template files named login.html in the resources/templates/ directory.

Project Structure and File Locations

Correct project structure is crucial for view resolution. HTML files should be placed in one of the following directories:

When using @Controller to return view names, Spring locates the actual HTML files according to the configured view resolver rules.

Using ModelAndView Objects

In addition to directly returning string view names, you can also use ModelAndView objects to return HTML pages:

@RequestMapping("/")
public ModelAndView index() {
    ModelAndView modelAndView = new ModelAndView();
    modelAndView.setViewName("index");
    return modelAndView;
}

This approach provides greater flexibility, allowing you to add data to the model while returning the view:

@RequestMapping("/user")
public ModelAndView userProfile() {
    ModelAndView modelAndView = new ModelAndView();
    modelAndView.setViewName("user");
    modelAndView.addObject("username", "John Doe");
    modelAndView.addObject("email", "john@example.com");
    return modelAndView;
}

Dependency Configuration and View Resolvers

To ensure HTML pages render correctly, necessary dependencies must be added to pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

You can also configure view resolvers in application.properties:

spring.mvc.view.suffix=.html
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html

These configurations affect how Spring resolves view names. For example, after setting spring.mvc.view.suffix=.html, the view name "login" is resolved to login.html.

Mixing @RestController and HTML Returns

In some scenarios, you might need to provide both REST APIs and HTML pages in the same controller. This can be achieved through method-level annotations:

@Controller
public class HybridController {
    
    // Return HTML page
    @RequestMapping("/")
    public String home() {
        return "home";
    }
    
    // Return JSON data
    @RequestMapping("/api/data")
    @ResponseBody
    public Map<String, Object> getData() {
        Map<String, Object> data = new HashMap<>();
        data.put("message", "Hello World");
        return data;
    }
}

Common Issues and Debugging Techniques

During development, you might encounter the following common issues:

You can use Spring Boot's developer tools to speed up development:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
</dependency>

Developer tools automatically restart the application when code changes and provide better error information.

Conclusion

Understanding the difference between @RestController and @Controller is key to solving HTML page return issues. @RestController is suitable for building REST APIs, while @Controller is more appropriate for returning HTML views. Through proper annotation selection, file location configuration, and dependency management, you can ensure Spring Boot applications correctly return HTML pages.

In practical development, it's recommended to choose the appropriate solution based on project requirements: use @RestController for pure frontend rendering applications; use @Controller for server-side rendering applications. Hybrid solutions can meet more complex business requirements.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.