SpringMVC的啓動

Spring MVC中的Servletjava

Spring MVC中Servlet一共有三個層次,分別是HttpServletBean、FrameworkServlet和DispatcherServlet。HttpServletBean直接繼承自Java的HttpServlet,其做用是將Servlet中配置的參數設置到相應的屬性;FrameworkServlet初始化了WebApplicationContext;DispatcherServlet初始化了自身的9個組件。web

DispatcherServletspring

DispatcherServlet的入口方法是onRefresh方法,其中簡單地調用了initStrategies方法,其中又調用了9個初始化方法,初始化策略組件。數組

protected void onRefresh(ApplicationContext context) {
    this.initStrategies(context);
}
onRefresh
protected void initStrategies(ApplicationContext context) {
    // 上傳組件
    this.initMultipartResolver(context);
    // 國際化組件
    this.initLocaleResolver(context);
    this.initThemeResolver(context);
    this.initHandlerMappings(context);
    this.initHandlerAdapters(context);
    this.initHandlerExceptionResolvers(context);
    this.initRequestToViewNameTranslator(context);
    this.initViewResolvers(context);
    this.initFlashMapManager(context);
}
initStrategies
// 以initLocaleResolver爲例分析初始化組件過程
private void initLocaleResolver(ApplicationContext context) {
    try {
        // 按照名稱或類型在容器中獲取
        // 咱們只要在SpringMVC的配置文件中配置相應類型的組件,容器就能夠自動找到
        this.localeResolver = (LocaleResolver)context.getBean("localeResolver", LocaleResolver.class);
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Using LocaleResolver [" + this.localeResolver + "]");
        }
    } catch (NoSuchBeanDefinitionException var3) {
        // 若是沒有配置,使用默認策略
        this.localeResolver = (LocaleResolver)this.getDefaultStrategy(context, LocaleResolver.class);
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Unable to locate LocaleResolver with name 'localeResolver': using default [" + this.localeResolver + "]");
        }
    }
}
initLocaleResolver
protected <T> T getDefaultStrategy(ApplicationContext context, Class<T> strategyInterface) {
    // 調用複數的方法
    List<T> strategies = this.getDefaultStrategies(context, strategyInterface);
    if (strategies.size() != 1) {
        throw new BeanInitializationException("DispatcherServlet needs exactly 1 strategy for interface [" + strategyInterface.getName() + "]");
    } else {
        // 返回第一個
        return strategies.get(0);
    }
}
protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) {
    String key = strategyInterface.getName();
    // Properties類型的defaultStrategies在靜態代碼塊中初始化
    String value = defaultStrategies.getProperty(key);
    if (value == null) {
        return new LinkedList();
    } else {
        // 若是有多個默認值,以逗號分隔數組
        String[] classNames = StringUtils.commaDelimitedListToStringArray(value);
        List<T> strategies = new ArrayList(classNames.length);
        String[] var7 = classNames;
        int var8 = classNames.length;
        // 初始化組件
        for(int var9 = 0; var9 < var8; ++var9) {
            String className = var7[var9];
            try {
                Class<?> clazz = ClassUtils.forName(className, DispatcherServlet.class.getClassLoader());
                Object strategy = this.createDefaultStrategy(context, clazz);
                strategies.add(strategy);
            } catch (ClassNotFoundException var13) {
                throw new BeanInitializationException("Could not find DispatcherServlet's default strategy class [" + className + "] for interface [" + key + "]", var13);
            } catch (LinkageError var14) {
                throw new BeanInitializationException("Error loading DispatcherServlet's default strategy class [" + className + "] for interface [" + key + "]: problem with class file or dependent class", var14);
            }
        }

        return strategies;
    }
}

static {
    try {
        // DispatcherServlet.properties在DispatcherServlet.java文件的旁邊
        ClassPathResource resource = new ClassPathResource("DispatcherServlet.properties", DispatcherServlet.class);
        defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
    } catch (IOException var1) {
        throw new IllegalStateException("Could not load 'DispatcherServlet.properties': " + var1.getMessage());
    }
}
View Code

DispatcherServlet.properties文件內容:mvc

org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver

org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver

org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,
    org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping

org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,
    org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,
    org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter

org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,
    org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,
    org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver

org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator

org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver

org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager
View Code

一共定義了8個組件,上傳組件MultipartResolver沒有默認配置,由於不是每一個應用都須要上傳功能,即便須要上傳也不必定就要使用MultipartResolver;HandlerMapping、HandlerAdapter和HandlerExceptionResolver都配置了多個;ViewResolver也能夠配置多個,默認是一個。
默認配置並非最優配置,也不是spring的推薦配置。
當使用<mvc:annotation-driven/>後,並不會所有使用默認配置,由於它配置了HandlerMapping、HandlerAdapter和HandlerExceptionResolver,並且還作了不少別的工做。app

Spring MVC的啓動ide

啓動DispatcherServlet以前先建立HttpServletBean、FrameworkServlet,建立DispatcherServlet後調用其onRefresh方法,再調用initStrategies方法初始化其它組件。 this

相關文章
相關標籤/搜索