Spring 시리즈. @ EnableRedisHttpSession 원리 간략 분석
세 션 이란 무엇 인가
여기 서 세 션 의 개념 을 보급 합 니 다. 세 션 은 서버 측의 key - value 데이터 구조 로 사용자 와 쿠키 에 의 해 자주 결합 되 어 사용자 의 로그 인 메 시 지 를 유지 합 니 다.클 라 이언 트 가 서버 를 처음 방문 할 때 서버 는 sessionid 에 응답 하고 로 컬 쿠키 에 저장 합 니 다. 다음 방문 은 쿠키 의 sessionid 를 요청 헤더 에 넣 고 서버 에 접근 합 니 다. 이 sessionid 를 통 해 해당 하 는 데 이 터 를 찾 지 못 하면 서버 는 새로운 sessionid 를 만 들 고 클 라 이언 트 에 응답 합 니 다.
분산 세 션 솔 루 션
마지막 방안 은 본문 이 소개 하고 자 하 는 중점 이다.
Spring Session 사용법
의존 도 를 높이다
org.springframework.session
spring-session-data-redis
org.springframework.session
spring-session
주석 추가 @ EnableRedisHttpSession
@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 86400*30)
public class RedisSessionConfig {
}
max InactiveIntervalInSeconds: Session 실효 시간 을 설정 하고 Redis Session 을 사용 하면 원래 Spring Boot 의 server. session. timeout 속성 이 유효 하지 않 습 니 다.
위의 설정 을 통 해 Session 호출 은 자동 으로 Redis 로 접근 합 니 다.또 세 션 공유 의 목적 을 달성 하려 면 다른 시스템 에서 같은 설정 을 하면 된다.
4. Spring Session Redis 의 원리 에 대한 간략 분석
위의 설정 을 보면 Redis Session 을 여 는 '비밀' 이 @ EnableRedisHttpSession 이라는 주석 에 있 음 을 알 수 있 습 니 다.@ EnableRedisHttpSession 의 원본 코드 열기:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(RedisHttpSessionConfiguration.class)
@Configuration
public @interface EnableRedisHttpSession {
//Session , , 30
int maxInactiveIntervalInSeconds() default MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS;
// key namespace, spring:session, redis, namespace, Session
String redisNamespace() default RedisOperationsSessionRepository.DEFAULT_NAMESPACE;
// Redis Session , ON_SAVE , Response Session Redis
// IMMEDIATE , Session Redis
RedisFlushMode redisFlushMode() default RedisFlushMode.ON_SAVE;
// Session 。
String cleanupCron() default RedisHttpSessionConfiguration.DEFAULT_CLEANUP_CRON;
}
이 주해 의 주요 역할 은 Session Repository Filter 를 등록 하 는 것 입 니 다. 이 Filter 는 모든 요청 을 차단 하고 Session 을 조작 합 니 다. 구체 적 인 조작 세부 사항 은 뒤에서 설명 합 니 다. 이 주해 의 역할 은 Session Repository Filter 를 등록 하면 됩 니 다.Session Repository Filter 를 주입 하 는 코드 는 RedisHttpSession Configuration 클래스 에 있 습 니 다.
@Configuration
@EnableScheduling
public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguration
implements BeanClassLoaderAware, EmbeddedValueResolverAware, ImportAware,
SchedulingConfigurer {
...
}
RedisHttpSession Configuration 은 SpringHttpSession Configuration 을 계승 하고 SpringHttpSession Configuration 에는 Session Repository Filter 가 등록 되 어 있 습 니 다.다음 코드 참조.
@Configuration
public class SpringHttpSessionConfiguration implements ApplicationContextAware {
...
@Bean
public SessionRepositoryFilter extends Session> springSessionRepositoryFilter(
SessionRepository sessionRepository) {
SessionRepositoryFilter sessionRepositoryFilter = new SessionRepositoryFilter<>(
sessionRepository);
sessionRepositoryFilter.setServletContext(this.servletContext);
sessionRepositoryFilter.setHttpSessionIdResolver(this.httpSessionIdResolver);
return sessionRepositoryFilter;
}
...
}
Session Repository Filter 를 등록 할 때 Session Repository 인자 가 필요 한 것 을 발 견 했 습 니 다. 이 인 자 는 RedisHttp Session Configuration 에 주입 되 었 습 니 다.
@Configuration
@EnableScheduling
public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguration
implements BeanClassLoaderAware, EmbeddedValueResolverAware, ImportAware,
SchedulingConfigurer {
...
@Bean
public RedisOperationsSessionRepository sessionRepository() {
RedisTemplate
들 어 오 라 고 요청 할 때 차단 기 는 먼저 request 와 response 를 차단 한 다음 에 이 두 대상 을 Spring 내부 의 포장 류 Session Repository Request Wrapper 와 Session Repository Response Wrapper 대상 으로 변환 합 니 다.Session Repository Request Wrapper 류 는 원생 의 getSession 방법 을 다시 썼 습 니 다.코드 는 다음 과 같 습 니 다:
@Override
public HttpSessionWrapper getSession(boolean create) {
// request getAttribue CURRENT_SESSION ,
HttpSessionWrapper currentSession = getCurrentSession();
if (currentSession != null) {
return currentSession;
}
// SESSION cookie, sessionRepository SESSIONID Redis Session
S requestedSession = getRequestedSession();
if (requestedSession != null) {
if (getAttribute(INVALID_SESSION_ID_ATTR) == null) {
requestedSession.setLastAccessedTime(Instant.now());
this.requestedSessionIdValid = true;
currentSession = new HttpSessionWrapper(requestedSession, getServletContext());
currentSession.setNew(false);
// Session request
setCurrentSession(currentSession);
// Session
return currentSession;
}
}
else {
// This is an invalid session id. No need to ask again if
// request.getSession is invoked for the duration of this request
if (SESSION_LOGGER.isDebugEnabled()) {
SESSION_LOGGER.debug(
"No session found by id: Caching result for getSession(false) for this HttpServletRequest.");
}
setAttribute(INVALID_SESSION_ID_ATTR, "true");
}
// Session null
if (!create) {
return null;
}
if (SESSION_LOGGER.isDebugEnabled()) {
SESSION_LOGGER.debug(
"A new session was created. To help you troubleshoot where the session was created we provided a StackTrace (this is not an error). You can prevent this from appearing by disabling DEBUG logging for "
+ SESSION_LOGGER_NAME,
new RuntimeException(
"For debugging purposes only (not an error)"));
}
// sessionRepository RedisSession , ,
//@EnableRedisHttpSession redisFlushMode IMMEDIATE ,
// RedisSession Redis 。 。
S session = SessionRepositoryFilter.this.sessionRepository.createSession();
session.setLastAccessedTime(Instant.now());
currentSession = new HttpSessionWrapper(session, getServletContext());
setCurrentSession(currentSession);
return currentSession;
}
Session Repository RequestWrapper 대상 의 getSession 방법 을 호출 하여 Session 을 가 져 올 때 현재 요청 한 속성 에서 먼저 찾 습 니 다. CURRENTSESSION 속성, 받 을 수 있 으 면 바로 되 돌려 줍 니 다. 이렇게 조작 하면 Redis 조작 을 감소 하고 성능 을 향상 시 킬 수 있 습 니 다.
지금까지 redis Flushmode 가 ON 으로 설정 되면세 이브 모드 의 경우 세 션 정보 가 레 디 스에 저장 되 지 않 았 다 면 이 동기 화 작업 은 도대체 어디에서 실 행 된 것 일 까?우 리 는 Session Repository Filter 의 doFilter Internal 방법 에 마지막 으로 finally 코드 블록 이 있 는 것 을 발견 했다. 이 코드 블록 의 기능 은 Session 을 Redis 에 동기 화 하 는 것 이다.
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
request.setAttribute(SESSION_REPOSITORY_ATTR, this.sessionRepository);
SessionRepositoryRequestWrapper wrappedRequest = new SessionRepositoryRequestWrapper(
request, response, this.servletContext);
SessionRepositoryResponseWrapper wrappedResponse = new SessionRepositoryResponseWrapper(
wrappedRequest, response);
try {
filterChain.doFilter(wrappedRequest, wrappedResponse);
}
finally {
// Session Redis, SESSIONID cookie ,
//SESSION
wrappedRequest.commitSession();
}
}
총결산
주요 핵심 유형 은 다음 과 같다.
원리 요약:
요청 이 들 어 왔 을 때, Session Repository Filter 는 요청 을 먼저 차단 하고, request 와 Response 대상 을 Session Repository Request Wrapper 와 Session Repository Response Wrapper 로 변환 합 니 다.추 후 request 의 getSession 방법 을 처음 호출 할 때 Session Repository RequestWrapper 의 getSession 방법 으로 호출 됩 니 다.이 방법의 논 리 는 먼저 request 의 속성 에서 찾 는 것 입 니 다. 찾 지 못 하면;키 값 이 "SESSION" 인 쿠키 를 찾 습 니 다. 이 쿠키 를 통 해 sessionId 를 가 져 와 redis 에서 찾 습 니 다. 찾 을 수 없 으 면 RedisSession 대상 을 직접 만 들 고 Redis 에 동기 화 합 니 다. (동기 화 시 기 는 설정 에 따라)
남 겨 진 문제
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.