详细解析SpringMVC:原理、架构与实战核心

SpringMVC是Spring框架的核心模块之一,是基于Java EE Servlet API构建的**MVC设计模式Web框架**,用于简化Java Web开发,实现请求与响应的标准化处理,同时完成视图与业务逻辑的解耦。它并非独立框架,而是Spring IoC容器在Web层的自然延伸,与Spring核心无缝融合,是目前Java企业级Web开发中最主流的框架之一。

本文将从核心定义、架构设计、核心组件、请求处理全流程、配置方式、常用注解、异常处理、实战要点等方面,全面且详细地讲解SpringMVC,帮你从"会用"到"懂原理"。

一、核心基础:什么是SpringMVC?

1. 本质与设计理念

SpringMVC的核心是**MVC(Model-View-Controller)设计模式**,其本质是"关注点分离"------通过分层设计,将Web应用的三大核心职责拆分,降低组件耦合,提升代码可维护性和扩展性:

  • Model(模型):封装业务数据和业务逻辑,对应Java中的实体类(POJO)、Service层、Dao层,负责数据的存储、查询和处理,不关心数据如何展示。

  • View(视图):负责数据展示,将Model中的数据以指定格式呈现给用户(如JSP、Thymeleaf、Freemarker等),不包含任何业务逻辑。

  • Controller(控制器):作为请求的入口,接收客户端HTTP请求,协调Model和View,调用Model处理业务,再通过View返回处理结果,起到"中间桥梁"的作用。

SpringMVC在传统MVC的基础上进行了优化,核心优势的是:采用"前端控制器模式",通过单一入口(DispatcherServlet)统一处理所有请求,标准化请求流程,同时支持灵活的扩展(如自定义拦截器、参数解析器等),解决了传统Servlet开发中"一个功能一个Servlet"的混乱问题。

2. 核心特性

  • 与Spring无缝融合:可直接复用Spring IoC容器中的Bean(如Service、Dao),无需额外配置,实现Web层与业务层的无缝协作。

  • 请求映射灵活:支持URL路径、请求方法(GET/POST等)、请求头、请求参数等多维度的请求映射,适配各种业务场景。

  • 参数绑定便捷:自动将HTTP请求参数绑定到Java实体类或方法参数,无需手动解析请求流,降低开发成本。

  • 视图解析多样化:支持多种视图技术(JSP、Thymeleaf等),可灵活切换,也支持JSON、XML等非视图响应(前后端分离场景)。

  • 强大的扩展能力:支持自定义拦截器、异常处理器、参数解析器等,满足复杂业务的扩展需求。

  • 内置常用功能:提供文件上传、数据校验、国际化等内置功能,无需额外引入第三方组件。

二、架构设计:SpringMVC的核心组件

SpringMVC的运转依赖一组高度协同的核心组件,所有组件均由Spring IoC容器管理,各组件各司其职、协同工作,构成完整的请求处理链路。核心组件如下(按请求处理顺序排序):

1. 前端控制器(DispatcherServlet)------ 核心中的核心

DispatcherServlet是SpringMVC的"大脑",也是所有HTTP请求的**唯一入口**,本质是一个Servlet(继承自HttpServlet),负责接收请求、分发请求、协调各组件工作,自身不处理任何业务逻辑,完全基于"委派模式"运作。

核心职责:

  • 接收客户端所有HTTP请求(通过web.xml或注解配置映射路径);

  • 通过HandlerMapping找到匹配的处理器(Handler,即Controller的方法);

  • 委托HandlerAdapter执行处理器方法,获取处理结果(ModelAndView或JSON等);

  • 调用ViewResolver将逻辑视图名解析为物理视图;

  • 协调拦截器的执行(前置、后置、完成后处理);

  • 处理请求过程中的异常(委托HandlerExceptionResolver)。

补充:DispatcherServlet初始化时,会加载SpringMVC的核心配置,创建WebApplicationContext(SpringMVC的子容器),该子容器可引用Spring根容器(ContextLoaderListener加载)中的Bean(如Service),实现Web层与业务层的分离与协作。

2. 处理器映射器(HandlerMapping)------ 找"处理器"的工具

HandlerMapping的核心职责是**建立HTTP请求与处理器(Handler)的映射关系**,即根据请求的URL、请求方法等信息,找到对应的Controller方法。

SpringMVC提供多种HandlerMapping实现,日常开发中最常用、最主流的是:

  • RequestMappingHandlerMapping:基于注解的映射器,解析@Controller、@RequestMapping(及派生注解@GetMapping、@PostMapping等),构建URL与Controller方法的映射表,是SpringMVC注解开发的核心映射器,默认自动配置。

补充:HandlerMapping找到匹配的处理器后,会返回一个HandlerExecutionChain对象,该对象包含处理器(Handler)和对应的拦截器链(HandlerInterceptor)。

3. 处理器适配器(HandlerAdapter)------ 执行"处理器"的工具

HandlerAdapter的核心职责是**适配不同类型的处理器,统一执行方式**,解决"DispatcherServlet无法直接调用不同类型处理器"的问题(适配模式的典型应用)。

因为处理器可能是注解式Controller方法、实现特定接口的类等多种形式,HandlerAdapter通过适配,让DispatcherServlet无需关心处理器的具体类型,只需调用其统一的执行方法。

日常开发中最常用的适配器是:

  • RequestMappingHandlerAdapter:适配注解式Controller方法(@RequestMapping标注的方法),负责参数绑定、数据转换、方法调用等关键操作,与RequestMappingHandlerMapping配套使用,默认自动配置。

4. 处理器(Handler)------ 业务逻辑的实际执行者

Handler就是我们编写的**Controller控制器**(或Controller中的方法),是业务逻辑的实际处理者,负责接收请求参数、调用Service层处理业务、返回处理结果(ModelAndView、JSON等)。

注意:Handler并非一个特定的接口,在注解开发中,只要用@Controller标注的类,其内部用@RequestMapping标注的方法,都可以作为Handler。

5. 模型和视图(ModelAndView)------ 处理器与视图的桥梁

ModelAndView是处理器(Handler)的返回值类型之一,封装了两个核心信息:

  • Model:一个Map集合,用于存储业务处理后的核心数据(如查询到的用户列表、表单提交的结果),数据会被传递到视图,供视图渲染使用。

  • View:逻辑视图名(如"user/list"),并非具体的视图对象,需要通过ViewResolver解析为物理视图(如/WEB-INF/views/user/list.jsp)。

补充:在前后端分离场景中,我们通常不返回ModelAndView,而是通过@ResponseBody注解将处理器返回的对象(如POJO)转换为JSON格式,直接响应给客户端,此时无需视图解析。

6. 视图解析器(ViewResolver)------ 解析视图的工具

ViewResolver的核心职责是**将逻辑视图名解析为物理视图对象**,即根据ModelAndView中的逻辑视图名,找到对应的视图文件(如JSP、Thymeleaf模板),并生成View对象,用于渲染数据。

常用的ViewResolver实现:

  • InternalResourceViewResolver:默认的视图解析器,用于解析JSP视图,可配置视图前缀(如/WEB-INF/views/)和后缀(如.jsp),简化逻辑视图名的编写。

  • ThymeleafViewResolver:用于解析Thymeleaf模板视图,是目前主流的非JSP视图解析器,支持HTML模板,更适合前后端分离的半分离场景。

7. 拦截器(HandlerInterceptor)------ 请求的"切面扩展"

HandlerInterceptor是SpringMVC提供的**切面扩展机制**,用于在请求处理的不同阶段执行自定义逻辑,无需修改核心业务代码,实现横切关注点(如权限校验、日志记录、性能监控)的统一处理。

拦截器与过滤器(Filter)的核心区别:拦截器是SpringMVC框架特有,基于Spring AOP思想实现,仅拦截Controller的请求;过滤器是Servlet规范原生组件,基于Java EE标准,拦截所有Web请求(包括静态资源),执行时机早于拦截器。

HandlerInterceptor包含三个核心方法(按执行顺序):

  • preHandle:请求到达Controller之前执行(前置处理),返回true则继续执行后续流程,返回false则中断请求(常用作权限校验、登录状态检查)。

  • postHandle:Controller方法执行完成后、视图渲染之前执行(后置处理),可修改ModelAndView中的数据和视图信息(如统一添加全局数据)。

  • afterCompletion:整个请求处理完成后(包括视图渲染完成)执行,无论请求成功或失败,都能执行,常用于资源清理(如关闭流、释放连接)。

8. 异常处理器(HandlerExceptionResolver)------ 统一异常处理

当请求映射或处理器执行过程中出现异常时,DispatcherServlet会委托HandlerExceptionResolver链处理异常,提供统一的异常响应,避免异常直接暴露给客户端,提升用户体验和系统稳定性。

SpringMVC提供多种HandlerExceptionResolver实现,常用的有:

  • ExceptionHandlerExceptionResolver:通过@ExceptionHandler注解处理异常,可在Controller内部或全局(@ControllerAdvice标注的类)定义异常处理方法,灵活度最高。

  • ResponseStatusExceptionResolver:解析带有@ResponseStatus注解的异常,将异常映射为对应的HTTP状态码(如404、500)。

  • SimpleMappingExceptionResolver:将异常类名与错误视图名映射,用于渲染浏览器端的错误页面。

补充:若所有异常处理器都无法处理异常,异常会冒泡到Servlet容器,由容器渲染默认的错误页面,我们也可通过web.xml配置自定义错误页面。

三、核心流程:HTTP请求从接收至响应的完整链路

SpringMVC的请求处理流程是标准化的,每一步都有明确的职责,理解这个流程,能快速定位开发中的问题(如请求映射失败、参数绑定异常等)。以下是基于注解开发的完整流程(9个核心步骤):

  1. 请求发起:客户端(浏览器、Postman等)发送HTTP请求(如GET /user/1),请求被Web服务器(Tomcat)接收,Tomcat根据请求路径,将请求转发给SpringMVC的DispatcherServlet(所有请求的唯一入口)。

  2. 请求分发:DispatcherServlet接收请求后,调用HandlerMapping,根据请求的URL、请求方法等信息,查找匹配的处理器(Controller方法),返回包含处理器和拦截器链的HandlerExecutionChain对象。

  3. 处理器适配:DispatcherServlet调用HandlerAdapter,适配找到的处理器(Controller方法),HandlerAdapter会完成参数绑定(将请求参数转换为Java方法参数)、数据转换等操作,准备执行处理器方法。

  4. 拦截器前置处理:执行拦截器链的preHandle方法,若所有拦截器的preHandle都返回true,继续执行;若有一个返回false,中断请求,直接返回响应。

  5. 业务逻辑处理:HandlerAdapter调用Controller中的目标方法,执行业务逻辑(调用Service、Dao层),处理完成后,返回处理结果(可能是ModelAndView、JSON对象、String类型的逻辑视图名等)。

  6. 拦截器后置处理:执行拦截器链的postHandle方法(按preHandle的逆序执行),可修改ModelAndView中的数据和视图信息,此时视图尚未渲染。

  7. 视图解析:若处理器返回ModelAndView,DispatcherServlet调用ViewResolver,将逻辑视图名解析为物理视图对象(如JSP、Thymeleaf模板)。

  8. 视图渲染:View对象将Model中的数据与视图模板合并,渲染成最终的响应内容(如HTML页面、JSON字符串),并将响应结果交给DispatcherServlet。

  9. 拦截器完成后处理:执行拦截器链的afterCompletion方法(按preHandle的逆序执行),进行资源清理;最后,DispatcherServlet将响应内容返回给客户端,完成整个请求流程。

四、配置方式:SpringMVC的两种核心配置

SpringMVC的配置分为两种方式:XML配置(传统方式)和注解配置(主流方式),Spring Boot环境下会自动配置核心组件,无需手动编写大量配置。

1. 传统XML配置(SSM整合常用)

需编写两个核心XML文件:web.xml(配置DispatcherServlet)和spring-mvc.xml(配置SpringMVC核心组件)。

(1)web.xml配置DispatcherServlet
复制代码
<!-- 配置前端控制器DispatcherServlet -->
<servlet>
    <servlet-name>springmvc</servlet-name>
   <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- 配置SpringMVC配置文件路径 -->
<init-param>
        <param-name>contextConfigLocation</param-name><param-value>classpath:spring-mvc.xml</param-value>
    </init-param>
    <!-- 启动时加载(优先级1,最高) -->
    <load-on-startup>1</load-on-startup>
</servlet>
<!-- 配置请求映射:所有请求都交给DispatcherServlet处理 -->
<servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>
(2)spring-mvc.xml配置核心组件
复制代码
<!-- 1. 开启注解驱动:自动配置RequestMappingHandlerMapping和RequestMappingHandlerAdapter -->
<mvc:annotation-driven />

<!-- 2. 扫描Controller包:让Spring IoC容器管理Controller -->
<context:component-scan base-package="com.example.controller" />

<!-- 3. 配置视图解析器(InternalResourceViewResolver,解析JSP) -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <!-- 视图前缀:JSP文件所在路径 --><property name="prefix" value="/WEB-INF/views/" />
    <!-- 视图后缀:JSP文件后缀 -->
    <property name="suffix" value=".jsp" />
</bean>

<!-- 4. 配置静态资源放行(避免DispatcherServlet拦截静态资源如CSS、JS) -->
<mvc:default-servlet-handler />

<!-- 5. 配置拦截器 -->
<mvc:interceptors>
    <mvc:interceptor>
        <!-- 拦截所有请求 -->
        <mvc:mapping path="/**" />
        <!-- 放行登录、注册接口 -->
        <mvc:exclude-mapping path="/user/login" />
        <mvc:exclude-mapping path="/user/register" />
        <!-- 自定义拦截器 -->
        <bean class="com.example.interceptor.AuthInterceptor" />
    </mvc:interceptor>
</mvc:interceptors>

2. 注解配置(Spring Boot主流)

Spring Boot通过自动配置(AutoConfiguration)机制,默认配置了SpringMVC的核心组件(DispatcherServlet、RequestMappingHandlerMapping等),我们只需通过注解完成个性化配置。

(1)核心注解开启SpringMVC

在Spring Boot启动类上添加@SpringBootApplication注解,该注解包含@EnableAutoConfiguration,会自动开启SpringMVC的自动配置。若需自定义SpringMVC配置,可创建配置类,实现WebMvcConfigurer接口(无需添加@EnableWebMvc,否则会覆盖自动配置);若需完全接管配置,可在配置类上添加@EnableWebMvc注解。

复制代码
// Spring Boot启动类
@SpringBootApplication
public class SpringMvcDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringMvcDemoApplication.class, args);
    }
}

// 自定义SpringMVC配置类
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    // 1. 配置视图解析器(Thymeleaf)
    @Bean
    public ViewResolver thymeleafViewResolver(SpringTemplateEngine templateEngine) {
        ThymeleafViewResolver resolver = new ThymeleafViewResolver();
        resolver.setTemplateEngine(templateEngine);
        return resolver;
    }

    // 2. 配置拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new AuthInterceptor())
                .addPathPatterns("/**") // 拦截所有请求
                .excludePathPatterns("/user/login", "/user/register"); // 放行路径
    }

    // 3. 配置静态资源映射
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**")
                .addResourceLocations("classpath:/static/");
    }
}

补充:在Spring Boot中,若使用@EnableWebMvc注解,会禁用自动配置,需要手动配置所有核心组件(如视图解析器、消息转换器等),一般不推荐使用,除非需要完全自定义配置。

五、常用注解:SpringMVC注解开发核心

注解开发是SpringMVC的主流方式,核心注解用于标识Controller、映射请求、绑定参数、返回响应等,以下是最常用、最核心的注解,结合示例说明用法:

1. @Controller ------ 标识控制器

作用:标注在类上,声明该类是SpringMVC的Controller,Spring IoC容器会自动扫描并实例化该类,使其成为处理器的载体。该类中的方法可通过@RequestMapping等注解映射请求。

复制代码
// 标识UserController为SpringMVC控制器
@Controller
@RequestMapping("/user") // 类级别的请求映射(一级路径)
public class UserController {
    // 方法级别的请求映射(二级路径)
    @GetMapping("/list")
    public String userList(Model model) {
        // 业务逻辑:查询用户列表
        List<User> userList = userService.findAll();
        // 将数据存入Model,供视图使用
        model.addAttribute("userList", userList);
        // 返回逻辑视图名,由视图解析器解析为物理视图
        return "user/list";
    }
}

2. @RequestMapping ------ 请求映射核心注解

作用:标注在类或方法上,用于映射HTTP请求,指定当前类/方法处理的请求路径、请求方法等。

核心属性:

  • value/path:指定请求路径(必填),可接收字符串数组,支持通配符(如/user/*)。

  • method:指定请求方法(如RequestMethod.GET、RequestMethod.POST),不指定则支持所有请求方法。

  • params:指定请求必须包含的参数(如params = "id",表示请求必须携带id参数)。

  • headers:指定请求必须包含的请求头(如headers = "Content-Type=application/json")。

  • consumes:指定请求的Content-Type(如application/json),即接收的请求体格式。

  • produces:指定响应的Content-Type(如application/json),即返回的响应格式。

简化注解(Spring 4.3+):为常用请求方法提供简化注解,替代@RequestMapping的method属性:

  • @GetMapping:等价于@RequestMapping(method = RequestMethod.GET),处理GET请求(查询数据)。

  • @PostMapping:等价于@RequestMapping(method = RequestMethod.POST),处理POST请求(提交数据)。

  • @PutMapping:处理PUT请求(修改数据)。

  • @DeleteMapping:处理DELETE请求(删除数据)。

3. @RequestParam ------ 请求参数绑定(普通参数)

作用:标注在方法参数上,用于绑定HTTP请求中的普通参数(如URL查询参数、表单参数),若参数名与请求参数名一致,可省略该注解。

复制代码
// 示例:绑定请求参数(如GET /user/query?id=1&name=张三)
@GetMapping("/query")
public String queryUser(
        // required = false:参数非必填,默认true(必填)
        @RequestParam(value = "id", required = false) Integer userId,
        // defaultValue:参数为空时的默认值
        @RequestParam(value = "name", defaultValue = "未知") String userName,
        Model model) {
    User user = userService.queryByIdAndName(userId, userName);
    model.addAttribute("user", user);
    return "user/detail";
}

4. @PathVariable ------ 路径参数绑定

作用:标注在方法参数上,用于绑定URL路径中的模板变量(如/user/{id}中的id),适用于RESTful风格的接口。

复制代码
// 示例:RESTful风格,路径参数id(如GET /user/1)
@GetMapping("/{id}")
public String getUserDetail(@PathVariable("id") Integer userId, Model model) {
    User user = userService.findById(userId);
    model.addAttribute("user", user);
    return "user/detail";
}

5. @RequestBody ------ 请求体参数绑定(JSON/XML)

作用:标注在方法参数上,用于将HTTP请求体中的数据(如JSON、XML)转换为Java实体类对象,适用于前后端分离场景(客户端提交JSON数据)。

注意:使用该注解时,客户端请求的Content-Type需设置为application/json或application/xml。

复制代码
// 示例:接收JSON请求体,转换为User对象(如POST /user/add,请求体{"name":"张三","age":20})
@PostMapping("/add")
@ResponseBody // 配合使用,返回JSON响应
public Result addUser(@RequestBody User user) {
    userService.add(user);
    return Result.success("添加成功");
}

6. @ResponseBody ------ 响应JSON/XML

作用:标注在方法上或方法返回值上,用于将方法返回的Java对象(如POJO、List)通过消息转换器(HttpMessageConverter)转换为JSON或XML格式,直接响应给客户端,无需视图解析。

简化注解:@RestController = @Controller + @ResponseBody,标注在类上,标识该类所有方法都返回JSON/XML响应,无需单独添加@ResponseBody。

复制代码
// @RestController = @Controller + @ResponseBody
@RestController
@RequestMapping("/api/user")
public class UserApiController {
    // 方法返回JSON,无需视图解析
    @GetMapping("/list")
    public List<User> getUserList() {
        return userService.findAll();
    }

    // 方法返回JSON格式的结果对象
    @PostMapping("/update")
    public Result updateUser(@RequestBody User user) {
        userService.update(user);
        return Result.success("修改成功");
    }
}

7. @ModelAttribute ------ 模型数据绑定

作用:可标注在方法或方法参数上,用于将请求参数绑定到Java实体类对象,并自动将该对象加入Model中,供视图使用。

复制代码
// 示例1:标注在参数上,绑定表单参数到User对象
@PostMapping("/update")
public String updateUser(@ModelAttribute("user") User user) {
    userService.update(user);
    return "redirect:/user/list"; // 重定向到用户列表页
}

// 示例2:标注在方法上,在所有@RequestMapping方法执行前执行,添加全局模型数据
@ModelAttribute
public void addGlobalData(Model model) {
    model.addAttribute("title", "用户管理系统"); // 所有视图都能获取该数据
}

8. @SessionAttributes ------ 会话数据存储

作用:标注在Controller类上,用于将Model中的指定数据存储到Session中,实现跨请求数据共享(如登录用户信息)。

复制代码
@Controller
@RequestMapping("/user")
@SessionAttributes("loginUser") // 将Model中key为loginUser的数据存入Session
public class UserController {
    // 登录方法,将用户信息存入Model,自动同步到Session
    @PostMapping("/login")
    public String login(String username, String password, Model model) {
        User loginUser = userService.login(username, password);
        model.addAttribute("loginUser", loginUser); // 同步到Session
        return "redirect:/user/home";
    }

    // 从Session中获取登录用户信息
    @GetMapping("/home")
    public String home(@SessionAttribute("loginUser") User loginUser, Model model) {
        model.addAttribute("user", loginUser);
        return "user/home";
    }
}

9. @ExceptionHandler ------ 局部异常处理

作用:标注在Controller内部的方法上,用于处理当前Controller中发生的指定类型异常,实现局部异常捕获。

复制代码
@Controller
@RequestMapping("/user")
public class UserController {
    // 处理当前Controller中发生的NullPointerException
    @ExceptionHandler(NullPointerException.class)
    public String handleNullPointerException(Exception e, Model model) {
        model.addAttribute("errorMsg", "数据为空:" + e.getMessage());
        return "error/500"; // 跳转到错误页面
    }

    // 处理当前Controller中发生的所有异常(兜底)
    @ExceptionHandler(Exception.class)
    public String handleAllException(Exception e, Model model) {
        model.addAttribute("errorMsg", "系统异常:" + e.getMessage());
        return "error/500";
    }
}

10. @ControllerAdvice + @ExceptionHandler ------ 全局异常处理

作用:@ControllerAdvice标注在类上,标识该类是全局异常处理类,配合@ExceptionHandler注解,可处理所有Controller中发生的异常,实现全局异常统一管理。

复制代码
// 全局异常处理类
@ControllerAdvice
public class GlobalExceptionHandler {
    // 处理空指针异常
    @ExceptionHandler(NullPointerException.class)
    public ModelAndView handleNullPointerException(Exception e) {
        ModelAndView mav = new ModelAndView();
        mav.addObject("errorMsg", "数据为空,请检查参数");
        mav.setViewName("error/500");
        return mav;
    }

    // 处理请求参数绑定异常
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public Result handleParamException(MethodArgumentNotValidException e) {
        // 获取参数校验失败信息
        String errorMsg = e.getBindingResult().getFieldError().getDefaultMessage();
        return Result.fail(400, errorMsg);
    }

    // 全局兜底异常处理
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public Result handleGlobalException(Exception e) {
        return Result.fail(500, "系统异常,请联系管理员");
    }
}

六、实战要点:常见问题与解决方案

1. 静态资源放行问题

问题:DispatcherServlet的映射路径为"/"时,会拦截所有请求,包括CSS、JS、图片等静态资源,导致静态资源无法访问。

解决方案:

  • XML配置:添加<mvc:default-servlet-handler />,让默认Servlet处理静态资源。

  • 注解配置(Spring Boot):通过WebMvcConfigurer的addResourceHandlers方法配置静态资源映射。

2. 参数绑定异常

问题:请求参数类型与方法参数类型不匹配(如将字符串"abc"绑定到Integer类型),导致参数绑定失败。

解决方案:

  • 确保请求参数类型与方法参数类型一致;

  • 使用@RequestParam的defaultValue属性,避免参数为空;

  • 自定义类型转换器(实现Converter接口),处理特殊类型的参数绑定(如String转Date)。

3. 视图解析异常

问题:返回的逻辑视图名无法被ViewResolver解析,导致404错误。

解决方案:

  • 检查视图解析器的prefix(前缀)和suffix(后缀)配置是否正确;

  • 确保物理视图文件(如JSP、Thymeleaf模板)的路径与配置一致;

  • 前后端分离场景中,确保方法添加了@ResponseBody注解,避免视图解析。

4. 拦截器不生效

问题:自定义拦截器未执行,无法实现权限校验等功能。

解决方案:

  • 检查拦截器是否正确注册(XML配置<mvc:interceptors>,注解配置重写addInterceptors方法);

  • 检查拦截器的addPathPatterns(拦截路径)和excludePathPatterns(放行路径)配置是否正确;

  • 确保拦截器的preHandle方法返回true(返回false会中断请求)。

相关推荐
惊讶的猫7 天前
SpringMVC介绍
java·springmvc·springboot
Zsh-cs2 个月前
苍穹外卖之SpringMVC的消息转换器在项目中的应用场景
springmvc·苍穹外卖·消息转换器
这周也會开心2 个月前
SSM 配置 index 页面的实现方式
java·tomcat·springmvc
海南java第二人2 个月前
Spring MVC核心流程深度解析:从请求到响应的完美掌控
java·springmvc
BD_Marathon2 个月前
RESTful快速开发
springmvc
自在极意功。2 个月前
简单介绍SpringMVC
java·mvc·springmvc·三层架构
Zsh-cs3 个月前
SpringMVC
java·springmvc
阿拉斯攀登3 个月前
设计模式:责任链模式(springmvc应用)
设计模式·springmvc·责任链模式
阿拉斯攀登3 个月前
设计模式:命令模式(Spring MVC中的实践)
设计模式·springmvc·命令模式