Springmvc理解从0到1 完整代码详解

SpringMVC 是 Spring 框架的一个核心模块,全称为 Spring Web MVC (Model-View-Controller),是基于 MVC 设计模式的Java Web 开发框架,用于简化 Web 应用程序的开发。

本文详细介绍了Springmvc易混淆的点,通过理解核心概念,了解mvc的发展,更深理解框架,最后编写一个demo来搭建流程

一、MVC设计模式

  1. Model(模型) :负责数据封装和业务逻辑,通常是 JavaBean / 实体类(如 UserOrder),用于存储处理后的数据。

  2. View(视图):负责数据展示,通常是 JSP、HTML、Thymeleaf 等页面模板,用于将 Model 中的数据呈现给用户。

  3. Controller(控制器):负责接收请求、协调调度(调用 Service 层处理业务),并将处理结果传递给 View 或直接返回数据(如 JSON),是请求处理的 "中枢"。

二、核心流程(请求处理步骤)

1.浏览器发送请求

2.请求被 DispatcherServlet(前端控制器,SpringMVC 的核心)拦截;

3.DispatcherServlet根据请求路径找到对应的controller方法

4.controller方法调用service层,其中service会调用dao层去访问数据库,最后生成数据Model

5.controller将视图名称和Model返回给DispatcherServlet

6.DispatcherServlet根据视图解析器将视图名称解析成前端页面

7.跳转前端页面并对Model完成渲染(页面展示)

三、session和cookie简单理解

1.session是服务端为客户端(浏览器)创建的对话容器,通常储存客户端一些信息,可理解为一个聊条框,session里面储存一个sessionID,客户端访问服务端时,就通过SessionID或者重写url来判断哪个客户端(request)

2.cookie 是客户端储存的小型文本文件,也是服务端创建的,由服务端创建并发给客户端(浏览器),浏览器接受的话,就要交接收responce,所有cookie在responce里面。

维度 Session Cookie
存储位置 服务端(如 Tomcat 等服务器内存 / 缓存) 客户端浏览器(本地文件)
存储内容 存储用户的敏感 / 复杂状态信息(如登录凭证、购物车详情、用户权限等) 存储用户的非敏感 / 标识性信息(如用户偏好、会话标识(Session ID)、广告追踪标识等)
生命周期 默认为一次会话(浏览器关闭则失效,也可手动设置超时时间) 可设置过期时间(如 1 天、7 天,也可设置为会话级(浏览器关闭失效))
大小限制 理论上无严格大小限制(受服务端资源限制) 单个 Cookie 一般不超过 4KB,单域名下 Cookie 数量一般限制在 20~50 个
安全性 存储在服务端,相对安全(但需防范 Session 劫持等攻击) 存储在客户端,易被窃取、篡改(敏感信息需加密)

四、jsp和html对比

首先,你要知道的是现在的 Java Web 开发中,JSP 确实已经几乎被淘汰,但是jsp的原理还是值得学的!

(1) jsp是什么?jsp和html区别

jsp本质是一个servlet,浏览器请求jsp文件,服务器(servlet)会把jsp文件编译成Java servlet类,然后服务器去执行servlet类,运行java代码生成html页面,最终返给前端。

对比项 HTML JSP
定义 纯静态的标记语言,用来描述网页的结构和内容 动态网页技术,本质是一个 Servlet(Java 类),需要在服务器端编译运行
文件后缀 .html .jsp
核心能力 只能展示固定的静态内容 可以嵌入 Java 代码、EL 表达式、JSTL 标签,动态生成内容

(2)jsp为什么被淘汰 ?

JSP 被淘汰的核心原因是它的设计已经跟不上现代 Web 开发的趋势,主要问题有:

  1. 前后端耦合严重:JSP 里混着 Java 代码、HTML、CSS、JS,前端开发人员无法独立工作,代码维护性极差;
  2. 容器依赖强:JSP 需要 Tomcat等 Servlet 容器编译成 Servlet 才能运行,无法适配现在的微服务、云原生部署(比如打包成 Jar 包时,JSP 路径容易出问题);
  3. 性能和扩展性差:JSP 每次修改都需要重启容器(开发阶段),编译后的 Servlet 也会占用容器资源;
  4. 不符合前后端分离趋势:现在主流是「后端提供 JSON 接口,前端(Vue/React/Angular)独立渲染 HTML」,JSP 这种服务端渲染(SSR)的方式逐渐被替代。

五、编写小demo

(1)引入依赖

复制代码
<!--引入springmvc-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>7.0.2</version>
</dependency>
<!--引入Servlet-->
<dependency>
  <groupId>jakarta.servlet</groupId>
  <artifactId>jakarta.servlet-api</artifactId>
  <version>6.1.0</version>
  <scope>provided</scope>
</dependency>

(2)在web-app下配置web.xml,配置前端控制器

java 复制代码
<!--配置SpringMVC的前端控制器,对浏览器发送的请求统一进行处理,也就是需要配置Servlet-->
<servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--配置初始化参数指定SpringMVC配置文件的位置和名称-->
    <init-param>
        <!--
            contextConfigLocation 为固定值
            初始化参数:contextConfigLocation:用来指定springMVC配置文件 在哪个路径
        -->
        <param-name>contextConfigLocation</param-name>
        <!--classpath:表示从类路径下加载-->
        <param-value>classpath:springmvc.xml</param-value>
    </init-param>
    <!--load-on-startup表示启动时加载-->
    <load-on-startup>1</load-on-startup>
</servlet>
<!--设置Servlet映射路径-->
<servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <!--/代表匹配请求是所有,但不包含.jsp请求路径-->
    <url-pattern>/</url-pattern>
</servlet-mapping>

(3)在resource目录下创建核心配置文件

java 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd ">
    <!--2、配置处理器映射器:BeanNameUrlHandlerMapping-->
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
    <!--3、配置处理器适配器:SimpleControllerHandlerAdapter-->
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
    <!--4、配置控制器-->
    <bean id="/helloController" class="com.guan.springmvc.HelloController"/>
    <!--5、配置视图解析器:InternalResourceViewResolver-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="" />
        <property name="suffix" value=".jsp" />
    </bean>
     <!--解决 DispatcherServlet 拦截所有请求导致静态资源访问 404 的问题,需要放在扫描注解之后-->
    <mvc:default-servlet-handler/>
</beans>

(4)编写controller类

java 复制代码
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.jspecify.annotations.Nullable;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

public class HelloController implements Controller {
    @Override
    public @Nullable ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // ModelAndView :模型和视图
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("msg","Hello SpringMVC");
        modelAndView.setViewName("index");
        return modelAndView;
    }
}

(5)最后启动tomcat,在浏览器输入上下文和控制器的id访问servlet。

六、DispatcherServlet和其他servlet对比

普通 Servlet:是 Java EE 规范定义的基础 Web 组件,是处理 HTTP 请求的 "最小单元",每个 Servlet 通常只负责处理一类或一个特定的请求。

DispatcherServlet :是 Spring MVC 框架的前端控制器(Front Controller),它本身也是一个 Servlet,但它是整个 Spring MVC 流程的 "调度中心",负责统一接收请求、分发请求、协调各个组件完成处理流程。


对比维度 普通 Servlet DispatcherServlet
设计定位 处理单个 / 一类特定请求的 "业务处理器" 统一调度所有请求的 "前端控制器"
核心职责 自己处理请求、生成响应(业务逻辑 + 请求响应耦合) 统一接收请求 → 分发到 Controller → 协调组件完成处理 → 返回响应(只调度,不处理业务)
请求处理方式 重写 doGet()/doPost() 等方法,直接在方法里写请求参数解析、业务逻辑、响应生成代码 不处理具体业务,通过 Spring 容器中的 HandlerMapping 找到对应 Controller,HandlerAdapter 执行方法,ViewResolver 解析视图
配置方式 每个 Servlet 需单独在 web.xml 配置(或 @WebServlet 注解),配置繁琐 只需在 web.xml 配置 1 个,后续新增功能只需添加 Controller,无需重复配置 Servlet
复用性 通用逻辑(如参数解析、异常处理)无法复用,每个 Servlet 需重复编写 通用逻辑(如全局拦截、异常处理、参数绑定)通过 Spring 统一配置,所有 Controller 复用
扩展能力 扩展需自己手写代码,整合第三方工具成本高 内置丰富扩展点(拦截器、全局异常处理器、数据绑定器等),无缝整合 Spring 生态(IOC、Security 等)
适用场景 小型、简单的 Web 应用,或需要直接控制请求全过程的场景 中大型 Web 应用,尤其是需要分层解耦、复用组件的 Spring MVC 项目

七、springMVC中流程组件分析

(1)DispatcherServlet用来统一接收请求,调用HanderMapping和HanderAdapter,最后协调ViewResolver

(2)HanderMappeing根据url找到对应的controller方法,本质就是url和controller映射表

(3)HanderAdapter主要用来统一适配不同类型的controlle。比如在我们的写代码时,有注解形式,有在SpringMVC配置文件配置bean,有实现controller接口的,HanderAdapter可以让DispatcherServlet无差别的调用Controller

还会解析url中的参数,把参数转换为controller需要的参数类型,最后把解析后的参数传递给controller

(4)controller就是逻辑层,处理对应的逻辑

(5)ViewResolver,视图解析层,比如在controller中返回index,通过配置视图解析器添加缀.jsp,将返回的物理视图名解析为物理视图路径,index - > index.jsp

八、SpringMVC处理流程

  • 1.客户端发起请求 用户端(浏览器)直接向 DispatcherServlet 发送 HTTP 请求(如访问 hello),DispatcherServlet 作为前端控制器,统一接收所有请求。

  • 2.DispatcherServlet 调用 HandlerMapping 查找处理器 DispatcherServlet 会调用 HandlerMapping,根据请求的 URL 查找对应的处理器执行链(HandlerExecutionChain)。这个执行链包含两部分:

    • Handler :即具体的处理器(通常是 Controller 中的某个方法)
    • HandlerInterceptor:对应的处理器拦截器(用于在请求前后做统一处理,如登录校验、日志记录)
  • 3.DispatcherServlet 调用 HandlerAdapter 进行处理器适配 DispatcherServlet 拿到 HandlerExecutionChain 后,会调用 HandlerAdapterHandlerAdapter 的核心作用是适配不同类型的 Handler(Controller),同时它会:

    • 解析请求中的参数(如 URL 参数、表单数据),转换为 Controller 方法所需的参数类型
    • 执行拦截器的前置处理逻辑
  • 4.HandlerAdapter 执行 Controller 处理业务逻辑 HandlerAdapter 调用 Controller(处理器)的方法,执行业务逻辑:

    • 调用 Service 层、DAO 层完成数据的查询或修改
    • 处理完成后,返回 ModelAndView 对象(包含模型数据 model 和逻辑视图名 viewName
  • 5.DispatcherServlet 接收 ModelAndView 并调用 ViewResolver Controller 返回的 ModelAndView 会先传回给 DispatcherServlet,再由 DispatcherServlet 调用 ViewResolver(视图解析器)。

  • 6.ViewResolver 解析视图并返回 View 对象 ViewResolver 会根据 ModelAndView 中的逻辑视图名 ,解析出对应的物理视图路径 (如将逻辑名 hello 解析为 /WEB-INF/views/hello.jsp),并返回一个 View 对象。

  • 7.View 对象渲染视图并生成响应 View 对象会将 ModelAndView 中的模型数据填充到视图模板中(如把 model 中的用户数据填充到 JSP 的 ${user.name} 标签),生成最终的 HTML 响应。

  • 8.DispatcherServlet 返回响应给客户端 渲染完成的 HTML 响应会通过 DispatcherServlet 返回给浏览器,用户最终看到渲染后的页面。

相关推荐
Knight_AL10 小时前
Mono 使用指南:响应式编程的核心概念与实践
java·mono
这里是彪彪10 小时前
Java中的volatile关键字的作用
java·开发语言
独自破碎E10 小时前
【归并】数组中的逆序对
java·数据结构·算法
范什么特西10 小时前
打开idea项目
java
黎雁·泠崖10 小时前
Java入门从零起步:CMD操作+JDK环境搭建+第一个Java程序
java·开发语言
我的golang之路果然有问题10 小时前
python中 unicorn 热重启问题和 debug 的 json
java·服务器·前端·python·json
码农小卡拉10 小时前
深度解析 Spring Boot 启动运行机制
java·spring boot·后端
weixin_4481199410 小时前
如何装docker
java·云原生·eureka
钦拆大仁10 小时前
如何手搓一个Spring Security
java·后端·spring