Skip to main content

Command Palette

Search for a command to run...

Java Series #16: Spring MVC to Spring Boot

Spring MVC to Spring Boot – Controllers, View Resolution, and Exception Handling Explained

Published
5 min read
Java Series #16: Spring MVC to Spring Boot
A

I am a Full-stack dev turning ideas into sleek, functional experiences 🚀. I am passionate about AI, intuitive UI/UX, and crafting user-friendly platforms . I am always curious – from building websites to diving into machine learning and under the hood workings ✨. Next.js, Node.js, MongoDB, and Tailwind are my daily tools. I am here to share dev experiments, lessons learned, and the occasional late-night code breakthroughs. Always evolving, always building.

Spring MVC gives you fine-grained control over web applications, while Spring Boot builds on top of it to remove friction and boilerplate. To really understand Spring Boot, you must first understand how Spring MVC works internally.

ViewResolver in Spring MVC

In Spring MVC, controllers do not return physical file paths.
They return logical view names.

return "login";

The job of a ViewResolver is to convert this logical name into an actual view file.

Why ViewResolver Exists

  • Avoid hardcoding paths

  • Centralize view configuration

  • Allow switching view technologies easily (JSP, Thymeleaf, etc.)

Example: InternalResourceViewResolver

@Bean
public InternalResourceViewResolver resolver() {
    InternalResourceViewResolver vr = new InternalResourceViewResolver();
    vr.setPrefix("/WEB-INF/views/");
    vr.setSuffix(".jsp");
    return vr;
}

Now:

return "login";

Resolves to:

/WEB-INF/views/login.jsp

@RequestMapping – Mapping URLs to Controllers

@RequestMapping maps incoming HTTP requests to controller methods.

At Class Level

@Controller
@RequestMapping("/users")
public class UserController {

At Method Level

@RequestMapping("/login")
public String login() {
    return "login";
}

Final URL becomes:

/users/login

Multiple Mappings in One Controller

@RequestMapping("/add")
@RequestMapping("/create")
public String addUser() {}

@RequestParam – Reading Request Data

@RequestParam extracts query parameters or form fields from HTTP requests.

@GetMapping("/login")
public String login(@RequestParam String username,
                    @RequestParam String password) {
}

Optional Parameters

@RequestParam(required = false) String role

Default Values

@RequestParam(defaultValue = "guest") String role

Used mainly in GET requests and form submissions.

@Controller vs @RestController

@Controller

  • Used in Spring MVC

  • Returns views (JSP, Thymeleaf)

  • Requires ViewResolver

@Controller
public class PageController {
    @GetMapping("/home")
    public String home() {
        return "home";
    }
}

@RestController

  • Used for REST APIs

  • Returns JSON/XML directly

  • No ViewResolver involved

@RestController
public class ApiController {
    @GetMapping("/users")
    public List<User> users() {
        return service.getUsers();
    }
}

Internally equivalent to:

@Controller
@ResponseBody

Exception Handling in Spring MVC

Spring provides layered exception handling, from local to global.

Try–Catch Block (Lowest Level)

Handled inside controller or service.

try {
    service.process();
} catch (Exception e) {
    return "error";
}

Downside: pollutes business logic.

@ExceptionHandler (Controller-Level)

Handles exceptions thrown within a controller.

@ExceptionHandler(NullPointerException.class)
public String handleError() {
    return "error";
}

Scoped to one controller only.

HandlerExceptionResolver (Framework-Level)

Low-level interface used internally by Spring.

  • Resolves exceptions globally

  • Used by Spring MVC infrastructure

  • Rarely implemented manually today

@ResponseStatus

Maps exceptions to HTTP status codes.

@ResponseStatus(HttpStatus.NOT_FOUND)
public class UserNotFoundException extends RuntimeException {}

No controller code required.

@ControllerAdvice (Global Exception Handling)

Applies exception handling across all controllers.

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)
    public String handle(Exception e) {
        return "error";
    }
}

Used heavily in real-world applications.


Intro to Spring Boot

Spring Boot sits on top of Spring and focuses on developer productivity.

Typical Spring Boot Flow

Client
→ Controller
→ Service
→ Repository
→ Database

All wired using Dependency Injection.

Core Layers in Spring Boot

  • Controller – Handles HTTP requests

  • Service – Business logic

  • Repository – Database interaction

  • Entity – Database model

  • Database – Persistence layer

Spring Boot enforces clean layered architecture.

Spring Boot Starters

Starters are preconfigured dependency bundles.

Types of Starters

Application Starters

  • spring-boot-starter-web

  • spring-boot-starter-data-jpa

Technical Starters

  • Logging

  • Validation

  • Security

Industrial / Enterprise Starters

  • Cloud

  • Messaging

  • Observability

Starters reduce dependency conflicts and manual configuration.

Auto Configuration – Spring Boot’s Core Power

Spring Boot auto-configures beans based on classpath detection.

Example:

  • If spring-webmvc is present → MVC is auto-enabled

  • If spring-data-jpa is present → JPA is auto-configured

This is done using:

  • @EnableAutoConfiguration

  • spring.factories

  • Conditional annotations

Maven vs Gradle in Spring Boot Context

Maven

  • XML-based

  • Convention over configuration

  • Strong lifecycle

  • Spring Boot provides auto-configuration plugins

Gradle

  • Groovy/Kotlin DSL

  • Task-based

  • More flexible

  • Faster builds

  • No default auto-config behavior (you configure tasks explicitly)

Spring Boot supports both, but Maven is simpler for beginners, Gradle is preferred for large builds.

AspectMavenGradle
Build Tool TypeDeclarative, lifecycle-basedTask-based, programmable
Configuration LanguageXML (pom.xml)Groovy / Kotlin DSL (build.gradle, build.gradle.kts)
Learning CurveEasier for beginnersSteeper due to DSL + flexibility
Build PhilosophyConvention over configurationConfiguration + code
Build ModelFixed lifecycle phasesCustomizable task graph
Build SpeedSlower (full rebuilds common)Faster (incremental builds, caching)
Incremental BuildsLimitedStrong support
Build CacheBasicAdvanced local + remote caching
Dependency ManagementStrong, centralized, predictableStrong but more flexible
Dependency ResolutionTransitive with strict scopesTransitive with rich configurations
Multi-Module ProjectsSupported but verboseExcellent, very scalable
Plugin EcosystemVery mature, stableGrowing fast, highly customizable
CustomizationLimited, XML-heavyHighly customizable using code
IDE SupportExcellentExcellent
CI/CD IntegrationVery strongVery strong
Error DebuggingSimpler logs, easier to tracePowerful but sometimes complex
Spring Boot SupportExcellent, officially favoredExcellent, slightly more setup
Best Use CaseStandard enterprise projects, beginnersLarge, complex, performance-critical builds