spring源码-6-springmvc
来源:互联网 发布:经济数据库都有什么 编辑:程序博客网 时间:2024/05/29 15:05
HttpServletBean
建立springmvc框架 与servlet API的联系。 init()
public final void init() throws ServletException { if (logger.isDebugEnabled()) { logger.debug("Initializing servlet '" + getServletName() + "'"); } // Set bean properties from init parameters. try { //封装加载必要的参数 PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties); //pojo包装类(可以修改pojo属性,通过属性描述器) BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this); ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext()); bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment())); //空实现,子类自定义其它初始化 initBeanWrapper(bw); bw.setPropertyValues(pvs, true); } catch (BeansException ex) { if (logger.isErrorEnabled()) { logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex); } throw ex; } // Let subclasses do whatever initialization they like. //子类自定义 initServletBean(); if (logger.isDebugEnabled()) { logger.debug("Servlet '" + getServletName() + "' configured successfully"); } }
FrameworkServlet
initServletBean : 子类自定义初始化
protected final void initServletBean() throws ServletException { getServletContext().log("Initializing Spring FrameworkServlet '" + getServletName() + "'"); if (this.logger.isInfoEnabled()) { this.logger.info("FrameworkServlet '" + getServletName() + "': initialization started"); } long startTime = System.currentTimeMillis(); try { this.webApplicationContext = initWebApplicationContext(); //初始化webApplictionContext initFrameworkServlet(); //子类自定义初始化 } catch (ServletException ex) { this.logger.error("Context initialization failed", ex); throw ex; } catch (RuntimeException ex) { this.logger.error("Context initialization failed", ex); throw ex; } if (this.logger.isInfoEnabled()) { long elapsedTime = System.currentTimeMillis() - startTime; this.logger.info("FrameworkServlet '" + getServletName() + "': initialization completed in " + elapsedTime + " ms"); } }
springmvc 启动时-》web.xml配置中声明的ContextLoaderListener、DispatcherServlet完成所有任务。1.ContextLoaderListener(环境加载) 完成对spring配置文件的加载。2.DispatcherServlet(中央调节作用) spring中央控制器,拦截request请求,由handlerMapping -》handler-》DispatcherServlet-》handlerAdapter-》modelAndView》DispatcherServlet-》viewResolver-》response。
ContextLoaderListener
加载spring配置文件 ContextLoaderListener实现了ServletContextListener,在容器启动时会调用contextInitialized
public void contextInitialized(ServletContextEvent event) { initWebApplicationContext(event.getServletContext()); //初始化WebApplicationContext}
继续跟踪如何初始化WebApplicationContext
//省略打印日志public WebApplicationContext initWebApplicationContext(ServletContext servletContext) { //检验是否已经加载过WebApplicationContext //即一个web.xml只能有一个ContextLoaderListener if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) { throw new IllegalStateException( "Cannot initialize context because there is already a root application context present - " + "check whether you have multiple ContextLoader* definitions in your web.xml!"); } long startTime = System.currentTimeMillis(); try { // Store context in local instance variable, to guarantee that // it is available on ServletContext shutdown. if (this.context == null) { //初始化WebApplicationContext this.context = createWebApplicationContext(servletContext); } if (this.context instanceof ConfigurableWebApplicationContext) { ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context; if (!cwac.isActive()) { // The context has not yet been refreshed -> provide services such as // setting the parent context, setting the application context id, etc if (cwac.getParent() == null) { // The context instance was injected without an explicit parent -> // determine parent for root web application context, if any. ApplicationContext parent = loadParentContext(servletContext); cwac.setParent(parent); } configureAndRefreshWebApplicationContext(cwac, servletContext); } } //将加载的WebApplicationContext 存储在servletContext域中 servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context); ClassLoader ccl = Thread.currentThread().getContextClassLoader(); if (ccl == ContextLoader.class.getClassLoader()) { currentContext = this.context; } else if (ccl != null) { //将classload对应的context缓存到map中 currentContextPerThread.put(ccl, this.context); } return this.context; } catch (RuntimeException ex) { servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex); throw ex; } catch (Error err) { servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, err); throw err; }}
DispatcherServlet
DispatcherServlet也是Servlet的实现类,对于http各种request(请求)方式会进行拦截,进行统一处理后,解析拦截的请求为handlerMapping(处理器映射器),由handlerMapping映射到handlerAdapter(处理器适配器),由相应的handlerAdapter返回modelAndView对象返回,进行viewResolver(视图解析器渲染)后,response(响应)给client。
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = request; 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); // Determine handler for the current request. //由request寻找对应的handler //由handlermapping -》 mappingHandler mappedHandler = getHandler(processedRequest); if (mappedHandler == null || mappedHandler.getHandler() == null) { noHandlerFound(processedRequest, response); return; } //由mappingHandler - 》 handlerAdapter HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // Process last-modified header, if supported by the handler. String method = request.getMethod(); boolean isGet = "GET".equals(method); if (isGet || "HEAD".equals(method)) { long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); if (logger.isDebugEnabled()) { logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified); } if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) { return; } } //执行过滤器操作 if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } // Actually invoke the handler. //由具体的handler执行 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return; } //视图结果设置 applyDefaultViewName(processedRequest, mv); //再次经过过滤器 mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception ex) { dispatchException = ex; } catch (Throwable err) { dispatchException = new NestedServletException("Handler dispatch failed", err); } processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } catch (Exception ex) { triggerAfterCompletion(processedRequest, response, mappedHandler, ex); } catch (Throwable err) { triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", err)); } finally { if (asyncManager.isConcurrentHandlingStarted()) { // Instead of postHandle and afterCompletion if (mappedHandler != null) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); } } else { // Clean up any resources used by a multipart request. if (multipartRequestParsed) { cleanupMultipart(processedRequest); } } } }//加载策略protected void initStrategies(ApplicationContext context) { initMultipartResolver(context); //文件处理解析器 initLocaleResolver(context); //国际化配置 initThemeResolver(context); //主题资源 initHandlerMappings(context); //处理器映射器 initHandlerAdapters(context); //处理器适配器 initHandlerExceptionResolvers(context); //处理异常 initRequestToViewNameTranslator(context); //逻辑视图 initViewResolvers(context); //视图解析 initFlashMapManager(context); //请求存储属性}
initMultipartResolver、initLocaleResolver、initThemeResolver相同的原理,只需配置对应的实现类,并保持默认名即可。 上述三者不存在时,则默认为null处理,initRequestToViewNameTranslator、initFlashMapManager不同之处为,不存在时,将会以spring默认的策略生成。
//文件请求 配置 multipartResolver (省略打印日志代码)private void initMultipartResolver(ApplicationContext context) { try { //注册multipartResolver 的bean 将MultipartResolver的实现类配置即可 this.multipartResolver = context.getBean(MULTIPART_RESOLVER_BEAN_NAME, MultipartResolver.class); } catch (NoSuchBeanDefinitionException ex) { // Default is no multipart resolver. this.multipartResolver = null; }}
initHandlerMappings、initHandlerAdapters、initHandlerExceptionResolvers、initViewResolvers相同原理,由DispatcherServlet对应属性生成配置方式。1.查询所有的映射器/适配器/...2.只加载配置特定name的映射器/适配器/...3.加载默认的映射器/适配器/...
private void initHandlerMappings(ApplicationContext context) { this.handlerMappings = null; //默认开启查询所有的处理器映射器(HandlerMapping) if (this.detectAllHandlerMappings) { // Find all HandlerMappings in the ApplicationContext, including ancestor contexts. //加载所有的HandlerMapping 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 { try { //否则将会只加载命名为handlerMapping 的处理器映射器 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. if (this.handlerMappings == null) { //加载spring默认提供的handlerMapping this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class); }}
完成配置的初始化,对请求的doDispatch 完成逻辑处理。
//部分代码protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null; boolean multipartRequestParsed = false; WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); try { ModelAndView mv = null; Exception dispatchException = null; try { //判断是否为multipart请求 processedRequest = checkMultipart(request); multipartRequestParsed = (processedRequest != request); // Determine handler for the current request. //根据当前请求,遍历handlerMapping 返回HandlerExecutionChain mappedHandler = getHandler(processedRequest); if (mappedHandler == null || mappedHandler.getHandler() == null) { noHandlerFound(processedRequest, response); //返回404 return; } // Determine handler adapter for the current request. //由handlerMapping 返回的handler查询匹配的handlerAdapter HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // Process last-modified header, if supported by the handler. String method = request.getMethod(); boolean isGet = "GET".equals(method); if (isGet || "HEAD".equals(method)) { //是否支持last-modified头 long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) { return; } } //调用preHandler 拦截器方法 if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } // Actually invoke the handler. //执行handler 返回modelAndView对象 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return; } //由相应RequestToViewNameTranslator 获取getViewName applyDefaultViewName(processedRequest, mv); //调用postHandler 方法 mappedHandler.applyPostHandle(processedRequest, response, mv); }
0 0
- spring源码-6-springmvc
- Spring源码解析-springmvc
- spring源码初步学习-SpringMVC
- Spring源码分析3----SpringMVC
- Spring mvc 源码 和 Spring+springmvc+hibernate整合源码
- Spring Framework源码(八):SpringMVC概览
- Spring+SpringMVC+Mybatis博客源码分享
- SpringMVC-Spring-MyBatis-Freemarker整合+源码下载
- spring 源码之二springmvc实现源码分析
- spring源码剖析(九)springMVC源码剖析
- Spring Framework源码(九):SpringMVC之从DispatcherServlet说起
- Spring Framework源码(十):SpringMVC之文件上传
- Spring Framework源码(十一):SpringMVC之URL匹配
- springmvc mybatis 整合 框架源码 bootstrap html5 mysql oracle spring
- springmvc mybatis 整合 框架源码 bootstrap html5 mysql oracle spring
- Maven+Mybatis+Spring+SpringMVC实现分页查询(附源码)
- spring+SpringMVC+Mybtis+maven+SSM框架搭建附源码
- Maven+Mybatis+Spring+SpringMVC实现分页查询(附源码)
- Sfilter过滤驱动框架
- 面试官谈游戏开发入行--选择
- Linux I/O复用——select系统调用
- linux配置禁止密码登陆,普通用户赋予sudo权限
- 如何把Bootstrap和JQuery在不能上网环境中生效并用Maven来管理版本?
- spring源码-6-springmvc
- Swift3 实现图片圆角、阴影、边框
- Hibernate_映射_关联关系_一对多多对一映射2、inverse属性
- 写在caffe2 的开始
- 僵尸进程&孤儿进程
- 根据Map的value排序
- scrapy random user agents
- MySQL 处理海量数据时的一些优化查询速度方法
- scrapy polipo