写个springmvc的,毕竟面试经常问的。。。
出自《Spring源码深度解析》
-----------------------------------
♦️SpringMVC是基于Servlet功能实现的,通过实现Servlet接口的DispatcherServlet来封装核心功能实现。实现原理是通过DispatcherServlet拦截所有的URL来达到控制的目的。
配置文件部分
1.web.xml
contextConfigLocation:上下文配置地址,一般指向applicationContext.xml
DispatcherServlet:这个是一定要配置的,配置这个拦截所有的URL
contextLoaderListener
2.applicationContext.xml(名字怎么取随便你)
viewResolver:这个呢,不同的模版需要指定不同的类,用来处理ModelAndView返回的视图名,比如prefix,suffix
-----------------------------------
ContextLoaderListener
在web.xml中以<context-param>的方式注册并使用ContextLoaderListener。因为 ContextLoaderListener implements ServletLoaderListener ,所以我们可以在为客户端提供服务之前向ServletContext中添加任意的对象,且这个对象会在 ServletContext 启动时初始化,整个ServletContext运行期间都是可见的。
每个Web应用都有一个ServletContext,在应用启动时被创建,应用关闭时销毁,全局范围内有效。其核心逻辑就是初始化WebApplicationContext实例并存放在ServletContext中。
WebApplicationContext在配置中只能被声明一次.
DispatcherServlet
先回顾一下Servlet:这个在学生时代用于处理请求的类(准确的说,Servlet是一个接口,我们称实现这个接口的类为Servlet类)
生命周期:
第一次调用servlet对象时被初始化
接收请求时会为当前请求创建一个servletRequest和servletResponse,返回响应结果后销毁
当web应用终止时,servlet容器会调用destroy方法销毁servlet对象
先看一下DispatcherServlet类的主要依赖关系:
图(1-1)
图1-1可以看出,DispatcherServlet的重要初始化信息全在onRefresh(ApplicationContext context)中。哦,对了,图里方法的参数我忘了写进去了,懒得改了,凑合着看吧。
也就是说,初始化DispatcherServlet时,ApplicationContext已存在,即spring的IOC容器已经运行了。
所以在servlet的配置当中,<load-on-startup>param</load-on-startup>param需要配置成正数,一般为1。标记容器是否在启动的时候就加载这个servlet。当param值为0或者大于0时,表示容器在应用启动时就加载这个servlet;当是一个负数时或者没有指定时,则指示容器在该servlet被选择时才加载。正数的值越小,启动该servlet的优先级越高。
------------------------------
图(1-2)
核心干货。。。认真阅读。。。一遍不行就两遍。。。
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
//从handlerMapping中得到的
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
//获取当前请求对应的handler
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
}
// 确定当前handler对应的handler适配器
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
//…………
try {
// 调用handler(controller)获取返回的ModelAndView
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
}
applyDefaultViewName(request, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
//处理结果
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Error err) {
triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
return;
}
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
------------------------------