Comprehensive Overview of Spring MVC: Architecture and Advanced Features

Spring MVC (Model-View-Controller) is a part of the Spring Framework that provides a comprehensive and flexible web development framework. It is designed to simplify the development of web applications by providing a clear separation of concerns between the various layers of an application.

Core Components of Spring MVC

  1. DispatcherServlet:
    • Acts as the front controller in the Spring MVC architecture.
    • Handles all incoming HTTP requests and delegates them to the appropriate controllers based on the URL patterns defined.
    • It is configured in the web.xml (if using XML configuration) or as a @Bean in a @Configuration class.
    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    <servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
    </servlet-mapping>
    <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    

     


    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    @Bean
    public DispatcherServlet dispatcherServlet() {
    return new DispatcherServlet();
    }
    @Bean public DispatcherServlet dispatcherServlet() { return new DispatcherServlet(); }
    @Bean
    public DispatcherServlet dispatcherServlet() {
        return new DispatcherServlet();
    }
    

     


  2. HandlerMapping:
    • Maps incoming requests to appropriate handler methods in the controllers.
    • Commonly used HandlerMapping implementations include RequestMappingHandlerMapping which maps requests based on @RequestMapping annotations.
    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    @RequestMapping("/hello")
    public String handleRequest() {
    return "hello";
    }
    @RequestMapping("/hello") public String handleRequest() { return "hello"; }
    @RequestMapping("/hello")
    public String handleRequest() {
        return "hello";
    }
    

     


  3. Controller:
    • Contains methods to handle requests and return model and view information.
    • Annotated with @Controller or @RestController (for REST APIs).
    • Methods are annotated with @RequestMapping (or other request mapping annotations like @GetMapping, @PostMapping, etc.) to specify request URL patterns.
    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    @Controller
    public class HelloController {
    @GetMapping("/hello")
    public String hello(Model model) {
    model.addAttribute("message", "Hello, World!");
    return "hello";
    }
    }
    @Controller public class HelloController { @GetMapping("/hello") public String hello(Model model) { model.addAttribute("message", "Hello, World!"); return "hello"; } }
    @Controller
    public class HelloController {
    
        @GetMapping("/hello")
        public String hello(Model model) {
            model.addAttribute("message", "Hello, World!");
            return "hello";
        }
    }
    

     


  4. Model:
    • Represents the data of the application.
    • Passed to the view for rendering, usually through the Model or ModelAndView objects.
    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    @GetMapping("/hello")
    public String hello(Model model) {
    model.addAttribute("message", "Hello, World!");
    return "hello";
    }
    @GetMapping("/hello") public String hello(Model model) { model.addAttribute("message", "Hello, World!"); return "hello"; }
    @GetMapping("/hello")
    public String hello(Model model) {
        model.addAttribute("message", "Hello, World!");
        return "hello";
    }
    

     


  5. View:
    • Responsible for rendering the model data.
    • Can be JSP, Thymeleaf, FreeMarker, or other view technologies supported by Spring.
    • Defined in the view resolver configuration.
    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    <!-- hello.jsp -->
    <html>
    <body>
    <h1>${message}</h1>
    </body>
    </html>
    <!-- hello.jsp --> <html> <body> <h1>${message}</h1> </body> </html>
    <!-- hello.jsp -->
    <html>
    <body>
        <h1>${message}</h1>
    </body>
    </html>
    

     


  6. ViewResolver:
    • Maps logical view names to actual view implementations.
    • Common implementations include InternalResourceViewResolver for JSPs and ThymeleafViewResolver for Thymeleaf templates.
    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    @Bean
    public InternalResourceViewResolver viewResolver() {
    InternalResourceViewResolver resolver = new InternalResourceViewResolver();
    resolver.setPrefix("/WEB-INF/views/");
    resolver.setSuffix(".jsp");
    return resolver;
    }
    @Bean public InternalResourceViewResolver viewResolver() { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setPrefix("/WEB-INF/views/"); resolver.setSuffix(".jsp"); return resolver; }
    @Bean
    public InternalResourceViewResolver viewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        return resolver;
    }
    

     


Request Handling Flow in Spring MVC

  1. Client Request: The client sends an HTTP request to the web application.
  2. DispatcherServlet: The request is received by the DispatcherServlet, which acts as the front controller.
  3. Handler Mapping: The DispatcherServlet consults HandlerMapping to determine the appropriate controller method to handle the request.
  4. Controller: The request is forwarded to the identified controller method.
  5. Business Logic: The controller processes the request, interacts with the service layer, and prepares the model data.
  6. Model and View: The controller returns a ModelAndView object, containing the model data and view name.
  7. View Resolver: The DispatcherServlet consults the ViewResolver to resolve the logical view name to an actual view.
  8. View Rendering: The view (e.g., JSP, Thymeleaf) is rendered with the model data and the response is sent back to the client.
See also  Deep Dive into Exception Handling in Spring Boot

Advanced Features

  1. Form Handling:
    • Spring MVC simplifies form handling through the use of @ModelAttribute and @RequestParam annotations.
    • The BindingResult object is used for validation and error handling.
    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    @Controller
    public class FormController {
    @GetMapping("/form")
    public String showForm(Model model) {
    model.addAttribute("formData", new FormData());
    return "form";
    }
    @PostMapping("/form")
    public String submitForm(@ModelAttribute FormData formData, BindingResult result) {
    if (result.hasErrors()) {
    return "form";
    }
    // Process formData
    return "result";
    }
    }
    @Controller public class FormController { @GetMapping("/form") public String showForm(Model model) { model.addAttribute("formData", new FormData()); return "form"; } @PostMapping("/form") public String submitForm(@ModelAttribute FormData formData, BindingResult result) { if (result.hasErrors()) { return "form"; } // Process formData return "result"; } }
    @Controller
    public class FormController {
    
        @GetMapping("/form")
        public String showForm(Model model) {
            model.addAttribute("formData", new FormData());
            return "form";
        }
    
        @PostMapping("/form")
        public String submitForm(@ModelAttribute FormData formData, BindingResult result) {
            if (result.hasErrors()) {
                return "form";
            }
            // Process formData
            return "result";
        }
    }
    

     


  2. Exception Handling:
    • Centralized exception handling can be achieved using @ControllerAdvice and @ExceptionHandler annotations.
    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    @ControllerAdvice
    public class GlobalExceptionHandler {
    @ExceptionHandler(Exception.class)
    public String handleException(Exception ex, Model model) {
    model.addAttribute("errorMessage", ex.getMessage());
    return "error";
    }
    }
    @ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(Exception.class) public String handleException(Exception ex, Model model) { model.addAttribute("errorMessage", ex.getMessage()); return "error"; } }
    @ControllerAdvice
    public class GlobalExceptionHandler {
    
        @ExceptionHandler(Exception.class)
        public String handleException(Exception ex, Model model) {
            model.addAttribute("errorMessage", ex.getMessage());
            return "error";
        }
    }
    

     


  3. Interceptors:
    • Interceptors provide a way to intercept requests for pre-processing and post-processing.
    • Implement the HandlerInterceptor interface and configure it in WebMvcConfigurer.
    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    public class LoggingInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    // Pre-processing logic
    return true;
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    // Post-processing logic
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    // After completion logic
    }
    }
    @Configuration
    public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new LoggingInterceptor());
    }
    }
    public class LoggingInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // Pre-processing logic return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // Post-processing logic } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // After completion logic } } @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoggingInterceptor()); } }
    public class LoggingInterceptor implements HandlerInterceptor {
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            // Pre-processing logic
            return true;
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            // Post-processing logic
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            // After completion logic
        }
    }
    
    @Configuration
    public class WebConfig implements WebMvcConfigurer {
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new LoggingInterceptor());
        }
    }
    

     


  4. RESTful Web Services:
    • Spring MVC supports building RESTful web services using @RestController, @GetMapping, @PostMapping, @PutMapping, and @DeleteMapping annotations.
    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    @RestController
    @RequestMapping("/api")
    public class ApiController {
    @GetMapping("/resource")
    public ResponseEntity<Resource> getResource() {
    Resource resource = new Resource();
    return ResponseEntity.ok(resource);
    }
    @PostMapping("/resource")
    public ResponseEntity<Void> createResource(@RequestBody Resource resource) {
    // Create resource logic
    return ResponseEntity.status(HttpStatus.CREATED).build();
    }
    }
    @RestController @RequestMapping("/api") public class ApiController { @GetMapping("/resource") public ResponseEntity<Resource> getResource() { Resource resource = new Resource(); return ResponseEntity.ok(resource); } @PostMapping("/resource") public ResponseEntity<Void> createResource(@RequestBody Resource resource) { // Create resource logic return ResponseEntity.status(HttpStatus.CREATED).build(); } }
    @RestController
    @RequestMapping("/api")
    public class ApiController {
    
        @GetMapping("/resource")
        public ResponseEntity<Resource> getResource() {
            Resource resource = new Resource();
            return ResponseEntity.ok(resource);
        }
    
        @PostMapping("/resource")
        public ResponseEntity<Void> createResource(@RequestBody Resource resource) {
            // Create resource logic
            return ResponseEntity.status(HttpStatus.CREATED).build();
        }
    }
    

     


  5. Asynchronous Request Processing:
    • Spring MVC supports asynchronous request processing to handle long-running tasks without blocking the main thread.
    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    @RestController
    public class AsyncController {
    @GetMapping("/async")
    public Callable<String> asyncRequest() {
    return () -> {
    // Simulate long-running task
    Thread.sleep(2000);
    return "asyncResult";
    };
    }
    }
    @RestController public class AsyncController { @GetMapping("/async") public Callable<String> asyncRequest() { return () -> { // Simulate long-running task Thread.sleep(2000); return "asyncResult"; }; } }
    @RestController
    public class AsyncController {
    
        @GetMapping("/async")
        public Callable<String> asyncRequest() {
            return () -> {
                // Simulate long-running task
                Thread.sleep(2000);
                return "asyncResult";
            };
        }
    }
    

     


Conclusion

Spring MVC is a powerful and flexible framework for building web applications in Java. By providing a clear separation of concerns and a comprehensive set of tools and features, it simplifies the development of robust and maintainable web applications. Understanding the core components and advanced features of Spring MVC is essential for any Java web developer aiming to build scalable and efficient web applications.

See also  Containers, Dependency Injection, and Inversion of Control in Spring Boot

Leave a Reply

Your email address will not be published. Required fields are marked *

Get a Quote

Give us a call or fill in the form below and we will contact you. We endeavor to answer all inquiries within 24 hours on business days.