Spring-session — это очень крутой новый проект, цель которого — предоставить более простой способ управления сеансами в веб-приложениях на основе Java. Одной из особенностей, которые я недавно исследовал в spring-session, было то, что он поддерживает экстернализацию состояния сеанса без необходимости работать с внутренними компонентами определенных веб-контейнеров, таких как Tomcat или Jetty.
Для тестирования весенней сессии я использовал приложение типа корзины для покупок (доступно здесь ), которое интенсивно использует сессию, сохраняя элементы, добавленные в корзину, в качестве атрибута сессии, как видно из этих снимков экрана:
Рассмотрим сначала сценарий без весенней сессии. Вот как я выставил свое приложение:
Я использую nginx для балансировки нагрузки между двумя экземплярами этого приложения. Эту настройку очень легко запустить с помощью Spring-загрузки, я запустил два экземпляра приложения, используя два разных серверных порта, таким образом:
mvn spring-boot:run -Dserver.port=8080 mvn spring-boot:run -Dserver.port=8082
и это мой nginx.conf для балансировки нагрузки между этими двумя экземплярами:
events { worker_connections 1024; } http { upstream sessionApp { server localhost:8080; server localhost:8082; } server { listen 80; location / { proxy_pass http://sessionApp; } } }
Я отображаю номер порта приложения в нижнем колонтитуле, чтобы показать, какой экземпляр обрабатывает запрос.
Если бы я ничего не делал для перемещения состояния сеанса из приложения, то поведение приложения было бы неустойчивым, поскольку сеанс, установленный в одном экземпляре приложения, не был бы распознан другим экземпляром, особенно если Tomcat получает сеанс Если он не распознает, то поведение заключается в создании нового сеанса.
Введение весенней сессии в приложение
Существуют специфические для контейнера способы представления внешних хранилищ сеансов. Один из примеров здесь , где Redis настроен как хранилище для Tomcat. Pivotal Gemfire предоставляет модуль для экстернализации состояния сеанса Tomcat .
Преимущество использования Spring-сеанса в том, что он вообще не зависит от контейнера — поддержание состояния сеанса становится проблемой приложения. Инструкции по настройке приложения для использования сеанса Spring подробно изложены на сайте сеанса Spring , просто для краткого изложения того, как я сконфигурировал свое приложение Spring Boot, это в первую очередь зависимости, которые я извлек:
<dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session</artifactId> <version>1.0.0.BUILD-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> <version>1.0.0.BUILD-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>1.4.1.RELEASE</version> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.4.1</version> </dependency>
и моя конфигурация для использования Spring-сессии для поддержки сеанса, обратите внимание на специфичный для Spring Boot FilterRegistrationBean, который используется для регистрации фильтра репозитория сеанса :
import org.springframework.boot.context.embedded.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; import org.springframework.session.web.http.SessionRepositoryFilter; import org.springframework.web.filter.DelegatingFilterProxy; import java.util.Arrays; @Configuration @EnableRedisHttpSession public class SessionRepositoryConfig { @Bean @Order(value = 0) public FilterRegistrationBean sessionRepositoryFilterRegistration(SessionRepositoryFilter springSessionRepositoryFilter) { FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); filterRegistrationBean.setFilter(new DelegatingFilterProxy(springSessionRepositoryFilter)); filterRegistrationBean.setUrlPatterns(Arrays.asList("/*")); return filterRegistrationBean; } @Bean public JedisConnectionFactory connectionFactory() { return new JedisConnectionFactory(); } }
И это все! волшебным образом теперь вся сессия обрабатывается Spring-сессией и аккуратно выводится на Redis.
Если бы мне пришлось повторить мою предыдущую конфигурацию использования nginx для балансировки нагрузки двух разных приложений Spring-Boot с использованием общего хранилища Redis, приложение просто работает независимо от экземпляра, обрабатывающего запрос. Я с нетерпением жду дальнейших улучшений этого превосходного нового проекта.
Пример приложения, использующего Spring-сессию, доступен здесь : https://github.com/bijukunjummen/shopping-cart-cf-app.git.