一、开篇:当火锅店来了个金牌迎宾小姐姐
想象一下你去吃火锅:门口迎宾小姐姐(DispatcherServlet)先问你要什么锅底(请求类型),然后把你领到对应区域(HandlerMapping),服务员(Controller)给你下单,后厨(Service)热火朝天煮菜,最后传菜员(ViewResolver)端着红油翻滚的锅底闪亮登场...
这就是Spring MVC的工作日常!而咱们今天的主角DispatcherServlet,就是这个火锅店里最会来事的金牌迎宾小姐姐!
二、解剖室:DispatcherServlet的三十六变
2.1 配置七十二式(XML vs 注解)
传统派XML配置(适合怀旧玩家):
<!-- 就像给手机贴膜一样小心翼翼 -->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-mvc-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
新潮派JavaConfig(年轻人的第一选择):
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { RootConfig.class }; // 好比火锅店的中央厨房
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { WebConfig.class }; // 前厅服务标准手册
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" }; // 拦截所有请求就像火锅店迎宾
}
}
三、黑科技揭秘:一个请求的奇幻漂流
- 安检口:Tomcat大叔把请求扔给DispatcherServlet
- 侦探环节:HandlerMapping拿着放大镜找"@Controller"
- 变形记:HandlerAdapter把请求参数变成Java对象(比川剧变脸还快)
- 核心战场:Controller方法执行(此处应有BGM)
- 视图魔法:ViewResolver把"home"变成/WEB-INF/views/home.jsp
- 最终演出:渲染视图时JSTL标签库集体蹦迪
四、大型车祸现场(避坑指南)
4.1 404惊魂夜
// 经典错误:忘记@ResponseBody导致视图找不到
@Controller
public class DemoController {
@GetMapping("/hello")
public String sayHello() {
return "Hello World"; // 此时在找名为"Hello World"的视图...
}
}
4.2 跨站脚本攻击的诱惑
<!-- 没有转义的XSS漏洞就像没盖的火锅 -->
<p>${userInput}</p>
<!-- 正确姿势:<c:out value="${userInput}"/> -->
4.3 文件上传的暗雷
// 忘记配置MultipartResolver
@PostMapping("/upload")
public String handleUpload(@RequestParam MultipartFile file) {
// 此处必抛异常,酸爽无比
}
五、最佳实践:老司机的秋名山漂移技巧
- 双配置战术:用RootConfig装Service/Repository,WebConfig专管Controller/View
- 异常处理三板斧:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleAll(Exception ex) {
return new ResponseEntity<>("程序员跑路了", HttpStatus.I_AM_A_TEAPOT);
}
}
- 异步大招:
@GetMapping("/async")
public Callable<String> asyncRequest() {
return () -> {
Thread.sleep(3000); // 模拟耗时操作
return "终于等到你~";
};
}
六、面试官的死亡连环问(附答案精讲)
Q1:DispatcherServlet和普通Servlet啥关系?
就像钢铁侠和普通机甲的关系!继承了HttpServlet,但多了:
- 自带Spring容器私生子(WebApplicationContext)
- 九大金刚策略接口(HandlerMapping等)
- 自动装配超能力
Q2:请求参数绑定是怎么黑魔法?
秘密在于HandlerAdapter的show time:
- DataBinder带着ConversionService登场
- @RequestParam/@RequestBody等注解是魔法咒语
- 类型转换时可能上演ClassCastException的悲剧
Q3:如何实现一个拦截器?
继承HandlerInterceptorAdapter就像写剧本:
public class LogInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(...) {
System.out.println("请求来了!"); // 此处应有Log框架
return true;
}
@Override
public void postHandle(...) {
System.out.println("处理完毕!");
}
}
七、终极总结:从青铜到王者的蜕变
DispatcherServlet就像瑞士军刀:
- 对新手:配置简单易上手
- 对高手:处处可扩展
- 对架构师:MVC体系的灵魂画手
记住:
当你的Controller开始膨胀,就该考虑:
- 切面编程来救场
- DTO/VO来瘦身
- 参数校验要趁早
最后送大家一句: "不会配置DispatcherServlet的Java程序员,就像不会调蘸料的吃货!"
(全文完,但你的Spring MVC之旅才刚刚开始...)