1. Прегледа
В този бърз урок ще проучим как да използваме Spring Session, подкрепен с MongoDB, както със, така и без Spring Boot.
Spring Session може да бъде подкрепен и с други магазини като Redis и JDBC.
2. Spring Boot Configuration
Първо, нека разгледаме зависимостите и конфигурацията, необходими за 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 сесията в 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);
}
}
Както можем да видим в този пример, ние увеличаваме counter при всяко посещение до крайната точка и съхраняване на стойността му в атрибут на сесия с име count .
5. Тестване на приложениетота
Нека тестваме приложението, за да видим дали всъщност можем да съхраняваме данните за сесията в MongoDB.
За да направим това, ще получим достъп до крайната точка и ще проверим бисквитката, която ще получим. Това ще съдържа идентификатор на сесията.
След това ще потърсим колекцията 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
- проверява дали има бисквитка присъства и ако е така, зарежда данните за сесията от магазина
- записва актуализираните данни за сесията в магазина
- проверява валидността на сесията
Също така SessionRepositoryFilter създава бисквитка с името SESSION това е HttpOnly и е сигурно. Тази бисквитка съдържа идентификатора на сесията, който е кодирана от Base64 стойност.
За да персонализираме името или свойствата на бисквитката, ще трябва да създадем Spring bean от тип DefaultCookieSerializer.
Например, тук деактивираме httponly свойство на бисквитката:
@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 и задайте като стойност в SESSION бисквитка. Също така имайте предвид, че attr атрибутът съдържа действителната стойност на нашия брояч.