从可以看到,启动上下文之后,紧接着就开始初始化servlet,调用init方法
private synchronized void initServlet() throws ServletException { ... //调用Servlet的init方法 _servlet.init(_config); ... }复制代码
从web.xml文件中可以看到,这个servlet就是DispatcherServlet,对应的init方法在父类GenericServlet中
public void init(ServletConfig config) throws ServletException {//这里servletconfig就被传下来this.config = config;//执行子类的init方法this.init();}复制代码
对应在 HttpServletBean中
public final void init() throws ServletException { ... initServletBean();}复制代码
在FrameworkServlet中实现对应的spring的servlet的初始化
protected final void initServletBean() throws ServletException {…this.webApplicationContext = initWebApplicationContext();…}复制代码
对应的初始化web容器,首先也会去查询是否已经初始化过了
protected WebApplicationContext initWebApplicationContext() { //获取根webapplicationcontext,这就是在IOC容器初始化的时候塞入的值,如果IoC容器已经初始化完成,那么这里的值肯定不是null WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext()); WebApplicationContext wac = null; if (this.webApplicationContext != null) { wac = this.webApplicationContext;if (wac instanceof ConfigurableWebApplicationContext) { ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac; if (!cwac.isActive()) { //如果没有执行过webcontextapplication的refresh,那么再执行一次 if (cwac.getParent() == null) { cwac.setParent(rootContext); } //这个过程就类似IOC的启动了 configureAndRefreshWebApplicationContext(cwac); }} } ... if (!this.refreshEventReceived) { //没有执行过refresh则执行一次 onRefresh(wac); } …. return wac;}复制代码
对于这个时间点的DispatcherServlet启动来说,核心在于 onRefresh
,它会去初始化各种resolver
protected void onRefresh(ApplicationContext context) { …initMultipartResolver(context);...initHandlerMappings(context);...initViewResolvers(context); …}复制代码
MultipartResolver
它会从容器中读取是否包含 bean ‘multipartResolver'
public static final String MULTIPART_RESOLVER_BEAN_NAME = "multipartResolver”;...private void initMultipartResolver(ApplicationContext context) { ... this.multipartResolver = context.getBean(MULTIPART_RESOLVER_BEAN_NAME, MultipartResolver.class); ...}复制代码
MultipartResolver是用来解决文件上传问题
HandlerMappings
默认自己去扫描所有HandlerMapping类型的
private void initHandlerMappings(ApplicationContext context) { this.handlerMappings = null; if (this.detectAllHandlerMappings) { //默认这里执行主动探测,这里的实现其实就是从BeanFactory中获取所有已经注册了的,且类型是HandlerMapping的类的名字,然后再从BeanFactory中获取所有这个名字的bean作为返回 MapmatchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false); if (!matchingBeans.isEmpty()) { this.handlerMappings = new ArrayList<>(matchingBeans.values()); AnnotationAwareOrderComparator.sort(this.handlerMappings); } } ... if (this.handlerMappings == null) { //没有handlerMapping,则使用默认的。 this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class); if (logger.isTraceEnabled()) { logger.trace("No HandlerMappings declared for servlet '" + getServletName() + "': using default strategies from DispatcherServlet.properties"); } }}复制代码
在没有配置的情况下,处理映射的类配置在spring自带的文件DispatcherServlet.properties
中,默认handlerMapping的类为
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\ org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping复制代码
HandlerMapping负责定义请求和处理请求的对象之间的映射
以RequestMappingHandlerMapping
为例。当获取到对应的名字后
protectedList getDefaultStrategies(ApplicationContext context, Class strategyInterface) { String key = strategyInterface.getName(); //获取默认的配置 String value = defaultStrategies.getProperty(key); …. //通过反射构建class对象 Class clazz = ClassUtils.forName(className, DispatcherServlet.class.getClassLoader()); //从beanFactory中获取对象,其实就是调用createBean方法 Object strategy = createDefaultStrategy(context, clazz); strategies.add((T) strategy); } ….}复制代码
对于beanFactory来说,创建一个bean或经历它的完整生命周期,经过多层查找,可以看到如下代码
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { BeanWrapper instanceWrapper = null; ... instanceWrapper = createBeanInstance(beanName, mbd, args); ... final Object bean = instanceWrapper.getWrappedInstance();... Object exposedObject = bean;... exposedObject = initializeBean(beanName, exposedObject, mbd);...}复制代码
执行一些列的生命名周期方法
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { ... //执行各种aware方法 invokeAwareMethods(beanName, bean); … //执行初始化之前的BeanPostProcessor相关方法 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); … //执行初始化bean方法 invokeInitMethods(beanName, wrappedBean, mbd); … //执行初始化之后的BeanPostProcessor相关方法 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); ...}复制代码
-aware 方法
private void invokeAwareMethods(final String beanName, final Object bean) { if (bean instanceof Aware) { if (bean instanceof BeanNameAware) { ((BeanNameAware) bean).setBeanName(beanName); } if (bean instanceof BeanClassLoaderAware) { ClassLoader bcl = getBeanClassLoader(); if (bcl != null) { ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl); } } if (bean instanceof BeanFactoryAware) { ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this); } }}复制代码
初始化bean又包含了相关生命周期要执行的逻辑
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd) throws Throwable { boolean isInitializingBean = (bean instanceof InitializingBean); if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) { … //执行afterPropertiesSet ((InitializingBean) bean).afterPropertiesSet(); ... } if (mbd != null && bean.getClass() != NullBean.class) { String initMethodName = mbd.getInitMethodName(); if (StringUtils.hasLength(initMethodName) && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) { //执行自己的initMethod方法 invokeCustomInitMethod(beanName, bean, mbd); } }}复制代码
对于 RequestMappingHandlerMapping 继承了接口ApplicationContextAware
和 InitializingBean
,都属于bean生命周期中的一环。
ApplicationContextAware
RequestMappingHandlerMapping的父类自己持有一个applicationContext的引用
public final void setApplicationContext(@Nullable ApplicationContext context) throws BeansException { ... else if (this.applicationContext == null) { ... this.applicationContext = context; this.messageSourceAccessor = new MessageSourceAccessor(context); initApplicationContext(context); } ...}复制代码
从父类开始往下去执行对应的方法
protected void initApplicationContext() throws BeansException { … //探测所有的interceptor,即找到所有类MappedInterceptor【这对应 mvc-interceptor标签】和实现了接口HandlerInterceptor的拦截器 detectMappedInterceptors(this.adaptedInterceptors); //初始化interceptor initInterceptors();}复制代码
InitializingBean
public void afterPropertiesSet() { …//getCandidateBeanNames默认就是获取所有的beanfor (String beanName : getCandidateBeanNames()) { //判断 bean 的名字是否是 “scopedTarget.” 字符串开头 if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) { processCandidateBean(beanName); }} …}复制代码
查到bean后,开始识别是否是用来处理请求的
protected void processCandidateBean(String beanName) { Class beanType = null; ... beanType = obtainApplicationContext().getType(beanName); … //isHandler即判断这个beanType是否包含注解 Controller 或者 RequestMapping if (beanType != null && isHandler(beanType)) { //找到这个注解bean的所有方法,构建映射关系 detectHandlerMethods(beanName); }}protected boolean isHandler(Class beanType) { return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) || AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));}复制代码
探测handler的方法分成两个主要部分
- 找到这个bean的所有的方法
- 将方法注册
protected void detectHandlerMethods(Object handler) { … //找到这个bean的方法 Mapmethods = MethodIntrospector.selectMethods(userType, (MethodIntrospector.MetadataLookup ) method -> { try { //找到方法对应的RequestMapping注解,将它的path等参数封装成RequestMappingInfo返回 return getMappingForMethod(method, userType); } catch (Throwable ex) { throw new IllegalStateException("Invalid mapping on handler class [" + userType.getName() + "]: " + method, ex); } }); ... methods.forEach((method, mapping) -> { Method invocableMethod = AopUtils.selectInvocableMethod(method, userType); //注册handler,在内部创建HandlerMethod,在urlLookup中存储 url和mapping的关系,而mapping和HandlerMethod则存储在mappingLookup中 registerHandlerMethod(handler, invocableMethod, mapping); }); ...}复制代码
initViewResolvers
同handlerMapping,默认类为
org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver复制代码
根据view的名字来找到对应的View。View则负责来渲染内容
spring 处理请求到来
从可以看到,执行请求对应着的是servlet的service方法,对应spring来说,他就是DispatcherServlet
protected void doService(HttpServletRequest request, HttpServletResponse response) { …//请求总设置applicationContextrequest.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());…//进行请求分发doDispatch(request, response);…}doDispatch负责把一次请求分配给对应的handler来处理protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { ... ModelAndView mv = null; ... //如果请求存在分段文件,则转换成Multipart,比如MultipartHttpServletRequest processedRequest = checkMultipart(request); … //获取对应请求的handler mappedHandler = getHandler(processedRequest); … //返回这个hander对应的适配器,比如对于HandlerMethod子类返回的就是AbstractHandlerMethodAdapter HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); … //调用interceptor的preHandle方法 if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } … //执行处理逻辑 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); … //掉interceptor的postHandle方法 mappedHandler.applyPostHandle(processedRequest, response, mv); …. //处理结果 processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); ...}复制代码
getHandler详细处理如下
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { //内部根据请求的路径执行lookupHandlerMethod(lookupPath, request),而它就会从 urlLookup.get(urlPath)中查到对应的mapping,再查到HanlerMethod Object handler = getHandlerInternal(request); … //匹配路径的拦截器全都加到handler链路里面来 HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); ... return executionChain;}复制代码
handler核心逻辑如下
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ... //将handlerMethod进行包装,以便后续通过反射执行 ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod); 。。。 //创建ModelAndView的容器 ModelAndViewContainer mavContainer = new ModelAndViewContainer(); … //通过反射执行 invocableMethod.invokeAndHandle(webRequest, mavContainer); … //获取ModeAndView,从内部可以看到,它会自行创建一个ModelAndView对象 return getModelAndView(mavContainer, modelFactory, webRequest); ...}复制代码
获得handler的结果之后,调用processDispatchResult,核心就是进行render
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv, @Nullable Exception exception) throws Exception { ... render(mv, request, response); ...}protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception { …. View view; //获取视图的名字 String viewName = mv.getViewName(); //根据名字获取对应的视图 view = resolveViewName(viewName, mv.getModelInternal(), locale, request); … //执行渲染 view.render(mv.getModelInternal(), request, response); ...}复制代码
执行render方法来源与所有render的父类AbstractView的render方法
@Overridepublic void render(@Nullable Mapmodel, HttpServletRequest request, HttpServletResponse response) throws Exception { …. Map mergedModel = createMergedOutputModel(model, request, response); prepareResponse(request, response); //真正执行渲染 renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);}复制代码
比如返回的是JSON对象,那么实际情况如下
protected void renderMergedOutputModel(Mapmodel, HttpServletRequest request, HttpServletResponse response) throws Exception { Object value = this.filterModel(model); //值封装成json String text = JSON.toJSONString(value, this.serializerFeatures); byte[] bytes = text.getBytes(this.charset); Object stream = this.updateContentLength?this.createTemporaryOutputStream():response.getOutputStream(); //结果写入outpuststream ((OutputStream)stream).write(bytes); if(this.updateContentLength) { //返回 this.writeToResponse(response, (ByteArrayOutputStream)stream); }}复制代码
对于Freemarker来说,就是执行FreemarkerView.renderMergedTemplateModel方法,内部执行doRender
protected void doRender(Mapmodel, HttpServletRequest request, HttpServletResponse response) throws Exception { exposeModelAsRequestAttributes(model, request); SimpleHash fmModel = buildTemplateModel(model, request, response); Locale locale = RequestContextUtils.getLocale(request); //这里就是调用Freemarker的template来处理对应的数据填充等等 template.process(model, response.getWriter()); processTemplate(getTemplate(locale), fmModel, response);}复制代码
至此一次请求结束