您的位置:首页 > 编程语言 > Java开发

Spring集成ehcache

2016-12-15 11:20 351 查看

1.导入jar包

ehcache-core-2.4.5.jar

ehcache-spring-annotations-1.2.0.jar(使用spring注解的形式配置时需要引入的jar包,依赖于guava)

ehcache-web-2.0.4.jar(做页面缓存需要用到)

guava-r09.jar(google推出可以帮助你写出更优雅代码的工具,和apache-commons差不多)

hibernate-ehcache-4.2.21.Final.jar(hibernate对于ehcache的支持)

2.编写ehcache.xml

将下载ehcache时附带的ehcache.xsd引入到工程中,我放在了src/config目录下

在classpath路径下新建xml文件,命名为ehcache.xml,然后其格式可以参考下载ehcache时附带的ehcache.xml,以下是我的配置

<?xml version="1.0" encoding="UTF-8"?>
<!--制定xsd的位置,这个xsd需要自己下载,贼坑,
网上的写的是用http://ehcache.org/ehcache.xsd 但是idea一直在报错,
最新版的是有附带ehcache.xsd的,然后自己加就好了,我发现我用的这个版本的jar如果点开
也有一个ehcache-*的一个配置文件的,里面的ehcache.xsd是可以使用的!但是我死活找不到,
没办法只能自己下载自己加了,网上的方法都没有什么好的,手动大笑-->

<!--updateCheck不要设置为true,否则每一次的开启都会自动检查更新,导致运行很慢-->
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="config/ehcache.xsd"
updateCheck="false">

<!--缓存保存地址-->
<diskStore path="java.io.tmpdir"/>

<!--默认的缓存配置-->
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="30"
timeToLiveSeconds="30"
overflowToDisk="false"/>

<!--自定义缓存配置-->
<!--
1.必须要有的属性:
name: cache的名字,用来识别不同的cache,必须惟一。
maxElementsInMemory: 内存管理的缓存元素数量最大限值。
maxElementsOnDisk: 硬盘管理的缓存元素数量最大限值。默认值为0,就是没有限制。
eternal: 设定元素是否持久话。若设为true,则缓存元素不会过期。
overflowToDisk: 设定是否在内存填满的时候把数据转到磁盘上。
2.下面是一些可选属性:
timeToIdleSeconds: 设定元素在过期前空闲状态的时间,只对非持久性缓存对象有效。默认值为0,值为0意味着元素可以闲置至无限长时间。
timeToLiveSeconds: 设定元素从创建到过期的时间。其他与timeToIdleSeconds类似。
diskPersistent: 设定在虚拟机重启时是否进行磁盘存储,默认为false.(我的直觉,对于安全小型应用,宜设为true)。
diskExpiryThreadIntervalSeconds: 访问磁盘线程活动时间。
diskSpoolBufferSizeMB: 存入磁盘时的缓冲区大小,默认30MB,每个缓存都有自己的缓冲区。
memoryStoreEvictionPolicy: 元素逐出缓存规则。共有三种,Recently Used (LRU)最近最少使用,为默认。
First In First Out (FIFO),先进先出。Less Frequently Used(specified as LFU)最少使用
-->
<cache name="sampleCache"
maxElementsInMemory="10000"
maxElementsOnDisk="1000"
eternal="false"
overflowToDisk="true"
diskSpoolBufferSizeMB="20"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LFU" />
</ehcache>

3.修改applicationContext.xml

修改applicationContext.xml用来集成ehcache。

<!--开启ehcache注解扫描-->
<ehcache:annotation-driven />

<!--ehcache工厂的配置-->
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:ehcache.xml"/>
</bean>
<!--配置cache-manager-->
<ehcache:config cache-manager="cacheManager">
<ehcache:evict-expired-elements interval="60" />
</ehcache:config>配置完这个之后,整个applicationContext.xml长这样
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:ehcache="http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.2.xsd http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring/ehcache-spring-1.1.xsd">
<!--自动扫描包-->
<context:component-scan base-package="cn.limbo">
<!--不要将Controller扫进来,否则aop无法使用-->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

<!--使Aspect注解起作用,自动为匹配的类生成代理对象-->
<aop:aspectj-autoproxy proxy-target-class="true"/>

<!--开启ehcache注解扫描-->
<ehcache:annotation-driven />

<!--ehcache工厂的配置-->
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:ehcache.xml"/>
</bean>
<!--配置cache-manager-->
<ehcache:config cache-manager="cacheManager">
<ehcache:evict-expired-elements interval="60" />
</ehcache:config>

<!--引入properties-->
<context:property-placeholder location="classpath:hibernate.properties"/>

<!--配置数据源-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="${dataSource.username}"/>
<property name="password" value="${dataSource.password}"/>
<property name="jdbcUrl" value="${dataSource.url}"/>
<property name="driverClass" value="${dataSource.driverClassName}"/>
</bean>

<!--<!–sessionFactory–>-->
<!--<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">-->
<!--<!– 配置数据源属性 –>-->
<!--<property name="dataSource" ref="dataSource"/>-->
<!--<!– 配置扫描的实体包(pojo) –>-->
<!--<property name="namingStrategy">-->
<!--<bean class="org.hibernate.cfg.ImprovedNamingStrategy"/>-->
<!--</property>-->
<!--<property name="packagesToScan" value="cn.limbo.entity"/>-->

<!--<property name="hibernateProperties">-->
<!--<props>-->
<!--<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>-->
<!--<prop key="hibernate.show_sql">true</prop>-->
<!--<prop key="hibernate.format_sql">true</prop>-->
<!--<prop key="hibernate.hbm2ddl.auto">update</prop>-->
<!--</props>-->
<!--</property>-->
<!--</bean>-->

<bean id="persistenceProvider"
class="org.hibernate.ejb.HibernatePersistence"/>

<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="MYSQL"/>
</bean>

<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>

<!--jpa工厂-->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<!--数据源-->
<property name="dataSource" ref="dataSource"/>
<!--持久层提供者-->
<property name="persistenceProvider" ref="persistenceProvider"/>
<!--适配器-->
<property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>

<property name="jpaDialect" ref="jpaDialect"/>

<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">${dataSource.dialect}</prop>
<prop key="hibernate.connection.driver_class">${dataSource.driverClassName}</prop>
<prop key="hibernate.max_fetch_depth">3</prop>
<prop key="hibernate.jdbc.fetch_size">18</prop>
<prop key="hibernate.jdbc.batch_size">10</prop>
<prop key="hibernate.hbm2ddl.auto">${dataSource.hbm2ddl.auto}</prop>
<prop key="hibernate.show_sql">${dataSource.show_sql}</prop>
<prop key="hibernate.format_sql">${dataSource.format_sql}</prop>
<!--做bean validation的也就是对你的输入的数据进行语义的验证-->
<prop key="javax.persistence.validation.mode">none</prop>
</props>
</property>

<property name="packagesToScan">
<list>
<value>cn.limbo.entity</value>
</list>
</property>
</bean>

<jpa:repositories base-package="cn.limbo.dao"
entity-manager-factory-ref="entityManagerFactory"
transaction-manager-ref="transactionManager"/>

<!-- 配置Hibernate 的事物管理器 -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>

<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

4.使用ehcache

配置完成之后使用ehcache就比较简单了,只要在需要缓存的地方加上@Cacheable标签就好了
但是需要注意的是,最好是在做查询的方法里使用ehcache,在做增删改的时候要清除缓存,这点比较重要,否则在并发情况下会出现数据的脏读和幻读之类的东西

一般在dao中的service层引入ehcache,使用方法如下:

package cn.limbo.service.impl;

import cn.limbo.dao.UserDao;
import cn.limbo.entity.User;
import cn.limbo.service.UserService;
import com.googlecode.ehcache.annotations.Cacheable;
import com.googlecode.ehcache.annotations.TriggersRemove;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
* Created by limbo on 2016/11/26.
*/
@Service("userService")
@Transactional
public class UserServiceImpl implements UserService{

@Autowired
private UserDao userDao;

@Override
@Cacheable(cacheName = "sampleCache")
public User getUserByID(int ID) {
return userDao.getUserByID(ID);
}

@Override
@Cacheable(cacheName = "sampleCache")
public List<User> getAllUsers() {
return userDao.getAllUsers();
}

@Override
@TriggersRemove(cacheName="sampleCache",removeAll=true)//清除缓存
public void addUser(String name,String password) {
User user = new User(name,password);
userDao.save(user);
}

@Override
@TriggersRemove(cacheName="sampleCache",removeAll=true)//清除缓存
public void deleteUserByID(int ID) {
userDao.delete(ID);
}

@Override
@TriggersRemove(cacheName="sampleCache",removeAll=true)//清除缓存
public void updateUser(User user) {
userDao.update(user.getID(),user.getName(),user.getPassword());
}

@Override
public boolean isExist(String userName) {
if(userDao.getUserByName(userName) != null)
return true;
return false;
}
}


5.总结

发现有两个坑点:
1.ehcache.xsd找不到,一开始网上给的解决方案都是改成http://ehcahce.org/ehcahce.xsd,但是我发现这样还是有问题的,后来发现我下载ehcache的时候附带了ehcahce.xsd,引入就好咯
2.使用cache的时候,@Cacheable(cacheName=""),使用的是在ehcache.xml自定义配置的ehcache名字,而不是在applicationContext.xml里面配置的bean的名字

源码我放到了github上:https://github.com/NetFilx/Google-Authenticator
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  缓存 ehcache