Fork me on GitHub

ThemeResolver

注意:所有文章除特别说明外,转载请注明出处.

第19章 ThemeResolver

·这里的SpringMVC框架提供的主题设置应用的整体样式和风格,提高用户体验。SpringMVC主题是一些静态资源的集合。ThemeResolver根据request解析Theme,ThemeResolver的实现和LocalResolver相似。AbstractThemeResolver设置默认的主题:defaultThemeName属性,提供get/set方法。在SpringMVC中包括两部分内容:Theme和ThemeResolver。

1.Theme

在应用Theme主题时需要实现org.springframework.ui.context.ThemeSource接口,WEB应用上下文WebApplication接口继承自ThemeSource,但实现功能委派给具体的类实现,默认:org.springframework.ui.context.support.ResouceBundleThemeSource类。此类默认从classpath加载主题文件。

注意:无论是自定义ThemeSource接口的实现 或 通过配置属性文件路径的ResourceBundleThemeSource实现,都需要在Spring上下文中定义此bean,并且bean的id必须为themeSource,Spring会自动发现并使用。

2.ThemeResolver

在Spring上下文中定义Theme之后,DispatcherServlet会在Spring容器中查找id是themeResolver的bean使用。

提示:ThemeResolver的使用和LocalResolver的工作原理一样,它在request中查找theme主题并且可以修改request的theme主题,Spring提供如下的主体解析器:

1.FixedThemeResolver:默认主题解析器,使用固定的主题,通过defaultThemeName属性设置,即此属性指定主题属性文件的文件名。此解析器不能动态设置主题。

2.SessionThemeResolver:通过用户会话来保持主题,每个会话(session)仅需要设置一次,所有请求共享主题,但是不能两个会话共享。

3.CookieThemeResolver:使用客户端cookie存储的主题。

提示:Spring提供ThemeChangeInterceptor拦截器,通过request参数控制改变用户请求的主题。

1.FixedThemeResolver

该解析器是默认的主题解析器(在DispatcherServlet.properties文件中配置默认策略),实现ThemeResolver接口,主题的名字通过defaultThemeName属性指定,该值默认是theme。

public class FixedThemeResolver extends AbstractThemeResolver {
    // 解析主题文件名
    @Override
    public String resolveThemeName(HttpServletRequest request) {
        // 返回主题文件名,默认值为theme(在父类中定义)
        return getDefaultThemeName();
    }

    // 设置主题文件名,此解析器不能设置。
    @Override
    public void setThemeName(
            HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable String themeName) {
        throw new UnsupportedOperationException("Cannot change theme - use a different theme resolution strategy");
    }
}

1.1 FixedThemeResolver 配置文件

<!-- 默认Servlet处理静态资源 -->
<mvc:default-servlet-handler />
<!-- jsp视图映射与视图解析 -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <property name="suffix" value=".jsp"/>
</bean>

<!-- 加载主题资源文件 -->
<bean id="themeSource" class="org.springframework.ui.context.support.ResourceBundleThemeSource">
    <!-- 指定文件前缀,即文件所在目录,如果放在classpath下,value为空(默认从classpath下加载) -->
    <property name="basenamePrefix" value="theme."/>
</bean>
<!-- 使用FixedThemeResolver -->
<bean id="themeResolver" class="org.springframework.web.servlet.theme.FixedThemeResolver">
    <!-- 定义theme文件的名称 -->
    <property name="defaultThemeName" value="myTheme"/>
</bean>

说明:1.ResourceBundleThemeSource的属性basenamePrefix即为主题属性文件所在目录名称,其后必须有”.”或”/“。 2.FixedThemeResolver是Spring默认的解析器,再此配置是为了自定义defaultThemeName属性值,即属性文件名称。

提示:在配置文件之后还应该有jsp文件和controller文件等。这里省略。

2.SessionThemeResolver

说明:1.SessionThemeResolver与FixedThemeResolver解析器的继承关系一样,都继承自AbstractThemeResolver抽象类,其中抽象类中定义了defaultThemeName属性,用于设置属性文件的名称,默认为theme。2.SessionThemeResolver类实现ThemeResolver接口,使用用户会话(session)中的主题。

public class SessionThemeResolver extends AbstractThemeResolver {
    // 用于设置session Attribute中的key使用
    public static final String THEME_SESSION_ATTRIBUTE_NAME = SessionThemeResolver.class.getName() + ".THEME";

    // 解析请求中使用的主题
    @Override
    public String resolveThemeName(HttpServletRequest request) {
        // 从请求会话中获取到主题
        String themeName = (String) WebUtils.getSessionAttribute(request, THEME_SESSION_ATTRIBUTE_NAME);
        // 如果会话中不存在,使用默认的主题
        return (themeName != null ? themeName : getDefaultThemeName());
    }
    // 设置请求的主题
    @Override
    public void setThemeName(
            HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable String themeName) {
        // 从客户端请求获取主题并设置到session的Attribute区中
        WebUtils.setSessionAttribute(request, THEME_SESSION_ATTRIBUTE_NAME,
                (StringUtils.hasText(themeName) ? themeName : null));
    }
}

2.1 SessionThemeResolver 配置文件

<mvc:interceptors>
    <!-- 该拦截器通过名为”theme”的参数来拦截HTTP请求,设置Theme主题 -->
    <bean class="org.springframework.web.servlet.theme.ThemeChangeInterceptor">
        <!-- 用户请求参数的名称为:theme -->
        <property name="paramName" value="theme"/>
    </bean>
</mvc:interceptors>

<!-- 指定ThemeResolver -->
<bean id="themeResolver" class="org.springframework.web.servlet.theme.SessionThemeResolver">
    <!-- 配置默认的主题文件 -->
    <property name="defaultThemeName" value="myTheme"/>
</bean>

<!-- 其余配置省略,参加上章 -->
...

3.CookieThemeResolver

CookieThemeResolver将主题保存到cookie中,为了处理cookie方便继承了CookieGenerator,所以不能继承AbstractThemeResolver,其实现了对默认主题的支持。

// 设置Theme,在请求到达Controller之前,进行设置
@Override
public void setThemeName(
        HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable String themeName) {

    Assert.notNull(response, "HttpServletResponse is required for CookieThemeResolver");
    // 请求参数中传来的themeName值
    if (StringUtils.hasText(themeName)) {
        // 把请求参数指定的主题设置request Attribute并写cookie
        request.setAttribute(THEME_REQUEST_ATTRIBUTE_NAME, themeName);
        addCookie(response, themeName);
    }
    else {
        // 将默认的主题设置request Attribute并写cookie
        request.setAttribute(THEME_REQUEST_ATTRIBUTE_NAME, getDefaultThemeName());
        removeCookie(response);
    }
}

// 解析请求的Theme
@Override
public String resolveThemeName(HttpServletRequest request) {
    // 从request中获取主题theme
    String themeName = (String) request.getAttribute(THEME_REQUEST_ATTRIBUTE_NAME);
    if (themeName != null) {
        return themeName;
    }

    // 从客户端cookie中获取指定名字的theme,在设置时指定了cookie名字
    String cookieName = getCookieName();
    if (cookieName != null) {
        Cookie cookie = WebUtils.getCookie(request, cookieName);
        if (cookie != null) {
            String value = cookie.getValue();
            if (StringUtils.hasText(value)) {
                themeName = value;
            }
        }
    }

    // 请求和cookie中都无时,使用默认theme
    if (themeName == null) {
        themeName = getDefaultThemeName();
    }
    request.setAttribute(THEME_REQUEST_ATTRIBUTE_NAME, themeName);
    return themeName;
}

本文标题:ThemeResolver

文章作者:Bangjin-Hu

发布时间:2019年10月15日 - 09:22:26

最后更新:2020年03月30日 - 08:17:26

原始链接:http://bangjinhu.github.io/undefined/第19章 ThemeResolver/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

Bangjin-Hu wechat
欢迎扫码关注微信公众号,订阅我的微信公众号.
坚持原创技术分享,您的支持是我创作的动力.