Spring | 0.9 Web

Servlet 初始化介绍

1、3.0 以前版本
Web 容器读取配置在web.xml 的 servlet ,filter。并且执行servlet,filter 的初始化 ,。从初始化中可以获取servletContext 。从而获取相关的配置信息

web.xml 配置样例

  
        HelloWorldFilter
        /hello
    

 
        HelloWorldServlet
        /hello
    

2、3.0 以后版本
servlet 提供了 ServletContainerInitializer#onStartup 接口,web 容器通过SPI 找到实现的 ServletContainerInitializer 接口 ,执行web容器初始化配置。


SPI.png

@HandlesTypes 注解,Servlet 3.0+ 会自动scan 实现handler WebApplicationInitializer 接口的所有类

@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
    @Override
    public void onStartup(@Nullable Set> webAppInitializerClasses, ServletContext servletContext)
            throws ServletException {
        List initializers = new LinkedList<>();
    for (Class waiClass : webAppInitializerClasses) {
initializers.add(ReflectionUtils.accessibleConstructor(waiClass).newInstance());}
}               
        AnnotationAwareOrderComparator.sort(initializers);
        for (WebApplicationInitializer initializer : initializers) {
            initializer.onStartup(servletContext);
        }
    }

}

Spring 与Servlet集成

核心类图

Servlet.png
FrameworkServlet

initServletBean,创建和初始化WebApplicationContext,由容器调用

protected final void initServletBean() throws ServletException {
  this.webApplicationContext =createWebApplicationContext();
  initFrameworkServlet();   
    }

createWebApplicationContext : 配置了Context 类就使用配置的类,默认使用XmlWebApplicationContext 。

private WebApplicationContext createWebApplicationContext() throws ServletException {
        ServletContext sc = getServletConfig().getServletContext();
        WebApplicationContext parent = WebApplicationContextUtils.getWebApplicationContext(sc);
        String namespace = getNamespace();
        WebApplicationContext waca = (this.contextClass != null) ?
                instantiateCustomWebApplicationContext(this.contextClass, parent, namespace) :
                new XmlWebApplicationContext(parent, namespace);
        waca.setServletContext(sc);
    
        return waca;
    }
DispatcherServlet

1、initFrameworkServle,来自于FrameworkServlet 的模板方法,由父类调用

protected void initFrameworkServlet() throws ServletException {
        initLocaleResolver();
        initThemeResolver();
        initHandlerMappings();
        initHandlerAdapters();
        initViewResolver();
    }

所有init方法 中获取的对象 从spring 容器获取, 这是创建context 之后的获取,bean 实例已经在context 中先生成好的。

this.localeResolver = (LocaleResolver) getWebApplicationContext().getBean(LOCALE_RESOLVER_BEAN_NAME);

this.themeResolver = (ThemeResolver) getWebApplicationContext().getBean(THEME_RESOLVER_BEAN_NAME);

HandlerMapping hm = (HandlerMapping) getWebApplicationContext().getBean(beanName);

String[] handlers = getWebApplicationContext().getBeanDefinitionNames(HandlerAdapter.class);

this.viewResolver = (ViewResolver) getWebApplicationContext().getBean(VIEW_RESOLVER_BEAN_NAME);

2、doService,提供servlet 核心服务

protected void doService(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
// request 设置属性
request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
        request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
        request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);

// 查找匹配的HandlerExecutionChain
        HandlerExecutionChain mappedHandler = getHandler(request);

// 前置拦截,后续版本中拦击器功能有所加强
        if (mappedHandler.getInterceptors() != null) {
            for (int i = 0; i < mappedHandler.getInterceptors().length; i++) {
                HandlerInterceptor interceptor = mappedHandler.getInterceptors()[i];
                if (!interceptor.preHandle(request, response, mappedHandler.getHandler())) {
                    return;
                }
            }
        }


        HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

// 处理请求
        ModelAndView mv = ha.handle(request, response, mappedHandler.getHandler());

//渲染页面响应客户端
        if (mv != null) {
            logger.debug("Will render model in DispatcherServlet with name '" + getServletName() + "'");
            Locale locale = this.localeResolver.resolveLocale(request);
            response.setLocale(locale);
            render(mv, request, response, locale);
        }
    
    }

XmlWebApplicationContext
核心类图
WebApplicationContext.png

1、setServletContext ,servlet 初始化调用

    public void setServletContext(ServletContext servletContext) throws ApplicationContextException {
        this.servletContext = servletContext;
               // 从servletContext 获取配置文件位置
        this.configLocation = getConfigLocationForNamespace();
              // 执行AbstractApplicationContext 方法
               refresh();
        if (this.namespace == null) {
        WebApplicationContextUtils.publishConfigObjects(this);          WebApplicationContextUtils.publishWebApplicationContext(this);
        }   
    }

2、从servletContext 获取配置文件位置

    protected String getConfigLocationForNamespace() {
        if (getNamespace() != null) {
            String configLocationPrefix = this.servletContext.getInitParameter(CONFIG_LOCATION_PREFIX_PARAM);
            String prefix = (configLocationPrefix != null) ? configLocationPrefix : DEFAULT_CONFIG_LOCATION_PREFIX;
            String configLocationSuffix = this.servletContext.getInitParameter(CONFIG_LOCATION_SUFFIX_PARAM);
            String suffix = (configLocationSuffix != null) ? configLocationSuffix : DEFAULT_CONFIG_LOCATION_SUFFIX;
            return prefix + getNamespace() + suffix;
        }
        else {
            String configLocation = this.servletContext.getInitParameter(CONFIG_LOCATION_PARAM);
            return (configLocation != null) ? configLocation : DEFAULT_CONFIG_LOCATION;
        }
    }

Spring 专题

你可能感兴趣的:(Spring | 0.9 Web)