导读:本期聚焦于关中王创作的《什么是SpringMVC?核心原理、搭建步骤与避坑建议一次讲透》,敬请观看详情。SpringMVC是Spring家族中处理Web请求的核心模块,但它到底解决了什么问题?本文从DispatcherServlet的工作流程入手,拆解HandlerMapping、HandlerAdapter、ViewResolver等组件如何协作完成一次请求的处理,并给出基于注解控制器的完整搭建步骤。同时对比SpringMVC与Struts2、Spring Boot的差异,帮你判断什么场景该选它。文末整理了常见的坑,包括静态资源被拦截、中文乱码、406错误、事务失效等问题,附上原因分析和解决办法,适合初学者系统学习和开发者排查问题时查阅收藏。

SpringMVC是Spring生态中最早成熟起来的Web层框架,直到今天大量传统Java项目依然运行在它之上。要真正理解它,不能只停留在“接收请求返回JSON”的层面,而要搞清楚它的请求处理流程、核心组件分工,以及实际使用中那些容易踩的坑。本文就从这三个维度把SpringMVC完整讲一遍。

什么是SpringMVC?核心原理、搭建步骤与避坑建议一次讲透

一、SpringMVC到底是什么

SpringMVC的全称是Spring Web MVC,它是Spring框架中基于MVC设计模式的Web层框架。MVC即Model(模型)、View(视图)、Controller(控制器)的分层思想:Controller负责接收和分发请求,Model封装业务数据,View负责最终呈现。SpringMVC对这套思想做了实现,并且天然与Spring的IoC容器融合,控制器可以像普通Bean一样被注入依赖。

它的核心是一个前端控制器——DispatcherServlet。所有请求先打到这个Servlet上,再由它统一调度后续组件完成处理。这种集中式分发的设计好处很明显:开发者只需要关注业务控制器怎么写,请求解析、适配、视图渲染等通用逻辑全部由框架接管。相比早期直接写Servlet的时代,代码量大幅下降,参数绑定、数据校验、统一异常处理等能力都开箱即用。

与Struts2相比,SpringMVC是方法级的拦截,一个Controller类里可以放多个处理方法,方法入参直接接收请求数据,返回值灵活支持视图、JSON、文件流等。而Struts2是类级拦截,每个请求要创建一个Action实例。加上SpringMVC与Spring容器无缝集成,这也是它逐渐成为Java Web开发主流选择的原因。

二、核心组件与请求处理流程详解

一次完整的请求会经过多个组件协作。首先DispatcherServlet接收请求,然后查询HandlerMapping找到对应的处理器(Handler)以及一组拦截器,返回一个HandlerExecutionChain执行链。接着HandlerAdapter负责真正调用处理器方法——之所以需要适配器,是因为处理器的形式多种多样,有基于注解的、有实现Controller接口的,适配器模式屏蔽了这些差异。

控制器方法执行完毕后返回一个ModelAndView对象(使用@ResponseBody时则直接由消息转换器写出响应)。如果是返回视图名,ViewResolver会把逻辑视图名解析为具体的物理视图,最后渲染数据输出到前端。整个流程中还有HandlerExceptionResolver处理异常、拦截器在前后插入通用逻辑。理解了这条链路,排查问题时的思路会清晰很多:404查HandlerMapping映射、500查异常解析器、返回内容不对查消息转换器。

下面用一段传统的XML加注解混合方式展示最小可运行的配置,帮助理解各组件在配置中如何体现:

<!-- web.xml 中注册前端控制器 -->
<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:springmvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>
@Controller
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    // 返回JSON数据
    @RequestMapping(value = "/info", method = RequestMethod.GET)
    @ResponseBody
    public User getUser(@RequestParam("id") Long id) {
        return userService.findById(id);
    }

    // 返回逻辑视图名,交给ViewResolver解析
    @RequestMapping("/list")
    public String list(Model model) {
        model.addAttribute("users", userService.findAll());
        return "user/list"; // 对应 /WEB-INF/views/user/list.jsp
    }
}

三、怎么做:搭建与进阶用法

搭建SpringMVC项目有三条路线。第一种是传统的XML配置,需要配置DispatcherServlet、组件扫描、注解驱动和视图解析器,适合维护老项目时阅读理解。第二种是完全Java Config的方式,继承AbstractAnnotationConfigDispatcherServletInitializer,摆脱web.xml,配置更类型安全。第三种是直接用Spring Boot,它内嵌Tomcat并自动配置了SpringMVC的绝大部分组件,加一个spring-boot-starter-web依赖即可写控制器,是目前新项目的首选。

日常开发中最常用的注解要掌握这几个:@Controller声明控制器,@RequestMapping映射请求路径(可细化为@GetMapping@PostMapping),@RequestParam接收URL参数,@PathVariable接收REST风格的路径变量,@RequestBody把请求体反序列化为Java对象,@ResponseBody把返回对象序列化为JSON。配合@RestController这个组合注解,可以省去每个方法上的@ResponseBody

进阶一点的功能包括统一异常处理和数据校验。全局异常处理用@ControllerAdvice@ExceptionHandler,把业务异常统一转成友好的错误响应;参数校验配合@Validated和JSR-303注解(如@NotNull@Size),在进入业务逻辑前就把非法参数拦下来,避免散落各处的if判断。

@RestControllerAdvice
public class GlobalExceptionHandler {

    // 捕获业务异常并返回统一格式
    @ExceptionHandler(BizException.class)
    public Result<Void> handleBiz(BizException e) {
        return Result.fail(e.getCode(), e.getMessage());
    }

    // 捕获参数校验异常
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result<Void> handleValid(MethodArgumentNotValidException e) {
        String msg = e.getBindingResult().getFieldError().getDefaultMessage();
        return Result.fail(400, msg);
    }
}

四、怎么选:SpringMVC的适用场景判断

如果团队维护的是传统WAR部署的单一应用,需要精细控制视图渲染流程,或者项目本身就是基于SpringMVC构建的历史系统,继续使用它完全没有问题,它的稳定性和生态成熟度经过了大量生产环境验证。对于前后端分离的项目,SpringMVC只承担REST接口层也非常合适,配合Jackson做JSON序列化即可。

但如果是全新项目,更推荐基于Spring Boot使用SpringMVC,因为底层依然是同一套东西,只是省去了繁琐配置。而在微服务架构下,网关转发、接口文档、链路追踪等需求增多,Spring Boot加Spring Cloud的组合显然更高效。简单说:SpringMVC是引擎,Spring Boot是整装好的汽车,选哪个取决于你是想自己组装还是直接上路。

五、注意事项与避坑建议

坑一:静态资源被前端控制器拦截。DispatcherServlet的url-pattern配置成/时,js、css、图片等静态资源请求也会进入SpringMVC,由于没有对应的Handler导致404。解决办法是在配置中加上<mvc:resources>或标注<mvc:default-servlet-handler>,Spring Boot项目则默认已经处理好。

坑二:POST请求中文乱码。Tomcat默认按ISO-8859-1解析请求体,提交中文就乱码。要在web.xml中配置CharacterEncodingFilter并放在所有Filter之前,GET请求的乱码则需修改Tomcat连接器的URIEncoding为UTF-8。

坑三:返回JSON报406错误。方法上有@ResponseBody却返回406,通常是缺少Jackson依赖,或者对应的<mvc:annotation-driven>/ @EnableWebMvc没有开启,导致找不到能处理application/json的消息转换器。

坑四:控制器中的事务失效。SpringMVC的容器是子容器,Spring核心容器是父容器。如果把Service的事务配置只加在父容器而扫描规则写错,或者在Controller方法里用try-catch吞掉异常后再手动抛受检异常,都可能导致事务不回滚。建议事务统一通过@Transactional声明在Service层,并注意默认只对运行时异常回滚。

坑五:拦截器路径匹配写错。Interceptor的excludePathPatterns少写或通配符写错,会造成登录校验意外放行或误拦截。上线前务必用真实路径回归一遍,特别是带路径参数的REST接口。

把这些坑点记牢,再配合对DispatcherServlet流程的理解,无论是阅读老项目还是排查线上问题,都能做到心里有数。建议把本文收藏起来,遇到具体报错时对照流程逐段排查,效率会高很多。

SpringMVCSpring框架MVC架构修改时间:2026-09-09 16:45:21

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