当你用@RestController轻松搞定一个API时,是否想过SpringMVC在背后默默抗下了多少"脏活累活"?这个被996程序员奉为神器的框架,内部竟藏着堪比谍战剧的权力游戏——DispatcherServlet如何运筹帷幄?九大组件暗藏什么玄机?注解背后的惊天阳谋又是什么?
一、从Servlet到SpringMVC:一场精心策划的「宫廷政变」
传统Servlet开发:
java
// 被if-else支配的恐惧
if ("/user".equals(request.getPathInfo())) {
UserService.handleRequest(request, response);
} else if ("/order".equals(...)) {
// 无限套娃中...
}
SpringMVC的降维打击:
- 前端控制器模式:DispatcherServlet一统江湖,成为所有请求的"总闸门"
- 策略模式武装到牙齿:HandlerMapping是情报官,ViewResolver是翻译官,各司其职
- 注解驱动革命:@RequestMapping像魔法标记,让方法自动升级成战斗单元
灵魂拷问: 你的Controller为何能像皇帝般只动嘴(注解)不干活?
二、九大核心组件「权力游戏」全解析
1. DispatcherServlet:紫禁之巅的终极Boss
- 初始化黑箱操作:
- java
// 源码中的权力初始化
initStrategies(context);
// 暗中部署九大部门:
initMultipartResolver(context); // 文件上传锦衣卫
initLocaleResolver(context); // 国际化翻译团
initHandlerMappings(context); // 路由情报局
2. HandlerMapping:路由江湖的活地图
- 注解派(RequestMappingHandlerMapping) vs 配置文件派(BeanNameUrlHandlerMapping)
- 匹配算法暗战:精准匹配 > 通配符匹配 > 默认匹配
3. HandlerAdapter:真正的执行刺客
java
// 适配器的致命一击
mav = ha.handle(processedRequest, response, mappedHandler.getHandler());
- HttpRequestHandlerAdapter:处理传统Servlet风格
- SimpleControllerHandlerAdapter:适配Controller接口
- RequestMappingHandlerAdapter:注解派终极杀手
4. ViewResolver:视图界的千面影帝
- 自由切换JSP/Thymeleaf/FreeMarker就像换脸:
- properties
spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp
三、深度解剖请求处理「十二时辰」
1. 请求抵达:DispatcherServlet的暴力拦截
java
public class DispatcherServlet extends FrameworkServlet {
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) {
// 权力核心代码(精简版)
HandlerExecutionChain mappedHandler = getHandler(processedRequest);
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
ModelAndView mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
}
2. 参数绑定的魔法陷阱
- @RequestParam:精确制导导弹
- @PathVariable:URL中的卧底特工
- @RequestBody:JSON化骨绵掌
3. 拦截器(Interceptor)的宫斗大戏
java
public class AuthInterceptor implements HandlerInterceptor {
// 在Controller执行前发动政变
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
if (!checkAuth(request)) {
response.sendRedirect("/login");
return false; // 拦截!
}
return true;
}
}
四、高阶开发者的「屠龙技」
1. 手写自定义参数解析器
java
public class CryptoArgumentResolver implements HandlerMethodArgumentResolver {
public Object resolveArgument(...) {
String encryptedText = request.getParameter("data");
return AESUtil.decrypt(encryptedText); // 自动解密!
}
}
// 注册到RequestMappingHandlerAdapter
2. 玩转异步请求
java
@GetMapping("/async")
public Callable asyncTask() {
return () -> {
Thread.sleep(3000);
return "熬完夜了!";
};
}
3. 异常处理的三十六计
java
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(NullPointerException.class)
public ResponseEntity handleNPE(NullPointerException ex) {
return new ResponseEntity<>("空指针警告!", HttpStatus.INTERNAL_SERVER_ERROR);
}
}
五、SpringMVC的「七寸」与反制之道
1. 性能刺客:
- 慎用@SessionAttributes引发内存泄漏
- 避免ModelAndView过度包装
2. 扩展秘籍: - 自定义HandlerMapping实现特殊路由逻辑
- 重写ViewResolver支持魔改模板引擎
终极挑战: 尝试在不用任何注解的情况下,用纯JavaConfig配置SpringMVC!
本文暂时没有评论,来添加一个吧(●'◡'●)