导读:本期聚焦于董浩然创作的《Spring Web MVC框架是什么?核心原理、实际用途与常见误区一次讲清楚》,敬请观看详情。为什么现在的Java Web项目里几乎都离不开Spring Web MVC?作为Spring生态中最经典的Web层框架,它通过前端控制器DispatcherServlet统一接收并分发请求,配合RequestMapping等注解就能写出简洁清晰的Controller,省去了大量Servlet样板代码。本文从框架定位讲起,详细拆解DispatcherServlet的执行流程、HandlerMapping与HandlerAdapter的协作机制、常用注解的使用方式,并总结初学者最容易踩的坑,比如拦截器与过滤器的执行顺序混淆、PathVariable与RequestParam区分不清、返回JSON时类型解析异常等。看完这篇文章,你不仅能明白Spring Web MVC到底解决了什么问题,还能在实际项目中避开高频错误,写出更规范的接口代码。

Spring Web MVC是Spring家族中最早出现的模块之一,也是目前Java Web开发中使用最广泛的框架。简单来说,它是一个基于Servlet构建的Web层框架,围绕请求分发、参数绑定、视图渲染这三件事,把过去需要手写大量配置的Servlet开发模式,简化成几个注解加一个Controller类的工作方式。很多初学者虽然天天在用@Controller@RequestMapping,但对请求到底是怎么流转的、框架在背后做了哪些事,往往一知半解,结果遇到问题就只能靠猜。这篇文章就把Spring Web MVC的定位、核心原理和常见误区一次讲透。

Spring Web MVC框架是什么?核心原理、实际用途与常见误区一次讲清楚

Spring Web MVC到底是什么,它解决了什么问题

在没有MVC框架的年代,用纯Servlet写Web应用的体验相当糟糕。你需要自己继承HttpServlet,重写doGet和doPost方法,手动解析请求参数、做类型转换、处理中文乱码、拼接跳转路径,每加一个功能就要多写一个Servlet,web.xml文件也越写越长。代码里充斥着与业务无关的重复劳动,可维护性很差。

Spring Web MVC的核心价值就是把这套流程标准化了。它引入了前端控制器模式,由一个总入口统一接收所有请求,再根据配置把请求分发给对应的处理器。参数解析、类型转换、视图定位这些通用工作全部由框架承担,开发者只需要关注业务逻辑本身。写一个接口从原来的几十行Servlet代码,变成了如下几行:

@Controller
public class UserController {

    @RequestMapping(value = "/user/detail", method = RequestMethod.GET)
    @ResponseBody
    public User getUserDetail(@RequestParam("id") Long id) {
        // 框架自动完成参数提取和Long类型转换,这里直接写业务逻辑
        return userService.findById(id);
    }
}

从职责划分上看,MVC三个字母分别对应Model(数据模型)、View(视图)、Controller(控制器)。Spring Web MVC在这套结构里主要承担Controller层和View层的调度工作,Model则通常配合Service层和ORM框架来完成。值得一提的是,现在前后端分离已经成为主流,View这个环节大多被JSON序列化取代,但框架的整体架构并没有变,只是视图渲染这一步换成了消息转换器。

核心原理:DispatcherServlet的一次完整请求流程

要理解Spring Web MVC,关键是搞懂DispatcherServlet这个总调度器。它在框架中的地位类似于一个总前台,所有进入应用的请求都会先经过它。可以在web.xml中看到这样的配置:

<servlet>
    <servlet-name>dispatcher</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>
</servlet>
<servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>/<url-pattern>
</servlet-mapping>

一个请求进来之后,DispatcherServlet大致会走这样一条链路:先通过HandlerMapping找到能处理这个请求的Handler(也就是Controller里的某个方法),然后通过HandlerAdapter执行这个Handler,执行前会经过一系列HandlerInterceptor的preHandle方法。Handler执行完毕返回ModelAndView(或直接返回对象由消息转换器处理),再经过拦截器的postHandle,最后完成视图渲染或响应写入,收尾时执行afterCompletion。

这套流程里有几个组件值得单独认识一下。HandlerMapping负责建立请求地址与处理方法之间的映射关系,常用的RequestMappingHandlerMapping会扫描所有带@RequestMapping注解的方法并生成映射表。HandlerAdapter负责真正的调用执行,之所以要有一层适配器,是因为Handler的实现方式可能多种多样,适配器模式让DispatcherServlet不必关心具体细节。HttpMessageConverter则负责请求体和响应体的序列化与反序列化,这就是为什么我们在方法上加一个@ResponseBody,返回的对象就能自动变成JSON。理解了这几个组件的分工,排查问题时就有了方向,比如接口返回404,多半是HandlerMapping没有找到映射;参数绑定失败,则要去查对应的ArgumentResolver。

常用注解的正确打开方式

注解驱动是Spring Web MVC开发的主要风格。@Controller标记一个类为控制器,@RequestMapping用于建立URL映射,@GetMapping@PostMapping是其简化形式,分别限定请求方式。接收参数时,@RequestParam用于获取查询参数或表单字段,@PathVariable用于获取路径中的占位符,@RequestBody用于把请求体反序列化成Java对象,三者职责完全不同,不能混用。

@RestController
@RequestMapping("/order")
public class OrderController {

    // GET /order/list?pageNum=1  page参数没传时使用默认值1
    @GetMapping("/list")
    public List<Order> list(@RequestParam(defaultValue = "1") int pageNum) {
        return orderService.findByPage(pageNum);
    }

    // GET /order/10086  id直接从路径中取
    @GetMapping("/{id}")
    public Order detail(@PathVariable("id") Long id) {
        return orderService.findById(id);
    }

    // POST /order/create  请求体为JSON字符串
    @PostMapping("/create")
    public String create(@RequestBody Order order) {
        orderService.save(order);
        return "ok";
    }
}

@RestController等于@Controller@ResponseBody,用了它之后类中所有方法的返回值都会走消息转换器而不是视图解析。此外@RequestHeader取请求头,@CookieValue取Cookie,这些注解都遵循同一个思路:框架根据注解类型选择对应的ArgumentResolver来完成参数装配,开发者不需要碰HttpServletRequest就能拿到想要的数据,代码可读性和可测试性都好了很多。

初学者最容易踩的几个坑

第一个坑是把@PathVariable@RequestParam搞混。路径占位符必须用@PathVariable接收,query参数必须用@RequestParam接收,用错了会直接报参数缺失异常。还有一种情况是参数名在编译时被压缩,某些场景下注解不写参数名就会绑定失败,所以建议养成显式写明参数名的习惯,比如@RequestParam("id"),这样最稳妥。

第二个坑是对404和静态资源拦截的误解。如果DispatcherServlet的url-pattern配成了/,它会拦截所有请求但不包括JSP,这时访问html、js、图片等静态资源可能404,需要在配置中启用默认Servlet或配置资源映射。另外要注意//*的区别,后者会连JSP一起拦截,容易导致页面渲染异常,这是纯配置层面的经典错误。

第三个坑是拦截器与过滤器的顺序问题。Filter属于Servlet规范,在DispatcherServlet之前执行;Interceptor属于Spring MVC,在DispatcherServlet内部执行。完整顺序是Filter的前置处理、Interceptor的preHandle、Controller执行、Interceptor的postHandle、视图渲染、Interceptor的afterCompletion、Filter的后置处理。跨域、编码这类与业务无关的处理适合放Filter,登录校验、权限控制这类需要Spring上下文的逻辑适合放Interceptor,别把职责放反了。

第四个坑是JSON序列化中的日期和循环引用问题。默认的Jackson对日期类型的格式化结果往往不符合预期,建议通过配置统一指定格式,同时在实体之间存在双向引用时要加@JsonIgnore避免无限递归。这类问题在联调阶段最容易被发现,提前了解能省下不少排查时间。掌握这些细节之后,再回头看待Spring Web MVC,你会发现它并非黑盒,而是一个职责清晰、可以逐层理解的请求处理管道,用好它的前提是理解它的每一环。

Spring Web MVCDispatcherServletSpringMVC注解修改时间:2026-09-08 21:23:26

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260908/52995.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。