Преамбула
Если вы планируете использовать ehCache в качестве первой проверки реализации управления сеансом, если вы не можете случайно использовать уже предоставленную и, вероятно, более подходящую реализацию сеанса. Если вы используете веб-контейнер или полноценный jee-сервер, вам действительно стоит попробовать это сначала
Почему
Хорошо. Вы уверены, что не сделаете это правильным легким способом. Вот несколько советов, почему вы можете использовать ehCache для сессий
- Ваш сервис не является частью jee-сервера / веб-контейнера.
- Ваш сервис не имеет состояния, но время от времени вам нужны состояния (код структуры).
- Вы не можете различать вызовы из-за того, что между вами и различимым клиентом находится прокси-сервер, например, вы являетесь своего рода промежуточным ПО для службы / службы, которое не предоставляет различимые данные по умолчанию, но использует такие параметры, как userId или sessionId, условно, но не конститутивно .
- Вы просто не RTFM и хотите сделать это по-своему.
Для 1, пожалуйста, проверьте, если веб-контейнер, как причал, вариант. Вы, конечно, используете веб-доступ ко всему сеансу, что бы вам не показалось.
Для 2, пожалуйста, проверьте, если Apache Shiro не будет делать то, что вы хотите. Если нет, ehCache может быть вашим другом.
На 3 ... добро пожаловать в клуб.
Для 4 ... ну, я думаю, что если вы не читали руководство, вы тоже не прочтете.
Как
Если вы хотите реализовать управление сеансами с помощью ehCache, убедитесь, что ваши данные сериализуемы. Это уменьшит проблемы и позволит вам использовать конфиденциальные функции ehCache. а именно сохранение на диск, кеширование узлов, восстановление после этого и т. д.
Do not использовать кеш для каждой сессии, но one cache для всех сессий. sessionId
- это ключ в вашем кеше, а значения равны Map
. Не забывайте о параллелизме (вспомните ajax-вызовы). Лучше всего использовать ConcurrentHashMap
из java.util.concurrent
. Но, может быть, вы доктор Хайнц М. Кабуц и найдете еще более клёвый способ сделать это.
Мне показалось очень полезным использовать размер, а не количество элементов для хранения. Вы можете не знать, какие данные / объекты хранятся позже. Не забудьте установить постоянную стратегию. Я использовал хранение во временную папку здесь.
<?xml version="1.0" encoding="UTF-8"?>
<ehcache
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd"
updateCheck="true"
monitoring="autodetect"
dynamicConfig="true">
<diskStore path="java.io.tmpdir"/>
<cache name="vocCache"
eternal="false"
maxElementsInMemory="100MB"
maxElementsOnDisk="1GB"
timeToIdleSeconds="3600"
timeToLiveSeconds="0"
memoryStoreEvictionPolicy="LRU"
diskExpiryThreadIntervalSeconds="60">
<persistence strategy="localTempSwap" />
</cache>
Поскольку мы хотим реализовать менеджер сеансов, мы не беспокоимся о timeToLiveSeconds
. Тайм-аут сеансов после определенного времени простоя. Таким образом, мы не ограничиваем элемент максимальным значением ttl, а используем timeToIdleSeconds
, чтобы позволить элементу истечь.
Не беспокойтесь о timeToIdleSeconds
и timeToLiveSeconds
, потому что вы можете установить определенные значения для элементов, которые будут добавлены позже.
Выселение
Одна заметка о времени истечения. Элемент в памяти никогда не будет выселен из-за настроенного времени. Память будет накапливаться до тех пор, пока не будет достигнуто указанное ограничение памяти. Поэтому, если вы определите 100 элементов, если будет добавлен элемент 101, memoryStoreEvictionPolicy
сделает ставку, и один элемент - в этой конфигурации - будет сброшен на диск (ehCache 2.2). Для дискового хранилища будет проверка потока на время истечения (diskExpiryThreadIntervalSeconds
). См. документацию .
Поэтому вы должны проверить извлеченный элемент из кэша, используя isExpired()
, чтобы убедиться, что он не истек.
Итак, в итоге вы получите что-то вроде этого:
GET
Cache cache = CacheManager.getInstance().getCache(CACHE_NAME);
Element elem = cache.get(identifier);
if (elem == null)
{
throw new SessionNotFoundException(identifier);
}
if (elem.isExpired())
{
throw new SessionExpiredException(identifier);
}
return elem.getObjectValue();
PUT
Cache cache = CacheManager.getInstance().getCache(CACHE_NAME);
// We use ttl = 0 and tti=<ttlInMinutes>, because session timeout is based on session idle timout.
element = new Element(identifier, new SessionElement(), Boolean.FALSE, (int) (timeToLive / VALUE_MS), 0);
cache.put(element);