讲道理,源码如果想完全搞懂真的很难,毕竟不是站在作者的角度去思考的,只能去理解一些浅显的思想和一些地方采用了设计模式。从源码中可以看出,为什么明明一行代码就可以搞定的CURD,要引入那么多接口、抽象类,以及各种设计模式??
从以前有一些工作经验之后,觉得springmvc的思想就是,有一个前端控制器去结合tomcat的统一监听入口做统一拦截,之后mvc作为任务的分发利用反射处理之后返回数据,但是万万没想到= =竟然这么复杂,有机会一定会更深入去了解,先继续往后学吧
SpringMVC 工作流程
mvc工作流程,客户端发送请求,tomcat监听端口,经过tomcat将request进行解析封装成 Java可识别的servlet,之后通过配置中的url请求地址,找到mvc定义的规范(dispatcherServlet一个普通的实现了Servlet规范的类),之后通过前端控制器 + url请求路径,找到对应的处理器类(mvc自己封装了处理器类信息,如requestmapping中的value值,还有对应的处理器类),随后基于mvc的执行链(handler)找到对应的所需的处理适配器,用于真正的调用方法(基于反射,期间还通过request请求信息 通过参数解析器找到方法所需的全部参数,遍历判断类型如果是一般配型直接赋值,如果是model或者map则直接从隐含类型的缓存中读取,如果是自定义类型那么首先会判断model隐含类型中是否对应的保存了这个自定义对象如果没有获取到,那么会自己new一个进行返回),随后得到结果,mvc会自动封装成modelandview交给视图解析器进行解析数据转发和页面跳转。
细节:mvc 中 有一个对接 tomcat的接口:dispatchServlet
dispatchServlet:
是一个普通的 实现了 Java定义Servlet规范的 前端控制器,主要用于统一处理客户端请求。
当接受到request 之后,会基于request最终调用doService,doService中调用 doDispatch(),
验证是否是文件上传请求,如果是文件上传请求如果是文件上传请求转为文件servlet,否则仍然是当前请求信息。
随后基于request中的信息(其中包括url,port,网络协议等等)
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
/**
* 如果没有找到,抛出异常
*/
noHandlerFound(processedRequest, response);
return;
}
基于 request请求信息,解析出所需要的 mappedHandler (处理器类),里面保存了一些处理器对象信息,如果没有找到直接抛出异常:404。
需要注意的是:getHandler() 中找到 处理器类的流程
@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
for (HandlerMapping mapping : this.handlerMappings) {
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
会通过:handlerMappings 遍历 里面的 handlerMapping 对象来获取 映射地址指向的 处理器类(handler),这个handler并非真正操作的方法,可以理解为bean对象。
那么这个handlerMappings 从哪里来的呢?
而实现了servlet 接口的 dispatcherServlet,会有一个初始化的接口。
/**
* This implementation calls {@link #initStrategies}.
*/
@Override
protected void onRefresh(ApplicationContext context) {
initStrategies(context);
}
而最终指向了 initStrategies(context);
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
// 我在这里,我是handlerMappings的初始化方法
initHandlerMappings(context);
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);
}
这里面初始化了一系列的东西,可以称为SpringMVC的九大组件,现在只关注 HandlerMappings(),我们点进去。
private void initHandlerMappings(ApplicationContext context) {
// 置为null
this.handlerMappings = null;
// 默认检测所有,否则只检测 bean名称为 handlerMapping的一个
if (this.detectAllHandlerMappings) {
// Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
// 找到全部的handlerMappings
Map<String, HandlerMapping> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
// 如果 找到了至少一个,那么会排个顺序
if (!matchingBeans.isEmpty()) {
this.handlerMappings = new ArrayList<>(matchingBeans.values());
// We keep HandlerMappings in sorted order.
AnnotationAwareOrderComparator.sort(this.handlerMappings);
}
}
else {
// 只找一个名称为handlerMapping的对象,并且尝试强转,如果转失败了,那么会报错
try {
HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
this.handlerMappings = Collections.singletonList(hm);
}
catch (NoSuchBeanDefinitionException ex) {
// Ignore, we'll add a default HandlerMapping later.
}
}
// Ensure we have at least one HandlerMapping, by registering
// a default HandlerMapping if no other mappings are found.
// 如果一个都没有找到,那么会采用默认的策略,至少保证该容器中有一个hanldermapping
if (this.handlerMappings == null) {
this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
if (logger.isTraceEnabled()) {
logger.trace("No HandlerMappings declared for servlet '" + getServletName() +
"': using default strategies from DispatcherServlet.properties");
}
}
}
// 默认检测所有,否则只检测 bean名称为 handlerMapping的一个
// 从bean中找到全部的handlerMappings
// 如果 找到了至少一个,那么会排个顺序
如果不是找到全部的hanlderMappings 只是找到一个bean名称为 handlerMapping的对象
// 只找一个名称为handlerMapping的对象,并且尝试强转,如果转失败了,那么会报错
// 如果一个都没有找到,那么会采用默认的策略,至少保证该容器中有一个hanldermapping
默认实现使用“ DispatcherServlet.properties”文件(与DispatcherServlet类位于同一包中)来确定类名称。 它通过上下文的BeanFactory实例化策略对象
@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
for (HandlerMapping mapping : this.handlerMappings) {
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
handlerMappings 是有序的,所以当找到了就会立刻返回后续的不会继续执行,排序靠后的就会被前面的handler给覆盖??
HandlerExecutionChain 执行链
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
随后通过 找到的处理器对象,mappedHandler.getHandler() 其实获取到的就是 对应的contraoller(handler) 类对象,随后通过类对象获取到指定的方法调用适配器。HandlerAdapter()
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
// handlerAdapters 来源: initHandlerAdapters(context);
if (this.handlerAdapters != null) {
for (HandlerAdapter adapter : this.handlerAdapters) {
if (adapter.supports(handler)) {
return adapter;
}
}
}
throw new ServletException("No adapter for handler [" + handler +
"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
之后通过处理器类,找到适合的处理器适配器,如果找不到那么就会报错。
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception
能力不够,只能到这了= =