Optimize session resolution in SessionRepositoryFilter

This commit optimizes SessionRepositoryFilter to avoid multiple retrievals of session from SessionRepository.

Closes gh-1048
This commit is contained in:
Vedran Pavic
2018-04-13 16:27:33 +02:00
parent 538712d162
commit 751375338c
2 changed files with 51 additions and 30 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2017 the original author or authors.
* Copyright 2014-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@ package org.springframework.session.web.http;
import java.io.IOException;
import java.time.Instant;
import java.util.List;
import javax.servlet.FilterChain;
import javax.servlet.ServletContext;
@@ -196,14 +197,18 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
private final class SessionRepositoryRequestWrapper
extends HttpServletRequestWrapper {
private Boolean requestedSessionIdValid;
private boolean requestedSessionInvalidated;
private final HttpServletResponse response;
private final ServletContext servletContext;
private S requestedSession;
private boolean requestedSessionCached;
private Boolean requestedSessionIdValid;
private boolean requestedSessionInvalidated;
private SessionRepositoryRequestWrapper(HttpServletRequest request,
HttpServletResponse response, ServletContext servletContext) {
super(request);
@@ -225,7 +230,7 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
}
else {
S session = wrappedSession.getSession();
SessionRepositoryFilter.this.sessionRepository.save(session);
saveSession(session);
String sessionId = session.getId();
if (!isRequestedSessionIdValid()
|| !sessionId.equals(getRequestedSessionId())) {
@@ -265,9 +270,11 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
@Override
public boolean isRequestedSessionIdValid() {
if (this.requestedSessionIdValid == null) {
String sessionId = getRequestedSessionId();
S session = sessionId == null ? null : getSession(sessionId);
return isRequestedSessionIdValid(session);
S requestedSession = getRequestedSession();
if (requestedSession != null) {
requestedSession.setLastAccessedTime(Instant.now());
}
return isRequestedSessionIdValid(requestedSession);
}
return this.requestedSessionIdValid;
@@ -284,28 +291,18 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
return getCurrentSession() == null && this.requestedSessionInvalidated;
}
private S getSession(String sessionId) {
S session = SessionRepositoryFilter.this.sessionRepository
.findById(sessionId);
if (session == null) {
return null;
}
session.setLastAccessedTime(Instant.now());
return session;
}
@Override
public HttpSessionWrapper getSession(boolean create) {
HttpSessionWrapper currentSession = getCurrentSession();
if (currentSession != null) {
return currentSession;
}
String requestedSessionId = getRequestedSessionId();
if (requestedSessionId != null) {
S requestedSession = getRequestedSession();
if (requestedSession != null) {
if (getAttribute(INVALID_SESSION_ID_ATTR) == null) {
S session = getSession(requestedSessionId);
requestedSession.setLastAccessedTime(Instant.now());
this.requestedSessionIdValid = true;
currentSession = new HttpSessionWrapper(session, getServletContext());
currentSession = new HttpSessionWrapper(requestedSession, getServletContext());
currentSession.setNew(false);
setCurrentSession(currentSession);
return currentSession;
@@ -353,11 +350,31 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
@Override
public String getRequestedSessionId() {
return SessionRepositoryFilter.this.httpSessionIdResolver
.resolveSessionIds(this).stream()
.filter(sessionId -> SessionRepositoryFilter.this.sessionRepository
.findById(sessionId) != null)
.findFirst().orElse(null);
S requestedSession = getRequestedSession();
return (requestedSession != null ? requestedSession.getId() : null);
}
private S getRequestedSession() {
if (!this.requestedSessionCached) {
List<String> sessionIds = SessionRepositoryFilter.this.httpSessionIdResolver
.resolveSessionIds(this);
for (String sessionId : sessionIds) {
S session = SessionRepositoryFilter.this.sessionRepository
.findById(sessionId);
if (session != null) {
this.requestedSession = session;
break;
}
}
this.requestedSessionCached = true;
}
return this.requestedSession;
}
private void saveSession(S session) {
this.requestedSessionCached = false;
this.requestedSession = null;
SessionRepositoryFilter.this.sessionRepository.save(session);
}
/**

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2017 the original author or authors.
* Copyright 2014-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -49,6 +49,7 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
/**
@@ -82,6 +83,9 @@ public class EnableSpringHttpSessionCustomCookieSerializerTests {
@Before
public void setup() {
this.chain = new MockFilterChain();
reset(this.sessionRepository);
reset(this.cookieSerializer);
}
@Test
@@ -99,7 +103,7 @@ public class EnableSpringHttpSessionCustomCookieSerializerTests {
@Test
public void usesWrite() throws Exception {
given(this.sessionRepository.findById(anyString())).willReturn(new MapSession());
given(this.sessionRepository.createSession()).willReturn(new MapSession());
this.sessionRepositoryFilter.doFilter(this.request, this.response,
new MockFilterChain() {