• SpringMVC框架中DispatcherServlet分发请求给对应处理器


    太长不看版

    • HTTPServlet 的 Service 方法将请求按类进行分解
      • 主要是根据HTTP方法的类型调用 doXXX 方法
      • GET 和 HEAD 方法需要对 if-modified-since 进行特殊处理,其他是直接调用
    • FrameworkServlet 重写 doXXX 方法,统一调用 doService 方法
      • doXXX 方法统一调用 processRequest 方法
        • doOptions 和 doTrace 有额外的处理
        • 其他是直接调用
      • processRequest 主要是初始化 ThreadLocal ,调用 doService 方法,并进行日志等处理
        • ThreadLocal 是 LocalContext 和 Attributes
        • doService 方法执行核心逻辑,是抽象方法
        • 完成后会清空 ThreadLocal,打印日志,产生事件。
    • DispatcherServlet 进行具体的实现
      • 重写 doService 方法
        1. 添加 DispatcherServlet 特有的请求属性
        2. 对 HTML 的 include 请求进行处理
        3. 对重定向的请求进行处理
        4. 将请求转交给 doDispatch 方法进行实际的分发
      • doDispatch 方法的逻辑为:
        1. 查找是否有合适的 Handler,该过程在基于RESTful API 设计的 SpringMVC 中有性能问题
        2. 查找 Handler 是否有支持的 Adapter
        3. 执行拦截器
        4. 执行处理
        5. 解析结果并返回

    DispatcherServlet 的父类做了什么

    DistpathcerServlet 的类图如下,可见其父类为 FrameworkServlet ,同时是一个 HttpServlet .

    1.1 HttpServlet 的分发逻辑:

    service 方法作为入口, 其逻辑如下:

    1. protected void service(HttpServletRequest req, HttpServletResponse resp)
    2. throws ServletException, IOException {
    3. String method = req.getMethod();
    4. if (method.equals(METHOD_GET)) {
    5. long lastModified = getLastModified(req);
    6. if (lastModified == -1) {
    7. // servlet doesn't support if-modified-since, no reason
    8. // to go through further expensive logic
    9. doGet(req, resp);
    10. } else {
    11. long ifModifiedSince;
    12. try {
    13. ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
    14. } catch (IllegalArgumentException iae) {
    15. // Invalid date header - proceed as if none was set
    16. ifModifiedSince = -1;
    17. }
    18. if (ifModifiedSince < (lastModified / 1000 * 1000)) {
    19. // If the servlet mod time is later, call doGet()
    20. // Round down to the nearest second for a proper compare
    21. // A ifModifiedSince of -1 will always be less
    22. maybeSetLastModified(resp, lastModified);
    23. doGet(req, resp);
    24. } else {
    25. resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
    26. }
    27. }
    28. } else if (method.equals(METHOD_HEAD)) {
    29. long lastModified = getLastModified(req);
    30. maybeSetLastModified(resp, lastModified);
    31. doHead(req, resp);
    32. } else if (method.equals(METHOD_POST)) {
    33. doPost(req, resp);
    34. } else if (method.equals(METHOD_PUT)) {
    35. doPut(req, resp);
    36. } else if (method.equals(METHOD_DELETE)) {
    37. doDelete(req, resp);
    38. } else if (method.equals(METHOD_OPTIONS)) {
    39. doOptions(req,resp);
    40. } else if (method.equals(METHOD_TRACE)) {
    41. doTrace(req,resp);
    42. } else {
    43. //
    44. // Note that this means NO servlet supports whatever
    45. // method was requested, anywhere on this server.
    46. //
    47. String errMsg = lStrings.getString("http.method_not_implemented");
    48. Object[] errArgs = new Object[1];
    49. errArgs[0] = method;
    50. errMsg = MessageFormat.format(errMsg, errArgs);
    51. resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
    52. }
    53. }

    可见对于 POST PUT DELETE OPTIONS TRACE 方法都是直接调用对应的具体方法 doXXX, 而 GET 方法会增加 

  • 相关阅读:
    PostGIS是否有方法能将一个Polygon面切割成若干份小的Polygon面,且每一份的面积差不多大
    民谣女神唱流行,基于AI人工智能so-vits库训练自己的音色模型(叶蓓/Python3.10)
    ubuntu 22.04版本修改时区的操作方法
    经验分享:判断字符串的显示宽度
    2022年认证杯SPSSPRO杯数学建模C题(第一阶段)污水流行病学原理在新冠疫情防控方面的作用求解全过程文档及程序
    【机器学习】图像语义分割常用指标Dice系数 敏感性 特异性 IOU及python代码实现
    Git的下载方法+版本控制器以及SVN与GIT的区别
    k8s篇二之、操作命令 与 yml配置文件编写
    Flutter笔记:AnimationMean、AnimationMax 和 AnimationMin 三个类的用法
    你写过的最蠢的代码是?
  • 原文地址:https://blog.csdn.net/dageliuqing/article/details/126684873