Spring基础源码分析(一)

打印 上一主题 下一主题

主题 887|帖子 887|积分 2661

实现Controller的三种方式分析

每种实现的方式对应的HanderAdapter都不同。
实现Controller接口

该接口对应的HanderAdapter为SimpleControllerHandlerAdapter。

使用案列:
  1. public class LeController implements Controller {
  2.          @Override
  3.          public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
  4.                  // 创建数据视图类
  5.                  ModelAndView mv = new ModelAndView();
  6.                  // 填充数据
  7.                  mv.addObject("msg","北方情韵");
  8.                  // 跳转的视图
  9.                  mv.setViewName("index");
  10.                  return mv;
  11.          }
  12. }
复制代码
配置对应的bean信息,这里的name就是访问该Controller的路径。
  1. [/code][img]https://img2023.cnblogs.com/blog/3087734/202303/3087734-20230302205346326-1149138823.png[/img]
  2. 我们可以通过debug那个执行链就可以知道。
  3. [img]https://img2023.cnblogs.com/blog/3087734/202303/3087734-20230302205347383-1985450586.png[/img]
  4. [size=3]实现HttpRequestHandler接口[/size]
  5. [b]该接口对应的HanderAdapter为HttpRequestHandlerAdapter。[/b]
  6. [img]https://img2023.cnblogs.com/blog/3087734/202303/3087734-20230302205346364-339977232.png[/img]
  7. 使用案例:
  8. [code] public class YueController implements HttpRequestHandler {
  9.      @Override
  10.      public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  11.          request.setAttribute("msg","实现接口HttpRequestHandler");
  12.          request.getRequestDispatcher("/WEB-INF/pages/index.jsp").forward(request,response);
  13.      }
  14. }
复制代码
配置对应的bean信息,这里的name就是访问该Controller的路径。
  1. [/code][img]https://img2023.cnblogs.com/blog/3087734/202303/3087734-20230302205346338-1630937163.png[/img]
  2. 继续查看当前对象的执行链:
  3. [img]https://img2023.cnblogs.com/blog/3087734/202303/3087734-20230302205346428-253923495.png[/img]
  4. 这两种方式大体上是类似的,我们可以区别的看一下,他们是怎么处理的。
  5. 先看实现HttpRequestHandlerAdapter接口的:
  6. [img]https://img2023.cnblogs.com/blog/3087734/202303/3087734-20230302205346383-1429029038.png[/img]
  7. [b]进入1075行代码:[/b]
  8. [img]https://img2023.cnblogs.com/blog/3087734/202303/3087734-20230302205346797-1125365361.png[/img]
  9. 可以发现,这是把当前Controller强转为HttpRequestHander,然后再执行HttpRequestHanderAdapter的handleRequest方法。(实际就是去执行我们Controller里面的方法。)
  10. [img]https://img2023.cnblogs.com/blog/3087734/202303/3087734-20230302205346841-21451172.png[/img]
  11. 而HttpRequestHandler正是我们Contoller类实现的HttpRequestHandler。
  12. [img]https://img2023.cnblogs.com/blog/3087734/202303/3087734-20230302205347884-97220771.png[/img]
  13. 同理,我们去看一下实现Controller接口的类的处理方法。
  14. [img]https://img2023.cnblogs.com/blog/3087734/202303/3087734-20230302205346860-1371839323.png[/img]
  15. 一样,都是先强转为接口类,然后执行对应的方法,也就是我们自己实现的方法:
  16. [img]https://img2023.cnblogs.com/blog/3087734/202303/3087734-20230302205346943-1594193355.png[/img]
  17. [indent]注意:当前的所处位置:
  18. [img]https://img2023.cnblogs.com/blog/3087734/202303/3087734-20230302205347019-1178927924.png[/img]
  19. [/indent][size=3]使用注解的方式[/size]
  20. [indent]待补充
  21. [/indent][size=4]探究HandlerAdapter的装配规则[/size]
  22. [indent]一直都很疑惑:
  23. [img]https://img2023.cnblogs.com/blog/3087734/202303/3087734-20230302205347125-1761808137.png[/img]
  24. 为什么不装配全部都能用,只装配一种,不符合的就不能用了呢?
  25. [/indent][size=3]未配置HandlerAdapter[/size]
  26. [b]观察DispatcherServlet的初始化方法:[/b]
  27. 可以看到有对HandlerAdapter的初始化,点进去加断点。
  28. [img]https://img2023.cnblogs.com/blog/3087734/202303/3087734-20230302205347373-2137767251.png[/img]
  29. [b]开始Debug:[/b]
  30. [img]https://img2023.cnblogs.com/blog/3087734/202303/3087734-20230302205347320-7774771.png[/img]
  31. [img]https://img2023.cnblogs.com/blog/3087734/202303/3087734-20230302205347434-963345364.png[/img]
  32. 根据注释,我们可以知道如果此时HandlerAdapters如果为空的话将加载初始化的HandlerAdapters
  33. [img]https://img2023.cnblogs.com/blog/3087734/202303/3087734-20230302205347421-24750745.png[/img]
  34. [b]可以看到,在664行加载了四个HandlerAdapter[/b]
  35. [img]https://img2023.cnblogs.com/blog/3087734/202303/3087734-20230302205347723-474647186.png[/img]
  36. [b]进入此方法继续debug查看:[/b]
  37. [indent]注意:DispatcherServlet的初始化方法只执行一次,后面需要重新启动tomcat才能继续进入初始化方法。
  38. [/indent][img]https://img2023.cnblogs.com/blog/3087734/202303/3087734-20230302205347777-480586739.png[/img]
  39. [b]重启后,继续Debug:[/b]
  40. [img]https://img2023.cnblogs.com/blog/3087734/202303/3087734-20230302205347892-652386474.png[/img]
  41. [img]https://img2023.cnblogs.com/blog/3087734/202303/3087734-20230302205348477-1838674372.png[/img]
  42. [b]往下走,可以看到这里读取到了几个HandlerAdapter[/b]
  43. [img]https://img2023.cnblogs.com/blog/3087734/202303/3087734-20230302205347874-2053107219.png[/img]
  44. 很明显872行代码是读取了什么文件
  45. [img]https://img2023.cnblogs.com/blog/3087734/202303/3087734-20230302205347926-641525577.png[/img]
  46. [b]重新Debug可以发现这里读取的是org/springframework/web/servlet/DispatcherServlet.properties文件。[/b]
  47. [img]https://img2023.cnblogs.com/blog/3087734/202303/3087734-20230302205347937-1753489472.png[/img]
  48. [b]DispatcherServlet.properties:[/b]
  49. [code]......
  50. org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
  51.         org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
  52.         org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter,\
  53.         org.springframework.web.servlet.function.support.HandlerFunctionAdapter
  54. ......
复制代码
文件里内容不少,我这里只留下了HandlerAdapter的信息了
继续往下看怎么处理的:
下面我感觉应该是利用泛型和反射得到所有的处理器。

配置了HandlerAdapter

如果我们再容器中装配了Adapter:

重启tomcat,继续Debug

可以看到642行读取到了我们配置的两个HandlerAdapter,并且再645行赋值给了DispatcherServlet的handlerAdapters,此时方法就会结束了。因为下面都不符合条件了。

总结:
如果我们在容器里添加了HandlerAdapter,那么就不会通过读取本地的文件添加默认的四个HandlerAdapter。
如果没在容器中添加HandlerAdapter,机会读取本地的DispatcherServlet.properties里面的四个HandlerAdapter。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

南飓风

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表