SpringBoot中结合SpringSession的原理

这篇文章主要讲解的是在SpringBoot项目中,SpringSession的运行原理,同时可以帮助大家更好的对SpringSession进行自定义使用。

一、SpringSession的使用:

1.导入依赖:

我使用的是maven项目,而项目中我们使用的是redis存储session,所以导入的依赖为:

    <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
            <version>1.3.1.RELEASE</version>
    </dependency>

因为spring-session-data-redis里自动引入了spring-data-redis依赖,所以只需要引入这一个就可以连接到redis。

如果用的其他数据源,引入相对应的依赖即可。

2.开启springsession

@SpringBootApplication
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800)
public class RedisSessionApplication{
    public static void main(String[] args) {
        SpringApplication.run(RedisSessionApplication.class,args);
    }
}

其中maxInactiveIntervalInSeconds设置的是session的过期时间,这里设置的是30分钟。

另外有的人可能会担心session的清除问题,经过测试springsession的过期时间策略是框架自己实现的,并没有用到redis本身的存储过期时间,当session过期后springsession会调用redis的删除方法将对应的session删除。

3.配置application.yml文件

其实在这里,如果只是做demo的话是不用配置的,当项目启动的时候他会默认访问本地的6379端口。当然需要配置redis集群或者哨兵模式,或者修改默认配置,则需要详细配置。这里不再阐述,有兴趣的朋友可以参考我写的关于配置redis的文章。

 

以上准备工作就算完成了,启动项目即可。

二、SpringSession的运行原理

1.配置加载

跟本文相关的主要两个配置类RedisHttpSessionConfiguration和SpringHttpSessionConfiguration

(1)以下是RedisHttpSessionConfiguration类中的一些主要配置:

    @Bean
	public RedisOperationsSessionRepository sessionRepository(
			@Qualifier("sessionRedisTemplate") RedisOperations<Object, Object> sessionRedisTemplate,
			ApplicationEventPublisher applicationEventPublisher) {
		RedisOperationsSessionRepository sessionRepository = new RedisOperationsSessionRepository(
				sessionRedisTemplate);
		sessionRepository.setApplicationEventPublisher(applicationEventPublisher);
		sessionRepository
				.setDefaultMaxInactiveInterval(this.maxInactiveIntervalInSeconds);
		if (this.defaultRedisSerializer != null) {
			sessionRepository.setDefaultSerializer(this.defaultRedisSerializer);
		}

		String redisNamespace = getRedisNamespace();
		if (StringUtils.hasText(redisNamespace)) {
			sessionRepository.setRedisKeyNamespace(redisNamespace);
		}

		sessionRepository.setRedisFlushMode(this.redisFlushMode);
		return sessionRepository;
	}

主要就是将操纵redis的redisTemplate放入sessionRepository中,而sessionRepository中统一规定了获取session的方法名。即可通过sessionRepository从redis里获取session。

(2)以下是SpringHttpSessionConfiguration中的一些主要配置:

@Bean
	public <S extends ExpiringSession> SessionRepositoryFilter<? extends ExpiringSession> springSessionRepositoryFilter(
			SessionRepository<S> sessionRepository) {
		SessionRepositoryFilter<S> sessionRepositoryFilter = new SessionRepositoryFilter<S>(
				sessionRepository);
		sessionRepositoryFilter.setServletContext(this.servletContext);
		if (this.httpSessionStrategy instanceof MultiHttpSessionStrategy) {
			sessionRepositoryFilter.setHttpSessionStrategy(
					(MultiHttpSessionStrategy) this.httpSessionStrategy);
		}
		else {
			sessionRepositoryFilter.setHttpSessionStrategy(this.httpSessionStrategy);
		}
		return sessionRepositoryFilter;
	}

这里生成了一个SessionRepositoryFilter过滤器,并将上一个配置类中的sessionRepository放入到这个过滤器中。所以这个过滤器就是替换服务器session的关键。

2.执行过滤器

当有http请求发送过来后,将会执行上文中的过滤器。

主要执行的方法:

@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);

		HttpServletRequest strategyRequest = this.httpSessionStrategy
				.wrapRequest(wrappedRequest, wrappedResponse);
		HttpServletResponse strategyResponse = this.httpSessionStrategy
				.wrapResponse(wrappedRequest, wrappedResponse);

		try {
			filterChain.doFilter(strategyRequest, strategyResponse);
		}
		finally {
			wrappedRequest.commitSession();
		}
	}

这个doFilterInternal方法重写的是OncePerRequestFilter抽象类的方法,而OncePerRequestFilter实现的是Filter接口,在doFilter方法中会调用doFilterInternal。

这里先是将sessionRepository放入到了request的attribute中,然后又用框架中的类SessionRepositoryRequestWrapper对request进行了封装。这个类里有利用sessionRepository创建,获取,删除session的方法。

同时对response也进行了封装,之后再讲封装过得request和response传给下一个过滤器。

至此session的替换就完成了。

3.其他的设置

在配置类里有很多其他的方法,可以让使用者自定义一些策略,比如cookie的序列化策略,session生成的策略等等。只需要手动写一个配置类,创建对应的bean即可,下面是其中一部分可自定的部分。

@Autowired(required = false)
	public void setServletContext(ServletContext servletContext) {
		this.servletContext = servletContext;
	}

	@Autowired(required = false)
	public void setCookieSerializer(CookieSerializer cookieSerializer) {
		this.cookieSerializer = cookieSerializer;
	}

	@Autowired(required = false)
	public void setHttpSessionStrategy(HttpSessionStrategy httpSessionStrategy) {
		this.httpSessionStrategy = httpSessionStrategy;
	}

	@Autowired(required = false)
	public void setHttpSessionListeners(List<HttpSessionListener> listeners) {
		this.httpSessionListeners = listeners;
	}

}
以上就是关于springsession原理的介绍,欢迎各位大佬指点

猜你喜欢

转载自blog.csdn.net/apricotCandy/article/details/84341894