SpringMVC源代码学习(五)九大组件下

5. RequestToViewNameTranslator

ViewResolver根据ViewName查找View,但有的Handler处理完并没有设置View,也没有设置viewName,这时就需要从request中获取viewName。也就是RequestToViewNameTranslator的任务。它是个接口,代码如下:

public interface RequestToViewNameTranslator {
    String getViewName(HttpServletRequest request) throws Exception;
}

就像之前说的,他只有一个getViewName方法,能够从request获取到viewName就可以了。下面是一个简单实现的示例:

if(request.getRequestURI().toString().startsWith("/todou")&&request.getMethod().equalsIgnoreCase("GET"))
    return "maidigua";
else
    return "404";

RequestToViewNameTranslator在spring MVC容器中只能配置一个,所以所有request到ViewName的转换规则都要在一个Translator里面实现。

6. LocaleResolver

还记得ViewResolver有两个参数,viewname和Locale,viewname来自Handler或RequestToViewNameTranslator。locale变量就来自LocaleResolver。 
LocaleResolver用于从request解析出Locale。

Locale就是zh-cn之类的,表示一个区域。有了这个就可以对不同区域的用户显示不同的结果,这就是il18n(国际化)的基本原理。

LocaleResolver是个接口,代码如下:

public interface LocaleResolver {
    Locale resolveLocale(HttpServletRequest request);
    void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale);

}

一共只有两个方法,第一个方法就是起到获取Locale的作用,在介绍doService方法时说过,容器会将localeResolver设置到request的attribute中。 
代码如下:

request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE,this.localeResolver);

切换Locale: 
第二个方法可以将Locale设置到request中。 
SpringMVC提供了统一修改request中Locale的机制,就是我们在分析doDispatch时见过的Interceptor。SpringMVC已经写好现成的了,配置一下就可以,也就是org.springframework.web.servlet.i18n.LocaleChangeInterceptor. 
配置方法如:

<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/*"/>
        <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"/>
        //这里也可以自定义参数的名称,如:
        //<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" p:paramName="lang"/>
    </mvc:interceptor>
</mvc:interceptors>

这样通过request的locale参数就可以修改Locale了,如:http://localhost:8080?locale=zh_CN 
http://localhost:8080?locale=en 
用到Locale的地方有两处,1、ViewResolver解析视图的时候。2、使用到国际化资源或者主题的时候。国际化资源或主题主要使用RequestContext的getMessage和getThemeMessage方法。

7.ThemeResolver

它是个接口,源码如下:

public interface ThemeResolver {
    String resolveThemeName(HttpServletRequest request);
    void setThemeName(HttpServletRequest request, HttpServletResponse response, String themeName);
}

SpringMVC中一套主题对应一个properties文件,里面存放着跟当前主题相关的所有资源,如图片、css样式表等,如:

#theme.properties
logo.pic=/images/default/logo.jpg
logo.word=excelib
style=/css/default/style.css

SpringMVC跟主题有关的类主要有ThemeResolver、ThemeSource和Theme。 
1. ThemeResolver的作用是从request解析出主题名。 
2. ThemeSource的作用是根据主题名找到具体的主题。 
3. Theme是ThemeSource找出的一个具体的主题。 
看一下如下代码:

    //org.springframework.web.servlet.support.RequestContext;
    public String getThemeMessage(String code, Object[] args, String defaultMessage) {
        return getTheme().getMessageSource().getMessage(code, args, defaultMessage, this.locale);
    }
    public Theme getTheme() {
        if (this.theme == null) {
            // Lazily determine theme to use for this RequestContext.
            this.theme = RequestContextUtils.getTheme(this.request);
            if (this.theme == null) {
                // No ThemeResolver and ThemeSource available -> try fallback.
                this.theme = getFallbackTheme();
            }
        }
        return this.theme;
    }
    //org.springframework.web.servlet.support.RequestContextUtils
    public static Theme getTheme(HttpServletRequest request) {
        ThemeResolver themeResolver = getThemeResolver(request);
        ThemeSource themeSource = getThemeSource(request);
        if (themeResolver != null && themeSource != null) {
            String themeName = themeResolver.resolveThemeName(request);
            return themeSource.getTheme(themeName);
        }
        else {
            return null;
        }
    }

从RequestContextUtils的代码中就可以看到ThemeResolver和ThemeSource的作用。ThemeResolver的默认实现是org.springframework.web.servlet.theme.FixedThemeResolver 
在讲SpringMVC容器创建时介绍过WebApplicationContext是在FrameworkServlet中创建的,默认使用的是XmlWebApplicationContext,它的父类是AbstractRefreshableWebApplicationContext,这个类实现了ThemeSource接口,实现方式是在内部封装了一个ThemeSource属性,然后将具体工作交给它。 
这里可以把ThemeSource理解成一个配置文件,默认使用的是WebApplicationContext。ThemeResolver默认使用的是FixedThemeResolver。这些我们可以自己配置,例如:

<bean id="themeSource" class="org.springframework.ui.context.support.ResourceBundleThemeSource" p:basenamePrefix="com.excelib.themes."/>
<bean id="themeResolver" class="org.springframework.web.servlet.theme.CookieThemeResolver" p:defaultThemeName="default"/>

这里配置了themeResolver,themeSource默认主题名为default,配置文件在comexcelib.themes包下。
切换Theme:同切换Locale相同,依然是使用Interceptor。配置如下:

<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/" />
        <bean class="org.springframework.web.servlet.theme.ThemeChangeInterceptor" p:paramName="theme"/>
    </mvc:interceptor>
</mvc:interceptors>

可以通过paramName设置修改主题的参数名,默认使用”theme”。下面的请求可以切换为summer主题。

8.MultipartResolver

用于处理上传请求,处理方法时将普通的request包装成MultipartHttpServletRequest,后者可以直接调用getFile方法获取File,如果上传多个文件,还可以调用getFileMap得到FileName->File结构的Map,这样就使得上传请求的处理变得非常简单。 
然后,其实不包装直接用request也可以。所以SpringMVC中此组件没有提供默认值。MultipartResolver代码如下:

public interface MultipartResolver {
    boolean isMultipart(HttpServletRequest request);//判断是不是上传请求
    MultipartHttpServletRequest resolveMultipart(HttpServletRequest request) throws MultipartException;//将request包装成MultipartHttpServletRequest
    void cleanupMultipart(MultipartHttpServletRequest request);//清除上传过程中产生的临时资源
}

9.FlashMapManager

FlashMap在之前的文章1中提到过了,主要用在redirect中传递参数。而FlashMapManager是用来管理FlashMap的,定义如下:

public interface FlashMapManager {
    FlashMap retrieveAndUpdate(HttpServletRequest request, HttpServletResponse response);//恢复参数,将恢复过的和超时的参数从保存介质中删除;
    void saveOutputFlashMap(FlashMap flashMap, HttpServletRequest request, HttpServletResponse response);//用于将参数保存起来。
}

默认实现是org.springframework.web.servlet.support.SessionFlashMapManager。它将参数保存在session中,实现原理就是利用session作为中转站保存request中的参数,达到redirect传递参数的。

原文地址:https://www.cnblogs.com/fupengpeng/p/7382782.html