Spring MVC 入门

Spring MVC入门

Spring MVC概述

Spring MVC是基于Java的Web框架,用于开发基于Model-View-Controller(MVC)架构的Web应用程序。它提供了一种组织和管理Web应用程序的方式,将应用程序分为模型(Model)、视图(View)和控制器(Controller),以提高代码的可维护性、可扩展性和可测试性。

对于Spring MVC而言,其最大的特色是结构松散,比如几乎可以在Spring MVC中使用各类视图,包括json、jsp、xml、pdf等,所以它能够满足手机端、PC页面端和平板及物联网等各类请求。Spring MVC的核心在于其流程,这是使用Spring MVC的基础,Spring MVC是一种基于servlet的技术,它提供了核心控制器DispatcherServlet和相关的组件,并制定了松散的结构,以适合各种灵活的需要。

image

图注:Spring MVC核心组件关系图

核心工作流程

Spring MVC框架是围绕DispatcherServlet而工作的,所以这个类是其最为重要的类。它是一个Servlet,可以拦截HTTP发送过来的请求,具体工作流程如下:

  1. Servlet初始化时,Spring MVC会根据配置,获取配置信息,从而得到统一资源标识符和处理器之间的映射关系,同时为处理器加入拦截器,构成处理器的执行链,并初始化视图解析器等内容。
  2. 当一个请求到来时,DispatcherServlet首先通过请求和事先解析好的HandlerMapping配置,找到相应的Handler(处理器),准备运行处理器和拦截器组成的执行链。
  3. 运行处理器需要对应的环境,通过处理器适配器HandlerAdapter,运行对应的处理器和拦截器(处理器包含了控制器的内容和其他增强功能)。
  4. 处理器返回模型和视图(ModelAndView)给DispatcherServlet后,DispatcherServlet会把对应的视图信息传递给视图解析器。
  5. 视图解析器定位视图,将数据模型渲染到视图中,响应用户的请求。

Spring MVC环境搭建

添加相关依赖

plugins {
    id 'war'
    id 'java'
}

dependencies {
    implementation 'org.springframework:spring-webmvc:7.0.2'
}

容器关系说明

image

图注:Spring MVC中WebApplicationContext容器层级关系图

在Spring MVC官方文档中可知,两个容器存在父子关系,具体说明如下:

  • RootContext会被注入到ServletContext的parentBeanFactory中。
  • Spring MVC的容器ServletContext中如果没有bean,则委派RootContext中去查找,即ServletContext中可以访问RootContext中的bean,反过来则不行。
  • 根WebApplicationContext(Root WebApplicationContext)通常包含基础设施bean,如需要在多个Servlet实例之间共享的数据存储库和业务服务。
  • Servlet特定的子WebApplicationContext通常包含给定Servlet的本地bean,如控制器、视图解析器和其他与Web相关的bean,根容器中的bean会被有效继承,且可在子容器中重写(重新声明)。

配置web.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<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_4_0.xsd"
         version="4.0">

    <!-- 配置ContextLoaderListener用于初始化Spring IoC容器(root WebApplicationContext) -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <!-- 配置spring IoC配置文件路径 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-root.xml</param-value>
    </context-param>

    <!-- 配置DispatcherServlet -->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--如果没有指定加载文件,会从/WEB-INF/下去加载以 servlet-name,即dispatcherServlet的xml文件-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>
</web-app>

web.xml配置内容说明

  1. 系统变量contextConfigLocation的配置:它会告诉Spring MVC其Spring IoC的配置文件在哪里,Spring会找到这些配置文件并加载。多个配置文件可使用逗号分割,支持正则式模糊匹配,默认值为/WEB-INF/applicationContext.xml
  2. ContextLoaderListener:实现了ServletContextListener接口,在Web工程初始化之前完成Spring IoC容器的初始化,在Web工程关闭时释放Spring IoC容器的资源。
  3. DispatcherServlet配置:配置了在服务器启动时对其进行初始化,且拦截以后缀do结尾的请求,所有以do结尾的请求都会被其拦截。

配置spring-root.xml(对应Root WebApplicationContext容器)

<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

</beans>

配置说明

配置组件自动扫描,对以@Controller标注的组件进行排除(Root WebApplicationContext通常包含基础架构bean)。

配置spring-mvc.xml(Spring MVC相关配置)

<?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
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc
       https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <context:component-scan base-package="com.controller" />
    <!--
        以注解驱动spring mvc
        内部已经包含针对注解的HandlerMapping和HandlerAdapter
     -->
    <mvc:annotation-driven/>

    <!-- 配置视图解析器:jstl + el解析jsp视图 -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 逻辑视图名的前缀 -->
        <property name="prefix" value="/WEB-INF/pages/"/>
        <!-- 逻辑视图名的后缀 -->
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

配置说明

  1. <mvc:annotation-driven/>:表示使用注解驱动Spring MVC,内部已包含针对注解的HandlerMapping和HandlerAdapter。
  2. 组件扫描:扫描com.controller包,加载对应的控制器。
  3. 视图解析器配置:定义了逻辑视图名的前缀(/WEB-INF/pages/)和后缀(.jsp),视图会到Web工程的/WEB-INF/pages文件夹中找到对应的jsp文件作为响应视图。

开发控制器(Controller)

package com.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class WelcomeController {
    /**
     * 处理器
     * @return 模型和视图
     * @RequestMapping: url(/mvc/index.do)和处理器映射
     */
    @RequestMapping("/mvc/index.do")
    public ModelAndView index(){
        //模型(共享数据,作用域范围为request)和视图
        ModelAndView mv = new ModelAndView();
        mv.addObject("message","hello spring mvc");//request.setAttribute("message","hello spring mvc");
        //绑定逻辑视图(默认是forward),指定了逻辑视图名,DispatcherServlet选择视图解析器解析视图,根据逻辑视图名找到view进行渲染
        mv.setViewName("index");//request.getRequestDispatcher(prefix + viewName + suffix).forward(request,response); //WEB-INF/pages/index.jsp
        //返回给DispatcherServlet
        return mv;
    }
}

控制器说明

  1. @Controller注解:标识该类为控制器,Spring MVC扫描时会将其作为控制器加载。
  2. @RequestMapping("/mvc/index.do"):指定对应的请求URI,Spring MVC初始化时会解析该信息并存储,形成HandlerMapping,请求到来时通过该信息找到对应的控制器提供服务。
  3. 返回值ModelAndView:方法中指定视图名称为index,结合视图解析器的前缀和后缀,最终会寻找/WEB-INF/pages/index.jsp作为响应视图,并将message数据传递到视图中。

编写视图页面(index.jsp)

<%--
  Created by IntelliJ IDEA.
  User: Jing61
  Date: 2025/12/23
  Time: 09:54
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    ${message}
</body>
</html>

控制器请求处理流程示意图

image

图注:Spring MVC控制器请求处理流程(包含注解解析、处理器映射、适配器调用、视图解析等环节)

Spring MVC启动过程

ServletContext初始化

Web容器(比如tomcat、jboss、weblogic等)启动时,会为每个Web应用程序创建一个ServletContext对象,它代表当前Web应用的上下文。一个Web应用(即一个Web工程)有且仅创建一个ServletContext,Web中的所有Servlet共享该对象,可通过ServletContext实现Servlet之间的通讯。在继承自HttpServlet的类中,可通过this.getServletContext获取ServletContext对象。

根上下文(Root WebApplicationContext)初始化

在Web程序中使用Spring时,需配置ContextLoaderListener监听器:

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
  • Web容器启动时会触发容器初始化事件,ContextLoaderListener监听到该事件后,其contextInitialized方法会被调用。
  • 在该方法中,Spring会初始化一个根上下文(WebApplicationContext,继承自ApplicationContext接口,实际实现类为XmlWebApplicationContext),即Spring的IoC容器。
  • 根上下文对应的Bean定义配置由web.xml中的context-param标签指定。
  • 根上下文初始化完毕后,Spring以WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE为属性Key,将其存储到ServletContext中,便于后续获取。

DispatcherServlet上下文初始化

  • ContextLoaderListener监听器初始化完毕后,开始初始化web.xml中配置的Servlet(可配置多个,以DispatcherServlet为例)。
  • DispatcherServlet是标准的前端控制器,用于转发、匹配、处理每个Servlet请求。
  • DispatcherServlet初始化时会建立自己的IoC上下文(持有Spring MVC相关的bean),建立时会通过WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE从ServletContext中获取根上下文,作为自己上下文的parent上下文。
  • 之后初始化自身持有的上下文,核心工作包括初始化处理器映射、视图解析器等(可在initStrategies方法中查看详细逻辑),其默认实现类也是XmlWebApplicationContext。
  • 初始化完毕后,Spring以与Servlet名字相关的属性为Key(具体转换规则可查看源码),将该上下文也存储到ServletContext中。
  • 最终每个Servlet持有自己的上下文(独立的bean空间),同时所有Servlet共享根上下文定义的bean。
posted @ 2025-12-23 13:16  Jing61  阅读(1)  评论(0)    收藏  举报