Try implementing a WebFlux session

We will continue to talk about WebFlux. This time, I will introduce how to use Session in WebFlux. In addition, here is an example of in-memory implementation that does not use Redis, which is the minimum configuration.

Sample environment

Project build configuration

In the case of Maven, [Basic build configuration](https://qiita.com/kilvis/items/fb18be963da6cac03ee9#%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7 Add the following dependency to% E3% 82% AF% E3% 83% 88% E3% 81% AE% E4% BD% 9C% E6% 88% 90).

pom.xml


~ Omitted ~
<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-core</artifactId>
</dependency>

For Gradle, please refer to the following dependencies.

build.gradle


~ Omitted ~
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-webflux'
    implementation 'org.springframework.session:spring-session-core'
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
}

Settings for using the session

First, set the DI of Session Repository to use the session with WebFlux.

InMemorySessionConfig.java


@Configuration
@EnableSpringWebSession    // 1
public class InMemorySessionConfig {

  @Bean
  public ReactiveSessionRepository reactiveSessionRepository() {

    ReactiveMapSessionRepository repository =
        new ReactiveMapSessionRepository(new ConcurrentHashMap<>());    // 2

    repository.setDefaultMaxInactiveInterval(60 * 30); // 3

    return repository;
  }

}

There are 3 points in the comments

  1. Enable WebSession by annotating @EnableSpringWebSession
  2. Bean registration of ReactiveSessionRepository
  3. Specify the session expiration date (seconds) (60 seconds * 10 = 10 minutes in the example)

Try using a session

Let's see an example of implementing a simple counter using a session.

CountController.java



@RestController
public class CountController {

  @GetMapping("count/{increments}")
  public Mono<Integer> count(@PathVariable Integer increments, WebSession webSession) {    // 1
    return Mono.fromSupplier(
        () -> {
          Integer total =
              Optional.ofNullable((Integer) webSession.getAttribute("count"))
                  .map(current -> current + increments)
                  .orElse(0);    // 2
          webSession.getAttributes().put("count", total);    // 3
          return total;
        });
  }
}

Use WebSession to access the session with WebFlux. However, field injection like HttpSession of Servlet cannot be performed, so the implementation is as follows.

  1. Specify WebSession as the method argument of the endpoint
  2. Take the current count from the session, add increments if there is one, and set the initial value 0 to total if not
  3. Pack the total calculation result into the session

With the above implementation localhost:8080/count/1 You can check the operation of counting up by 1 each time you access to. Also, if there is no access for 10 minutes, it will return to the initial value of 0.

It's a little difficult to use ...

If you want to use the session value, you have to get WebSession in Controller and pass the value to subsequent processing (Service etc.)

--Define SessionScope beans like Servlet implementation, --DI HttpSession in any Component field or constructor,

You need to be careful when designing the Component that handles the session, because you cannot use it like this.

(In the first place, SessionScope and RequestScope depend on ThreadLocal, so it may be unavoidable that WebFlux can not handle it in the same way ^ ^;)

reference

https://docs.spring.io/spring-session/docs/current/reference/html5/#websession → Officially, how to link Redis and WebSession is also listed, so please refer to it.

Recommended Posts

Try implementing a WebFlux session
Try implementing a WebFlux filter
Try sending a notification.
Try implementing Yubaba in Kinx
Try the Spring WebFlux tutorial
Try implementing Android Hilt in Java
Try implementing asynchronous processing in Azure
Try implementing recaptcha with Jetty embedded.
Try Spring WebFlux (mainly Router Functions)
Try to create a server-client app
Try to make a peepable iterator