作者:Eddy 历史版本:1 最后编辑:龚清 更新时间:2024-11-20 15:41
适用版本:v3.3.6+;
dependency
<dependency>
<groupId>net.oschina.j2cache</groupId>
<artifactId>j2cache-core</artifactId>
<version>${j2cache-core.version}</version>
</dependency>
<dependency>
<groupId>net.oschina.j2cache</groupId>
<artifactId>j2cache-mybatis</artifactId>
<version>${j2cache.version}</version>
</dependency>
配置说明
j2cache.properties配置说明:
配置文件位于platform/business服务下的
config/j2cache.properties
文件# 缓存广播方法,支持 jgroups/redis/lettuce/rabbitmq/rocketmq j2cache.broadcast = lettuce # 第一二级缓存实现方式,一级支持 ehcache/caffeine, 二级支持 redis/lettuce/memcached j2cache.L1.provider_class = caffeine j2cache.L2.provider_class = lettuce # 在redis缓存数据中启用/禁用ttl(如果禁用,redis中的对象将永远不会过期,默认值:true) j2cache.sync_ttl_to_redis = true # 默认情况下是否缓存空对象(默认为false) j2cache.default_cache_null_object = true # 缓存序列化方式,支持 fst/kryo/fastjson/java/json/fse j2cache.serialization = kryo # caffeine配置文件 caffeine.properties = /config/caffeine.properties # 缓存名称空间可选,默认为[空] # redis存储模式 支持 generic/hash # 发布/订阅频道名称 lettuce.namespace = lettuce.storage = generic lettuce.channel = j2cache.platform
caffeine.properties配置说明:
- 配置文件位于platform/business服务下的
config/caffeine.properties
文件
#########################################
# Caffeine configuration
# [name] = size, xxxx[s|m|h|d]
#########################################
// 默认缓存,大小是 1000 个对象,TTL 是 30 分钟
// default 是当我们调用如下方法时:
//public void set(String region, String key, Object value)
//如果我们传入的 region 参数(假设为:region1)没有在 caffeine.properties 中定义的话,那 J2Cache 会自动创建一个名为 region1 的缓存 Region,其配置和 default 的配置一致。
default = 1000, 30m
ibps.context = 10000, 10m
ibps.sys = 10000, 1h
ibps.res = 10000, 1h
ibps.client = 3000, 1h
ibps.category = 10000, 2h
ibps.desktop = 1000, 8h
ibps.group = 1000, 1h
ibps.attr = 10000, 1h
ibps.level = 100, 1h
ibps.party = 10000, 1h
API说明
缓存的相关操作是在Domain和Repository层实现的,具体代码可以在 IBase,IRepository,AbstracDomain,AbstracRepository
中查看。
IBase
// 对象缓存是否启用 default boolean isCacheOpenning() // 对象缓存是否启用空对象缓存,v3.2.4配置 default boolean isCacheNullObject() // 返回缓存名称 default String getCacheName() // 返回内部缓存名称 default String getInternalCacheName() // 根据pk清除对应缓存 default void evict(PK pk) // 根据pk和data存入缓存 default void caching(PK pk, P data) // 返回内部类型 default String getInternalType() // 根据pk值返回存入缓存中的key值 default String getPKString(PK pk)
IRepository
// 列表缓存是否启用 default boolean isCacheListOpenning() // 是否跳过内部方法 default Boolean isSkipInternal() // 是否跳过缓存 default Boolean isSkipCache()
AbstracRepository
// 根据id值从缓存中获取到对应对象完整信息 public P get(PK id) // originSqlKey:查询所有字段的SqlKey,cacheSqlKey:只查询id字段的SqlKey,queryFilter:查询条件 public List<P> queryByKey(String originSqlKey, String cacheSqlKey, QueryFilter queryFilter)
使用示例
以 DefaultPartyUser
的仓库和领域类为例子
仓库
// DefaultPartyUserRepositoryImpl ... @Override public String getInternalCacheName() { return CacheKeyConstants.Region.REGION_IBPS_PARTY; // 返回对应的region名称 } @Override public String getInternalType() { return "DefaultPartyUser"; // 返回对应的类型名称,一般为类的名称即可 } @Override public void getInternal(DefaultPartyUserPo p) { if(BeanUtils.isEmpty(p)) { return; } partyEmployeeRepository.setSkipInternal(); PartyEmployeePo employeePo = partyEmployeeRepository.get(p.getId()); partyEmployeeRepository.removeSkipInternal(); if(BeanUtils.isEmpty(employeePo)) { return; } p.setFullname(employeePo.getName()); p.setName(employeePo.getName()); p.setStatus(employeePo.getStatus()); p.setGender(employeePo.getGender()); p.setMobile(employeePo.getMobile()); p.setEmail(employeePo.getEmail()); p.setAddress(employeePo.getAddress()); p.setQq(employeePo.getQq()); p.setPhoto(employeePo.getPhoto()); p.setWcAccount(employeePo.getWcAccount()); } @Override public List<DefaultPartyUserPo> findByParams(Map<String, Object> params) { return findByKey("findByParams", "findIdsByParams", params); } ...
领域
// DefaultPartyUser ... @Override public String getInternalCacheName() { return CacheKeyConstants.Region.REGION_IBPS_PARTY; // 返回对应的region名称 } @Override public String getInternalType() { return "DefaultPartyUser"; // 返回对应的类型名称,一般为类的名称即可 } ...
Provider
// PartyUserProvider ... @ApiOperation(value = "查询", notes = "根据id查询") @Override public APIResult<PartyUserPo> get( @ApiParam(name = "userId", value = "用户ID", required = true) @RequestParam(name = "userId", required = true)String userId) { APIResult<PartyUserPo> result = new APIResult<>(); try { PartyUserPo partyUserPo = defaultPartyUserRepository.get(userId); result.setData(partyUserPo); } catch (Exception e) { setExceptionResult(result, StateEnum.ERROR_EMPLOYEE.getCode(), I18nUtil.getMessage(StateEnum.ERROR_EMPLOYEE.getCode()+""), e); } return result; } ...
映射文件
// DefaultPartyUser.map <sql id="querySql"> SELECT * FROM IBPS_PARTY_USER left join ( select ID_ USER_ID_, NAME_, NAME_ FULL_NAME_,STATUS_,GENDER_,EMAIL_,WC_ACCOUNT_,ADDRESS_,MOBILE_,QQ_,PHOTO_ from IBPS_PARTY_EMPLOYEE )A on USER_ID_ = ID_ <where> USER_ID_ != '-1' AND A.STATUS_ != 'deleted' <if test="@o.Ognl@isNotEmpty(whereSql)"> and ${whereSql} </if> </where> <if test="@o.Ognl@isNotEmpty(orderBySql)"> ORDER BY ${orderBySql} </if> <if test="@o.Ognl@isEmpty(orderBySql)"> ORDER BY CREATE_TIME_ DESC </if> </sql> <select id="query" parameterType="java.util.Map" resultMap="DefaultPartyUser"> <include refid="querySql"/> </select> <select id="queryIds" parameterType="java.util.Map" resultMap="DefaultPartyUser"> SELECT ID_ FROM (<include refid="querySql"/>) T </select> <select id="findDialogUserByParam" parameterType="java.util.Map" resultMap="DefaultPartyUser"> <include refid="findDialogUserByParamSql"/> </select> <select id="findDialogUserIdsByParamNew" parameterType="java.util.Map" resultMap="DefaultPartyUser"> SELECT ID_ FROM (<include refid="findDialogUserByParamSql"/>) T </select>
缓存中对象是根据id值进行区分,映射文件中,除了常规的query
方法,还应该有只查询id字段的queryIds
方法,提供给缓存使用。findByKey
和queryByKey
方法同理,但非必须,写法参考如上代码。
仓库和领域类需要重写getInternalCacheName
方法,参考如上写法,返回对应的缓存分区。setSkipInternal
和 removeSkipInternal
方法为设置是否跳过内部方法,即是否跳过getInternal
方法,具体可查看AbstracReposity
类中的get
方法。
通过如上配置后,通过仓库的get
方法,传入对象的id值,会先去缓存中查找对象,缓存中没有,才会到数据库中查询。