Spring MVC
字数: 0 字 时长: 0 分钟
简介
Spring MVC 是指 MVC(Model-View-Controller)模式,它将请求处理流程分为三层:模型层、视图层和控制层,用一种松耦合的方式将用户请求、业务逻辑和视图渲染分离开来。
Spring MVC 与 Spring 的关系
Spring 是底层基础,Spring MVC 构建在 Spring 核心之上,利用其提供的 IOC/DI、AOP 等功能来实现 Web 层的管理
工作流程
DispatcherServlet
接收 HTTP 请求
DispatcherServlet
(作为整个流程的调度中心)会首先接收到 HTTP 请求,然后调用 doDispatch()
执行分发调度逻辑
- 通过
HandlerMapping
解析请求映射
DispatcherServlet
会首先去请求 HandlerMapping
,返回一个 HandlerExecutionChain
处理器执行链
其实这个 HandlerExecutionChain
对象包含了一个处理器和一系列拦截器
HandlerAdapter
适配器反射执行实际处理器方法
先通过 HandlerExecutionChain
找到对应的 HandlerAdapter
实际执行之前,还会调用拦截器的 preHandle()
方法,返回为 true
的情况下,才会执行处理器方法,返回 ModelAndView
- 处理
ModelAndView
将 ModelAndView
委托给 ViewResolver
进行解析渲染
核心组件
DispatcherServlet
DispatcherServlet
是请求的入口与出口,也是整个流程的中央调度器,将请求委托给其他组件处理,比如 HandlerMapping
、HandlerAdapter
、ViewResolver
等
HandlerMapping
处理器映射器:负责解析请求,匹配请求 URL 对应的 Controller
(或Handler
)以及关联的拦截器 (HandlerInterceptor
)链
HandlerAdapter
处理器适配器:适配器模式实现,负责调用目标 Handler
的相应方法(如@RequestMapping
注解的方法),将请求参数、模型数据等进行封装,最后返回 ModelAndView
对象
Controller / Handler
实际处理器,负责接收 HandlerAdapter
传递过来的请求数据,执行业务逻辑(通常需要调用 Service
层)
ViewResolver / View
视图解析器与视图,将 Handler
返回的逻辑视图解析为具体的视图对象,并使用具体的视图模板进行渲染
HandlerExceptionResolver
处理器异常解析器,负责处理请求处理过程中发生的异常,可以将异常映射到特定的错误页面。常见的实现是 @ControllerAdvice
+ @ExceptionHandler
Spring 父子容器
父容器指的是 Spring 的根容器,主要管理应用程序的全局 Bean,如服务层(Service
)、数据访问层(DAO
)等。通过 ContextLoaderListener
在应用启动时就初始化。
子容器指的是 Spring MVC 中的 DispatcherServlet
创建的容器,用于管理 Web 层相关 Bean (如 Controller
、HandlerMapping
);在 DispatcherServlet
启动时初始化。
父子容器设计的好处
子容器可以访问父容器,父容器不能访问子容器。开发者可以将业务逻辑和 Web 层分离,避免不必要的耦合。
拦截器
拦截器 (Interceptor
)在 Spring MVC 的请求处理流程中起到类似过滤器的作用,但比过滤器更灵活。
- 过滤器:Servlet 规范定义,可以过滤所有请求,包括静态资源、Servlet、JSP、Controller 请求,类似门卫的角色
- 拦截器:Spring MVC 框架定义,只对 Controller 层请求起作用,提供更细粒度的控制,类似内部各流程关卡
拦截器提供三个核心方法:
preHandle()
:在控制器方法执行之前调用,如果返回false
则不会调用控制器方法postHandle()
:在控制器方法执行之后,视图渲染之前调用。afterCompletion()
:在视图渲染完成后调用,用于清理资源或记录执行时间等
拦截器配置案例
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 在处理器方法调用前进行拦截
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
// 处理器方法执行后,但视图渲染前执行
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// 视图渲染后执行
}
}
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor())
.addPathPatterns("/**") // 拦截所有路径
.excludePathPatterns("/login", "/error"); // 排除某些路径
}
}
Spring MVC 拦截器与 Spring AOP 拦截器的区别
Spring MVC 拦截器与 Spring AOP 拦截器其实完全不是一个东西!不要混淆
- AOP 拦截器基于动态代理实现,拦截的是方法调用
- MVC 拦截器通过实现
HandlerInterceptor
接口定义拦截逻辑,用于增强 Web 层的 HTTP 请求流程
常用注解
请求映射相关
@RequestMapping
、@GetMapping
、@PostMapping
、@PutMapping
、@DeleteMapping
、@PatchMapping
处理相对应的请求
参数绑定相关
// 获取 URL 路径中的变量
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id)
// 绑定单个字段
public List<User> search(@RequestParam String keyword)
// 将请求体(JSON/XML)解析为 Java 对象
@PostMapping
public User createUser(@RequestBody User user)
// 将请求参数绑定到对象 (常用于表单提交)
public String submitForm(@ModelAttribute UserForm form)
// 处理文件上传
public String upload(@RequestPart("file") MultipartFile file)
// 将 HTTP 请求头的值注入到控制器中
@GetMapping("/header-info")
public String getHeaderInfo(@RequestHeader("User-Agent") String userAgent) {
// 使用 userAgent 进行业务处理
return "headerInfoView";
}
// 从 HTTP 请求的 Cookie 中提取值,注入到控制器方法的参数中
@GetMapping("/cookie-info")
public String getCookieInfo(@CookieValue("sessionId") String sessionId) {
// 使用 sessionId 进行业务处理
return "cookieInfoView";
}
请求响应相关
// 将返回值直接写入响应体(代替视图渲染)
@ResponseBody
public User getUser()
// 组合注解 = @Controller + @ResponseBody
@RestController
public class ApiController
// 设置 HTTP 响应状态码
@ResponseStatus(HttpStatus.CREATED)
public void create()
// 全局响应处理器 = @ControllerAdvice + @ResponseBody
@RestControllerAdvice
public class GlobalApiExceptionHandler {
@ExceptionHandler(ValidationException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ErrorResponse handleValidationError(ValidationException ex) {
return new ErrorResponse("VALIDATION_FAILED", ex.getErrors());
}
}
全局异常处理器
@ControllerAdvice
拦截所有 @Controller
,常用来进行全局异常统一处理
@ControllerAdvice
public class GlobalControllerAdvice {
// 全局异常处理器
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<String> handleNotFound(ResourceNotFoundException ex) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(ex.getMessage());
}
}
跨域支持
@CrossOrigin
标注在类或方法上,启用跨域请求支持,不过一般都是使用全局跨域配置支持。