Backend Development 23 min read

Spring MVC Introduction, Core Principles, and Source Code Analysis

This article introduces Spring MVC, explains the problems of mixing JSP and Servlets, details the MVC layered architecture, walks through essential configuration files and Maven dependencies, presents sample controller code, and analyzes the DispatcherServlet source to illustrate the complete request‑response flow in a Java web application.

Full-Stack Internet Architecture
Full-Stack Internet Architecture
Full-Stack Internet Architecture
Spring MVC Introduction, Core Principles, and Source Code Analysis

Spring MVC Introduction

Spring MVC is a core component of the SSM framework used to separate front‑end and back‑end code, replacing the tightly coupled JSP‑Servlet model with a clean three‑layer MVC architecture.

Problems with JSP/Servlet Mixing

Old projects often mixed HTML and Java code, causing heavy coupling, difficult maintenance, and poor testability. The solution is to strictly separate concerns into presentation, controller, service, and persistence layers.

Spring MVC Architecture

The framework introduces a front‑controller DispatcherServlet that dispatches requests to custom controllers. Core components include:

DispatcherServlet : global request dispatcher.

HandlerMapping : maps URLs to handler chains (interceptors + controller).

HandlerAdapter : invokes the appropriate controller via reflection.

Handler (the controller itself).

ModelAndView : holds model data and logical view name.

View : resolves the logical view to a physical view for rendering.

Project Setup and Configuration Files

Using Maven, create an SSM project with the following configuration files placed under src/main/resources :

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
                           http://www.springframework.org/schema/tx
                           http://www.springframework.org/schema/tx/spring-tx.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="classpath:jdbc.properties"/>
    </bean>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
    </bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="typeAliasesPackage" value="com.ldc.model"/>
        <property name="mapperLocations" value="classpath:mapper/*.xml"/>
    </bean>
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <property name="basePackage" value="com.ldc.dao"/>
    </bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
</beans>

The accompanying jdbc.properties defines database connection details, while log4j.properties sets up simple logging.

# Log output level
log4j.rootLogger=debug,stdout,D,E

# Console appender
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} -[%p]  method:[%c (%rms)] - %m%n

The Spring MVC specific file spring-mvc.xml enables annotation‑driven controllers, component scanning, and view resolution:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/mvc
                           http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
    <context:component-scan base-package="com.ldc"/>
    <mvc:annotation-driven/>
    <mvc:default-servlet-handler/>
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

The web.xml registers the DispatcherServlet , character encoding filter, and links the Spring configuration files:

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <display-name>mvcDemo</display-name>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
        <async-supported>true</async-supported>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

Sample Controller

A simple UserController demonstrates typical Spring MVC annotations:

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

    @Autowired
    private IUserService userService;

    @RequestMapping("/getUserById")
    public ModelAndView selectUser(@PathVariable("id") Long id) throws Exception {
        ModelAndView mv = new ModelAndView();
        User user = userService.selectUser(id);
        mv.addObject("user", user);
        mv.setViewName("user");
        return mv;
    }
}

The annotations indicate controller role, request mapping, and dependency injection.

DispatcherServlet Source Code Analysis

The core method doDispatch(HttpServletRequest request, HttpServletResponse response) orchestrates the whole request lifecycle:

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    HttpServletRequest processedRequest = request;
    HandlerExecutionChain mappedHandler = null;
    int interceptorIndex = -1;
    try {
        ModelAndView mv;
        boolean errorView = false;
        try {
            // multipart check
            processedRequest = checkMultipart(request);
            // 1. Find handler via HandlerMapping
            mappedHandler = getHandler(processedRequest, false);
            if (mappedHandler == null || mappedHandler.getHandler() == null) {
                noHandlerFound(processedRequest, response);
                return;
            }
            // 2. Get appropriate HandlerAdapter
            HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
            // 3. Invoke handler (controller) -> obtain ModelAndView
            mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
            // view name translation if needed
            if (mv != null && !mv.hasView()) {
                mv.setViewName(getDefaultViewName(request));
            }
        } catch (ModelAndViewDefiningException ex) {
            logger.debug("ModelAndViewDefiningException encountered", ex);
            mv = ex.getModelAndView();
        } catch (Exception ex) {
            Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
            mv = processHandlerException(processedRequest, response, handler, ex);
            errorView = (mv != null);
        }
        // 4. Render view
        if (mv != null && !mv.wasCleared()) {
            render(mv, processedRequest, response);
            if (errorView) {
                WebUtils.clearErrorRequestAttributes(request);
            }
        } else {
            if (logger.isDebugEnabled()) {
                logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() + "': assuming HandlerAdapter completed request handling");
            }
        }
        // afterCompletion of interceptors
    } catch (Exception ex) {
        triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
        throw ex;
    } catch (Error err) {
        ServletException ex = new NestedServletException("Handler processing failed", err);
        triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
        throw ex;
    } finally {
        if (processedRequest != request) {
            cleanupMultipart(processedRequest);
        }
    }
}

The method performs multipart handling, handler mapping, adapter selection, controller invocation via reflection, interceptor pre‑ and post‑processing, view resolution, and final rendering.

Subsequent sections walk through how HandlerMapping builds a HandlerExecutionChain , how HandlerAdapter invokes the controller, and how the view is finally rendered, illustrating the complete front‑end → back‑end → front‑end cycle of a Spring MVC request.

Overall, the article provides a practical guide to setting up a simple SSM project, configuring Spring MVC, and understanding the internal flow of requests by examining key source code.

Javabackend developmentconfigurationsource code analysisSpring MVCDispatcherServletMVC Architecture
Full-Stack Internet Architecture
Written by

Full-Stack Internet Architecture

Introducing full-stack Internet architecture technologies centered on Java

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.