[JAVA] Introduction to Ratpack (8)-Session

Ratpack introductory series

  1. Introduction to Ratpack (1) --What is Ratpack
  2. Introduction to Ratpack (2) --Architecture
  3. Introduction to Ratpack (3) --Hello world detailed explanation
  4. Introduction to Ratpack (4) --Routing & Static Content
  5. Introduction to Ratpack (5) --Json & Registry
  6. Introduction to Ratpack (6) --Promise
  7. Introduction to Ratpack (7) --Guice & Spring
  8. Introduction to Ratpack (8) --Session
  9. Introduction to Ratpack (9) --Thymeleaf

session

Ratpack does not provide sessions by default. To use so-called Sticky sessions, you need the ratpack-session module. You also need the ratpack-session-redis module to enable session support with Redis.

build.gradle


dependencies {
    compile "io.ratpack:ratpack-session:1.5.1"
}

You need to register the module. As mentioned earlier, Ratpack provides extension modules as Guice modules.

Function<Registry, Registry> registry = ratpack.guice.Guice.registry( bindings -> {
    bindings.module( SessionModule.class );
} );

Get the Session class that manages the session from Registry and manipulate the session data. The handler's Context inherits from Registry, so you can get the session by calling the Context.get () method.

Session session = context.get( Session.class );

The session key can be a String or the class itself. However, the String key requires a cast to get the data, and if you use a class you will not be able to register the same class. The best way is to use the SessionKey <T> class.

public static final SessionKey<String> KEY = SessionKey.of( "KEY_NAME", String.class );

Data can be exchanged safely by specifying the key name and type.

Use get (SessionKey) and set (SessionKey <T>, T) to get and set the data, respectively. ** These operations are treated as blocking operations **. Therefore, these methods return Promise and ʻOperation` instead of returning values directly. This is because how session information is stored depends on the implementation, and it is assumed that it will be stored in KVS etc. outside the server instead of inside.

Below is an example of saving the number and time of user visits to your site.

Session session = ctx.get( Session.class );

session.get( countKey ).flatRight( v -> session.get( lastVisit ) ).then( pair -> {

    int count = pair.left.orElse( 0 );

    String response = count == 0
                      ? "This is the first visit."
                      : "You have visited " + count + " times.\n" +
                        "Last visit: " + pair.right.get().format( DateTimeFormatter.ISO_LOCAL_DATE_TIME );

    session.set( countKey, count + 1 )
           .next( session.set( lastVisit, LocalDateTime.now() ) )
           .then( () -> {
               ctx.render( response );
           } );
} );

The type returned by get () is Promise <Optional <T >>. Since it wraps in ʻOptional, there is no need to check for null like Servlet. As you can see, when I try to get multiple values, the Promises overlap and the code gets dirty. You can get the values in bulk with the getData ()method. In addition, the stored data is serialized by Java's serialization function. Therefore, you need to implementSerializable. Serialization is done by SessionSerializer. You can change the serialization method by providing your own implementation for Registry`.

ClientSideSessionModule

The default implementation of ratpack-session uses an in-memory cache that leverages Guava's cache. On the other hand, there is also a module that uses a client-side session that encrypts data in a cookie and stores the data by using ClientSideSessionModule.

By default, the information is not encrypted. You must always specify the key.

ratpack-session-redis

A ratpack-session-redis module is provided to store session information in Redis.

build.gradle


dependencies {
    compile "io.ratpack:ratpack-session-redis:1.5.1"
}

Set the module.

RedisSessionModule redisModule = new RedisSessionModule();
redisModule.configure( config -> {
    config.setHost( "localhost" );
    config.setPort( 6379 );
    config.setPassword( null );
} );

Function<Registry, Registry> registry = ratpack.guice.Guice.registry( bindings -> {
    bindings.module( SessionModule.class );
    bindings.module( redisModule );
} );

The RedisSessionModule must be registered ** after ** of the SessionModule. Ratpack gives priority to classes registered later. If you reverse the order, the implementation of Session will be for Sticky session instead of Redis. The host and port are set programmatically here, but you can set them from ConfigSource.

The usage itself is the same as a normal ratpack-session. Once set, you won't even notice that your backend is Redis.

Data is stored on the Redis server using the session ID as the key. UUID is used as the session ID by default. ID generation is done via SessionIdGenerator and the implementation can be switched from Registry.

キャプチャ2.png

# redis-cli
127.0.0.1:6379> keys *
1) "036f9723-3df8-e018-9abe-2db2bca5f6f6"
127.0.0.1:6379> get 036f9723-3df8-e018-9abe-2db2bca5f6f6
"\xac\xed\x00\x05sr\x006ratpack.session.internal.DefaultSession$SerializedForm\x00\x00\x00\x00\x00\x00\x00\x02\x0c\x00\x00xpw\xd3\x00\x01\x00\x02\x01\x00\x05COUNT\x01\x00\x11java.lang.Integer\x00\x00\x00
Q\xac\xed\x00\x05sr\x00\x11java.lang.Integer\x12\xe2\xa0\xa4\xf7\x81\x878\x02\x00\x01I\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\x00\x02\x01\x00\nLAST_V
ISIT\x01\x00\x17java.time.LocalDateTime\x00\x00\x003\xac\xed\x00\x05sr\x00\rjava.time.Ser\x95]\x84\xba\x1b\"H\xb2\x0c\x00\x00xpw\x0e\x05\x00\x00\a\xe2\x02\t\r8!\x1a\xe1\xb6\xc0xx"
127.0.0.1:6379>

By the way, I use Lettuce to communicate with Redis (always mistaken for cabbage).

Recommended Posts

Introduction to Ratpack (8)-Session
Introduction to Ratpack (6) --Promise
Introduction to Ratpack (9) --Thymeleaf
Introduction to Ratpack (2)-Architecture
Introduction to Ratpack (5) --Json & Registry
Introduction to Ratpack (7) --Guice & Spring
Introduction to Ratpack (1) --What is Ratpack?
Introduction to Ruby 2
Introduction to SWING
Introduction to web3j
Introduction to Micronaut 1 ~ Introduction ~
[Java] Introduction to Java
Introduction to migration
Introduction to java
Introduction to Doma
Introduction to Ratpack (Extra Edition) --Using Sentry
Introduction to Ratpack (3) --hello world detailed explanation
Introduction to Ratpack (Extra Edition) --Ratpack written in Kotlin
Introduction to JAR files
Introduction to RSpec 1. Test, RSpec
Introduction to bit operation
Introduction to PlayFramework 2.7 ① Overview
Introduction to Android Layout
Introduction to design patterns (introduction)
Introduction to Practical Programming
Introduction to javadoc command
Introduction to jar command
Introduction to lambda expression
Introduction to java command
Introduction to RSpec 2. RSpec setup
Introduction to Keycloak development
Introduction to javac command
Introduction to RSpec 5. Controller specs
Introduction to RSpec 6. System specifications
Introduction to Android application development
Introduction to RSpec 3. Model specs
Introduction to Metabase ~ Environment Construction ~
(Dot installation) Introduction to Java8_Impression
Introduction to Design Patterns (Composite)
Introduction to Micronaut 2 ~ Unit test ~
Introduction to JUnit (study memo)
Introduction to Spring Boot ① ~ DI ~
Introduction to design patterns (Flyweight)
[Java] Introduction to lambda expressions
Introduction to Spring Boot ② ~ AOP ~
Introduction to Apache Beam (2) ~ ParDo ~
[Ruby] Introduction to Ruby Error statement
Introduction to EHRbase 2-REST API
Introduction to design patterns Prototype
GitHub Actions Introduction to self-made actions
[Java] Introduction to Stream API
Introduction to Design Patterns (Iterator)
Introduction to Spring Boot Part 1
XVim2 introduction memo to Xcode12.3
Introduction to RSpec-Everyday Rails Summary-
Introduction to Design Patterns (Strategy)
[Introduction to rock-paper-scissors games] Java
Introduction to Linux Container / Docker (Part 1)
Introduction to swift practice output Chapter5
[Introduction to Java] About lambda expressions
Introduction to algorithms in java-cumulative sum