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

Весенняя сессия с MongoDB

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

1. Обзор

В этом кратком руководстве мы рассмотрим, как использовать сеанс Spring с поддержкой MongoDB как с Spring Boot, так и без него.

Spring Session также может поддерживаться другими хранилищами, такими как Redis и JDBC .

2. Конфигурация весенней загрузки

Во-первых, давайте рассмотрим зависимости и конфигурацию, необходимые для Spring Boot. Для начала добавим в наш проект последние версии spring-session-data-mongodb и spring-boot-starter-data-mongodb :

<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-mongodb</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>

После этого, чтобы включить автоматическую настройку Spring Boot, нам нужно добавить тип хранилища Spring Session как mongodb в application.properties :

spring.session.store-type=mongodb

3. Конфигурация Spring без Spring Boot

Теперь давайте посмотрим на зависимости и конфигурацию, необходимые для хранения сеанса Spring в MongoDB без Spring Boot.

Как и в конфигурации Spring Boot, нам понадобится зависимость spring-session-data-mongodb . Однако здесь мы будем использовать зависимость spring-data-mongodb для доступа к нашей базе данных MongoDB:

<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-mongodb</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>

Наконец, давайте посмотрим, как настроить приложение:

@EnableMongoHttpSession
public class HttpSessionConfig {

@Bean
public JdkMongoSessionConverter jdkMongoSessionConverter() {
return new JdkMongoSessionConverter(Duration.ofMinutes(30));
}
}

Аннотация @EnableMongoHttpSession включает конфигурацию, необходимую для хранения данных сеанса в MongoDB .

Также обратите внимание, что JdkMongoSessionConverter отвечает за сериализацию и десериализацию данных сеанса.

4. Пример приложения

Давайте создадим приложение для тестирования конфигураций. Мы будем использовать Spring Boot, так как он быстрее и требует меньше настроек.

Мы начнем с создания контроллера для обработки запросов:

@RestController
public class SpringSessionMongoDBController {

@GetMapping("/")
public ResponseEntity<Integer> count(HttpSession session) {

Integer counter = (Integer) session.getAttribute("count");

if (counter == null) {
counter = 1;
} else {
counter++;
}

session.setAttribute("count", counter);

return ResponseEntity.ok(counter);
}
}

Как видно из этого примера, мы увеличиваем счетчик при каждом обращении к конечной точке и сохраняем его значение в атрибуте сеанса с именем count .

5. Тестирование приложения

Давайте протестируем приложение, чтобы увидеть, действительно ли мы можем хранить данные сеанса в MongoDB.

Для этого мы получим доступ к конечной точке и проверим полученный файл cookie. Это будет содержать идентификатор сеанса.

После этого мы запросим коллекцию MongoDB, чтобы получить данные сеанса, используя идентификатор сеанса:

@Test
public void
givenEndpointIsCalledTwiceAndResponseIsReturned_whenMongoDBIsQueriedForCount_thenCountMustBeSame() {

HttpEntity<String> response = restTemplate
.exchange("http://localhost:" + 8080, HttpMethod.GET, null, String.class);
HttpHeaders headers = response.getHeaders();
String set_cookie = headers.getFirst(HttpHeaders.SET_COOKIE);

Assert.assertEquals(response.getBody(),
repository.findById(getSessionId(set_cookie)).getAttribute("count").toString());
}

private String getSessionId(String cookie) {
return new String(Base64.getDecoder().decode(cookie.split(";")[0].split("=")[1]));
}

6. Как это работает?

Давайте посмотрим, что происходит за кулисами весенней сессии.

SessionRepositoryFilter отвечает за большую часть работы:

  • преобразует HttpSession в MongoSession
  • проверяет наличие файла cookie и, если да, загружает данные сеанса из хранилища
  • сохраняет обновленные данные сеанса в хранилище
  • проверяет валидность сеанса

Кроме того, SessionRepositoryFilter создает файл cookie с именем SESSION , который является HttpOnly и безопасным. Этот файл cookie содержит идентификатор сеанса, который представляет собой значение в кодировке Base64.

Чтобы настроить имя или свойства файла cookie, нам нужно создать bean-компонент Spring типа DefaultCookieSerializer.

Например, здесь мы отключаем свойство httponly файла cookie:

@Bean
public DefaultCookieSerializer customCookieSerializer(){
DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();

cookieSerializer.setUseHttpOnlyCookie(false);

return cookieSerializer;
}

7. Сведения о сеансе хранятся в MongoDB

Давайте запросим нашу коллекцию сеансов, используя следующую команду в нашей консоли MongoDB:

db.sessions.findOne()

В результате мы получим документ BSON , похожий на:

{
"_id" : "5d985be4-217c-472c-ae02-d6fca454662b",
"created" : ISODate("2019-05-14T16:45:41.021Z"),
"accessed" : ISODate("2019-05-14T17:18:59.118Z"),
"interval" : "PT30M",
"principal" : null,
"expireAt" : ISODate("2019-05-14T17:48:59.118Z"),
"attr" : BinData(0,"rO0ABXNyABFqYXZhLnV0aWwuSGFzaE1hcAUH2sHDFmDRAwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAx3CAAAABAAAAABdAAFY291bnRzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAC3g=")
}

_id — это UUID , который будет закодирован в Base64 DefaultCookieSerializer и установлен в качестве значения в файле cookie SESSION . Также обратите внимание, что атрибут attr содержит фактическое значение нашего счетчика. ``

8. Заключение

В этом руководстве мы рассмотрели Spring Session с поддержкой MongoDB — мощного инструмента для управления HTTP-сессиями в распределенной системе. Имея в виду эту цель, он может быть очень полезен при решении проблемы репликации сеансов между несколькими экземплярами приложения.

Как обычно, исходный код доступен на GitHub .