One, add jetcache dependency
<dependency>
<groupId>com.alicp.jetcache</groupId>
<artifactId>jetcache-starter-redis-lettuce</artifactId>
<version>${jetcache.version}</version>
</dependency>
<dependency>
<groupId>com.alicp.jetcache</groupId>
<artifactId>jetcache-starter-redis</artifactId>
<version>${jetcache.version}</version>
</dependency>
Two, add configuration items
jetcache:
statIntervalMinutes: 15
areaInCacheName: false
local:
default:
type: linkedhashmap
keyConvertor: fastjson
remote:
default:
keyConvertor: fastjson
valueEncoder: kryo
valueDecoder: kryo
# redis
# type: redis
# host: 10.2.140.31
# port: 32263
# password: 123456
# database: 7
# lettuce
type: redis.lettuce
uri: redis://[email protected]:32263/7?timeout=5s
poolConfig:
minIdle: 5
maxIdle: 20
maxTotal: 50
Attributes | Defaults | Description |
---|---|---|
jetcache.statIntervalMinutes | 0 | Statistics interval, 0 means no statistics |
jetcache.areaInCacheName | true | jetcache-anno uses cacheName as the remote cache key prefix. Versions prior to 2.4.3 always add areaName to cacheName, so areaName also appears in the key prefix. It can be configured after 2.4.4. In order to maintain remote key compatibility, the default value is true, but false is more reasonable for new projects. |
jetcache.hiddenPackages | no | When @Cached and @CreateCache automatically generate the name, in order not to make the name too long, the package name prefix specified by hiddenPackages is truncated |
jetcache.[local|remote].${area}.type | no | Cache type. tair and redis are currently supported remote caches; linkedhashmap and caffeine are currently supported local cache types |
jetcache.[local|remote].${area}.keyConvertor | no | key global configuration of the converter, is currently only one has achieved keyConvertor: fastjson . It can be specified only when @CreateCache is used and the cache type is LOCAL none . At this time, the equals method is used to identify the key. Method cache must specify keyConvertor |
jetcache.[local|remote].${area}.valueEncoder | java | The global configuration of the serializer. Only the remote type cache needs to be specified, java and kryo are optional |
jetcache.[local|remote].${area}.valueDecoder | java | The global configuration of the serializer. Only the remote type cache needs to be specified, java and kryo are optional |
jetcache.[local|remote].${area}.limit | 100 | The global configuration of the largest element of each cache instance, only the local type of cache needs to be specified. Note that the limit of each cache instance, not all, for example, specify 100 here, and then use @CreateCache to create two cache instances (and the localLimit attribute is not set on the annotation), then the limit of each cache instance is 100 |
jetcache.[local|remote].${area}.expireAfterWriteInMillis | gigantic | Global configuration that specifies the timeout period in milliseconds (previously defaultExpireInMillis) |
jetcache.local.${area}.expireAfterAccessInMillis | 0 | Requires jetcache2.2 or more, in milliseconds, specify how long there is no access to invalidate the cache, currently only the local cache supports. 0 means that this function is not used. |
In the above table, ${area} corresponds to the area attributes of @Cached and @CreateCache. Note that if area is not specified in the annotation, the default value is "default".
Regarding the cache timeout period, there are multiple places to specify, please clarify:
- If the timeout time is specified on put and other methods, this time shall prevail
- No timeout is specified on put and other methods, and the default timeout of the Cache instance is used
- The default timeout time of the Cache instance is specified by the expire attribute on @CreateCache and @Cached. If not specified, the global configuration defined in yml is used. For example, @Cached(cacheType=local) uses jetcache.local.default.expireAfterWriteInMillis, if If it is still unspecified, it is infinite
Three, enable annotation caching
@EnableMethodCache(basePackages = "com.hikvision.smbg.content")
@EnableCreateCacheAnnotation
@Configuration
public class JetCacheConfig {
}
Fourth, the cache constant class
public class CacheConst {
public static class ContentDetail {
public static final String redisKeyPrefix = "content:detail:";
public static final int expire = 60 * 60 * 24;
}
public static class Content {
public static final int sign = 0;
public static final String redisKeyPrefix = "content:user:like:";
}
public static class Comment {
public static final int sign = 1;
public static final String redisKeyPrefix = "comment:user:like:";
}
public static class CommentReply {
public static final int sign = 2;
public static final String redisKeyPrefix = "commentReply:user:like:";
}
public static class CommentLike {
public static final String redisKeyPrefix = "comment:like:";
public static final int expire = 60;
}
public static class ContentView {
public static final String redisKeyPrefix = "content:view:";
public static final int expire = 60;
}
public static class ContentLike {
public static final String redisKeyPrefix = "content:like:";
public static final int expire = 60;
}
public static class ContentFavourite {
public static final String redisKeyPrefix = "content:favourite:";
public static final int expire = 60;
}
}
Five, annotation cache usage
(1) Generally, @Cached annotations are used to create caches on large data interfaces that do not change frequently, such as obtaining a detailed list, cache the data in redis, specify the key, expiration time, and so on.
@Cached(name = CacheConst.ContentDetail.redisKeyPrefix, key = "#response.contentId",
expire = CacheConst.ContentDetail.expire, timeUnit = TimeUnit.DAYS)
@Override
public ContentBaseResponse assembleDetail(ContentBaseResponse response) {
// 获取兴趣标签
List<Long> labelIds = this.listLabelIdsByContentId(response.getContentId());
response.setLabelIds(labelIds);
// 获取案例轮播图
List<String> picUrls = this.listPicUrlsByContentIdAndPicType(response.getContentId(), PicTypeEnum.MAIN.getCode());
response.setPicUrls(picUrls);
// 获取产品清单
List<GoodsResponse> goods = this.listGoodsByContentId(response.getContentId());
response.setGoods(goods);
// 获取附件列表
List<AttachResponse> attachs = this.listAttachByContentId(response.getContentId());
response.setAttachs(attachs);
// 获取评论
// List<CommentResponse> comments = this.listCommentByContentId(response.getContentId());
// response.setComments(comments);
return response;
}
4. When updating the details and list of the big data to be queried, add the @CacheInvalidate annotation to make it delete (destroy), so that the latest data will be cached in redis again when querying.
In this way, the ultimate consistency of the database is guaranteed
@CacheInvalidate(name = CacheConst.ContentDetail.redisKeyPrefix, key = "#contentId")
@Transactional(rollbackFor = Exception.class)
@Override
public void update(CaseUpdateRequest request, Long contentId) {
// 获取客户案例
CaseDO dataobject = getDataobjectByContentId(contentId);
// 客户案例权限校验
if (ContentFromEnum.MERCHANT.getCode().equals(dataobject.getCaseFrom())) {
String creator = dataobject.getCreator();
String modifier = request.getModifier();
if (!StringUtils.equals(creator, modifier)) {
throw new ContentCenterException(100002, "平台或商家【" + modifier + "】没有权限编辑客户案例【" + contentId + "】");
}
}
....
....
}