«1. Обзор
При разработке веб-приложения его внешний вид или тема являются ключевым компонентом. Это влияет на удобство использования и доступность нашего приложения и может еще больше укрепить бренд нашей компании.
В этом руководстве мы рассмотрим шаги, необходимые для настройки тем в приложении Spring MVC.
2. Варианты использования
Проще говоря, темы — это набор статических ресурсов, обычно таблиц стилей и изображений, которые влияют на визуальный стиль нашего веб-приложения.
Мы можем использовать темы, чтобы:
-
Создать общий внешний вид с фиксированной темой. Настроить бренд с темой брендинга — это обычное дело в приложении SAAS, где каждый клиент хочет разного внешнего вида. and-feel Решите проблемы доступности с помощью темы удобства использования — например, нам может понадобиться темная или высококонтрастная тема
3. Зависимости Maven
Итак, обо всем по порядку, давайте добавим зависимости Maven, которые мы будем использовать в первой части этого урока.
Нам потребуются зависимости Spring WebMVC и Spring 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, JSP и 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.css и white.css должны быть помещены в каталог с именем /themes.
И мы должны настроить ResourceHandler, чтобы Spring MVC мог правильно находить файлы по запросу:
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/themes/**").addResourceLocations("classpath:/themes/");
}
4.3. ThemeSource
Мы можем управлять этими специфичными для темы файлами .properties как ResourceBundles через ResourceBundleThemeSource:
@Bean
public ResourceBundleThemeSource resourceBundleThemeSource() {
return new ResourceBundleThemeSource();
}
4.4. ThemeResolvers
Далее нам нужен 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 и настроим его для поиска параметра запроса темы:
@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 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. Custom ThemeResolver ~~ ~ Давайте теперь углубимся в ThemeResolver и реализуем один из наших собственных. Этот пользовательский ThemeResolver сохранит настройки темы пользователя в базе данных.
«Для этого давайте сначала добавим объект UserPreference:
Затем мы создадим UserPreferenceThemeResolver, который должен реализовать интерфейс ThemeResolver. Его основные обязанности заключаются в разрешении и сохранении информации о теме.
@Entity
@Table(name = "preferences")
public class UserPreference {
@Id
private String username;
private String theme;
}
Давайте сначала обратимся к разрешению имени, реализовав UserPreferenceThemeResolver#resolveThemeName:
И теперь мы можем написать нашу реализацию для сохранения темы в UserPreferenceThemeResolver#setThemeName:
@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();
}
И, наконец, давайте теперь изменим ThemeResolver в нашем приложении:
@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);
}
}
Теперь настройки темы пользователя сохраняются в базе данных, а не в виде файла cookie.
@Bean
public ThemeResolver themeResolver() {
return new UserPreferenceThemeResolver();
}
Альтернативным способом сохранения пользовательских настроек мог быть контроллер Spring MVC и отдельный API.
7. Заключение
В этой статье мы узнали, как настроить темы Spring MVC.
Мы также можем найти полный код на GitHub.
«