1. Visão geral
Neste tutorial rápido, exploraremos como usar o Spring Session com o MongoDB, com e sem Spring Boot.
A Spring Session também pode ser apoiada com outras lojas, como Redis e JDBC.
2. Configuração do Spring Boot
Primeiro, vamos ver as dependências e a configuração necessária para o Spring Boot. Para começar, vamos adicionar as versões mais recentes de spring-session-data-mongodb e spring-boot-starter-data-mongodb ao nosso projeto:
<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>
Depois disso, para habilitar a configuração automática do Spring Boot, precisaremos adicionar o tipo de armazenamento Spring Session como mongodb em application.properties :
spring.session.store-type=mongodb
3. Configuração do Spring sem Spring Boot
Agora, vamos dar uma olhada nas dependências e na configuração necessária para armazenar a sessão do Spring no MongoDB sem o Spring Boot.
Semelhante à configuração do Spring Boot, precisaremos do spring-session-data-mongodb dependência. No entanto, aqui usaremos o spring-data-mongodb dependência para acessar nosso banco de dados 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>
Por fim, vamos ver como configurar o aplicativo:
@EnableMongoHttpSession
public class HttpSessionConfig {
@Bean
public JdkMongoSessionConverter jdkMongoSessionConverter() {
return new JdkMongoSessionConverter(Duration.ofMinutes(30));
}
}
A @EnableMongoHttpSession anotação habilita a configuração necessária para armazenar os dados da sessão no MongoDB .
Além disso, observe que o JdkMongoSessionConverter é responsável por serializar e desserializar os dados da sessão.
4. Aplicativo de exemplo
Vamos criar um aplicativo para testar as configurações. Estaremos usando Spring Boot, pois é mais rápido e requer menos configuração.
Começaremos criando o controlador para lidar com as solicitações:
@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);
}
}
Como podemos ver neste exemplo, estamos incrementando counter em cada hit para o endpoint e armazenando seu valor em um atributo de sessão chamado count .
5. Testando o aplicativo
Vamos testar o aplicativo para ver se realmente conseguimos armazenar os dados da sessão no MongoDB.
Para fazer isso, acessaremos o endpoint e inspecionaremos o cookie que receberemos. Isso conterá um ID de sessão.
Depois disso, consultaremos a coleção do MongoDB para buscar os dados da sessão usando o ID da sessão:
@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. Como funciona?
Vamos dar uma olhada no que acontece na sessão de primavera nos bastidores.
O SessionRepositoryFilter é responsável pela maior parte do trabalho:
- converte a HttpSession em uma MongoSession
- verifica se há um Cookie presente e, em caso afirmativo, carrega os dados da sessão da loja
- salva os dados atualizados da sessão na loja
- verifica a validade da sessão
Além disso, o SessionRepositoryFilter cria um cookie com o nome SESSION que é HttpOnly e seguro. Este cookie contém o ID da sessão, que é um valor codificado em Base64.
Para personalizar o nome ou as propriedades do cookie, teremos que criar um bean Spring do tipo DefaultCookieSerializer.
Por exemplo, aqui estamos desabilitando o httponly propriedade do cookie:
@Bean
public DefaultCookieSerializer customCookieSerializer(){
DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
cookieSerializer.setUseHttpOnlyCookie(false);
return cookieSerializer;
}
7. Detalhes da sessão armazenados no MongoDB
Vamos consultar nossa coleção de sessões usando o seguinte comando em nosso console do MongoDB:
db.sessions.findOne()
Como resultado, obteremos um documento BSON semelhante a:
{
"_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=")
}
O _id é um UUID que será codificado em Base64 pelo DefaultCookieSerializer e definido como um valor na SESSION biscoito. Além disso, observe que o attr O atributo contém o valor real do nosso contador.