最近做了个东西,使用的数据是根据元数据进行读取和加工,加工后又基本不变,使用又比较频繁。所以要用到缓存。ehcache是当对象超过配置的最大内存时才部分写入磁盘(非完整),或者配置diskPersistent=true才可以写入磁盘。当初一直以为ehcache在磁盘中读取的缓存是非完整的(重启完就没了)。当初没发现有diskPersistent这个配置,所以就自己先实现了一个简单的。
1、对序列化文件进行读写的类:
/**
* 对缓存序列号
* 读写内存对象到文件
*/
public abstract class FileReader {
/**
* 根据key读取缓存中的数据
* @param key 多种组合
* @return 缓存对象对象
* @throws Exception
*/
public Object read(String path) throws Exception {
Object o = null;
ObjectInputStream in = null;
try {
//判断文件是否存在
File file = new File(path);
if (!file.exists()) {
return o;
}
//读取缓存文件
in = new ObjectInputStream(new FileInputStream(file));
o = in.readObject();
} catch (FileNotFoundException e) {
throw new Exception("read inputstream exception", e);
} catch (IOException e) {
throw new Exception("red inputstream io exception", e);
} finally {
if (null != in) {
try {
in.close();
} catch (IOException e) {
throw new Exception("close inputstream exception", e);
}
}
}
return o;
}
/**
* @param key 将key当初文件名
* @param o 缓存的对象
* @throws Exception IO抛出异常
*/
public void write(String path, Object o) throws Exception {
ObjectOutputStream out = null;
FileOutputStream fout = null;
File file;
try {
file = new File(path);
if (!file.exists()) {
file.createNewFile();
}
fout = new FileOutputStream(file);
out = new ObjectOutputStream(fout);
//清空输出流
out.reset();
//写入对象
out.writeObject(o);
} catch (IOException e) {
throw new Exception("write outputstream exception", e);
} finally {
if (null != out) {
try {
out.close();
} catch (IOException e) {
throw new Exception("close outputstream exception", e);
}
}
if (null != fout) {
try {
fout.close();
} catch (IOException e) {
throw new Exception("close outputstream exception", e);
}
}
}
}
}
2、关键的缓存类:
/**
* 数据内存缓存,同时写入缓存文件,用于重启服务时内存数据消失时读取
* 此处不用ehcache,因为ehcache需要读取配置,不能及时存入缓存文件,只是部分存放。
*/
public class MpCache extends FileReader {
private static MpCache mpCache = new MpCache();
private static Map<CacheKey, Cache> contents;
private static String path;
private static State state;
static {
path = System.getProperty("java.io.tmpdir");
contents = new HashMap<CacheKey, Cache>();
state = State.getInstance();
}
//这是个单例
public static MpCache getInstance() {
return mpCache;
}
/**
* 存入缓存数据,同时更新缓存文件
* @param k
* @param v
* @throws Exception
*/
public synchronized void put(CacheKey k, Cache v) throws Exception {
contents.put(k, v);
write(k, v);
}
/**
* 读取缓存数据
* @param key
* @return
* @throws Exception
*/
public Cache get(CacheKey k) throws Exception {
Cache c = contents.get(k);
if (null == c && !state.hasSync(k)) {
c = read(k);
contents.put(k, c);
}
return c;
}
/**
* 根据key读取缓存中的数据
* @param key 多种组合
* @return 缓存对象对象
* @throws Exception
*/
private Cache read(CacheKey k) throws Exception {
String key = k.getKey();
String p = path.concat(key).concat(".dat");
Cache c = (Cache) super.read(p);
return c;
}
/**
* @param key 将key当初文件名
* @throws Exception IO抛出异常
*/
private void write(CacheKey k, Object o) throws Exception {
String key = k.getKey();
String p = path.concat(key).concat(".dat");
super.write(p, o);
}
public void clear() {
contents.clear();
state.clear();
}
}
3、状态类,对应内存对象是否已经从磁盘中读取过。
/**
* 文件状态和内存对象是否同步
*/
public class State extends FileReader {
private static State state = new State();
private static Map<String, Boolean> map = new HashMap<String, Boolean>();
/**
*
* @param key
* @return
*/
public boolean hasSync(CacheKey key) {
String k = key.getKey();
Boolean v = map.get(k);
if (null == v) {
//设置已经被同步
map.put(k, true);
//返回未同步
return false;
}
return v;
}
public static State getInstance() {
return state;
}
public void clear() {
map.clear();
}
}
4、存放的对象需要实现的接口
/**
* 缓存顶层接口
*/
public interface Cache {
CacheKey getCacheKey();
}
5、缓存唯一标识接口
public interface Key {
String getKey();
}
6、缓存唯一标识类
/**
* 存放key值 , 重写hashcode 比较方法
*/
public class CacheKey implements Key,Serializable{
private static final long serialVersionUID = 1L;
//目前只存放属性
private String type;
/**
* 比较文件中的缓存是否是同一个
*/
public boolean equals(Object o) {
if (getKey() == null) {
throw new CacheException("cachekey 不能为空.");
}
if (this == o) {
return true;
}
if (!(o instanceof Key))
return false;
Key otherCache = (Key) o;
return getKey().equals(otherCache.getKey());
}
/**
* hashmap是根据hashcode为key获取数据
* 重写这个方法以取得需要的key对应的数据
*/
public int hashCode() {
if (getKey() == null) {
throw new CacheException("cachekey 不能为空.");
}
return getKey().hashCode();
}
/**
* 仓库编号,包编号,类编号
* @return 唯一key
*/
public String getKey() {
return type;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
7、需要缓存的对象
public class Content implements Cache,Serializable {
private static final long serialVersionUID = 6963213185510643340L;
//缓存对象的key, 各种类型的缓存
private CacheKey key;
private Object obj;
public String getKey() {
return key.getKey();
}
public void setObject(Object obj) {
this.obj = obj;
}
}
8、最后写一个注册类方便调用
/**
* 注册缓存,将组装完的数据放入内存
* 单服务器用, 多服务器(分布式)时将不可用,文件都不知道在哪个服务器上没有同步。
*/
public class Register {
//整个会话都保存唯一的一个缓存变量
private static MpCache mPcache = MpCache.getInstance();
/**
* 注册解析的内存对象到缓存(全局)
* @throws Exception
*/
public static void regist(Cache c) throws Exception {
CacheKey k = c.getCacheKey();
mPcache.put(k, c);
}
/**
* 根据key值获取缓存对象
* @param key
* @return
* @throws Exception
*/
public static Cache getCache(CacheKey key) throws Exception {
return mPcache.get(key);
}
/**
* 清空缓存对象
*/
public static void clear() {
mPcache.clear();
}
}
话外:分布式缓存也可以用ehcache,或者用mencache。
分享到:
相关推荐
Java利用ConcurrentHashMap实现本地缓存demo; 基本功能有缓存有效期、缓存最大数、缓存存入记录、清理线程、过期算法删除缓存、LRU算法删除、获取缓存值等功能。 复制到本地项目的时候,记得改包路径哦~
参考链接提供的CSDN博客文章《[Spring简单缓存实现](http://blog.csdn.net/maoyeqiu/article/details/50238035)》中,作者详细介绍了如何在Spring项目中实现缓存,包括配置、注解使用以及注意事项,是一个很好的学习...
3. 内置缓存:内置了本地缓存机制,无需额外编写代码即可实现数据的本地存储和读取。 4. 支持多种请求方法:GET、POST、PUT、DELETE等HTTP方法都可轻松使用。 5. 请求参数与Header管理:方便地添加请求参数和自定义...
微信小程序基于本地缓存实现点赞功能的方法 微信小程序基于本地缓存实现点赞功能的方法是指在微信小程序中使用本地缓存来实现点赞功能的方法。这种方法主要涉及到微信小程序界面布局、事件响应及缓存操作等相关实现...
在“redis本地缓存与redis缓存”的主题中,我们将深入探讨这两种缓存方式及其各自的特点。 首先,我们要理解什么是本地缓存。本地缓存指的是将数据存储在应用程序的内存中,通常是Java的HashMap、Guava Cache或C#的...
"Java本地缓存的实现代码" Java本地缓存的实现代码是指在Java应用中,使用本地缓存来提高访问频率高、更新少的数据的读取效率。在集群环境下,分布式缓存如Redis、Memcached等都是常用的选择,但是在单机环境下,...
Kotlin缓存Kotlin中的缓存实现可以在代码中本地使用。 这个想法是要消除开发人员为每个项目创建的恒定缓存。 当前实现:永久性快取永久缓存是一个简单的缓存,它将无限期保存该值。用法val cache = PermanentCache ...
4. **Guava Cache**:Google Guava 库的一部分,提供了一个简单的本地缓存实现,适用于Java应用程序。 5. **Hazelcast**:一个开源的内存数据网格,提供分布式缓存、Map、Queue、Topic等功能。 缓存框架的选择应...
实现 Java 本地缓存的方法解析 本文主要介绍了实现 Java 本地缓存的方法解析,通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值。缓存肯定是项目中必不可少的,市面上有非常多的缓存工具,...
LoadingCache 是 Guava 库提供的一种缓存实现方式,本文将详细介绍如何基于 LoadingCache 实现 Java 本地缓存。 一、Guava 介绍 Guava 是 Google 开源的一套工具库,其中提供的 cache 模块非常方便,是一种与 ...
可以通过检查`window.localStorage`是否存在来实现。如果该对象存在,说明浏览器支持localStorage。 ```javascript if (typeof(Storage) !== "undefined") { // 支持localStorage } else { // 不支持localStorage...
在本地缓存中,我们可以使用 Guava 或 Caffeine 等库来实现缓存机制。 1. 场景描述 在实际开发中,我们经常遇到需要频繁访问数据库或远程服务以获取数据的情况,这种情况下,使用本地缓存可以大大提高应用程序的...
本篇文章将详细介绍Android本地缓存的基本概念、实现方式,以及如何使用`AsimpleCacheDemo`进行实践。 **本地缓存的基本概念** 本地缓存可以分为内存缓存和磁盘缓存。内存缓存通常使用`WeakReference`或`...
### MAC版本Outlook本地缓存路径详解 #### 一、Outlook for Mac 介绍 Microsoft Outlook for Mac 是一款由微软公司开发的专业电子邮件客户端与个人信息管理软件,它为Mac用户提供了与Windows版本相媲美的功能体验...
在新的版本中,Ehcache 引入了 Caffeine 库作为其默认的本地缓存实现。Caffeine 是一个高性能、低延迟的本地缓存,它利用了现代多核处理器的特性,提供了出色的并发性能。一级缓存位于应用程序服务器内部,数据读取...
"延时加载+静态资源本地缓存"是两种非常有效的技术手段,它们能够帮助我们实现这一目标。本篇文章将详细探讨这两种策略,以及如何将它们应用于实际项目中。 首先,让我们来看看静态资源本地缓存。静态资源通常包括...
这个文件名"iscsicache.exe"很可能是一个执行文件,它是实现"远景本地缓存iscsicache"功能的软件组件。这可能是一个服务或驱动程序,负责管理和优化iSCSI连接的本地缓存操作。当这个程序运行时,它会监控iSCSI会话,...
Guava Cache提供了线程安全的本地缓存实现,支持自定义加载函数、过期时间、大小限制等特性。源码中,你可以看到它使用了Striped64来实现并发控制,以及WeakReference和SoftReference来管理内存占用。Guava Cache的...