Spring MVC
Spring MVC 是基于 Servlet 的 Web 框架,核心是 DispatcherServlet,负责请求分发、处理器映射和视图解析。
提示
Spring MVC 是基于 Servlet 的 Web 框架,核心是 DispatcherServlet。
请求处理流程
HTTP 请求 → DispatcherServlet.doDispatch()
→ HandlerMapping 查找 Handler
→ HandlerAdapter 执行 Handler
→ Handler 返回 ModelAndView
→ ViewResolver 解析视图 → View 渲染
→ HTTP 响应核心组件
| 组件 | 职责 |
|---|---|
| DispatcherServlet | 前端控制器,统一请求入口 |
| HandlerMapping | 请求到处理器的映射 |
| HandlerAdapter | 执行处理器方法 |
| ViewResolver | 视图名称到视图对象的解析 |
DispatcherServlet 初始化
入口链:HttpServletBean.init → FrameworkServlet.initServletBean → DispatcherServlet.onRefresh
@Override
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context); // 文件上传
initLocaleResolver(context); // 地区解析
initThemeResolver(context); // 主题解析
initHandlerMappings(context); // 处理器映射
initHandlerAdapters(context); // 处理器适配器
initHandlerExceptionResolvers(context); // 异常处理
initViewResolvers(context); // 视图解析
initFlashMapManager(context); // FlashMap
}双容器结构
Spring MVC 支持双容器:根容器(Service、DAO)和 MVC 容器(Controller、ViewResolver)。
<!-- 根容器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- MVC 容器 -->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>HandlerAdapter
参数解析器
| 解析器 | 说明 |
|---|---|
@PathVariable | 路径参数 |
@RequestParam | 请求参数 |
@RequestBody | 请求体 |
@ModelAttribute | 模型属性 |
返回值解析器
| 解析器 | 说明 |
|---|---|
@ResponseBody | JSON/XML 输出 |
ModelAndView | 视图 + 模型 |
String | 视图名 |
HttpMessageConverter
@ResponseBody 通过 HttpMessageConverter 将返回值序列化:
| 转换器 | 支持类型 |
|---|---|
| MappingJackson2HttpMessageConverter | application/json |
| MappingJackson2XmlHttpMessageConverter | application/xml |
| StringHttpMessageConverter | text/plain |
ViewResolver
| 类型 | 说明 |
|---|---|
| InternalResourceViewResolver | JSP/HTML 视图 |
| ThymeleafViewResolver | Thymeleaf 模板 |
| FreeMarkerViewResolver | FreeMarker 模板 |
拦截器
public interface HandlerInterceptor {
boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler);
void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView);
void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex);
}执行顺序:preHandle (1→2) → Controller → postHandle (2→1) → afterCompletion (2→1)
异常处理
| 解析器 | 说明 |
|---|---|
| ExceptionHandlerExceptionResolver | @ExceptionHandler |
| ResponseStatusExceptionResolver | @ResponseStatus |
| DefaultHandlerExceptionResolver | Spring 默认异常 |
@ExceptionHandler(Exception.class)
public ModelAndView handleException(Exception e) {
ModelAndView mv = new ModelAndView("error");
mv.addObject("exception", e);
return mv;
}请求参数绑定
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.setDisallowedFields("id", "createTime");
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
}核心配置
@EnableWebMvc
@Configuration
public class WebConfig implements WebMvcConfigurer {
// configurePathMatch() 路径匹配
// configureMessageConverters() 消息转换器
// addInterceptors() 拦截器
// addResourceHandlers() 静态资源
// configureViewResolvers() 视图解析器
}常见问题
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 404 错误 | 路径不匹配或未扫描 | 检查 @RequestMapping 路径和组件扫描 |
| 参数绑定失败 | 参数名不一致或类型错误 | 使用 @RequestParam 明确指定,检查 Content-Type |
| 静态资源无法访问 | 未配置资源映射 | 通过 addResourceHandlers 配置,检查 Security 拦截 |