实现Controller的三种方式分析

实现Controller接口

该接口对应的HanderAdapterSimpleControllerHandlerAdapter

Spring基础源码分析(一)-LMLPHP

使用案列:

 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" />

Spring基础源码分析(一)-LMLPHP

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

Spring基础源码分析(一)-LMLPHP

实现HttpRequestHandler接口

该接口对应的HanderAdapterHttpRequestHandlerAdapter

Spring基础源码分析(一)-LMLPHP

使用案例:

 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" />

Spring基础源码分析(一)-LMLPHP

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

Spring基础源码分析(一)-LMLPHP

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

先看实现HttpRequestHandlerAdapter接口的:

Spring基础源码分析(一)-LMLPHP

进入1075行代码:

Spring基础源码分析(一)-LMLPHP

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

Spring基础源码分析(一)-LMLPHP

HttpRequestHandler正是我们Contoller类实现的HttpRequestHandler

Spring基础源码分析(一)-LMLPHP

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

Spring基础源码分析(一)-LMLPHP

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

Spring基础源码分析(一)-LMLPHP

使用注解的方式

探究HandlerAdapter的装配规则

未配置HandlerAdapter

观察DispatcherServlet的初始化方法:

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

Spring基础源码分析(一)-LMLPHP

开始Debug:

Spring基础源码分析(一)-LMLPHP

Spring基础源码分析(一)-LMLPHP

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

Spring基础源码分析(一)-LMLPHP

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

Spring基础源码分析(一)-LMLPHP

进入此方法继续debug查看:

Spring基础源码分析(一)-LMLPHP

重启后,继续Debug:

Spring基础源码分析(一)-LMLPHP

Spring基础源码分析(一)-LMLPHP

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

Spring基础源码分析(一)-LMLPHP

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

Spring基础源码分析(一)-LMLPHP

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

Spring基础源码分析(一)-LMLPHP

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的信息了

继续往下看怎么处理的:

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

Spring基础源码分析(一)-LMLPHP

配置了HandlerAdapter

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

Spring基础源码分析(一)-LMLPHP

重启tomcat,继续Debug

Spring基础源码分析(一)-LMLPHP

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

Spring基础源码分析(一)-LMLPHP

总结:

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

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

03-02 20:57