webmvc 是一套基于 servlet 的 MVC 框架,较为全面,但是随着时间推进,前后端分离称为主流。
MVC 中为视图服务的能力就不那么重要了。
但是仍然使用相同的处理模型。
try {
val mv: ModelAndView? = null
val dispatchException: Exception? = null
try {
val processedRequest = checkMultipart(request)
val multipartRequestParsed = processedRequest != request
// 从 dispatcherServlet 持有的所有 handler 中,拿到一个匹配当前请求的handler
val mappedHandler :Handler? = getHandler(processedRequest)
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// 拿到一个handler 对应的 adapter,这里很奇怪,为什么不直接保留经过 adapter 包装的 handler,也就是只持有 adapter
// 此处有可能找不到adapter,就会抛出异常
// 仔细考虑一遍,查看后面的代码,
// 不难发现,adapter 是少数几种,而handler 是多数
// adapter 并不持有handler,而是每次调用
val ha = getHandlerAdapter(mappedHandler.getHandler())
// 处理 lastmodified
// 对于 get/head 方法
val modified = processLastModified(request, ha, mappedHandler.getHandler())
if(!modified) {
return
}
// interceptor 前置处理,可能被拦截
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return
}
// 调用handler,得到modelAndView
// 通过 requestMapping 可能直接返回 JavaObject,然后通过 adapter转为 modelAndView(最后渲染,搭配 Jackson等序列化工具,转为 json)
mv = ha.handle(processedRequest, response, mappedHandler.getHandler())
if (asyncManager.isConcurrentHandlingStarted()) {
return
}
applyDefaultViewName(processedRequest, mv)
// interceptor 后置处理
mappedHandler.applyPostHandle(processedRequest, response, mv);
} catch (Exception ex) {
dispatchException = ex
}
} catch (Throwable err) {
// As of 4.3, we're processing Errors thrown from handler methods as well,
// making them available for @ExceptionHandler methods and other scenarios. dispatchException = new NestedServletException("Handler dispatch failed", err);
}
processDispatchResult(
processedRequest,
response,
mappedHandler,
mv,
dispatchException
)
}
MVC 如何拿到 controller / requestMapping?
每个 handlerMapping 在初始化之后,从 bean factory 中扫描符合条件的 Bean 中的方法作为 handler
比如 requestMapping,本身用的是 HandlerMethodMapping,对所有的 Bean,判断是否带有 Controller 注解,如果是,就检测其内部可以作为 HandlerMethod 的方法 (带有 @requsetMapping 或者 @httpExchange) 作为 handler
而 routeFunction 则是扫描 RouteFunction.class 的 bean,将其中的 route 加入 handler 中
MVC 如何构成 handler 的链,进行筛选?