Commit bb2749fd by fsn

增加缓存的支持

parent 775b5836
......@@ -19,6 +19,13 @@
<dependencies>
<!--缓存框架-->
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>3.3.1</version>
</dependency>
<!-- mock数据和测试 -->
<dependency>
<groupId>org.powermock</groupId>
......
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd"
updateCheck="false" monitoring="autodetect"
dynamicConfig="true" >
<diskStore path="java.io.tmpdir/ehcache"/>
<!-- 全局变量:永不过期-->
<cache name="CONSTANT"
maxElementsInMemory="50000"
eternal="true"
clearOnFlush="false"
overflowToDisk="true"
diskSpoolBufferSizeMB="1024"
maxElementsOnDisk="100000"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LFU"
transactionalMode="off">
</cache>
</ehcache>
<!--
maxElementsInMemory="10000" //Cache中最多允许保存的数据对象的数量
external="false" //缓存中对象是否为永久的,如果是,超时设置将被忽略,对象从不过期
timeToLiveSeconds="3600" //缓存的存活时间,从开始创建的时间算起
timeToIdleSeconds="3600" //多长时间不访问该缓存,那么ehcache 就会清除该缓存
这两个参数很容易误解,看文档根本没用,我仔细分析了ehcache的代码。结论如下:
1、timeToLiveSeconds的定义是:以创建时间为基准开始计算的超时时长;
2、timeToIdleSeconds的定义是:在创建时间和最近访问时间中取出离现在最近的时间作为基准计算的超时时长;
3、如果仅设置了timeToLiveSeconds,则该对象的超时时间=创建时间+timeToLiveSeconds,假设为A;
4、如果没设置timeToLiveSeconds,则该对象的超时时间=min(创建时间,最近访问时间)+timeToIdleSeconds,假设为B;
5、如果两者都设置了,则取出A、B最少的值,即min(A,B),表示只要有一个超时成立即算超时。
overflowToDisk="true" //内存不足时,是否启用磁盘缓存
diskSpoolBufferSizeMB //设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区
maxElementsOnDisk //硬盘最大缓存个数
diskPersistent //是否缓存虚拟机重启期数据The default value is false
diskExpiryThreadIntervalSeconds //磁盘失效线程运行时间间隔,默认是120秒。
memoryStoreEvictionPolicy="LRU" //当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
clearOnFlush //内存数量最大时是否清除
maxEntriesLocalHeap="0"
maxEntriesLocalDisk="1000"
-->
package com.stylefeng.guns.common.constant.factory;
import com.stylefeng.guns.common.constant.state.*;
import com.stylefeng.guns.common.constant.state.ManagerStatus;
import com.stylefeng.guns.common.constant.state.MenuStatus;
import com.stylefeng.guns.common.constant.state.Sex;
import com.stylefeng.guns.core.support.StrKit;
import com.stylefeng.guns.core.util.Convert;
import com.stylefeng.guns.core.util.SpringContextHolder;
......@@ -9,6 +11,7 @@ import com.stylefeng.guns.persistence.dao.DeptMapper;
import com.stylefeng.guns.persistence.dao.RoleMapper;
import com.stylefeng.guns.persistence.model.Dept;
import com.stylefeng.guns.persistence.model.Role;
import org.springframework.cache.annotation.Cacheable;
/**
* 常量的生产工厂
......@@ -16,6 +19,7 @@ import com.stylefeng.guns.persistence.model.Role;
* @author fengshuonan
* @date 2017年2月13日 下午10:55:21
*/
@Cacheable("CONSTANT")
public class ConstantFactory {
private static RoleMapper roleMapper = SpringContextHolder.getBean(RoleMapper.class);
......
/**
* Copyright (c) 2015-2017, Chill Zhuang 庄骞 (smallchill@163.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.stylefeng.guns.core.support.cache;
/**
* 缓存工厂基类
*/
public abstract class BaseCacheFactory implements ICache {
@SuppressWarnings("unchecked")
public <T> T get(String cacheName, Object key, ILoader iLoader) {
Object data = get(cacheName, key);
if (data == null) {
data = iLoader.load();
put(cacheName, key, data);
}
return (T) data;
}
@SuppressWarnings("unchecked")
public <T> T get(String cacheName, Object key, Class<? extends ILoader> iLoaderClass) {
Object data = get(cacheName, key);
if (data == null) {
try {
ILoader dataLoader = iLoaderClass.newInstance();
data = dataLoader.load();
put(cacheName, key, data);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
return (T) data;
}
}
/**
* Copyright (c) 2015-2017, Chill Zhuang 庄骞 (smallchill@163.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.stylefeng.guns.core.support.cache;
import java.util.List;
/**
* 缓存工具类
*/
public class CacheKit {
private static ICache defaultCacheFactory = new EhcacheFactory();
public static void put(String cacheName, Object key, Object value) {
defaultCacheFactory.put(cacheName, key, value);
}
public static <T> T get(String cacheName, Object key) {
return defaultCacheFactory.get(cacheName, key);
}
@SuppressWarnings("rawtypes")
public static List getKeys(String cacheName) {
return defaultCacheFactory.getKeys(cacheName);
}
public static void remove(String cacheName, Object key) {
defaultCacheFactory.remove(cacheName, key);
}
public static void removeAll(String cacheName) {
defaultCacheFactory.removeAll(cacheName);
}
public static <T> T get(String cacheName, Object key, ILoader iLoader) {
return defaultCacheFactory.get(cacheName, key, iLoader);
}
public static <T> T get(String cacheName, Object key, Class<? extends ILoader> iLoaderClass) {
return defaultCacheFactory.get(cacheName, key, iLoaderClass);
}
}
/**
* Copyright (c) 2011-2016, James Zhan 詹波 (jfinal@126.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.stylefeng.guns.core.support.cache;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import org.apache.log4j.Logger;
import java.util.List;
/**
* Ehcache缓存工厂
*/
public class EhcacheFactory extends BaseCacheFactory {
private static CacheManager cacheManager;
private static volatile Object locker = new Object();
private static final Logger log = Logger.getLogger(EhcacheFactory.class);
private static CacheManager getCacheManager() {
if (cacheManager == null) {
synchronized (EhcacheFactory.class) {
if (cacheManager == null) {
cacheManager = CacheManager.create();
}
}
}
return cacheManager;
}
static Cache getOrAddCache(String cacheName) {
CacheManager cacheManager = getCacheManager();
Cache cache = cacheManager.getCache(cacheName);
if (cache == null) {
synchronized(locker) {
cache = cacheManager.getCache(cacheName);
if (cache == null) {
log.warn("无法找到缓存 [" + cacheName + "]的配置, 使用默认配置.");
cacheManager.addCacheIfAbsent(cacheName);
cache = cacheManager.getCache(cacheName);
log.debug("缓存 [" + cacheName + "] 启动.");
}
}
}
return cache;
}
public void put(String cacheName, Object key, Object value) {
getOrAddCache(cacheName).put(new Element(key, value));
}
@SuppressWarnings("unchecked")
public <T> T get(String cacheName, Object key) {
Element element = getOrAddCache(cacheName).get(key);
return element != null ? (T)element.getObjectValue() : null;
}
@SuppressWarnings("rawtypes")
public List getKeys(String cacheName) {
return getOrAddCache(cacheName).getKeys();
}
public void remove(String cacheName, Object key) {
getOrAddCache(cacheName).remove(key);
}
public void removeAll(String cacheName) {
getOrAddCache(cacheName).removeAll();
}
}
/**
* Copyright (c) 2015-2017, Chill Zhuang 庄骞 (smallchill@163.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.stylefeng.guns.core.support.cache;
import java.util.List;
/**
* 通用缓存接口
*/
public interface ICache {
public void put(String cacheName, Object key, Object value);
public <T> T get(String cacheName, Object key);
@SuppressWarnings("rawtypes")
public List getKeys(String cacheName);
public void remove(String cacheName, Object key);
public void removeAll(String cacheName);
public <T> T get(String cacheName, Object key, ILoader iLoader);
public <T> T get(String cacheName, Object key, Class<? extends ILoader> iLoaderClass);
}
/**
* Copyright (c) 2015-2017, Chill Zhuang 庄骞 (smallchill@163.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.stylefeng.guns.core.support.cache;
/**
* 数据重载
*/
public interface ILoader {
Object load();
}
package project.config.cache;
import net.sf.ehcache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
/**
* ehcache缓存的配置
*
* @author fengshuonan
* @date 2017-04-24 20:41
*/
@Configuration
@EnableCaching
public class EhcacheConfig {
@Bean
public EhCacheCacheManager cacheManager(CacheManager cacheManager){
return new EhCacheCacheManager(cacheManager);
}
@Bean
public EhCacheManagerFactoryBean ehcache(){
EhCacheManagerFactoryBean ehCacheManagerFactoryBean = new EhCacheManagerFactoryBean();
ehCacheManagerFactoryBean.setConfigLocation(new ClassPathResource("ehcache.xml"));
return ehCacheManagerFactoryBean;
}
}
package project.config.root;
import project.config.datasource.DataSourceConfig;
import project.config.web.monitor.DruidMonitorConfig;
import project.config.shiro.ShiroConfig;
import org.springframework.context.annotation.*;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import project.config.cache.EhcacheConfig;
import project.config.datasource.DataSourceConfig;
import project.config.shiro.ShiroConfig;
import project.config.web.monitor.DruidMonitorConfig;
/**
* spring的根配置
......@@ -18,7 +19,7 @@ import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@Filter(type = FilterType.ANNOTATION, value = EnableWebMvc.class)// 这个是为了不让扫描到springmvc的控制器
})
@EnableAspectJAutoProxy
@Import(value = {DataSourceConfig.class, ShiroConfig.class, DruidMonitorConfig.class})
@Import(value = {DataSourceConfig.class, ShiroConfig.class, DruidMonitorConfig.class, EhcacheConfig.class})
public class RootSpringConfig {
}
package com.stylefeng.guns.base;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
......@@ -11,9 +10,4 @@ import project.config.root.RootSpringConfig;
@ContextConfiguration(classes = RootSpringConfig.class)
public class BaseTest {
@Test
public void test() {
}
}
package com.stylefeng.guns.cache;
import com.alibaba.fastjson.JSON;
import com.stylefeng.guns.base.BaseTest;
import com.stylefeng.guns.common.constant.factory.ConstantFactory;
import com.stylefeng.guns.common.node.ZTreeNode;
import com.stylefeng.guns.core.support.cache.CacheKit;
import com.stylefeng.guns.modular.system.dao.DeptDao;
import com.stylefeng.guns.modular.system.dao.DictDao;
import com.stylefeng.guns.modular.system.dao.UserMgrDao;
import com.stylefeng.guns.persistence.model.Dict;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
/**
* 缓存测试
*
* @author fengshuonan
* @date 2017-04-24 21:00
*/
public class CacheTest extends BaseTest{
@Autowired
UserMgrDao userMgrDao;
/**
* 测试没有缓存的情况
*
* @author fengshuonan
* @Date 2017/4/24 21:00
*/
@Test
public void testNoCache(){
long beginTIme = System.currentTimeMillis();
for(int i = 1;i<1000;i++){
List<Map<String, Object>> maps = userMgrDao.selectUsers(null, null, null);
}
System.out.println(System.currentTimeMillis() - beginTIme);
Object constant = CacheKit.get("CONSTANT", 1);
System.out.println(constant);
List constant1 = CacheKit.getKeys("CONSTANT");
System.out.println(JSON.toJSONString(constant1));
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment