init local code

This commit is contained in:
chenxing
2026-09-07 09:09:39 +08:00
commit 99cd26b3d2
259 changed files with 20554 additions and 0 deletions
@@ -0,0 +1,23 @@
package com.yunhai.cms.event;
/**
* 文章内容变更事件(保存修改/下架/删除)。事务提交后触发缓存失效(方案 §8.4)。
*/
public class ArticleChangedEvent {
private final Integer articleId;
private final Integer siteId;
public ArticleChangedEvent(Integer articleId, Integer siteId) {
this.articleId = articleId;
this.siteId = siteId;
}
public Integer getArticleId() {
return articleId;
}
public Integer getSiteId() {
return siteId;
}
}
@@ -0,0 +1,31 @@
package com.yunhai.cms.event;
/**
* 文章发布事件(方案 §7.4 微信预留挂点):事务提交后由 AFTER_COMMIT 监听器消费。
* 本期监听方 = 缓存失效 + WeChatPushService(Noop 实现,零外联);
* 启用《微信平台对接方案》时仅替换 Noop 实现,零表结构变更。
*/
public class ArticlePublishedEvent {
private final Integer articleId;
private final Integer siteId;
private final String title;
public ArticlePublishedEvent(Integer articleId, Integer siteId, String title) {
this.articleId = articleId;
this.siteId = siteId;
this.title = title;
}
public Integer getArticleId() {
return articleId;
}
public Integer getSiteId() {
return siteId;
}
public String getTitle() {
return title;
}
}
@@ -0,0 +1,26 @@
package com.yunhai.cms.event;
/**
* 站点内容/结构变更事件:站点本身、栏目树、轮播、友链 任一变更即发,
* 门户站点快照缓存(cms:site)整体失效 + 列表缓存清除(方案 §8.4)。
*/
public class SiteContentChangedEvent {
private final Integer siteId;
/** 变更来源说明(日志用):site/category/banner/link */
private final String scope;
public SiteContentChangedEvent(Integer siteId, String scope) {
this.siteId = siteId;
this.scope = scope;
}
public Integer getSiteId() {
return siteId;
}
public String getScope() {
return scope;
}
}
@@ -0,0 +1,60 @@
package com.yunhai.cms.event.listener;
import com.yunhai.cms.config.CacheNames;
import com.yunhai.cms.event.ArticleChangedEvent;
import com.yunhai.cms.event.ArticlePublishedEvent;
import com.yunhai.cms.event.SiteContentChangedEvent;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Component;
import org.springframework.transaction.event.TransactionPhase;
import org.springframework.transaction.event.TransactionalEventListener;
/**
* 门户缓存失效监听(方案 §8.4):全部 AFTER_COMMIT(fallbackExecution=true 兼容
* 定时任务等无事务路径),失效失败仅记日志,靠 TTL 自愈。
*
* <p>cms:list / cms:site 的 key 含分页与站点维度,MVP 直接整缓存 clear:
* 单实例 Caffeine、站点 ≤20,clear 成本可忽略;精确 evict 留给 Redis 演进。
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class PortalCacheEvictListener {
private final CacheManager cacheManager;
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT, fallbackExecution = true)
public void onArticlePublished(ArticlePublishedEvent event) {
evictArticle(event.getArticleId());
clear(CacheNames.LIST);
}
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT, fallbackExecution = true)
public void onArticleChanged(ArticleChangedEvent event) {
evictArticle(event.getArticleId());
clear(CacheNames.LIST);
}
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT, fallbackExecution = true)
public void onSiteContentChanged(SiteContentChangedEvent event) {
clear(CacheNames.SITE);
clear(CacheNames.LIST);
}
private void evictArticle(Integer articleId) {
Cache cache = cacheManager.getCache(CacheNames.ARTICLE);
if (cache != null && articleId != null) {
cache.evict(articleId);
}
}
private void clear(String cacheName) {
Cache cache = cacheManager.getCache(cacheName);
if (cache != null) {
cache.clear();
}
}
}
@@ -0,0 +1,24 @@
package com.yunhai.cms.event.listener;
import com.yunhai.cms.event.ArticlePublishedEvent;
import com.yunhai.cms.service.WeChatPushService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.event.TransactionPhase;
import org.springframework.transaction.event.TransactionalEventListener;
/**
* 文章发布 → 微信推送挂点(方案 §7.4 后端层预留)。
* 事务提交后才触发,保证推送方读到的数据已落库;推送失败不影响业务事务。
*/
@Component
@RequiredArgsConstructor
public class WeChatPushListener {
private final WeChatPushService weChatPushService;
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT, fallbackExecution = true)
public void onArticlePublished(ArticlePublishedEvent event) {
weChatPushService.onArticlePublished(event);
}
}