实现Controller的三种方式分析
每种实现的方式对应的HanderAdapter都不同。
实现Controller接口
该接口对应的HanderAdapter
为SimpleControllerHandlerAdapter
。
使用案列:
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" />
我们可以通过debug那个执行链就可以知道。
实现HttpRequestHandler接口
该接口对应的HanderAdapter
为HttpRequestHandlerAdapter
。
使用案例:
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" />
继续查看当前对象的执行链
:
这两种方式大体上是类似的,我们可以区别的看一下,他们是怎么处理的。
先看实现HttpRequestHandlerAdapter
接口的:
进入1075行代码:
可以发现,这是把当前Controller强转为HttpRequestHander
,然后再执行HttpRequestHanderAdapter
的handleRequest
方法。(实际就是去执行我们Controller里面的方法。)
而HttpRequestHandler
正是我们Contoller类实现的HttpRequestHandler
。
同理,我们去看一下实现Controller
接口的类的处理方法。
一样,都是先强转为接口类,然后执行对应的方法,也就是我们自己实现的方法:
注意:当前的所处位置:
使用注解的方式
待补充
探究HandlerAdapter的装配规则
一直都很疑惑:
为什么不装配全部都能用,只装配一种,不符合的就不能用了呢?
未配置HandlerAdapter
观察DispatcherServlet的初始化方法:
可以看到有对HandlerAdapter的初始化,点进去加断点。
开始Debug:
根据注释,我们可以知道如果此时HandlerAdapters如果为空的话将加载初始化的HandlerAdapters
可以看到,在664行加载了四个HandlerAdapter
进入此方法继续debug查看:
注意:
DispatcherServlet
的初始化方法只执行一次,后面需要重新启动tomcat才能继续进入初始化方法。
重启后,继续Debug:
往下走,可以看到这里读取到了几个HandlerAdapter
很明显872行代码
是读取了什么文件
重新Debug可以发现这里读取的是org/springframework/web/servlet/DispatcherServlet.properties
文件。
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的信息了
继续往下看怎么处理的:
下面我感觉应该是利用泛型和反射得到所有的处理器。
配置了HandlerAdapter
如果我们再容器中装配了Adapter:
重启tomcat,继续Debug
可以看到642行读取到了我们配置的两个HandlerAdapter,并且再645行赋值给了DispatcherServlet的handlerAdapters
,此时方法就会结束了。因为下面都不符合条件了。
总结:
如果我们在容器里添加了HandlerAdapter,那么就不会通过读取本地的文件添加默认的四个HandlerAdapter。
如果没在容器中添加HandlerAdapter,机会读取本地的DispatcherServlet.properties里面的四个HandlerAdapter。