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个核心步骤):
-
请求发起:客户端(浏览器、Postman等)发送HTTP请求(如GET /user/1),请求被Web服务器(Tomcat)接收,Tomcat根据请求路径,将请求转发给SpringMVC的DispatcherServlet(所有请求的唯一入口)。
-
请求分发:DispatcherServlet接收请求后,调用HandlerMapping,根据请求的URL、请求方法等信息,查找匹配的处理器(Controller方法),返回包含处理器和拦截器链的HandlerExecutionChain对象。
-
处理器适配:DispatcherServlet调用HandlerAdapter,适配找到的处理器(Controller方法),HandlerAdapter会完成参数绑定(将请求参数转换为Java方法参数)、数据转换等操作,准备执行处理器方法。
-
拦截器前置处理:执行拦截器链的preHandle方法,若所有拦截器的preHandle都返回true,继续执行;若有一个返回false,中断请求,直接返回响应。
-
业务逻辑处理:HandlerAdapter调用Controller中的目标方法,执行业务逻辑(调用Service、Dao层),处理完成后,返回处理结果(可能是ModelAndView、JSON对象、String类型的逻辑视图名等)。
-
拦截器后置处理:执行拦截器链的postHandle方法(按preHandle的逆序执行),可修改ModelAndView中的数据和视图信息,此时视图尚未渲染。
-
视图解析:若处理器返回ModelAndView,DispatcherServlet调用ViewResolver,将逻辑视图名解析为物理视图对象(如JSP、Thymeleaf模板)。
-
视图渲染:View对象将Model中的数据与视图模板合并,渲染成最终的响应内容(如HTML页面、JSON字符串),并将响应结果交给DispatcherServlet。
-
拦截器完成后处理:执行拦截器链的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会中断请求)。