1

SpringMVC基础源码分析(一) - 情韵

 1 year ago
source link: https://www.cnblogs.com/beishanqingyun/p/17173468.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

实现Controller的三种方式分析

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

实现Controller接口

该接口对应的HanderAdapterSimpleControllerHandlerAdapter

image-20230302193001463

使用案列:

 public class LeController implements Controller {

	 @Override
	 public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
		 // 创建数据视图类
		 ModelAndView mv = new ModelAndView();
		 // 填充数据
		 mv.addObject("msg","北方情韵");
		 // 跳转的视图
		 mv.setViewName("index");
		 return mv;
	 }
 }

配置对应的bean信息,这里的name就是访问该Controller的路径。

<bean class="cn.lele.controller.LeController" name="/le" />

image-20230302192439527

我们可以通过debug那个执行链就可以知道。

image-20230302193816106

实现HttpRequestHandler接口

该接口对应的HanderAdapterHttpRequestHandlerAdapter

image-20230302194119786

使用案例:

 public class YueController implements HttpRequestHandler {
     @Override
     public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
         request.setAttribute("msg","实现接口HttpRequestHandler");
         request.getRequestDispatcher("/WEB-INF/pages/index.jsp").forward(request,response);
     }

 }

配置对应的bean信息,这里的name就是访问该Controller的路径。

<bean class="cn.lele.controller.YueController" name="/yue" />

image-20230302194358371

继续查看当前对象的执行链

image-20230302194510537

这两种方式大体上是类似的,我们可以区别的看一下,他们是怎么处理的。

先看实现HttpRequestHandlerAdapter接口的:

image-20230302194828062

进入1075行代码:

image-20230302195104082

可以发现,这是把当前Controller强转为HttpRequestHander,然后再执行HttpRequestHanderAdapterhandleRequest方法。(实际就是去执行我们Controller里面的方法。)

image-20230302195206479

HttpRequestHandler正是我们Contoller类实现的HttpRequestHandler

image-20230302195708545

同理,我们去看一下实现Controller接口的类的处理方法。

image-20230302195830409

一样,都是先强转为接口类,然后执行对应的方法,也就是我们自己实现的方法:

image-20230302195925956

注意:当前的所处位置:

image-20230302195957002

使用注解的方式

探究HandlerAdapter的装配规则

一直都很疑惑:

image-20230302200218040

为什么不装配全部都能用,只装配一种,不符合的就不能用了呢?

未配置HandlerAdapter

观察DispatcherServlet的初始化方法:

可以看到有对HandlerAdapter的初始化,点进去加断点。

image-20230302200635511

开始Debug:

image-20230302201006875

image-20230302201217525

根据注释,我们可以知道如果此时HandlerAdapters如果为空的话将加载初始化的HandlerAdapters

image-20230302201509490

可以看到,在664行加载了四个HandlerAdapter

image-20230302201646916

进入此方法继续debug查看:

注意:DispatcherServlet的初始化方法只执行一次,后面需要重新启动tomcat才能继续进入初始化方法。

image-20230302201903668

重启后,继续Debug:

image-20230302202053167

往下走,可以看到这里读取到了几个HandlerAdapter

image-20230302202511819

很明显872行代码是读取了什么文件

image-20230302202739434

重新Debug可以发现这里读取的是org/springframework/web/servlet/DispatcherServlet.properties文件。

image-20230302202904925

DispatcherServlet.properties:

......

org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
	org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
	org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter,\
	org.springframework.web.servlet.function.support.HandlerFunctionAdapter


......

文件里内容不少,我这里只留下了HandlerAdapter的信息了

继续往下看怎么处理的:

下面我感觉应该是利用泛型和反射得到所有的处理器。

image-20230302204028529

配置了HandlerAdapter

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

image-20230302204619120

重启tomcat,继续Debug

image-20230302204651428

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

image-20230302204909088

总结:

如果我们在容器里添加了HandlerAdapter,那么就不会通过读取本地的文件添加默认的四个HandlerAdapter。

如果没在容器中添加HandlerAdapter,机会读取本地的DispatcherServlet.properties里面的四个HandlerAdapter。

__EOF__


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK