前言
⭐️ 在做微信小程序项目的时候,需要在 Java 后台暂时缓存 openid,以获取用户身份(openid 是公众号用户的唯一标识)
⭐️ 这操作让我想到了曾经做的项目的【登录】功能
💦 登录(客户端身份认证)有两种实现思路:
【1】基于 Cookie、Session
🌸 执行流程:
① 客户端:发送用户名和密码
② 服务器端:验证客户端发送的用户名和密码。验证成功后,创建并保留一个跟客户端相关联的 Session(把客户端信息缓存到 Session 中),返回 Session_ID 给客户端
③ 客户端:将 Session_ID 保存到 Cookie 中
④ 客户端:后续的请求都带上包含了 Session_ID 的 Cookie
⑤ 服务器:通过验证 Cookie 中的 Session_ID 确认用户身份
🌸 该方案的优点:
服务器、客户端基本自动完成一系列的流程,不用编程太多额外的代码
🌸 该方案的确定
在分布式架构下,需解决 Session 共享问题(分布式架构下 Session 默认无法共享)
不支持非浏览器环境(没有 Cookie 机制的环境,如:微信小程序)
【2】 基于 token
🌸 执行流程:
① 客户端:发送用户名和密码
② 服务器端:验证客户端发送的用户名和密码。验证成功后,生成一个跟客户端相关的 token,返回 token 给客户端
③ 客户端:存储 token 到本地
④ 客户端:后续的请求都带上 token
⑤ 服务器:通过 验证 token 确认用户身份
🌸 该方案优点:
支持分布式架构、支持非浏览器环境
🌸 该方案缺点:
需要客户端手动存储和发送 token
有些 token 会 比 Session_ID 大,需要消耗更多的流量
有些 token 方案默认无法在服务器端主动销毁 token
💦 方案一通过 Session【
request.getSession().setAttribute(k, v)
】缓存用户信息在服务器端。可通过 Session 的 key 把用户信息给移除掉,实现【让用户下线的功能】
💦 方案二可使用 Session 缓存用户信息(不推荐,在非浏览器环境或前后端分离的时候 Session 是不共享的)。最佳实践使用 Redis 环境用户信息,用 Redis 缓存用户信息一般是分布式架构的时候。单体应用的使用可使用简单的 Ehcache 框架。
下面是对 Ehcache 框架的基本介绍和基本使用(包括工具类的封装和配置文件解释)
一、EhCache 简介
🍀 EhCache 是一个纯 Java 的缓存框架。具有快速、精干等特点,是 Hibernate(一个持久层框架,类似 MyBatis) 中默认的 CacheProvider
🍀 EhCache 是一款简单易用的缓存框架。它支持 3 层缓存:Heap(JVM 的堆内存)、Off-Heap(堆外内存)、Disk(磁盘)。【Off-Heap 和 Disk 要求对象支持序列化和反序列化】
🍀 它简单易用,没有 Java 的 Session 在非浏览器环境或前后端分离时候的 Session 不共享情况;没有 Redis 框架的庞大(Redis 太高级了,常被使用于分布式架构),是单体应用中最好的缓存者。
https://www.ehcache.org/documentation/3.8/getting-started.html
二、简单使用(MAVEN 和 配置文件)
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xmlns='http://www.ehcache.org/v3'
xsi:schemaLocation="http://www.ehcache.org/v3
http://www.ehcache.org/schema/ehcache-core.xsd">
<!-- 需要把缓存数据存放到磁盘的时候, 存放到磁盘的该文件夹下 -->
<persistence directory="F:/ehcache"/>
<!--【公共的配置】-->
<cache-template name="common">
<!-- 缓存中存放的 key 和 value 都是 Object 类型 -->
<key-type>java.lang.Object</key-type>
<value-type>java.lang.Object</value-type>
<resources>
<!-- 堆中最多存放1000个对象 -->
<heap>1000</heap>
<!-- 堆外内存存放100MB -->
<!--<offheap unit="MB">100</offheap>-->
<!-- 服务器硬盘存放1GB -->
<!--<disk unit="GB" persistent="true">1</disk>-->
</resources>
</cache-template>
<!-- 用于缓存 token -->
<cache alias="token" uses-template="common">
<expiry>
<!-- 连续7天不访问就过期 -->
<tti unit="days">7</tti> <!--time to idle-->
</expiry>
</cache>
<!-- 用于缓存 openid -->
<cache alias="openid" uses-template="common">
<expiry>
<!-- 1天后自动过期 -->
<ttl unit="days">1</ttl>
</expiry>
</cache>
<!-- 用于缓存希望永不过期的数据 -->
<cache alias="default" uses-template="common">
<expiry>
<none/> <!--永不过期-->
</expiry>
</cache>
</config>
🌿 【cache】标签用于创建不同的缓存空间,不同的缓存空间缓存不同类型的数据。同一个缓存空间缓存的数据是相似的
🌿 【expiry】标签用于设置缓存的过期时间
🌿 【ttl】指定时间后缓存过期
🌿 【tti】指定时间内未使用缓存过期
三、简单使用(Ehcache 工具类)
需在工具类中读取配置文件 cache.xml,并编写【增删改】缓存数据的代码
/**
* 缓存工具类
*/
@SuppressWarnings("all")
public class EhCaches {
// 缓存管理器(只用初始化一次)
private static final CacheManager MGR;
private static final Cache<Object, Object> DEFAULT_CACHE;
private static final Cache<Object, Object> TOKEN_CACHE;
private static final Cache<Object, Object> OPENID_CACHE;
static {
/* 初始化缓存管理器 */
// 读取配置文件
URL url = Ehcache.class.getClassLoader().getResource("ehcache.xml");
assert url != null;
XmlConfiguration xmlConfiguration = new XmlConfiguration(url);
MGR = CacheManagerBuilder.newCacheManager(xmlConfiguration);
MGR.init();
/* 拿到缓存对象 */
DEFAULT_CACHE = MGR.getCache("default", Object.class, Object.class);
TOKEN_CACHE = MGR.getCache("token", Object.class, Object.class);
OPENID_CACHE = MGR.getCache("openid", Object.class, Object.class);
}
/* 增 */
public static void defaultPut(Object key, Object val) {
DEFAULT_CACHE.put(key, val);
}
public static void openidPut(Object key, Object val) {
OPENID_CACHE.put(key, val);
}
public static void tokenPut(Object key, Object val) {
TOKEN_CACHE.put(key, val);
}
/* 删 */
public static void defaultRemove(Object key) {
DEFAULT_CACHE.remove(key);
}
public static void openidRemove(Object key) {
OPENID_CACHE.remove(key);
}
public static void tokenRemove(Object key) {
TOKEN_CACHE.remove(key);
}
/* 查 */
public static <T> T defaultGet(Object key) {
return (T) DEFAULT_CACHE.get(key);
}
public static <T> T openidGet(Object key) {
return (T) OPENID_CACHE.get(key);
}
public static <T> T tokenGet(Object key) {
return (T) TOKEN_CACHE.get(key);
}
/* 清空所有 */
public static void defaultClear() {
DEFAULT_CACHE.clear();
}
public static void openidClear() {
OPENID_CACHE.clear();
}
public static void tokenClear() {
TOKEN_CACHE.clear();
}
}