知識庫 / Spring / Spring MVC RSS 訂閱

Spring MVC 主題

Spring MVC
HongKong
9
01:06 PM · Dec 06 ,2025

1. 概述

在設計 Web 應用程序時,其外觀和感覺(主題)是一個關鍵組成部分。它會影響應用程序的可用性和可訪問性,並進一步確立公司的品牌形象。

在本教程中,我們將介紹配置 Spring MVC 應用程序中主題的步驟。

2. 使用場景

簡單來説,主題是一組靜態資源,通常包括樣式表和圖像,它們會影響我們 Web 應用程序的視覺風格。

我們可以使用主題來:

  • 使用固定主題來建立一致的視覺風格
  • 針對品牌進行定製,使用品牌主題——這在 SaaS 應用程序中很常見,每個客户都希望擁有不同的視覺風格
  • 通過可用性主題來解決可訪問性問題——例如,我們可能需要一個深色主題或高對比度主題

3. Maven 依賴

首先,讓我們添加用於本教程第一部分所需的 Maven 依賴項。

我們需要 Spring WebMVCSpring Context 依賴項:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.1.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.1.RELEASE</version>
</dependency>

由於我們將使用 JSP 在我們的示例中,因此我們需要 Java ServletJSP,以及 JSTL

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
</dependency>
<dependency>
     <groupId>javax.servlet.jsp</groupId>
     <artifactId>javax.servlet.jsp-api</artifactId>
     <version>2.3.3</version>
</dependency>
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>

4. 配置 Spring 主題

4.1. 主題屬性

現在,讓我們為我們的應用程序配置淺色和深色主題。

對於深色主題,讓我們創建一個名為 dark.properties 的文件:

styleSheet=themes/black.css
background=black

對於亮色主題,請參考 light.properties

styleSheet=themes/white.css
background=white

從以上屬性中可以看出,一個指向 CSS 文件,另一個指向 CSS 樣式。稍後我們將看到它們在視圖中是如何體現的。

4.2. ResourceHandler

閲讀以上配置信息,black.csswhite.css 文件必須放置在名為 /themes 的目錄下。

並且,我們必須配置一個 ResourceHandler 以啓用 Spring MVC 正確地定位這些文件:

@Override 
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/themes/**").addResourceLocations("classpath:/themes/");
}

4.3. ThemeSource

我們可以使用 ResourceBundle 作為資源包,通過 ResourceBundleThemeSource 來管理這些主題特定的 .properties 文件。

@Bean
public ResourceBundleThemeSource resourceBundleThemeSource() {
    return new ResourceBundleThemeSource();
}

4.4. <em >ThemeResolver</em>

我們需要一個 <em >ThemeResolver</em> 來確定應用程序的主題。 根據我們的設計需求,我們可以選擇現有的實現方案或創建自己的方案。

對於我們的示例,讓我們配置 <em >CookieThemeResolver</em>。 如其名稱所示,它從瀏覽器 Cookie 中解析主題信息,或者在信息不可用時回退到默認主題:

@Bean
public ThemeResolver themeResolver() {
    CookieThemeResolver themeResolver = new CookieThemeResolver();
    themeResolver.setDefaultThemeName("light");
    return themeResolver;
}

框架中提供的 ThemeResolver 的其他變體包括:

  • FixedThemeResolver:用於在應用程序中指定固定的主題
  • SessionThemeResolver:用於允許用户在活動會話中切換主題

4.5. 視圖

為了將主題應用於我們的視圖,我們必須配置一個機制來查詢資源包。

我們將僅限於 JSP,儘管也可以配置類似的查找機制,用於替代視圖渲染引擎。

對於 JSP,我們可以導入一個標籤庫來完成這項工作:

<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>

然後,我們可以引用任何指定適當屬性名稱的屬性。

<link rel="stylesheet" href="<spring:theme code='styleSheet'/>"/>

或者:

<body bgcolor="<spring:theme code='background'/>">

現在,讓我們將一個名為 index.jsp的視圖添加到我們的應用程序中,並將其放置在 WEB-INF/目錄下:

<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <link rel="stylesheet" href="<spring:theme code='styleSheet'/>"/>
        <title>Themed Application</title>
    </head>
    <body>
        <header>
            <h1>Themed Application</h1>
            <hr />
        </header>
        <section>
            <h2>Spring MVC Theme Demo</h2>
            <form action="<c:url value='/'/>" method="POST" name="themeChangeForm" id="themeChangeForm">
                <div>
                    <h4>
                        Change Theme
                    </h4>
                </div>
                <select id="theme" name="theme" onChange="submitForm()">
                    <option value="">Reset</option>
                    <option value="light">Light</option>
                    <option value="dark">Dark</option>
                </select>
            </form>
        </section>

        <script type="text/javascript">
            function submitForm() {
                document.themeChangeForm.submit();
            }
        </script>
    </body>
</html>

實際上,我們的應用程序在這個階段已經可以正常工作,始終選擇淺色主題。

讓我們看看如何允許用户更改主題。

4.6. ThemeChangeInterceptor

The job of the ThemeChangeInterceptor is to understand the theme change request.

Let’s now add a ThemeChangeInterceptor and configure it to look for a theme request parameter:

@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(themeChangeInterceptor());
}

@Bean
public ThemeChangeInterceptor themeChangeInterceptor() {
    ThemeChangeInterceptor interceptor = new ThemeChangeInterceptor();
    interceptor.setParamName("theme");
    return interceptor;
}

5. 進一步依賴

接下來,我們實現自己的 ThemeResolver,該組件將用户的偏好存儲到數據庫中。

為了實現這一點,我們需要使用 Spring Security 來識別用户:

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-web</artifactId>
    <version>5.2.1.RELEASE</version>
</dependency>

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config</artifactId>
    <version>5.2.1.RELEASE</version>
</dependency>

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-taglibs</artifactId>
    <version>5.2.1.RELEASE</version>
</dependency>

以及 Spring DataHibernateHSQLDB 用於存儲用户的偏好設置:

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-jpa</artifactId>
    <version>2.2.2.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>5.4.9.Final</version>
</dependency>

<dependency>
    <groupId>org.hsqldb</groupId>
    <artifactId>hsqldb</artifactId>
    <version>2.5.0</version>
</dependency>

6. 自定義主題解析器 (ThemeResolver)

現在,讓我們更深入地瞭解主題解析器 (ThemeResolver) 並實現一個自定義的。這個自定義主題解析器 (ThemeResolver) 將保存用户的自定義主題偏好到數據庫中。

為了實現這一點,首先添加一個用户偏好實體 (UserPreference):

@Entity
@Table(name = "preferences")
public class UserPreference {
    @Id
    private String username;

    private String theme;
}

接下來,我們將創建 UserPreferenceThemeResolver,它必須實現 ThemeResolver 接口。 它的主要職責是解析和保存主題信息。

讓我們首先通過實現 UserPreferenceThemeResolver#resolveThemeName 來解決主題名稱:

@Override
public String resolveThemeName(HttpServletRequest request) {
    String themeName = findThemeFromRequest(request)
      .orElse(findUserPreferredTheme().orElse(getDefaultThemeName()));
    request.setAttribute(THEME_REQUEST_ATTRIBUTE_NAME, themeName);
    return themeName;
}

private Optional<String> findUserPreferredTheme() {
    Authentication authentication = SecurityContextHolder.getContext()
            .getAuthentication();
    UserPreference userPreference = getUserPreference(authentication).orElse(new UserPreference());
    return Optional.ofNullable(userPreference.getTheme());
}

private Optional<String> findThemeFromRequest(HttpServletRequest request) {
    return Optional.ofNullable((String) request.getAttribute(THEME_REQUEST_ATTRIBUTE_NAME));
}
    
private Optional<UserPreference> getUserPreference(Authentication authentication) {
    return isAuthenticated(authentication) ? 
      userPreferenceRepository.findById(((User) authentication.getPrincipal()).getUsername()) : 
      Optional.empty();
}

現在我們可以為保存主題編寫我們的實現,在 UserPreferenceThemeResolver#setThemeName 中:

@Override
public void setThemeName(HttpServletRequest request, HttpServletResponse response, String theme) {
    Authentication authentication = SecurityContextHolder.getContext()
        .getAuthentication();
    if (isAuthenticated(authentication)) {
        request.setAttribute(THEME_REQUEST_ATTRIBUTE_NAME, theme);
        UserPreference userPreference = getUserPreference(authentication).orElse(new UserPreference());
        userPreference.setUsername(((User) authentication.getPrincipal()).getUsername());
        userPreference.setTheme(StringUtils.hasText(theme) ? theme : null);
        userPreferenceRepository.save(userPreference);
    }
}

最後,讓我們現在更改應用程序中的ThemeResolver

@Bean 
public ThemeResolver themeResolver() { 
    return new UserPreferenceThemeResolver();
}

現在,用户的偏好主題已保存在數據庫中,而不是通過 cookie 保存。

另一種保存用户偏好的方式可以是使用 Spring MVC 控制器和單獨的 API。

7. 結論

在本文中,我們學習了配置 Spring MVC 主題的步驟。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.