zoukankan      html  css  js  c++  java
  • springmvc DispatchServlet初始化九大加载策略(一)

    由于篇幅较长,因此分三篇进行讲解:

    springmvc DispatchServlet初始化九大加载策略(一)

    springmvc DispatchServlet初始化九大加载策略(二)

    springmvc DispatchServlet初始化九大加载策略(三)

     

    正文

    SpringMVC 容器初始化时,

    protected void onRefresh(ApplicationContext context) {
        this.initStrategies(context);
    }
    
    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);
    }
    

     

    1. initMultipartResolver 文件上传

    源码:

    this.multipartResolver = (MultipartResolver)context.getBean("multipartResolver", MultipartResolver.class);

    MultipartResolver接口定义如下:

    public interface MultipartResolver {
        // 检查请求头是否包含文件流上传
        boolean isMultipart(HttpServletRequest var1);
        
        // 文件流上传请求解析方法,解析后封装在 MultipartHttpServletRequest 对象中
        MultipartHttpServletRequest resolveMultipart(HttpServletRequest var1) throws MultipartException;
      
        //
        void cleanupMultipart(MultipartHttpServletRequest var1);
    }

    我们知道,相应的请求会被DispatchServlet的doDispatch方法拦截,doDispatch方法中共首先就会调用checkMultipart方法检查请求是否是包含文件流:

    protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException {
            if (this.multipartResolver != null && this.multipartResolver.isMultipart(request)) {
                if (WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class) != null) {
                    this.logger.debug("...");
                } else if (this.hasMultipartException(request)) {
                    this.logger.debug("...");
                } else {
                    try {
                        // 具体的文件流解析方法
                        return this.multipartResolver.resolveMultipart(request);
                        ...
    }  

    配置例子

    CommonsFileUploadSupport实现了 MultipartResolver 接口

    //上传文件配置
    @Bean(name = "multipartResolver")
    public CommonsFileUploadSupport commonsFileUploadSupport(){
        CommonsFileUploadSupport resolver = new CommonsMultipartResolver();
        resolver.setMaxInMemorySize(40960);
        resolver.setMaxUploadSize(10485760000L);
        return resolver;
    }
    

      

    2. initLocaleResolver 国际化

    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

    DispatchServlet中定义一个静态的容器初始化默认defaultStrategies方法块,如果用户没有自定义的话,就使用默认的,

    static {
        // Load default strategy implementations from properties file.
        // This is currently strictly internal and not meant to be customized
        // by application developers.
        try {
            ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class);
            defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
        }
        catch (IOException ex) {
            throw new IllegalStateException("Could not load '" +     DEFAULT_STRATEGIES_PATH + "': " + ex.getMessage());
        }
    }

    流程:

    1. this.localeResolver = getDefaultStrategy(context, LocaleResolver.class);
     
    2. List<T> strategies = getDefaultStrategies(context, strategyInterface)
    
    3. String key = strategyInterface.getName();
       String value = defaultStrategies.getProperty(key);
       // 如果value不为空, 将value转换为class类名称,然后在容器了创建对象
       Object strategy = this.createDefaultStrategy(context, clazz);

    pringMVC国际化提供了四个国际化的实现的类AcceptHeaderLocaleResolver(默认),FixedLocaleResolver、CookieLocaleResolver和SessionLocaleResolver。

     

    3. initThemeResolver 主题

    主题的实现原理:大概就是把网站版面的css样式表和图片之类的文件和网站的程序进行解耦,程序读取theme的持久化配置,然后找到相应的css样式表和图片,配置网站版面。

    要在程序中使用主题,必须设置一个org.springframework.ui.context.ThemeSource的实现类。SpringMVC IOC容器本身实现了ThemeSource,这个类只是简单的把责任代理给了一个特定的实现类,默认情况下这个代理类是:org.springframework.ui.context.support.ResourceBundleThemeSource,这个实现类可以从classpath目录下载入一个properties文件。如设置setBasenamePrefix、setDefaultEncoding等。

    原理(实践)

    如:SpringMVC中一套主题对应一个cool.properties文件,该文件在classpath根目录下, 这个文件列出了主题组成的资源:

    styleSheet=/themes/cool/style.css
    background=/themes/cool/img/coolBg.jpg

    properties文件中的key是指视图文件中元素的名称,value值主题存放的位置。jsp中可以通过jsp文件可以通过spring:theme来访问这个key,然后找到value(对应的主题)。

    ResourceBundleThemeSourceuses(默认的ThemeSource)的作用是根据主题名找到具体的主题,这个例子中就是找到配置文件themedemo.properties中的,默认情况下ResourceBundleThemeSource使用空的前缀名称,所以,classpath根目录下的properties文件会被载入。如果想制定位置,则可以使用basenamePrefix

    找到主题文件后,如何去解析?此时就出现了ThemeResolver。

    SpringMVC中有实现主题类有3个:

    1. FixedThemeResolver(默认):固定格式的theme,不能在系统运行时动态更改theme。

    2. SessionThemeResolver:可在运行中通过更改cookie中的相应的key值来动态调整theme的值。

    3. CookieThemeResolver:可在运行中通过更改session中的相应的key值来动态调整theme的值

    主题加载策略和initLocaleResolver类似,也是如果用户没有自定义就采用默认的方式。默认的方式为FixedThemeResolver。

    一个例子:

    application context .xml配置文件:

    <bean class="org.springframework.ui.context.support.ResourceBundleThemeSource" id="themeSource">  
        <property name="basenamePrefix" value="themes/"></property>  
    </bean>  
    <bean id="themeResolver"  class="org.springframework.web.servlet.theme.SessionThemeResolver">  
        <property name="defaultThemeName" value="red" />  
    </bean>

    简单叙述为:ThemeResolver找到themes/目录下的所有properties中,然后SessionThemeResolver在发生改变主题请求后来解析主题。

    附:如果需要根据用户请求来改变主题,则需要使用ThemeChangeInterceptor拦截器来改变主题。(拦截器有关的知识可以看本文下面的handlerMapping)

    参考:

    https://www.xuebuyuan.com/zh-tw/1578077.html

    https://blog.csdn.net/u012410733/article/details/52915063

     

  • 相关阅读:
    SqlServer 2008 R2定时备份数据库,并且发送邮件通知
    C# ICSharpCode.SharpZipLib.dll文件压缩和解压功能类整理,上传文件或下载文件很常用
    C#按回车Enter使输入焦点自动跳到下一个TextBox的方法收集
    SqlServer知识点记录分享
    C#为工作Sql而产生的字符串分割小工具(很实用,你值得拥有)
    SqlServer一张表数据导入另一张表,收藏使用,工作中更新数据错误很有用
    C#根据CPU+磁盘标号来注册软件
    C# winform调用浏览器打开页面方法分享,希望对大家有帮助
    H5 audio标签
    H5 video标签的第二种格式
  • 原文地址:https://www.cnblogs.com/chenjunjie12321/p/9357668.html
Copyright © 2011-2022 走看看