Перейти к основному содержимому

Весенние темы MVC

· 6 мин. чтения

Задача: Наибольшая подстрока без повторений

Для заданной строки s, найдите длину наибольшей подстроки без повторяющихся символов. Подстрока — это непрерывная непустая последовательность символов внутри строки...

ANDROMEDA 42

1. Обзор

При разработке веб-приложения ключевым компонентом является его внешний вид или тема . Это влияет на удобство использования и доступность нашего приложения и может еще больше укрепить бренд нашей компании.

В этом руководстве мы рассмотрим шаги, необходимые для настройки тем в приложении Spring MVC .

2. Варианты использования

Проще говоря, темы — это набор статических ресурсов, обычно таблиц стилей и изображений, которые влияют на визуальный стиль нашего веб-приложения.

Мы можем использовать темы для:

  • Установите общий внешний вид с фиксированной темой
  • Настройте бренд с помощью фирменной темы — это обычное дело в приложении SAAS, где каждый клиент хочет иметь свой внешний вид.
  • Решите проблемы доступности с помощью темы удобства использования — например, нам может понадобиться темная или высококонтрастная тема.

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. Настройка весенней темы

4.1. Свойства темы

Теперь давайте настроим светлую и темную темы для нашего приложения.

Для темной темы создадим dark.properties :

styleSheet=themes/black.css
background=black

И для светлой темы light.properties :

styleSheet=themes/white.css
background=white

Из приведенных выше свойств мы замечаем, что одно относится к файлу CSS, а другое — к стилю CSS. Через мгновение мы увидим, как они проявляются в нашем представлении.

4.2. обработчик ресурсов

Читая свойства выше, файлы black.css и white.css должны быть помещены в каталог с именем /themes .

И мы должны настроить ResourceHandler , чтобы Spring MVC мог правильно находить файлы по запросу:

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

4.3. ThemeSource

Мы можем управлять этими специфическими для темы файлами . файлы свойств как ResourceBundle s через ResourceBundleThemeSource :

@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 и настроим его для поиска параметра запроса темы :

@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. Пользовательский 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.

Мы также можем найти полный код на GitHub .