From 6f8e03baf5774d8f439bbc0b89b105fa5bc54612 Mon Sep 17 00:00:00 2001 From: LamGC Date: Thu, 3 Sep 2020 14:03:18 +0800 Subject: [PATCH] =?UTF-8?q?[Add]=20=E6=B7=BB=E5=8A=A0CacheStore-API;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [Add] CacheStore 添加缓存存储容器父接口; [Add] CollectionCacheStore, SetCacheStore, ListCacheStore 添加集合型缓存存储容器接口; [Add] SingleCacheStore 添加单项缓存存储容器接口; [Add] Converter, StringConverter 添加数据类型转换器接口; [Add] CacheStoreFactory 添加CacheStore工厂接口; --- .../net/lamgc/cgj/bot/cache/CacheStore.java | 88 ++++++++++++++++++ .../cgj/bot/cache/CacheStoreFactory.java | 53 +++++++++++ .../cgj/bot/cache/CollectionCacheStore.java | 89 +++++++++++++++++++ .../net/lamgc/cgj/bot/cache/Converter.java | 42 +++++++++ .../lamgc/cgj/bot/cache/ListCacheStore.java | 72 +++++++++++++++ .../lamgc/cgj/bot/cache/SetCacheStore.java | 32 +++++++ .../lamgc/cgj/bot/cache/SingleCacheStore.java | 58 ++++++++++++ .../lamgc/cgj/bot/cache/StringConverter.java | 27 ++++++ 8 files changed, 461 insertions(+) create mode 100644 ContentGrabbingJi-CacheStore-api/src/main/java/net/lamgc/cgj/bot/cache/CacheStore.java create mode 100644 ContentGrabbingJi-CacheStore-api/src/main/java/net/lamgc/cgj/bot/cache/CacheStoreFactory.java create mode 100644 ContentGrabbingJi-CacheStore-api/src/main/java/net/lamgc/cgj/bot/cache/CollectionCacheStore.java create mode 100644 ContentGrabbingJi-CacheStore-api/src/main/java/net/lamgc/cgj/bot/cache/Converter.java create mode 100644 ContentGrabbingJi-CacheStore-api/src/main/java/net/lamgc/cgj/bot/cache/ListCacheStore.java create mode 100644 ContentGrabbingJi-CacheStore-api/src/main/java/net/lamgc/cgj/bot/cache/SetCacheStore.java create mode 100644 ContentGrabbingJi-CacheStore-api/src/main/java/net/lamgc/cgj/bot/cache/SingleCacheStore.java create mode 100644 ContentGrabbingJi-CacheStore-api/src/main/java/net/lamgc/cgj/bot/cache/StringConverter.java diff --git a/ContentGrabbingJi-CacheStore-api/src/main/java/net/lamgc/cgj/bot/cache/CacheStore.java b/ContentGrabbingJi-CacheStore-api/src/main/java/net/lamgc/cgj/bot/cache/CacheStore.java new file mode 100644 index 0000000..1ec905e --- /dev/null +++ b/ContentGrabbingJi-CacheStore-api/src/main/java/net/lamgc/cgj/bot/cache/CacheStore.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2020 LamGC + * + * ContentGrabbingJi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * ContentGrabbingJi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package net.lamgc.cgj.bot.cache; + +import java.util.Set; + +/** + * 缓存存储容器. + * 缓存库之间不应该出现干扰的情况, 即使允许在实现上共用一个存储. + * @author LamGC + */ +public interface CacheStore { + + /** + * 设置指定缓存的生存时间. + * 当该缓存项的 TTL 为 0 时, 该缓存项将会失效, 并被删除. + * 关于删除失效缓存项的时机在此并不特别规定, 依照各实现自行处理. + * @param key 欲设置过期时间的缓存项键名. + * @param ttl 有效期时间, 如果设为 -1 则代表清除缓存项的 TTL, 缓存项不会因为 TTL 为 0 而失效. 单位"毫秒(ms)". + * @return 如果设置成功, 返回 true, 如果设置失败, 或缓存项不存在, 返回 false. + * @throws NullPointerException 当 key 为 null 时抛出. + */ + boolean setTimeToLive(String key, long ttl); + + /** + * 查询指定缓存项的 TTL. + * @param key 欲查询 TTL 的缓存项键名. + * @return 如果缓存项存在且已设置 TTL, 则返回当前剩余 TTL, 如果缓存项不存在或未设置 TTL, 返回 -1. + * @throws NullPointerException 当 key 为 null 时抛出. + */ + long getTimeToLive(String key); + + /** + * 获取当前缓存项数量. + * @return 返回缓存项数量. + */ + long size(); + + /** + * 清空缓存存储容器. + * @return 操作成功返回 true. + */ + boolean clear(); + + /** + * 检查指定缓存项是否存在. + * 如果缓存项不存在或失效(比如因 TTL 为 0 而失效), 则会判定为不存在. + * 缓存项失效不代表不存在(因为根据实现的不同, 可能还没来得及清理失效缓存项), 但缓存项不存在一定是失效的(即便如此, 缓存项一旦失效, 便不可获取). + * 故后续除特殊情况使用"缓存项 失效"描述, 文档将以"缓存项不存在"描述缓存项失效或不存在的情况. + * @param key 缓存项键名 + * @return 如果存在, 返回 true, 如果不存在或失效, 返回 false. + * @throws NullPointerException 当 key 为 null 时抛出. + */ + boolean exists(String key); + + /** + * 删除指定缓存. + * @param key 欲删除的缓存项键名. + * @return 如果存在并删除成功, 返回 true. + * @throws NullPointerException 当 key 为 null 时抛出. + */ + boolean remove(String key); + + // 文档没有硬性要求"Set 中不能存在失效缓存项"的原因是因为: 即便确保了当时获取到的 Set 没有失效缓存项, + // 但是如果在获取后立刻出现失效缓存项了呢? 这个情况下依然不能保证没有失效的缓存项, 故不在文档中做出该硬性要求. + // 虽然是没说吧, 但是在返回时依然需要确保不会有过多失效缓存项的情况, 且获取时务必检查缓存项是否存在, 不要认为 Set 中的缓存项必然存在! + /** + * 获取缓存存储容器中的所有缓存项键名. + * @return 返回存储了所有缓存项键名的 Set 对象. + */ + Set keySet(); + +} diff --git a/ContentGrabbingJi-CacheStore-api/src/main/java/net/lamgc/cgj/bot/cache/CacheStoreFactory.java b/ContentGrabbingJi-CacheStore-api/src/main/java/net/lamgc/cgj/bot/cache/CacheStoreFactory.java new file mode 100644 index 0000000..59f4573 --- /dev/null +++ b/ContentGrabbingJi-CacheStore-api/src/main/java/net/lamgc/cgj/bot/cache/CacheStoreFactory.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2020 LamGC + * + * ContentGrabbingJi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * ContentGrabbingJi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package net.lamgc.cgj.bot.cache; + +/** + * 缓存存储容器构造工厂. + * 可支持不同实现缓存存储容器. + * @author LamGC + */ +public interface CacheStoreFactory { + + /** + * 获取一个新的 CacheStore 对象. + * @param identify 缓存标识. + * @param converter 类型的转换器. + * @return 返回 CacheStore 对象. + */ + SingleCacheStore newMapCacheStore(String identify, StringConverter converter); + + /** + * 获取一个新的有序列表缓存存储容器. + * @param identify 缓存标识. + * @param converter 元素类型与 String 的转换器. + * @param 元素类型. + * @return 返回新的有序列表缓存存储容器. + */ + ListCacheStore newListCacheStore(String identify, StringConverter converter); + + /** + * 获取一个新的无序集合缓存存储容器. + * @param identify 缓存标识. + * @param converter 元素类型与 String 的转换器. + * @param 元素类型. + * @return 返回新的无序集合缓存存储容器. + */ + SetCacheStore newSetCacheStore(String identify, StringConverter converter); + +} diff --git a/ContentGrabbingJi-CacheStore-api/src/main/java/net/lamgc/cgj/bot/cache/CollectionCacheStore.java b/ContentGrabbingJi-CacheStore-api/src/main/java/net/lamgc/cgj/bot/cache/CollectionCacheStore.java new file mode 100644 index 0000000..6da09c6 --- /dev/null +++ b/ContentGrabbingJi-CacheStore-api/src/main/java/net/lamgc/cgj/bot/cache/CollectionCacheStore.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2020 LamGC + * + * ContentGrabbingJi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * ContentGrabbingJi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package net.lamgc.cgj.bot.cache; + +import java.util.Collection; + +/** + * 集合型缓存存储容器. + * @param 元素类型. + * @author LamGC + */ +public interface CollectionCacheStore extends CacheStore> { + + /** + * 为缓存项添加一个元素. + * 当缓存项不存在时, 将会创建一个新的缓存项. + * @param key 缓存项键名. + * @param value 待添加的元素. + * @return 如果成功返回 true. + * @throws NullPointerException 当 key 或 value 为 null 时抛出; 本方法不允许存储 null 值, 因为 null 代表"没有/不存在". + */ + boolean addElement(String key, E value); + + /** + * 为缓存项添加一组元素. + * 当缓存项不存在时, 将会创建一个新的缓存项. + * @param key 缓存项键名. + * @param values 欲添加的元素集合. + * @return 如果成功添加, 返回 true, 如果无法添加(例如缓存项 List/Set 长度限制), 返回 false. + * @throws NullPointerException 当 key 或 value 为 null 时抛出; 本方法不允许存储 null 值, 因为 null 代表"没有/不存在". + */ + boolean addElements(String key, Collection values); + + /** + * 检查指定元素是否包含在指定缓存项中. + * @param key 待检查的缓存项键名. + * @param value 待查找的缓存值. + * @return 如果存在, 返回 true, 如果元素不存在, 或缓存项不存在, 返回 false. + * @throws NullPointerException 当 key 或 value 为 null 时抛出; 本方法不允许存储 null 值, 因为 null 代表"没有/不存在". + */ + boolean containsElement(String key, E value); + + /** + * 检查指定缓存项是否为空. + * @param key 待检查的缓存项键名. + * @return 如果缓存项无元素, 返回 true, 等效于 {@code elementsLength(key) == 0} + * @throws NullPointerException 当 key 为 null 时抛出. + */ + boolean isEmpty(String key); + + /** + * 获取指定缓存项中的元素数量. + * @param key 待获取元素的缓存项键名. + * @return 返回指定缓存项中的元素数量, 如果缓存项不存在, 返回 -1. + * @throws NullPointerException 当 key 为 null 时抛出. + */ + int elementsLength(String key); + + /** + * 清空集合中的所有元素. + * @return 操作成功返回 true. + */ + boolean clearCollection(); + + /** + * 删除缓存项中指定的元素. + * 该方法与 {@link CacheStore#remove(String)} 不同, 该方法仅删除缓存项中的指定元素, 即使删除后缓存项中没有元素, 也不会删除缓存项. + * @param key 待操作的缓存项键名. + * @param element 欲删除的元素. + * @return 如果元素存在且删除成功, 返回 true. + */ + boolean removeElement(String key, E element); + +} diff --git a/ContentGrabbingJi-CacheStore-api/src/main/java/net/lamgc/cgj/bot/cache/Converter.java b/ContentGrabbingJi-CacheStore-api/src/main/java/net/lamgc/cgj/bot/cache/Converter.java new file mode 100644 index 0000000..d45fdae --- /dev/null +++ b/ContentGrabbingJi-CacheStore-api/src/main/java/net/lamgc/cgj/bot/cache/Converter.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020 LamGC + * + * ContentGrabbingJi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * ContentGrabbingJi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package net.lamgc.cgj.bot.cache; + +/** + * 转换器接口 + * @param 源类型 + * @param 目标类型 + * @author LamGC + */ +public interface Converter { + + /** + * 将源类型对象转换成目标类型. + * @param source 源类型对象. + * @return 对应的目标类型对象. + */ + T to(S source); + + /** + * 从目标类型对象转换回源类型. + * @param target 目标类型对象. + * @return 对应的源类型对象. + */ + S from(T target); + +} diff --git a/ContentGrabbingJi-CacheStore-api/src/main/java/net/lamgc/cgj/bot/cache/ListCacheStore.java b/ContentGrabbingJi-CacheStore-api/src/main/java/net/lamgc/cgj/bot/cache/ListCacheStore.java new file mode 100644 index 0000000..533f99c --- /dev/null +++ b/ContentGrabbingJi-CacheStore-api/src/main/java/net/lamgc/cgj/bot/cache/ListCacheStore.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2020 LamGC + * + * ContentGrabbingJi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * ContentGrabbingJi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package net.lamgc.cgj.bot.cache; + +import java.util.List; + +/** + * List 类型的缓存存储容器. + * 该存储容器内的 List 与 {@link List} 概念相同, 即"有序列表". + * @param 值类型. + * @author LamGC + */ +public interface ListCacheStore extends CollectionCacheStore> { + + /** + * 获取缓存项中的指定元素. + * @param key 欲取值的缓存项键名. + * @param index 元素索引. + * @return 如果缓存项存在, 返回缓存项的值, 否则返回 null. + * @throws NullPointerException 当 key 为 null 时抛出. + */ + E getElement(String key, int index); + + /** + * 根据返回获取部分元素. + * @param key 欲取值的缓存项键值. + * @param index 起始元素索引. + * @param length 获取长度. + * @return 如果成功, 返回成功获取到的元素数量, 失败返回 null. + * 对于起始元素索引超出范围, 或获取长度与实际能获取的长度不同的情况, 不允许返回 null, + * 相反, 返回的 List 中的元素数量应反映实际所可获取的元素数量, 例如: + * 因 index 超出范围而无法获取元素, 则返回无元素 List 对象; + * 如果从起始元素开始获取无法获取 length 数量的元素, 则直接返回包含已成功获取元素的 List 对象. + * 但需要注意的是: 获取异常不包括在上述范围, 因此如果在获取中出现错误导致获取失败, 应以失败返回 null. + */ + List getElementsByRange(String key, int index, int length); + + /** + * 删除指定索引的元素. + * 该方法与 {@link CacheStore#remove(String)} 不同, 该方法仅删除缓存项中的指定元素, 即使删除后缓存项中没有元素, 也不会删除缓存项. + * @param key 待操作的缓存项键名. + * @param index 欲删除元素的索引. + * @return 如果元素存在且删除成功, 返回 true. + */ + boolean removeElement(String key, int index); + + /** + * 删除缓存项中指定的元素. + * 当 List 存在多个该元素时, 删除第一个匹配到的元素. + * 该方法与 {@link CacheStore#remove(String)} 不同, 该方法仅删除缓存项中的指定元素, 即使删除后缓存项中没有元素, 也不会删除缓存项. + * @param key 待操作的缓存项键名. + * @param element 欲删除的元素. + * @return 如果元素存在且删除成功, 返回 true. + */ + @Override + boolean removeElement(String key, List element); +} diff --git a/ContentGrabbingJi-CacheStore-api/src/main/java/net/lamgc/cgj/bot/cache/SetCacheStore.java b/ContentGrabbingJi-CacheStore-api/src/main/java/net/lamgc/cgj/bot/cache/SetCacheStore.java new file mode 100644 index 0000000..e7b5495 --- /dev/null +++ b/ContentGrabbingJi-CacheStore-api/src/main/java/net/lamgc/cgj/bot/cache/SetCacheStore.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2020 LamGC + * + * ContentGrabbingJi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * ContentGrabbingJi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package net.lamgc.cgj.bot.cache; + +import java.util.Set; + +/** + * 无序集合的缓存存储容器. + * @param 值类型. + * @author LamGC + */ +public interface SetCacheStore extends CollectionCacheStore> { + + + + +} diff --git a/ContentGrabbingJi-CacheStore-api/src/main/java/net/lamgc/cgj/bot/cache/SingleCacheStore.java b/ContentGrabbingJi-CacheStore-api/src/main/java/net/lamgc/cgj/bot/cache/SingleCacheStore.java new file mode 100644 index 0000000..03053cc --- /dev/null +++ b/ContentGrabbingJi-CacheStore-api/src/main/java/net/lamgc/cgj/bot/cache/SingleCacheStore.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2020 LamGC + * + * ContentGrabbingJi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * ContentGrabbingJi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package net.lamgc.cgj.bot.cache; + +/** + * 单项存取的缓存存储容器. + * 该缓存存储容器在存储上, 一个键对应一个值, 不存在一对多的情况. + * @param 值类型. + * @author LamGC + */ +public interface SingleCacheStore extends CacheStore { + + /** + * 设置指定键为指定值. + * 如果缓存项不存在, 则新建缓存并存储, 如果存在, 则覆盖原缓存; + * 覆盖缓存相当于是"删除"该缓存并重新创建, "删除"意味着原缓存项的相关设置将会丢失(例如"过期时间"). + * @param key 缓存项键名. + * @param value 缓存值. + * @return 如果成功返回 true. + * @throws NullPointerException 当 key 或 value 为 null 时抛出; 本方法不允许存储 null 值, 因为 null 代表"没有/不存在". + */ + boolean set(String key, V value); + + /** + * 设置指定键为指定值. + * 该方法与 {@link #set(String, Object)} 类似, 但如果该 key 已经存在缓存, 则不执行 set 操作并返回 false. + * @param key 缓存项键名. + * @param value 缓存值. + * @return 如果成功返回 true, 当 key 已存在, 或设置失败时返回 false. + * @throws NullPointerException 当 key 或 value 为 null 时抛出; 本方法不允许存储 null 值, 因为 null 代表"没有/不存在". + */ + @SuppressWarnings("AlibabaLowerCamelCaseVariableNaming") + boolean setIfNoExist(String key, V value); + + /** + * 获取缓存项值. + * @param key 欲取值的缓存项键名. + * @return 如果缓存项存在, 返回缓存项的值, 否则返回 null. + * @throws NullPointerException 当 key 为 null 时抛出. + */ + V get(String key); + +} diff --git a/ContentGrabbingJi-CacheStore-api/src/main/java/net/lamgc/cgj/bot/cache/StringConverter.java b/ContentGrabbingJi-CacheStore-api/src/main/java/net/lamgc/cgj/bot/cache/StringConverter.java new file mode 100644 index 0000000..f982de6 --- /dev/null +++ b/ContentGrabbingJi-CacheStore-api/src/main/java/net/lamgc/cgj/bot/cache/StringConverter.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2020 LamGC + * + * ContentGrabbingJi is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * ContentGrabbingJi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package net.lamgc.cgj.bot.cache; + +/** + * 某类型到字符串的转换器接口. + * @param 源类型. + * @author LamGC + */ +public interface StringConverter extends Converter { + +}