1.先上shiro.xml中的配置 将缓存管理器配置进去
-------------------------------------------------------------------------------------------------------- 2.上ehcache.xml配置文件 记录缓存参数
----------------------------------------------------------------------------------------------------------------------- 3.自定义凭证匹配器 缓存使用实例 密码错误大于五次抛ExcessiveAttemptsException异常
package cn.cjq.util.shiro; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.ExcessiveAttemptsException; import org.apache.shiro.authc.credential.HashedCredentialsMatcher; import org.apache.shiro.cache.Cache; import org.apache.shiro.cache.CacheManager; import java.util.concurrent.atomic.AtomicInteger; public class RetryLimitHashedCredentialsMatcher extends HashedCredentialsMatcher { private CachepasswordRetryCache; public RetryLimitHashedCredentialsMatcher(CacheManager cacheManager) { passwordRetryCache = cacheManager.getCache("passwordRetryCache"); } @Override public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) { String username = (String)token.getPrincipal(); //retry count + 1 AtomicInteger retryCount = passwordRetryCache.get(username); if(retryCount == null) { retryCount = new AtomicInteger(0); passwordRetryCache.put(username, retryCount); } if(retryCount.incrementAndGet() > 5) { //if retry count > 5 throw throw new ExcessiveAttemptsException(); } boolean matches = super.doCredentialsMatch(token, info); if(matches) { //clear retry count passwordRetryCache.remove(username); } return matches; } } ---------------------------------------------------------------------------------------------------------------------------- 4.缓存实例 注入cacheManager
@Resource private CacheManager cacheManager; //获取
CachepasswordRetryCache=cacheManager.getCache("passwordRetryCache"); //捕捉认证异常
catch (AuthenticationException e) { //参数认证异常 return new Response("999999","输入参数有误,您还有" +(6-passwordRetryCache.get(userName).get())+"次机会重新输入!"); }
------------------------------------------------------------------------------------------------------ 附录:AtomicInteger类 AtomicInteger是一个提供原子操作的Integer类,通过线程安全的方式操作加减。十分适合高并发情况下的使用 在使用Integer的时候,必须加上synchronized保证不会出现并发线程同时访问的情况,而在AtomicInteger中却不用加上synchronized,在这里AtomicInteger是提供原子操作的。
AtomicInteger运算
- public class Test {
- public static void main(String[] args) {
- AtomicInteger integer = new AtomicInteger();
- integer.set(1);
- int i = integer.get(); //获得值
- System.out.println(i);
- i = integer.incrementAndGet(); //先+1,然后在返回值,相当于++i
- System.out.println(i);
- i = integer.getAndIncrement();//先返回值,然后在+1,相当于i++
- System.out.println(i);
- i = integer.get();
- System.out.println(i);
- i = integer.decrementAndGet();//先-1,然后在返回值,相当于--i
- System.out.println(i);
- i = integer.getAndDecrement();//先返回值,然后在-1,相当于i--
- System.out.println(i);
- i = integer.get();
- System.out.println(i);//1
- i = integer.addAndGet(1);//先+n,然后在返回值,
- System.out.println(i);
- i = integer.getAndAdd(1);//先返回,然后+n
- System.out.println(i);
- i = integer.get();
- System.out.println(i);
- }
- }
---------------------------------------------------------------------------------------------------------------------------------------------- 附录2 主要的特性有:
1. 快速
2. 简单
3. 多种缓存策略
4. 缓存数据有两级:内存和磁盘,因此无需担心容量问题
5. 缓存数据会在 重启的过程中写入磁盘
6. 可以通过RMI、可插入API等方式进行分布式缓存
7. 具有缓存和缓存管理器的侦听接口
8. 支持多 管理器实例,以及一个实例的多个缓存区域
9. 提供Hibernate的缓存实现
ehcache.xml:里面的注释写的很清楚了。
: 当内存缓存中对象数量超过maxElementsInMemory时,将缓存对象写到磁盘缓存中(需对象实现序列化接口) : 用来配置磁盘缓存使用的物理路径,Ehcache磁盘缓存使用的文件后缀名是*.data和*.index name : "缓存名称,cache的唯一标识(ehcache会把这个cache放到HashMap里) maxElementsInMemory : 缓存最大个数。 eternal="false" : 对象是否永久有效,一但设置了,timeout将不起作用。 (必须设置) maxEntriesLocalHeap="1000" : 堆内存中最大缓存对象数,0没有限制(必须设置) maxEntriesLocalDisk= "1000" : 硬盘最大缓存个数。 overflowToDisk="false" : 当缓存达到maxElementsInMemory值是,是否允许溢出到磁盘(必须设置)(内存不足时,是否启用磁盘缓存。) diskSpoolBufferSizeMB : 这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。 diskPersistent="false" : 磁盘缓存在JVM重新启动时是否保持(默认为false) timeToIdleSeconds="0" : 导致元素过期的访问间隔(秒为单位),即当缓存闲置n秒后销毁。 当eternal为false时,这个属性才有效,0表示可以永远空闲,默认为0 timeToLiveSeconds="600" : 元素在缓存里存在的时间(秒为单位),即当缓存存活n秒后销毁. 0 表示永远存在不过期 memoryStoreEvictionPolicy="LFU" : 当达到maxElementsInMemory时,如何强制进行驱逐默认使用"最近使用(LRU)"策略,其它还有先入先出FIFO,最少使用LFU,较少使用LRU diskExpiryThreadIntervalSeconds :磁盘失效线程运行时间间隔,默认是120秒。 clearOnFlush : 内存数量最大时是否清除。