SpringMVC中的Handler、HandlerMapping、HandlerAdapter到底是啥
这东西,虽然说和我们的开发没啥关系,尤其是当你用SpringBoot进行开发时,这些接口离你越来越远了。讲实话,要不是这学期扫一眼学校的课件,我都不知道有这东西,这东西本来就是对使用框架进行开发的开发者隐藏的。人家好不容易隐藏起来,你却要我们学起来,没事儿干了吧。
下图是网上流传的总览图,来自这篇文章:SpringMVC框架理解
下面通过阅读源码,来学习这些接口都是干啥的
DispathcerServlet#
不管是哪个Web框架,基于什么语言,都会提供一个在整个系统最前端接受用户请求的东西,我们暂且称它“前端调度器”,它会解析用户请求请求,调度你编写的用于接收请求的组件。这样,你可以根据不同的请求编写不同的组件,在SpringMVC里,DispathcerServlet就是前端调度器,Controller就是你编写的处理请求的组件。
SpringMVC也是基于JavaWeb的那套ServletAPI的,所以,它使用一个Servlet用来接收所有请求,它就像一个桥,一头是ServletAPI,一头是SpringMVC,把Servlet世界里的话翻译成框架中的通用语言。
既然是Servlet,那我们就看它的doService方法呗:
解释
@Overrideprotected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
logRequest(request);
// … 省略一些代码 …
try {doDispatch(request, response);
}// ... 再省略一些代码 ...}
调用了doDispatch来执行调度。doDispatch里的代码太多了,我做了精简之后还是很多,所以我在代码中写上注释:
解释
@SuppressWarnings(“deprecation”)protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
// 记住它的类型,是一个Handler执行链
HandlerExecutionChain mappedHandler = null;ModelAndView mv = null;
Exception dispatchException = null;// ... 省略代码 ...
try {// processedRequest是经过一定处理的请求对象// 这里是根据请求,获取一个能够处理该请求的Handler对象(实际是一个Handler执行链)// Handler用于对请求进行处理mappedHandler = getHandler(processedRequest);if (mappedHandler == null) {noHandlerFound(processedRequest, response);return;}// 根据Handler对象获取一个HandlerAdapter对象// 具体为啥要这一层,我们稍后会说HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());// 在实际执行对请求的处理之前,先调用Handler的预处理方法`preHandle`if (!mappedHandler.applyPreHandle(processedRequest, response)) {return;}// 实际调用Handler,这里调用的是Handler的适配器对象,HandlerAdapter,它会返回一个ModelAndViewmv = ha.handle(processedRequest, response, // 请求处理完毕,这里调用Handler的`postHandle`方法mappedHandler.applyPostHandle(processedRequest, response, mv);
}
// 记录异常
catch (Exception ex) {dispatchException = ex;
}
catch (Throwable err) {dispatchException = new NestedServletException("Handler dispatch failed", err);
}
// 对上面一同折腾得到的处理结果进行处理,返回给前端
processDispatchResult(processedRequest, response, mapp