1. 概要

Webアプリケーションを設計する場合、そのルックアンドフィール、つまりテーマが重要なコンポーネントです。 これは、アプリケーションの使いやすさとアクセシビリティに影響を与え、当社のブランドをさらに確立することができます。

このチュートリアルでは、 aSpringMVCアプリケーションでテーマを構成するために必要な手順を実行します。

2. ユースケース

簡単に言うと、テーマは静的リソースのセットであり、通常はスタイルシートと画像であり、Webアプリケーションの視覚的なスタイルに影響を与えます。

テーマを使用して次のことができます。

  • 固定テーマで共通のルックアンドフィールを確立する
  • ブランディングテーマを使用してブランドをカスタマイズする–これは、各クライアントが異なるルックアンドフィールを必要とするSAASアプリケーションで一般的です。
  • ユーザビリティテーマでアクセシビリティの懸念に対処する–たとえば、暗いテーマやコントラストの高いテーマが必要な場合があります

3. Mavenの依存関係

したがって、まず最初に、このチュートリアルの最初の部分で使用するMavenの依存関係を追加しましょう。

SpringWebMVCおよびSpringコンテキストの依存関係が必要です。

<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サーブレット JSP 、およびJSPLが必要になります。

<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. 春のテーマの構成

4.1. テーマのプロパティ

それでは、アプリケーションの明るいテーマと暗いテーマを構成しましょう。

ダークテーマの場合、dark.propertiesを作成しましょう。

styleSheet=themes/black.css
background=black

ライトテーマの場合、 light.properties

styleSheet=themes/white.css
background=white

上記のプロパティから、1つはCSSファイルを参照し、もう1つはCSSスタイルを参照していることがわかります。 これらが私たちの見解にどのように現れているかをすぐに見ていきます。

4.2. ResourceHandler

上記のプロパティを読んで、ファイルblack.cssおよびwhite.css/themesという名前のディレクトリに配置する必要があります。

また、 ResourceHandler を構成して、SpringMVCが要求されたときにファイルを正しく検索できるようにする必要があります。

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

4.3. ThemeSource

これらのテーマ固有の。プロパティファイルは、ResourceBundleThemeSourceを介してResourceBundlesとして管理できます。

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

4.4. ThemeResolver s

次に、アプリケーションの正しいテーマを解決するためにThemeResolverが必要です。 設計のニーズに応じて、既存の実装から選択することも、独自の実装を作成することもできます。

この例では、 CookieThemeResolver。 名前が示すように、これはブラウザの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

ThemeChangeInterceptor の仕事は、テーマ変更リクエストを理解することです。

次に、 ThemeChangeInterceptor を追加し、themeリクエストパラメーターを検索するように構成します。

@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セキュリティが必要です。

<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 Data Hibernate、、および HSQLDB は、ユーザーの設定を保存します。

<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 について詳しく説明し、独自の1つを実装しましょう。 このカスタムThemeResolverは、ユーザーのテーマ設定をデータベースに保存します。

これを実現するために、最初に UserPreferenceentityを追加しましょう。

@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としてではなくデータベースに保存されるようになりました。

ユーザーの好みを保存する別の方法は、SpringMVCコントローラーと別のAPIを使用することでした。

7. 結論

この記事では、SpringMVCテーマを構成する手順を学びました。

完全なコードはGitHubにもあります。