ehcache + spring 整合以及配置说明 ,附带整合问题 (已解决)
Posted a java coder
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ehcache + spring 整合以及配置说明 ,附带整合问题 (已解决)相关的知识,希望对你有一定的参考价值。
新做的项目,因为流量不大 就是一个征信平台,高峰流量不多,但缓存是必须的,cache到server上就可以,不需要额外的memcache、redis之类的东西。
但是遇到一个大坑,事情是这样的:
通过阅读大量教程,官方文档所知,该缓存框架是java进程内的缓存,开发便捷,缺点就是java kill掉后缓存就消失了,不会想其他缓存框架可以独立于JAVA程序外。
总结起来就是以下几点,特此记录
1:我配置好ehcache缓存框架,如下所示:重点就是cache name
<?xml version="1.0" encoding="UTF-8"?> <ehcache name="es"> <diskStore path="java.io.tmpdir"/> <!--1 timeToIdleSeconds ,多长时间不访问该缓存,那么ehcache 就会清除该缓存. 2 timeToLiveSeconds ,缓存的存活时间,从开始创建的时间算起. 3 eternal 缓存是否持久 4 overflowToDisk 是否保存到磁盘,当系统宕机时 --> <defaultCache maxEntriesLocalHeap="1000" eternal="false" timeToIdleSeconds="3600" timeToLiveSeconds="3600" overflowToDisk="false"> </defaultCache> <cache name="cisReportRoot" maxEntriesLocalHeap="2000" eternal="false" timeToIdleSeconds="600" timeToLiveSeconds="600" overflowToDisk="false" statistics="true"> </cache> <cache name="user" maxEntriesLocalHeap="2000" eternal="false" timeToIdleSeconds="600" timeToLiveSeconds="600" overflowToDisk="false" statistics="true"> </cache> </ehcache>
2: 开始配置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:cache="http://www.springframework.org/schema/cache" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" 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/cache http://www.springframework.org/schema/cache/spring-cache-4.3.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd"> <context:component-scan base-package="com.xxxx.credit.*"/> <cache:annotation-driven/> <!-- 使用全注释事务 --> <tx:annotation-driven transaction-manager="transactionManager"/> <!-- cacheManager, 指定ehcache.xml的位置 --> <bean id="ehcacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"> <property name="configLocation" value="classpath:ehcache.xml"/> </bean> <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"> <property name="cacheManager" ref="ehcacheManager"/> <property name="transactionAware" value="true"/> </bean> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location" value="classpath:jdbc.properties"/> </bean> <!-- 数据源配置, 使用应用中的DBCP数据库连接池 --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <!-- Connection Info --> <property name="driverClassName" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> <!-- Connection Pooling Info --> <property name="maxActive" value="${dbcp.maxActive}"/> <property name="maxIdle" value="${dbcp.maxIdle}"/> <property name="defaultAutoCommit" value="false"/> <!-- 连接Idle一个小时后超时 --> <property name="timeBetweenEvictionRunsMillis" value="3600000"/> <property name="minEvictableIdleTimeMillis" value="3600000"/> </bean> <!-- spring和MyBatis整合 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="configLocation" value="classpath:mybatis-config.xml"/> <!-- 自动扫描Mapper.xml文件 --> <property name="mapperLocations" value="classpath:mybatis/*Mapper.xml"/> </bean> <!-- DAO接口所在包名,Spring会自动查找其下的类 --> <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.pingan.credit.dao"/> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> </bean> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg index="0" ref="sqlSessionFactory"/> </bean> <!-- 事务管理 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 懒加载 --> <bean id="jacksonObjectMapper" class="com.pingan.credit.model.MyJsonMapper" /> </beans>
4:然后写一个简单的bean,service 做测试验证配置是否正确:
Bean
package com.pingan.credit.model; import java.io.Serializable; public class User implements Serializable { private Long id; private String username; private String email; public User() { } public User(Long id, String username, String email){ this.id = id; this.username = username; this.email = email; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; User user = (User) o; if (id != null ? !id.equals(user.id) : user.id != null) return false; return true; } @Override public int hashCode() { return id != null ? id.hashCode() : 0; } @Override public String toString() { return "User{" + "id=" + id + ", username=‘" + username + ‘\‘‘ + ", email=‘" + email + ‘\‘‘ + ‘}‘; } }
Service:
package com.xxxx.credit.service; import com.xxxx.credit.model.User; import org.apache.log4j.Logger; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CachePut; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import java.util.HashSet; import java.util.Set; @Service("userService") public class UserService { private static Logger logger = Logger.getLogger(UserService.class); Set<User> users = new HashSet<User>(); @CachePut(value = "user", key = "#user.id") public User save(User user) { users.add(user); logger.info(user.toString()); return user; } @CachePut(value = "user", key = "#user.id") public User update(User user) { users.remove(user); users.add(user); return user; } @CacheEvict(value = "user", key = "#user.id") public User delete(User user) { users.remove(user); return user; } @CacheEvict(value = "user", allEntries = true) public void deleteAll() { users.clear(); } @Cacheable(value = "user", key = "#id") public User findById(final Long id) { System.out.println("cache miss, invoke find by id, id:" + id); for (User user : users) { if (user.getId().equals(id)) { return user; } } return null; } }
然后开始测试:
@Test public void testCacheUser() { System.out.println("test cache()"); Long id = 1L; User user = new User(id, "zhang333", "[email protected]"); User save = userService.save(user); junit.framework.TestCase.assertEquals(true,user==save); System.out.println("123"); User result = userService.findById(id); }
通过验证: 缓存正常输出 ,也理解通过UserService中@Cacheable注解后,不会进入方法体内,也就是说不会有sysout.out.println()这句输出
直接返回save方法中 save() 方法return的值
也就是说 save方法 会缓存 return的那个user
好了 道理都懂了 junit也测过了 差不许多可以开始上测试服务器了
这个时候,折磨了我4个小时的问题来了,
我在本地一切问题都没有,但是通过post man(http 请求工具)就是拿不到缓存数据,当时总觉得是缓存框架配置的有问题,但恰恰并不是
原因在这:spring-mvc.xml
<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:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!--自动扫描,注解控制器 --> <context:component-scan base-package="com.xxxx.credit.*"/> <!--注解驱动 --> <mvc:annotation-driven/> <!--静态资源映射--> <!--本项目把静态资源放在了WEB-INF的statics目录下,资源映射如下--> <mvc:resources mapping="/css/**" location="/WEB-INF/statics/css/"/> <mvc:resources mapping="/js/**" location="/WEB-INF/statics/js/"/> <mvc:resources mapping="/image/**" location="/WEB-INF/statics/image/"/> <!-- 对模型视图名称的解析,即在模型视图名称添加前后缀(如果最后一个还是表示文件夹,则最后的斜杠不要漏了) 使用JSP--> <!-- 默认的视图解析器 在上边的解析错误时使用 (默认使用html)- --> <bean id="defaultViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> <property name="prefix" value="/"/><!--设置JSP文件的目录位置--> <property name="suffix" value=".jsp"/> </bean> <!-- springMvc文件上传需要配置的节点--> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="maxUploadSize" value="20971500"/><!--设置JSP文件的目录位置--> <property name="defaultEncoding" value="UTF-8"/><!--设置默认编码--> <property name="resolveLazily" value="true"/><!--启用是为了推迟文件解析,以便捕获文件大小异常--> </bean> </beans>
但是更改成:
<context:component-scan base-package="com.pingan.xxxx.controller"/>
就没有问题了,擦 折腾了我4个小时的问题终于找到了,魔鬼细节啊 魔鬼细节啊 魔鬼细节啊 还是马虎造成的,如次简单的问题又耗费了大量的时间
谨记
以上是关于ehcache + spring 整合以及配置说明 ,附带整合问题 (已解决)的主要内容,如果未能解决你的问题,请参考以下文章