SpringMVC原理剖析
SpringMVC框架和Servlet容器具体详细图,周舟
1 初始环境是 tomcat 容器!
根据你的web.xml 读取配置信息,
2 Tomcat 依赖servlet.jar规范
--- Init(config) 初始化配置,配置从web.xml 通过servlet规范读取
--- Service 请求进行服务
--- Destory 销毁
3 SpringMVC (Servlet服务) 实现了Servlet规范
这边重写了init,service,destory
SpringMVC入口在 DispatcherServlet
可以从继承树上找到SpringMVC是Servlet的扩展,
上图是servlet的规范
总结,延续Servlet体系的半封装框架
1. 如何初始化SpringMVC上下文
a) Init()方法在httpServlet的父类GenericServlet
b) Destory()方法也在GenericServlet中(如下图所示)
c) httpServlet只重写了service()
d) 而HttpServletBean中重写了init()方法
HttpServletBean 重写了GenericServlet里面的init()方法而进入了SpringMVC自身上下文初始化
public final void init() throws ServletException{
if (logger.isDebugEnabled()) {
logger.debug("Initializing servlet '" + getServletName() + "'");
}
// 将Servlet中封装的参数封装到PropertyValues
// requiredProperties:必须的参数数据,如果没有会报异常
try {
// 这里的getServletContext就是获取web.xml中的
PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
// 属性编辑器,控制修改我们的ServletConfig属性
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
// 获取资源加载器
ResourceLoaderresourceLoader = new ServletContextResourceLoader(getServletContext());
// 注册我们的资源类型
bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader));
// 初始化属性编辑器对象bw
initBeanWrapper(bw);
bw.setPropertyValues(pvs, true);
}
catch (BeansExceptionex) {
logger.error("Failed to set bean properties onservlet '" + getServletName()+ "'", ex);
throw ex;
}
// 模板方法, 给我们子类FramworkServlet具体实现了他
// 他用来初始化SpringMvc框架Bean组件Controller 还有九大组件
initServletBean();
if (logger.isDebugEnabled()) {
logger.debug("Servlet '" + getServletName() + "' configured successfully");
}
}
init这个方法主要调用了(initServletBean()方法),protected修饰, 在FramworkServlet中实现了
// initServletBean方法里主要调用了initWebApplicationContext()方法, 由于SpringMVC的上下文继承了WebApplicationContext
所以这个方法主要是用来刷新和获取上下文, 详情如下
刷新后!! 执行最注重要的onRefresh()
if (!this.refreshEventReceived) { // Apparently not a ConfigurableApplicationContext with refresh support: // triggering initial onRefresh manually here. onRefresh(wac); }
最终调用了DispatcherServlet的OnRefresh方法, 初始化九大组件
@Override
protected void onRefresh(ApplicationContext context) {
initStrategies(context);
}
/**
* Initialize the strategy objects that this servlet uses.
* <p>May be overridden in subclasses in order to initialize further strategy objects.
*/
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);
// 本地解析
initLocaleResolver(context);
// 主题解析
initThemeResolver(context);
// 映射器组件
initHandlerMappings(context);
// 初始化适配器
initHandlerAdapters(context);
// 初始化程序异常解析器
initHandlerExceptionResolvers(context);
//
initRequestToViewNameTranslator(context);
//初始化视图解析器
initViewResolvers(context);
}
Init完成点done
2. 接受业务请求!
a) 来到HttpServlet这里,寻找service()请求;
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { HttpServletRequest request; HttpServletResponse response; try { request = (HttpServletRequest) req; response = (HttpServletResponse) res; } catch (ClassCastException e) { throw new ServletException("non-HTTP request or response"); } service(request, response); }
总结:SpringMVC的业务请求流程是重写HttpServlet的service方法中的分派方法(例如doPost())
b) protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String method = req.getMethod(); if (method.equals(METHOD_GET)) { long lastModified = getLastModified(req); if (lastModified == -1) { // servlet doesn't support if-modified-since, no reason // to go through further expensive logic doGet(req, resp); } else { long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE); if (ifModifiedSince < lastModified) { // If the servlet mod time is later, call doGet() // Round down to the nearest second for a proper compare // A ifModifiedSince of -1 will always be less maybeSetLastModified(resp, lastModified); doGet(req, resp); } else { resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED); } } } else if (method.equals(METHOD_HEAD)) { long lastModified = getLastModified(req); maybeSetLastModified(resp, lastModified); doHead(req, resp); } else if (method.equals(METHOD_POST)) { doPost(req, resp); } else if (method.equals(METHOD_PUT)) { doPut(req, resp); } else if (method.equals(METHOD_DELETE)) { doDelete(req, resp); } else if (method.equals(METHOD_OPTIONS)) { doOptions(req,resp); } else if (method.equals(METHOD_TRACE)) { doTrace(req,resp); } else { // // Note that this means NO servlet supports whatever // method was requested, anywhere on this server. // String errMsg = lStrings.getString("http.method_not_implemented"); Object[] errArgs = new Object[1]; errArgs[0] = method; errMsg = MessageFormat.format(errMsg, errArgs); resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg); } }
c) 分类方法在FramworkServlet中重写了, 主要调用了processRequest(request,response)方法
@Override protected final void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); }
d) 真正执行的是doService()方法, 他在DispatcherServlet里重写
try { doService(request, response); }
e) doService()方法中,快照备份后, 组装一些组件,和解析器执行doDispatch(request,response);方法
/**
/*
*处理实际调度到处理程序。
* <p>处理程序将通过按顺序应用servlet的HandlerMappings来获得。
HandlerAdapter将通过查询Servlet的已安装HandlerAdapter获得 *找到支持处理程序类的第一个。
* <p>所有HTTP方法都由此方法处理。 这取决于HandlerAdapters或Handler
*自己决定哪些方法可以接受。
@param response current HTTP response
* @throws Exception in case of any kind of processing failure
*/
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
int interceptorIndex = -1;
try {
// 模型视图对象
ModelAndView mv;
boolean errorView = false;
try {
// 检查是否是上传 请求
processedRequest = checkMultipart(request);
// 根据请求找到handler.
mappedHandler = getHandler(processedRequest, false);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
}
// 根据HandlerAdapter 找到HandlerExecutionChain处理执行链来确定handler
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// 处理GET/HEAD请求的LastModified
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
// 查看是否有缓存
if (logger.isDebugEnabled()) {
String requestUri = urlPathHelper.getRequestUri(request);
logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);
}
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
}
// 执行相应的拦截器的PreHandle
HandlerInterceptor[] interceptors = mappedHandler.getInterceptors();
if (interceptors != null) {
for (int i = 0; i < interceptors.length; i++) {
HandlerInterceptor interceptor = interceptors[i];
if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) {
triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
return;
}
interceptorIndex = i;
}
}
// 执行handle处理请求返回modelAndView
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
// 当view为空(比如Handler返回为void),根据request设置默认的mv
if (mv != null && !mv.hasView()) {
mv.setViewName(getDefaultViewName(request));
}
// 拦截器后处理, 在modeAndView返回DispatcherServlet前,按照执行链的反顺序操作
if (interceptors != null) {
for (int i = interceptors.length - 1; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv);
}
}
}
catch (ModelAndViewDefiningException ex) {
logger.debug("ModelAndViewDefiningException encountered", ex);
mv = ex.getModelAndView();
}
catch (Exception ex) {
Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
mv = processHandlerException(processedRequest, response, handler, ex);
errorView = (mv != null);
}
// Did the handler return a view to render?
if (mv != null && !mv.wasCleared()) {
render(mv, processedRequest, response);
if (errorView) {
WebUtils.clearErrorRequestAttributes(request);
}
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +
"': assuming HandlerAdapter completed request handling");
}
}
// 处理完成后的回调! 回调
triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
}
catch (Exception ex) {
// Trigger after-completion for thrown exception.
triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
throw ex;
}
catch (Error err) {
ServletException ex = new NestedServletException("Handler processing failed", err);
// Trigger after-completion for thrown exception.
triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
throw ex;
}
finally {
// Clean up any resources used by a multipart request.
if (processedRequest != request) {
cleanupMultipart(processedRequest);
}
}
}
f) 拦截器的三种方法全部执行到
3.
4.
5.