DispatcherServlet: 当火锅店来了个金牌迎宾小姐姐

133 阅读3分钟

一、开篇:当火锅店来了个金牌迎宾小姐姐

想象一下你去吃火锅:门口迎宾小姐姐(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[] { "/" }; // 拦截所有请求就像火锅店迎宾
    }
}

三、黑科技揭秘:一个请求的奇幻漂流

  1. 安检口:Tomcat大叔把请求扔给DispatcherServlet
  2. 侦探环节:HandlerMapping拿着放大镜找"@Controller"
  3. 变形记:HandlerAdapter把请求参数变成Java对象(比川剧变脸还快)
  4. 核心战场:Controller方法执行(此处应有BGM)
  5. 视图魔法:ViewResolver把"home"变成/WEB-INF/views/home.jsp
  6. 最终演出:渲染视图时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) {
    // 此处必抛异常,酸爽无比
}

五、最佳实践:老司机的秋名山漂移技巧

  1. 双配置战术:用RootConfig装Service/Repository,WebConfig专管Controller/View
  2. 异常处理三板斧
@ControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(Exception.class)
    public ResponseEntity<String> handleAll(Exception ex) {
        return new ResponseEntity<>("程序员跑路了", HttpStatus.I_AM_A_TEAPOT);
    }
}
  1. 异步大招
@GetMapping("/async")
public Callable<String> asyncRequest() {
    return () -> {
        Thread.sleep(3000); // 模拟耗时操作
        return "终于等到你~";
    };
}

六、面试官的死亡连环问(附答案精讲)

Q1:DispatcherServlet和普通Servlet啥关系?

就像钢铁侠和普通机甲的关系!继承了HttpServlet,但多了:

  • 自带Spring容器私生子(WebApplicationContext)
  • 九大金刚策略接口(HandlerMapping等)
  • 自动装配超能力

Q2:请求参数绑定是怎么黑魔法?

秘密在于HandlerAdapter的show time:

  1. DataBinder带着ConversionService登场
  2. @RequestParam/@RequestBody等注解是魔法咒语
  3. 类型转换时可能上演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开始膨胀,就该考虑:

  1. 切面编程来救场
  2. DTO/VO来瘦身
  3. 参数校验要趁早

最后送大家一句: "不会配置DispatcherServlet的Java程序员,就像不会调蘸料的吃货!"

(全文完,但你的Spring MVC之旅才刚刚开始...)