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 implement
Serializable. 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
.
# 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