zoukankan      html  css  js  c++  java
  • SpringMVC的启动

    Spring MVC中的Servlet

    Spring MVC中Servlet一共有三个层次,分别是HttpServletBean、FrameworkServlet和DispatcherServlet。HttpServletBean直接继承自Java的HttpServlet,其作用是将Servlet中配置的参数设置到相应的属性;FrameworkServlet初始化了WebApplicationContext;DispatcherServlet初始化了自身的9个组件。

    DispatcherServlet

    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文件内容:

    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,而且还做了很多别的工作。

    Spring MVC的启动

    启动DispatcherServlet之前先创建HttpServletBean、FrameworkServlet,创建DispatcherServlet后调用其onRefresh方法,再调用initStrategies方法初始化其它组件。 

  • 相关阅读:
    软件工程结对作业02
    最大子数组和
    四则运算2单元测试
    软件工程个人作业03
    梦断代码阅读笔记01
    最大值的单元测试
    构建之法阅读笔记01
    进度条记录02
    软件工程个人作业02
    【BZOJ2595_洛谷4294】[WC2008]游览计划(斯坦纳树_状压DP)
  • 原文地址:https://www.cnblogs.com/Mike_Chang/p/10495854.html
Copyright © 2011-2022 走看看