Spring Boot Learning Sharing (6) - Integrating shiro+ehcahce


Implementation of SpringBoot+ehcache+shiro and pits encountered


A brief introduction to ehcache:
ehcache is a pure Java in-process caching framework with fast, lean and other characteristics, and is the default CacheProvider in Hibernate.
Advantages: EHcache is directly cached in the JVM virtual machine, which is fast and efficient;
Disadvantages: But the cache sharing is troublesome, and the cluster distributed application is inconvenient.


Use ehcache for data caching and integrate ehcache into shiro. Since shiro itself provides support for ehcache, it is very simple to integrate


The following are the configuration files required for spring project integration:

   <!-- 缓存配置  -->
    <bean id="ehCacheManager"
        class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
        <property name="configLocation" value="classpath:ehcache/ehcache.xml" />
    </bean>

    <!-- shiro封装cacheManager -->
    <bean id="shiroCacheManager"
        class="org.apache.shiro.cache.ehcache.EhCacheManager">
        <property name="cacheManager" ref="ehCacheManager" />
    </bean>

    <!-- spring 封装ehcache缓存管理器  -->
    <bean id="springCacheManager"
        class="org.springframework.cache.ehcache.EhCacheCacheManager">
        <property name="cacheManager" ref="ehCacheManager" />
    </bean>

    <!-- 激活spring 缓存注解 -->
    <cache:annotation-driven cache-manager="springCacheManager"/>

With Spring Boot, you must implement the above configuration yourself through the configuration class:

Shiro's cache implementation (ShiroConfiguration.class), here is only the implementation of the cache manager, the specific code can refer to Spring Boot Learning Sharing (2) this article

    /**
     * @param cm EHcache工厂bean
     * @return shiro的缓存管理器
     */
    @Bean(name = "cacheManagerShiro")
    public CacheManager cacheManagerShiro(@Qualifier("ehcacheManager") EhCacheManagerFactoryBean cm) {
        EhCacheManager cacheManagershiro = new EhCacheManager();
        cacheManagershiro.setCacheManager(cm.getObject());
        return cacheManagershiro;
    }

Spring's ehcache cache implementation (SpringConfiguration.class):

@Configuration
public class SpringConfiguration {

    /**
     * @return ehcache工厂实例
     */
    @Bean(name = "ehcacheManager")
    public EhCacheManagerFactoryBean cacheManager() {
        EhCacheManagerFactoryBean cacheManager = new EhCacheManagerFactoryBean();
        //配置路径使用classpath加载
        cacheManager.setConfigLocation(new ClassPathResource("ehcache/ehcache.xml"));
        cacheManager.setShared(true);//单例模式
        return cacheManager;
    }

    /**
     * @param cm ehcache工廠的实例
     * @return spring的缓存管理器
     */
    @Bean(name = "cacheManagerSpring")
    public EhCacheCacheManager cacheManagerSpring(
            @Qualifier("ehcacheManager") EhCacheManagerFactoryBean cm) {
        EhCacheCacheManager cacheManager = new EhCacheCacheManager()
        cacheManager.setCacheManager(cm.getObject());
        return cacheManager;
    }
}

The code is basically converted according to the configuration file, and there are other implementation schemes, so I won’t go into details here.


here comes the point

The blogger encountered a bug during the integration. The blogger used the spring cache annotation in the implementation class of the service layer. However, the annotations of some special classes took effect, and the annotations of some classes did not take effect , did not take effect , and did not take effect . . .
Finally I found a post
, which probably means that because Shiro's custom Realm class is automatically injected very early, the attributes of the automatically injected service layer interface have been injected before it has been added, which means that the cache annotations of some classes do not take effect. The reason, and the solution, is also very simple, as long as a @Lazylabel is added to the injected interface, so that the interface can be loaded later. . .


A sample configuration file for ehcache is attached below:
ehcache.xml:

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://www.ehcache.org/ehcache.xsd">

    <diskStore path="java.io.tmpdir/ehcache"/>

    <!-- 默认缓存 -->
    <defaultCache
            maxElementsInMemory="1000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            overflowToDisk="false"/>

    <!-- 
        配置自定义缓存
        maxElementsInMemory:缓存中允许创建的最大对象数
        eternal:缓存中对象是否为永久的,如果是,超时设置将被忽略,对象从不过期。
        timeToIdleSeconds:缓存数据的钝化时间,也就是在一个元素消亡之前,
        两次访问时间的最大时间间隔值,这只能在元素不是永久驻留时有效,
        如果该值是 0 就意味着元素可以停顿无穷长的时间。
        timeToLiveSeconds:缓存数据的生存时间,也就是一个元素从构建到消亡的最大时间间隔值,
        这只能在元素不是永久驻留时有效,如果该值是0就意味着元素可以停顿无穷长的时间。
        overflowToDisk:内存不足时,是否启用磁盘缓存。
        memoryStoreEvictionPolicy:缓存满了之后的淘汰算法。
    -->
    <!-- userService查询用户的缓存 -->
    <!--缓存用户的信息 -->
    <cache name="User"
           maxElementsInMemory="2000"
           eternal="false"
           timeToIdleSeconds="3000"
           timeToLiveSeconds="30000"
           overflowToDisk="false"
           memoryStoreEvictionPolicy="LRU"/>
    <!-- 密码尝试次数的缓存 -->
    <cache name="passwordRetryCache"
           maxElementsInMemory="2000"
           eternal="false"
           timeToIdleSeconds="60"
           timeToLiveSeconds="60"
           overflowToDisk="false"
           statistics="true">
    </cache>
</ehcache>

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325351229&siteId=291194637