diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/config/CMSPublishConfig.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/config/CMSPublishConfig.java deleted file mode 100644 index 75dc0f64..00000000 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/config/CMSPublishConfig.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2022-2024 兮玥(190785909@qq.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.chestnut.contentcore.config; - -import com.chestnut.contentcore.config.properties.CMSPublishProperties; -import com.chestnut.contentcore.publish.IPublishTask; -import com.chestnut.contentcore.publish.PublishTaskReceiver; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.data.redis.connection.stream.Consumer; -import org.springframework.data.redis.connection.stream.MapRecord; -import org.springframework.data.redis.connection.stream.ReadOffset; -import org.springframework.data.redis.connection.stream.StreamOffset; -import org.springframework.data.redis.core.StringRedisTemplate; -import org.springframework.data.redis.stream.StreamMessageListenerContainer; -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; - -import java.time.Duration; -import java.util.Map; - -/** - * 内容发布配置 - * - * @author 兮玥 - * @email 190785909@qq.com - */ -@Slf4j -@Configuration -@EnableConfigurationProperties(CMSPublishProperties.class) -@RequiredArgsConstructor -public class CMSPublishConfig { - - private final CMSPublishProperties properties; - - private final StringRedisTemplate redisTemplate; - - private final Map> publishTaskMap; - - public static final String PublishStreamName = "ChestnutCMSPublishStream"; - - public static final String PublishConsumerGroup = "ChestnutCMSPublishConsumerGroup"; - - @Bean - public StreamMessageListenerContainer> streamMessageListenerContainer() { - // 启动清理消息队列数据 - if (properties.isClearOnStart()) { - redisTemplate.delete(PublishStreamName); - } - // 监听容器配置 - StreamMessageListenerContainer.StreamMessageListenerContainerOptions> streamMessageListenerContainerOptions = StreamMessageListenerContainer.StreamMessageListenerContainerOptions - .builder() - .batchSize(10) // 一次拉取消息数量 - .pollTimeout(Duration.ofSeconds(2)) // 拉取消息超时时间 - .executor(cmsPublishThreadPoolTaskExecutor()) - .build(); - // 创建监听容器 - StreamMessageListenerContainer> container = StreamMessageListenerContainer - .create(redisTemplate.getRequiredConnectionFactory(), streamMessageListenerContainerOptions); - //创建消费者组 - try { - redisTemplate.opsForStream().createGroup(PublishStreamName, PublishConsumerGroup); - } catch (Exception e) { - log.info("消费者组:{} 已存在", PublishConsumerGroup); - } - // 添加消费者 - for (int i = 0; i < properties.getConsumerCount(); i++) { - Consumer consumer = Consumer.from(PublishConsumerGroup, "cms-publish-consumer-" + i); - PublishTaskReceiver publishTaskReceiver = new PublishTaskReceiver(publishTaskMap, redisTemplate); - publishTaskReceiver.setConsumer(consumer); - container.receive(consumer, StreamOffset.create(PublishStreamName, ReadOffset.lastConsumed()), publishTaskReceiver); - } - container.start(); - return container; - } - - @Bean - ThreadPoolTaskExecutor cmsPublishThreadPoolTaskExecutor() { - ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); - executor.setThreadNamePrefix(properties.getPool().getThreadNamePrefix()); - executor.setCorePoolSize(properties.getPool().getCoreSize()); - executor.setQueueCapacity(properties.getPool().getQueueCapacity()); - executor.setMaxPoolSize(properties.getPool().getMaxSize()); - executor.setKeepAliveSeconds((int) properties.getPool().getKeepAlive().getSeconds()); - executor.setAllowCoreThreadTimeOut(this.properties.getPool().isAllowCoreThreadTimeout()); - executor.setWaitForTasksToCompleteOnShutdown(properties.getShutdown().isAwaitTermination()); - executor.setAwaitTerminationSeconds((int) properties.getShutdown().getAwaitTerminationPeriod().toSeconds()); - log.info("Cms publish task executor initialize: {}", executor.getThreadNamePrefix()); - executor.initialize(); - return executor; - } -} diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/listener/event/SiteThemeExportEvent.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/listener/event/SiteThemeExportEvent.java deleted file mode 100644 index 1a194d1b..00000000 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/listener/event/SiteThemeExportEvent.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.chestnut.contentcore.listener.event; - -import com.chestnut.contentcore.domain.CmsSite; -import jodd.io.ZipBuilder; -import lombok.Getter; -import org.springframework.context.ApplicationEvent; - -@Getter -public class SiteThemeExportEvent extends ApplicationEvent { - - private static final long serialVersionUID = 1L; - - private CmsSite site; - - private ZipBuilder zipBuilder; - - public SiteThemeExportEvent(Object source, CmsSite site, ZipBuilder zipBuilder) { - super(source); - this.site = site; - this.zipBuilder = zipBuilder; - } -} \ No newline at end of file diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/listener/event/SiteThemeImportEvent.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/listener/event/SiteThemeImportEvent.java deleted file mode 100644 index 8400abc0..00000000 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/listener/event/SiteThemeImportEvent.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.chestnut.contentcore.listener.event; - -import com.chestnut.common.security.domain.LoginUser; -import com.chestnut.contentcore.domain.CmsSite; -import lombok.Getter; -import org.springframework.context.ApplicationEvent; - -@Getter -public class SiteThemeImportEvent extends ApplicationEvent { - - private static final long serialVersionUID = 1L; - - private CmsSite site; - - private String destDir; - - private LoginUser operator; - - public SiteThemeImportEvent(Object source, CmsSite site, String destDir, LoginUser operator) { - super(source); - this.site = site; - this.destDir = destDir; - this.operator = operator; - } -} \ No newline at end of file diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/CatalogPublishTask.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/CatalogPublishTask.java deleted file mode 100644 index 32a371b7..00000000 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/CatalogPublishTask.java +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright 2022-2024 兮玥(190785909@qq.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.chestnut.contentcore.publish; - -import com.chestnut.common.async.AsyncTaskManager; -import com.chestnut.common.staticize.StaticizeService; -import com.chestnut.common.staticize.core.TemplateContext; -import com.chestnut.common.utils.IdUtils; -import com.chestnut.common.utils.StringUtils; -import com.chestnut.common.utils.file.FileExUtils; -import com.chestnut.contentcore.config.CMSPublishConfig; -import com.chestnut.contentcore.core.impl.CatalogType_Link; -import com.chestnut.contentcore.core.impl.PublishPipeProp_DefaultListTemplate; -import com.chestnut.contentcore.core.impl.PublishPipeProp_IndexTemplate; -import com.chestnut.contentcore.core.impl.PublishPipeProp_ListTemplate; -import com.chestnut.contentcore.domain.CmsCatalog; -import com.chestnut.contentcore.domain.CmsPublishPipe; -import com.chestnut.contentcore.domain.CmsSite; -import com.chestnut.contentcore.properties.MaxPageOnContentPublishProperty; -import com.chestnut.contentcore.service.ICatalogService; -import com.chestnut.contentcore.service.IPublishPipeService; -import com.chestnut.contentcore.service.ISiteService; -import com.chestnut.contentcore.service.ITemplateService; -import com.chestnut.contentcore.template.ITemplateType; -import com.chestnut.contentcore.template.impl.CatalogTemplateType; -import com.chestnut.contentcore.util.SiteUtils; -import com.chestnut.contentcore.util.TemplateUtils; -import freemarker.template.TemplateException; -import lombok.RequiredArgsConstructor; -import org.apache.commons.collections4.MapUtils; -import org.springframework.data.redis.connection.stream.MapRecord; -import org.springframework.data.redis.connection.stream.RecordId; -import org.springframework.data.redis.core.StringRedisTemplate; -import org.springframework.stereotype.Component; - -import java.io.File; -import java.io.IOException; -import java.time.Instant; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -/** - * 栏目发布任务 - * - * @author 兮玥 - * @email 190785909@qq.com - */ -@RequiredArgsConstructor -@Component(IPublishTask.BeanPrefix + CatalogPublishTask.Type) -public class CatalogPublishTask implements IPublishTask { - - public final static String Type = "catalog"; - - private final ISiteService siteService; - - private final ICatalogService catalogService; - - private final IPublishPipeService publishPipeService; - - private final ITemplateService templateService; - - private final StaticizeService staticizeService; - - private final StringRedisTemplate redisTemplate; - - @Override - public String getType() { - return Type; - } - - @Override - public void publish(CmsCatalog catalog) { - if (!catalog.isStaticize() || !catalog.isVisible() || CatalogType_Link.ID.equals(catalog.getCatalogType())) { - return; - } - String dataId = catalog.getCatalogId().toString(); - MapRecord record = MapRecord.create(CMSPublishConfig.PublishStreamName, Map.of( - "type", Type, - "id", dataId - )); - redisTemplate.opsForStream().add(record); - } - - @Override - public void staticize(Map dataMap) { - Long catalogId = MapUtils.getLong(dataMap, "id"); - if (IdUtils.validate(catalogId)) { - CmsCatalog catalog = this.catalogService.getCatalog(catalogId); - if (Objects.nonNull(catalog)) { - this.catalogStaticize(catalog); - } - } - } - public void catalogStaticize(CmsCatalog catalog) { - CmsSite site = this.siteService.getSite(catalog.getSiteId()); - int maxPage = MaxPageOnContentPublishProperty.getValue(site.getConfigProps()); - this.catalogStaticize(catalog, maxPage); - } - - public void catalogStaticize(CmsCatalog catalog, int pageMax) { - if (!catalog.isStaticize() || !catalog.isVisible() || CatalogType_Link.ID.equals(catalog.getCatalogType())) { - return; - } - List publishPipes = this.publishPipeService.getPublishPipes(catalog.getSiteId()); - for (CmsPublishPipe pp : publishPipes) { - this.doCatalogStaticize(catalog, pp.getCode(), pageMax); - } - } - - private void doCatalogStaticize(CmsCatalog catalog, String publishPipeCode, int pageMax) { - CmsSite site = this.siteService.getSite(catalog.getSiteId()); - if (!catalog.isStaticize()) { - logger.warn("【{}】未启用静态化的栏目跳过静态化:{}", publishPipeCode, catalog.getName()); - return; - } - if (!catalog.isVisible()) { - logger.warn("【{}】不可见状态的栏目跳过静态化:{}", publishPipeCode, catalog.getName()); - return; - } - if (CatalogType_Link.ID.equals(catalog.getCatalogType())) { - logger.warn("【{}】链接类型栏目跳过静态化:{}", publishPipeCode, catalog.getName()); - return; - } - String indexTemplate = PublishPipeProp_IndexTemplate.getValue(publishPipeCode, catalog.getPublishPipeProps()); - String listTemplate = PublishPipeProp_ListTemplate.getValue(publishPipeCode, catalog.getPublishPipeProps()); - if (StringUtils.isEmpty(listTemplate)) { - listTemplate = PublishPipeProp_DefaultListTemplate.getValue(publishPipeCode, site.getPublishPipeProps()); // 取站点默认模板 - } - File indexTemplateFile = this.templateService.findTemplateFile(site, indexTemplate, publishPipeCode); - File listTemplateFile = this.templateService.findTemplateFile(site, listTemplate, publishPipeCode); - if (indexTemplateFile == null && listTemplateFile == null) { - logger.warn(AsyncTaskManager.addErrMessage(StringUtils.messageFormat("[{0}]栏目首页模板和列表页模板未配置或不存在:{1}", - publishPipeCode, catalog.getCatalogId() + "#" + catalog.getName()))); - return; - } - String siteRoot = SiteUtils.getSiteRoot(site, publishPipeCode); - String dirPath = siteRoot + catalog.getPath(); - FileExUtils.mkdirs(dirPath); - String staticSuffix = site.getStaticSuffix(publishPipeCode); // 静态化文件类型 - - // 发布栏目首页 - long s = System.currentTimeMillis(); - if (Objects.nonNull(indexTemplateFile)) { - try { - String templateKey = SiteUtils.getTemplateKey(site, publishPipeCode, indexTemplate); - TemplateContext templateContext = new TemplateContext(templateKey, false, publishPipeCode); - templateContext.setDirectory(dirPath); - templateContext.setFirstFileName("index" + StringUtils.DOT + staticSuffix); - // init template variables - TemplateUtils.initGlobalVariables(site, templateContext); - // init templateType variables - ITemplateType templateType = templateService.getTemplateType(CatalogTemplateType.TypeId); - templateType.initTemplateData(catalog.getCatalogId(), templateContext); - // staticize - this.staticizeService.process(templateContext); - logger.debug("[{}]栏目首页模板解析:{},耗时:{}ms", publishPipeCode, catalog.getCatalogId() + "#" + catalog.getName(), (System.currentTimeMillis() - s)); - } catch (IOException | TemplateException e) { - logger.error(AsyncTaskManager.addErrMessage(StringUtils.messageFormat("[{0}]栏目首页解析失败:{1}", - publishPipeCode, catalog.getCatalogId() + "#" + catalog.getName())), e); - } - } - // 发布栏目列表页 - if (Objects.nonNull(listTemplateFile)) { - s = System.currentTimeMillis(); - try { - String templateKey = SiteUtils.getTemplateKey(site, publishPipeCode, listTemplate); - TemplateContext templateContext = new TemplateContext(templateKey, false, publishPipeCode); - templateContext.setMaxPageNo(pageMax); - templateContext.setDirectory(dirPath); - String name = Objects.nonNull(indexTemplateFile) ? "list" : "index"; - templateContext.setFirstFileName(name + StringUtils.DOT + staticSuffix); - templateContext.setOtherFileName( - name + "_" + TemplateContext.PlaceHolder_PageNo + StringUtils.DOT + staticSuffix); - // init template variables - TemplateUtils.initGlobalVariables(site, templateContext); - // init templateType variables - ITemplateType templateType = templateService.getTemplateType(CatalogTemplateType.TypeId); - templateType.initTemplateData(catalog.getCatalogId(), templateContext); - // staticize - this.staticizeService.process(templateContext); - logger.debug("[{}]栏目列表模板解析:{},耗时:{}ms", publishPipeCode, catalog.getCatalogId() + "#" + catalog.getName(), (System.currentTimeMillis() - s)); - } catch (Exception e1) { - logger.error(AsyncTaskManager.addErrMessage(StringUtils.messageFormat("[{0}]栏目列表页解析失败:{1}", - publishPipeCode, catalog.getCatalogId() + "#" + catalog.getName())), e1); - } - } - } -} diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/CmsStaticizeService.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/CmsStaticizeService.java deleted file mode 100644 index ca1512ce..00000000 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/CmsStaticizeService.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2022-2024 兮玥(190785909@qq.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.chestnut.contentcore.publish; - -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -import java.util.Map; - -/** - * CmsStaticizeService - * - * @author 兮玥 - * @email 190785909@qq.com - */ -@Service -@RequiredArgsConstructor -public class CmsStaticizeService { - - private final Map staticizeTypeMap; - - public IStaticizeType getStaticizeType(String type) { - return staticizeTypeMap.get(IStaticizeType.BEAN_PREFIX + type); - } -} - diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/ContentPublishTask.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/ContentPublishTask.java deleted file mode 100644 index 747f333e..00000000 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/ContentPublishTask.java +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Copyright 2022-2024 兮玥(190785909@qq.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.chestnut.contentcore.publish; - -import com.chestnut.common.async.AsyncTaskManager; -import com.chestnut.common.staticize.StaticizeService; -import com.chestnut.common.staticize.core.TemplateContext; -import com.chestnut.common.utils.IdUtils; -import com.chestnut.common.utils.StringUtils; -import com.chestnut.contentcore.config.CMSPublishConfig; -import com.chestnut.contentcore.core.IPublishPipeProp; -import com.chestnut.contentcore.core.impl.PublishPipeProp_ContentTemplate; -import com.chestnut.contentcore.domain.CmsCatalog; -import com.chestnut.contentcore.domain.CmsContent; -import com.chestnut.contentcore.domain.CmsPublishPipe; -import com.chestnut.contentcore.domain.CmsSite; -import com.chestnut.contentcore.service.*; -import com.chestnut.contentcore.template.ITemplateType; -import com.chestnut.contentcore.template.impl.ContentTemplateType; -import com.chestnut.contentcore.util.ContentUtils; -import com.chestnut.contentcore.util.SiteUtils; -import com.chestnut.contentcore.util.TemplateUtils; -import freemarker.template.TemplateException; -import lombok.RequiredArgsConstructor; -import org.apache.commons.collections4.MapUtils; -import org.springframework.data.redis.connection.stream.MapRecord; -import org.springframework.data.redis.connection.stream.RecordId; -import org.springframework.data.redis.core.StringRedisTemplate; -import org.springframework.stereotype.Component; - -import java.io.File; -import java.io.IOException; -import java.time.Instant; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -/** - * 内容发布任务 - * - * @author 兮玥 - * @email 190785909@qq.com - */ -@RequiredArgsConstructor -@Component(IPublishTask.BeanPrefix + ContentPublishTask.Type) -public class ContentPublishTask implements IPublishTask { - - public final static String Type = "content"; - - private final ISiteService siteService; - - private final ICatalogService catalogService; - - private final IContentService contentService; - - private final IPublishPipeService publishPipeService; - - private final ITemplateService templateService; - - private final StaticizeService staticizeService; - - private final StringRedisTemplate redisTemplate; - - @Override - public String getType() { - return Type; - } - - - @Override - public void publish(CmsContent content) { - CmsCatalog catalog = catalogService.getCatalog(content.getCatalogId()); - if (!catalog.isStaticize() || content.isLinkContent()) { - return; // 不静态化直接跳过,标题内容不需要静态化 - } - CmsSite site = siteService.getSite(content.getSiteId()); - List publishPipes = publishPipeService.getPublishPipes(content.getSiteId()); - // 判断内容是否有设置模板 - boolean hasTemplate = false; - for (CmsPublishPipe pp : publishPipes) { - final String detailTemplate = getDetailTemplate(site, catalog, content, pp.getCode()); - File templateFile = this.templateService.findTemplateFile(site, detailTemplate, pp.getCode()); - if (Objects.nonNull(templateFile)) { - hasTemplate = true; - break; - } - } - if (!hasTemplate) { - return; // 没有可用模板不需要静态化 - } - // 加入消息队列 - String dataId = content.getContentId().toString(); - MapRecord record = MapRecord.create(CMSPublishConfig.PublishStreamName, Map.of( - "type", Type, - "id", dataId - )); - redisTemplate.opsForStream().add(record); - } - - @Override - public void staticize(Map dataMap) { - Long contentId = MapUtils.getLong(dataMap, "id"); - if (IdUtils.validate(contentId)) { - CmsContent content = this.contentService.getById(contentId); - if (Objects.nonNull(content)) { - this.contentStaticize(content); - } - } - } - - public void contentStaticize(CmsContent cmsContent) { - List publishPipes = publishPipeService.getPublishPipes(cmsContent.getSiteId()); - // 发布内容 - for (CmsPublishPipe pp : publishPipes) { - doContentStaticize(cmsContent, pp.getCode()); - // 内容扩展模板静态化 - doContentExStaticize(cmsContent, pp.getCode()); - } - } - - private void doContentStaticize(CmsContent content, String publishPipeCode) { - CmsSite site = this.siteService.getSite(content.getSiteId()); - CmsCatalog catalog = this.catalogService.getCatalog(content.getCatalogId()); - if (!catalog.isStaticize()) { - logger.warn("[ {} ]栏目设置不静态化[ {}#{} ]:{}", publishPipeCode, site.getName(), - catalog.getName(), content.getTitle()); - return; // 不静态化直接跳过 - } - if (content.isLinkContent()) { - logger.warn("[ {} ]标题内容不需要静态化[ {}#{} ]:{}", publishPipeCode, site.getName(), - catalog.getName(), content.getTitle()); - return; // 标题内容不需要静态化 - } - final String detailTemplate = getDetailTemplate(site, catalog, content, publishPipeCode); - File templateFile = this.templateService.findTemplateFile(site, detailTemplate, publishPipeCode); - if (templateFile == null) { - logger.warn(AsyncTaskManager.addErrMessage( - StringUtils.messageFormat("[ {0} ]内容模板未设置或文件不存在[ {1}#{2} ]:{3}", - publishPipeCode, site.getName(), catalog.getName(), content.getTitle()))); - return; - } - try { - long s = System.currentTimeMillis(); - // 自定义模板上下文 - String templateKey = SiteUtils.getTemplateKey(site, publishPipeCode, detailTemplate); - TemplateContext templateContext = new TemplateContext(templateKey, false, publishPipeCode); - // init template datamode - TemplateUtils.initGlobalVariables(site, templateContext); - // init templateType data to datamode - ITemplateType templateType = this.templateService.getTemplateType(ContentTemplateType.TypeId); - templateType.initTemplateData(content.getContentId(), templateContext); - // 静态化文件地址 - this.setContentStaticPath(site, catalog, content, templateContext); - // 静态化 - this.staticizeService.process(templateContext); - logger.debug("[ {} ]内容详情页模板解析[ {}#{} ]:{},耗时:{}ms", publishPipeCode, site.getName(), - catalog.getName(), content.getTitle(), (System.currentTimeMillis() - s)); - } catch (TemplateException | IOException e) { - logger.error(AsyncTaskManager.addErrMessage(StringUtils.messageFormat("[{0}]内容详情页解析失败:[{1}]{2}", - publishPipeCode, catalog.getName(), content.getTitle())), e); - } - } - - private void setContentStaticPath(CmsSite site, CmsCatalog catalog, CmsContent content, TemplateContext context) { - String siteRoot = SiteUtils.getSiteRoot(site, context.getPublishPipeCode()); - if (StringUtils.isNotBlank(content.getStaticPath())) { - String dir = ""; - String filename = content.getStaticPath(); - if (filename.indexOf("/") > 0) { - dir = filename.substring(0, filename.lastIndexOf("/") + 1); - filename = filename.substring(filename.lastIndexOf("/") + 1); - } - context.setDirectory(siteRoot + dir); - context.setFirstFileName(filename); - String name = filename.substring(0, filename.lastIndexOf(".")); - String suffix = filename.substring(filename.lastIndexOf(".")); - context.setOtherFileName(name + "_" + TemplateContext.PlaceHolder_PageNo + suffix); - } else { - context.setDirectory(siteRoot + catalog.getPath()); - String suffix = site.getStaticSuffix(context.getPublishPipeCode()); - context.setFirstFileName(content.getContentId() + StringUtils.DOT + suffix); - context.setOtherFileName( - content.getContentId() + "_" + TemplateContext.PlaceHolder_PageNo + StringUtils.DOT + suffix); - } - } - - private void doContentExStaticize(CmsContent content, String publishPipeCode) { - CmsSite site = this.siteService.getSite(content.getSiteId()); - CmsCatalog catalog = this.catalogService.getCatalog(content.getCatalogId()); - if (!catalog.isStaticize()) { - logger.warn("[{}]栏目设置不静态化[{}#{}]:{}", publishPipeCode, site.getName(), catalog.getName(), content.getTitle()); - return; // 不静态化直接跳过 - } - if (content.isLinkContent()) { - logger.warn("[{}]标题内容不需要静态化[ {}#{} ]:{}", publishPipeCode, site.getName(), catalog.getName(), content.getTitle()); - return; // 标题内容不需要静态化 - } - String exTemplate = ContentUtils.getContentExTemplate(content, catalog, publishPipeCode); - if (StringUtils.isEmpty(exTemplate)) { - return; // 未设置扩展模板直接跳过 - } - File templateFile = this.templateService.findTemplateFile(site, exTemplate, publishPipeCode); - if (templateFile == null) { - logger.warn("[{}]内容扩展模板未设置或文件不存在[ {}#{} ]:{}", publishPipeCode, site.getName(), catalog.getName(), content.getTitle()); - return; - } - try { - long s = System.currentTimeMillis(); - // 自定义模板上下文 - String templateKey = SiteUtils.getTemplateKey(site, publishPipeCode, exTemplate); - TemplateContext templateContext = new TemplateContext(templateKey, false, publishPipeCode); - // init template datamode - TemplateUtils.initGlobalVariables(site, templateContext); - // init templateType data to datamode - ITemplateType templateType = this.templateService.getTemplateType(ContentTemplateType.TypeId); - templateType.initTemplateData(content.getContentId(), templateContext); - // 静态化文件地址 - String siteRoot = SiteUtils.getSiteRoot(site, publishPipeCode); - templateContext.setDirectory(siteRoot + catalog.getPath()); - String fileName = ContentUtils.getContextExFileName(content.getContentId(), site.getStaticSuffix(publishPipeCode)); - templateContext.setFirstFileName(fileName); - // 静态化 - this.staticizeService.process(templateContext); - logger.debug("[{}]内容扩展模板解析[ {}#{} ]:{},耗时:{}ms", publishPipeCode, site.getName(), - catalog.getName(), content.getTitle(), (System.currentTimeMillis() - s)); - } catch (TemplateException | IOException e) { - logger.error(AsyncTaskManager.addErrMessage(StringUtils.messageFormat("[{0}] 内容扩展模板解析失败 [{1}#{2}]:{3}", - publishPipeCode, site.getName(), catalog.getName(), content.getTitle())), e); - } - } - - private String getDetailTemplate(CmsSite site, CmsCatalog catalog, CmsContent content, String publishPipeCode) { - String detailTemplate = PublishPipeProp_ContentTemplate.getValue(publishPipeCode, - content.getPublishPipeProps()); - if (StringUtils.isEmpty(detailTemplate)) { - // 无内容独立模板取栏目配置 - detailTemplate = this.publishPipeService.getPublishPipePropValue( - IPublishPipeProp.DetailTemplatePropPrefix + content.getContentType(), publishPipeCode, - catalog.getPublishPipeProps()); - if (StringUtils.isEmpty(detailTemplate)) { - // 无栏目配置去站点默认模板配置 - detailTemplate = this.publishPipeService.getPublishPipePropValue( - IPublishPipeProp.DefaultDetailTemplatePropPrefix + content.getContentType(), publishPipeCode, - site.getPublishPipeProps()); - } - } - return detailTemplate; - } -} diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/IPublishStrategy.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/IPublishStrategy.java deleted file mode 100644 index ea889969..00000000 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/IPublishStrategy.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2022-2024 兮玥(190785909@qq.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.chestnut.contentcore.publish; - -/** - * IPublishStrategy - * - * @author 兮玥 - * @email 190785909@qq.com - */ -public interface IPublishStrategy { - - /** - * 发布策略ID - */ - String getId(); - - /** - * 创建发布任务 - * - * @param dataType 数据类型 - * @param dataId 数据ID - */ - void publish(String dataType, String dataId); - - /** - * 获取待处理发布任务数量 - */ - long getTaskCount(); - - /** - * 清空所有待处理发布任务 - */ - void cleanTasks(); -} diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/IPublishTask.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/IPublishTask.java deleted file mode 100644 index c780f49b..00000000 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/IPublishTask.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2022-2024 兮玥(190785909@qq.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.chestnut.contentcore.publish; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Map; - -/** - * - * - * @author 兮玥 - * @email 190785909@qq.com - */ -public interface IPublishTask { - - Logger logger = LoggerFactory.getLogger("publish"); - - String BeanPrefix = "PublishTask_"; - - String getType(); - - /** - * 创建发布任务 - */ - void publish(T data); - - /** - * 静态化 - */ - void staticize(Map dataMap); -} diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/IStaticizeType.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/IStaticizeType.java deleted file mode 100644 index 5397f6c5..00000000 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/IStaticizeType.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2022-2024 兮玥(190785909@qq.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.chestnut.contentcore.publish; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public interface IStaticizeType { - - Logger logger = LoggerFactory.getLogger("publish"); - - String BEAN_PREFIX = "CmsStaticizeType"; - - String getType(); - - void staticize(String dataId); -} diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/PublishTaskReceiver.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/PublishTaskReceiver.java deleted file mode 100644 index 3e3e689a..00000000 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/PublishTaskReceiver.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2022-2024 兮玥(190785909@qq.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.chestnut.contentcore.publish; - -import com.chestnut.contentcore.config.CMSPublishConfig; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import lombok.Setter; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections4.MapUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.data.redis.connection.stream.Consumer; -import org.springframework.data.redis.connection.stream.MapRecord; -import org.springframework.data.redis.core.StringRedisTemplate; -import org.springframework.data.redis.stream.StreamListener; - -import java.util.Map; -import java.util.Objects; - -/** - * 发布任务消费监听 - * - * @author 兮玥 - * @email 190785909@qq.com - */ -@Slf4j -@RequiredArgsConstructor -public class PublishTaskReceiver implements StreamListener> { - - private final static Logger logger = LoggerFactory.getLogger("publish"); - - private final Map> publishTaskMap; - - private final StringRedisTemplate redisTemplate; - - @Setter - @Getter - private Consumer consumer; - - @Override - public void onMessage(MapRecord message) { - String stream = message.getStream(); - if (Objects.nonNull(stream)) { - try { - Map map = message.getValue(); - String type = MapUtils.getString(map, "type"); - IPublishTask publishTask = publishTaskMap.get(IPublishTask.BeanPrefix + type); - if (Objects.nonNull(publishTask)) { - publishTask.staticize(map); - } - } catch(Exception e) { - logger.error("Publish err.", e); - } finally { - redisTemplate.opsForStream().acknowledge(stream, CMSPublishConfig.PublishConsumerGroup, message.getId().getValue()); - redisTemplate.opsForStream().delete(stream, message.getId().getValue()); - } - } - } -} diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/SitePublishTask.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/SitePublishTask.java deleted file mode 100644 index 46465f7c..00000000 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/SitePublishTask.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2022-2024 兮玥(190785909@qq.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.chestnut.contentcore.publish; - -import com.chestnut.common.async.AsyncTaskManager; -import com.chestnut.common.staticize.StaticizeService; -import com.chestnut.common.staticize.core.TemplateContext; -import com.chestnut.common.utils.IdUtils; -import com.chestnut.common.utils.JacksonUtils; -import com.chestnut.common.utils.StringUtils; -import com.chestnut.contentcore.config.CMSPublishConfig; -import com.chestnut.contentcore.domain.CmsSite; -import com.chestnut.contentcore.service.IPublishPipeService; -import com.chestnut.contentcore.service.ISiteService; -import com.chestnut.contentcore.service.ITemplateService; -import com.chestnut.contentcore.template.ITemplateType; -import com.chestnut.contentcore.template.impl.SiteTemplateType; -import com.chestnut.contentcore.util.SiteUtils; -import com.chestnut.contentcore.util.TemplateUtils; -import lombok.RequiredArgsConstructor; -import org.apache.commons.collections4.MapUtils; -import org.springframework.data.redis.connection.stream.MapRecord; -import org.springframework.data.redis.core.StringRedisTemplate; -import org.springframework.stereotype.Component; - -import java.io.File; -import java.util.Map; -import java.util.Objects; - -/** - * 站点发布任务 - * - * @author 兮玥 - * @email 190785909@qq.com - */ -@RequiredArgsConstructor -@Component(IPublishTask.BeanPrefix + SitePublishTask.Type) -public class SitePublishTask implements IPublishTask { - - public final static String Type = "site"; - - private final ISiteService siteService; - - private final IPublishPipeService publishPipeService; - - private final ITemplateService templateService; - - private final StaticizeService staticizeService; - - private final StringRedisTemplate redisTemplate; - - @Override - public String getType() { - return Type; - } - - @Override - public void publish(CmsSite site) { - String dataId = site.getSiteId().toString(); - MapRecord record = MapRecord.create(CMSPublishConfig.PublishStreamName, Map.of( - "type", Type, - "id", dataId - )); - redisTemplate.opsForStream().add(record); - } - - @Override - public void staticize(Map dataMap) { - logger.info("开始发布:" + JacksonUtils.to(dataMap)); - Long siteId = MapUtils.getLong(dataMap, "id"); - if (IdUtils.validate(siteId)) { - CmsSite site = this.siteService.getSite(siteId); - if (Objects.nonNull(site)) { - this.siteStaticize(site); - } - } - logger.info("结束发布:" + JacksonUtils.to(dataMap)); - } - - public void siteStaticize(CmsSite site) { - this.publishPipeService.getPublishPipes(site.getSiteId()) - .forEach(pp -> doSiteStaticize(site, pp.getCode())); - } - - private void doSiteStaticize(CmsSite site, String publishPipeCode) { - try { - AsyncTaskManager - .setTaskMessage(StringUtils.messageFormat("[{0}]正在发布站点首页:{1}", publishPipeCode, site.getName())); - - String indexTemplate = site.getIndexTemplate(publishPipeCode); - File templateFile = this.templateService.findTemplateFile(site, indexTemplate, publishPipeCode); - if (Objects.isNull(templateFile)) { - logger.warn(AsyncTaskManager.addErrMessage(StringUtils.messageFormat("[{0}]站点首页模板未配置或不存在:{1}", - publishPipeCode, site.getSiteId() + "#" + site.getName()))); - return; - } - // 模板ID = 通道:站点目录:模板文件名 - String templateKey = SiteUtils.getTemplateKey(site, publishPipeCode, indexTemplate); - TemplateContext context = new TemplateContext(templateKey, false, publishPipeCode); - // init template datamode - TemplateUtils.initGlobalVariables(site, context); - // init templateType data to datamode - ITemplateType templateType = templateService.getTemplateType(SiteTemplateType.TypeId); - templateType.initTemplateData(site.getSiteId(), context); - - long s = System.currentTimeMillis(); - context.setDirectory(SiteUtils.getSiteRoot(site, publishPipeCode)); - context.setFirstFileName("index" + StringUtils.DOT + site.getStaticSuffix(publishPipeCode)); - this.staticizeService.process(context); - logger.debug("[{}]首页模板解析:{},耗时:{}ms", publishPipeCode, site.getName(), (System.currentTimeMillis() - s)); - } catch (Exception e) { - logger.error(AsyncTaskManager.addErrMessage(StringUtils.messageFormat("[{0}][{1}]站点首页解析失败:{2}", - publishPipeCode, site.getName(), e.getMessage())), e); - } - } -} diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/staticize/CatalogStaticizeType.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/staticize/CatalogStaticizeType.java deleted file mode 100644 index c29d5cba..00000000 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/staticize/CatalogStaticizeType.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright 2022-2024 兮玥(190785909@qq.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.chestnut.contentcore.publish.staticize; - -import com.chestnut.common.async.AsyncTaskManager; -import com.chestnut.common.staticize.StaticizeService; -import com.chestnut.common.staticize.core.TemplateContext; -import com.chestnut.common.utils.IdUtils; -import com.chestnut.common.utils.StringUtils; -import com.chestnut.common.utils.file.FileExUtils; -import com.chestnut.contentcore.core.impl.CatalogType_Link; -import com.chestnut.contentcore.core.impl.PublishPipeProp_DefaultListTemplate; -import com.chestnut.contentcore.core.impl.PublishPipeProp_IndexTemplate; -import com.chestnut.contentcore.core.impl.PublishPipeProp_ListTemplate; -import com.chestnut.contentcore.domain.CmsCatalog; -import com.chestnut.contentcore.domain.CmsPublishPipe; -import com.chestnut.contentcore.domain.CmsSite; -import com.chestnut.contentcore.properties.MaxPageOnContentPublishProperty; -import com.chestnut.contentcore.publish.IStaticizeType; -import com.chestnut.contentcore.service.ICatalogService; -import com.chestnut.contentcore.service.IPublishPipeService; -import com.chestnut.contentcore.service.ISiteService; -import com.chestnut.contentcore.service.ITemplateService; -import com.chestnut.contentcore.template.ITemplateType; -import com.chestnut.contentcore.template.impl.CatalogTemplateType; -import com.chestnut.contentcore.util.SiteUtils; -import com.chestnut.contentcore.util.TemplateUtils; -import freemarker.template.TemplateException; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Component; - -import java.io.File; -import java.io.IOException; -import java.util.List; -import java.util.Objects; - -/** - * CatalogStaticizeType - * - * @author 兮玥 - * @email 190785909@qq.com - */ -@RequiredArgsConstructor -@Component(IStaticizeType.BEAN_PREFIX + CatalogStaticizeType.TYPE) -public class CatalogStaticizeType implements IStaticizeType { - - public static final String TYPE = "catalog"; - - private final ISiteService siteService; - - private final ICatalogService catalogService; - - private final IPublishPipeService publishPipeService; - - private final ITemplateService templateService; - - private final StaticizeService staticizeService; - - @Override - public String getType() { - return TYPE; - } - - @Override - public void staticize(String dataId) { - Long catalogId = Long.valueOf(dataId); - if (IdUtils.validate(catalogId)) { - CmsCatalog catalog = this.catalogService.getCatalog(catalogId); - if (Objects.nonNull(catalog)) { - this.catalogStaticize(catalog); - } - } - } - - public void catalogStaticize(CmsCatalog catalog) { - CmsSite site = this.siteService.getSite(catalog.getSiteId()); - int maxPage = MaxPageOnContentPublishProperty.getValue(site.getConfigProps()); - this.catalogStaticize(catalog, maxPage); - } - - public void catalogStaticize(CmsCatalog catalog, int pageMax) { - if (!catalog.isStaticize() || !catalog.isVisible() || CatalogType_Link.ID.equals(catalog.getCatalogType())) { - return; - } - List publishPipes = this.publishPipeService.getPublishPipes(catalog.getSiteId()); - for (CmsPublishPipe pp : publishPipes) { - this.doCatalogStaticize(catalog, pp.getCode(), pageMax); - } - } - - private void doCatalogStaticize(CmsCatalog catalog, String publishPipeCode, int pageMax) { - CmsSite site = this.siteService.getSite(catalog.getSiteId()); - if (!catalog.isStaticize()) { - logger.warn("【{}】未启用静态化的栏目跳过静态化:{}", publishPipeCode, catalog.getName()); - return; - } - if (!catalog.isVisible()) { - logger.warn("【{}】不可见状态的栏目跳过静态化:{}", publishPipeCode, catalog.getName()); - return; - } - if (CatalogType_Link.ID.equals(catalog.getCatalogType())) { - logger.warn("【{}】链接类型栏目跳过静态化:{}", publishPipeCode, catalog.getName()); - return; - } - String indexTemplate = PublishPipeProp_IndexTemplate.getValue(publishPipeCode, catalog.getPublishPipeProps()); - String listTemplate = PublishPipeProp_ListTemplate.getValue(publishPipeCode, catalog.getPublishPipeProps()); - if (StringUtils.isEmpty(listTemplate)) { - listTemplate = PublishPipeProp_DefaultListTemplate.getValue(publishPipeCode, site.getPublishPipeProps()); // 取站点默认模板 - } - File indexTemplateFile = this.templateService.findTemplateFile(site, indexTemplate, publishPipeCode); - File listTemplateFile = this.templateService.findTemplateFile(site, listTemplate, publishPipeCode); - if (indexTemplateFile == null && listTemplateFile == null) { - logger.warn(AsyncTaskManager.addErrMessage(StringUtils.messageFormat("[{0}]栏目首页模板和列表页模板未配置或不存在:{1}", - publishPipeCode, catalog.getCatalogId() + "#" + catalog.getName()))); - return; - } - String siteRoot = SiteUtils.getSiteRoot(site, publishPipeCode); - String dirPath = siteRoot + catalog.getPath(); - FileExUtils.mkdirs(dirPath); - String staticSuffix = site.getStaticSuffix(publishPipeCode); // 静态化文件类型 - - // 发布栏目首页 - long s = System.currentTimeMillis(); - if (Objects.nonNull(indexTemplateFile)) { - try { - String templateKey = SiteUtils.getTemplateKey(site, publishPipeCode, indexTemplate); - TemplateContext templateContext = new TemplateContext(templateKey, false, publishPipeCode); - templateContext.setDirectory(dirPath); - templateContext.setFirstFileName("index" + StringUtils.DOT + staticSuffix); - // init template variables - TemplateUtils.initGlobalVariables(site, templateContext); - // init templateType variables - ITemplateType templateType = templateService.getTemplateType(CatalogTemplateType.TypeId); - templateType.initTemplateData(catalog.getCatalogId(), templateContext); - // staticize - this.staticizeService.process(templateContext); - logger.debug("[{}]栏目首页模板解析:{},耗时:{}ms", publishPipeCode, catalog.getCatalogId() + "#" + catalog.getName(), (System.currentTimeMillis() - s)); - } catch (IOException | TemplateException e) { - logger.error(AsyncTaskManager.addErrMessage(StringUtils.messageFormat("[{0}]栏目首页解析失败:{1}", - publishPipeCode, catalog.getCatalogId() + "#" + catalog.getName())), e); - } - } - // 发布栏目列表页 - if (Objects.nonNull(listTemplateFile)) { - s = System.currentTimeMillis(); - try { - String templateKey = SiteUtils.getTemplateKey(site, publishPipeCode, listTemplate); - TemplateContext templateContext = new TemplateContext(templateKey, false, publishPipeCode); - templateContext.setMaxPageNo(pageMax); - templateContext.setDirectory(dirPath); - String name = Objects.nonNull(indexTemplateFile) ? "list" : "index"; - templateContext.setFirstFileName(name + StringUtils.DOT + staticSuffix); - templateContext.setOtherFileName( - name + "_" + TemplateContext.PlaceHolder_PageNo + StringUtils.DOT + staticSuffix); - // init template variables - TemplateUtils.initGlobalVariables(site, templateContext); - // init templateType variables - ITemplateType templateType = templateService.getTemplateType(CatalogTemplateType.TypeId); - templateType.initTemplateData(catalog.getCatalogId(), templateContext); - // staticize - this.staticizeService.process(templateContext); - logger.debug("[{}]栏目列表模板解析:{},耗时:{}ms", publishPipeCode, catalog.getCatalogId() + "#" + catalog.getName(), (System.currentTimeMillis() - s)); - } catch (Exception e1) { - logger.error(AsyncTaskManager.addErrMessage(StringUtils.messageFormat("[{0}]栏目列表页解析失败:{1}", - publishPipeCode, catalog.getCatalogId() + "#" + catalog.getName())), e1); - } - } - } -} diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/staticize/ContentStaticizeType.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/staticize/ContentStaticizeType.java deleted file mode 100644 index 0df893ee..00000000 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/staticize/ContentStaticizeType.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright 2022-2024 兮玥(190785909@qq.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.chestnut.contentcore.publish.staticize; - -import com.chestnut.common.async.AsyncTaskManager; -import com.chestnut.common.staticize.StaticizeService; -import com.chestnut.common.staticize.core.TemplateContext; -import com.chestnut.common.utils.IdUtils; -import com.chestnut.common.utils.StringUtils; -import com.chestnut.contentcore.core.IPublishPipeProp; -import com.chestnut.contentcore.core.impl.PublishPipeProp_ContentTemplate; -import com.chestnut.contentcore.domain.CmsCatalog; -import com.chestnut.contentcore.domain.CmsContent; -import com.chestnut.contentcore.domain.CmsPublishPipe; -import com.chestnut.contentcore.domain.CmsSite; -import com.chestnut.contentcore.publish.IStaticizeType; -import com.chestnut.contentcore.service.*; -import com.chestnut.contentcore.template.ITemplateType; -import com.chestnut.contentcore.template.impl.ContentTemplateType; -import com.chestnut.contentcore.util.ContentUtils; -import com.chestnut.contentcore.util.SiteUtils; -import com.chestnut.contentcore.util.TemplateUtils; -import freemarker.template.TemplateException; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Component; - -import java.io.File; -import java.io.IOException; -import java.util.List; -import java.util.Objects; - -/** - * ContentStaticizeType - * - * @author 兮玥 - * @email 190785909@qq.com - */ -@RequiredArgsConstructor -@Component(IStaticizeType.BEAN_PREFIX + ContentStaticizeType.TYPE) -public class ContentStaticizeType implements IStaticizeType { - - public static final String TYPE = "content"; - - private final ISiteService siteService; - - private final ICatalogService catalogService; - - private final IContentService contentService; - - private final IPublishPipeService publishPipeService; - - private final ITemplateService templateService; - - private final StaticizeService staticizeService; - - @Override - public String getType() { - return TYPE; - } - - @Override - public void staticize(String dataId) { - Long contentId = Long.valueOf(dataId); - if (IdUtils.validate(contentId)) { - CmsContent content = this.contentService.dao().getById(contentId); - if (Objects.nonNull(content)) { - this.contentStaticize(content); - } - } - } - - public void contentStaticize(CmsContent cmsContent) { - List publishPipes = publishPipeService.getPublishPipes(cmsContent.getSiteId()); - // 发布内容 - for (CmsPublishPipe pp : publishPipes) { - doContentStaticize(cmsContent, pp.getCode()); - // 内容扩展模板静态化 - doContentExStaticize(cmsContent, pp.getCode()); - } - } - - private void doContentStaticize(CmsContent content, String publishPipeCode) { - CmsSite site = this.siteService.getSite(content.getSiteId()); - CmsCatalog catalog = this.catalogService.getCatalog(content.getCatalogId()); - if (!catalog.isStaticize()) { - logger.warn("[ {} ]栏目设置不静态化[ {}#{} ]:{}", publishPipeCode, site.getName(), - catalog.getName(), content.getTitle()); - return; // 不静态化直接跳过 - } - if (content.isLinkContent()) { - logger.warn("[ {} ]标题内容不需要静态化[ {}#{} ]:{}", publishPipeCode, site.getName(), - catalog.getName(), content.getTitle()); - return; // 标题内容不需要静态化 - } - final String detailTemplate = getDetailTemplate(site, catalog, content, publishPipeCode); - File templateFile = this.templateService.findTemplateFile(site, detailTemplate, publishPipeCode); - if (templateFile == null) { - logger.warn(AsyncTaskManager.addErrMessage( - StringUtils.messageFormat("[ {0} ]内容模板未设置或文件不存在[ {1}#{2} ]:{3}", - publishPipeCode, site.getName(), catalog.getName(), content.getTitle()))); - return; - } - try { - long s = System.currentTimeMillis(); - // 自定义模板上下文 - String templateKey = SiteUtils.getTemplateKey(site, publishPipeCode, detailTemplate); - TemplateContext templateContext = new TemplateContext(templateKey, false, publishPipeCode); - // init template datamode - TemplateUtils.initGlobalVariables(site, templateContext); - // init templateType data to datamode - ITemplateType templateType = this.templateService.getTemplateType(ContentTemplateType.TypeId); - templateType.initTemplateData(content.getContentId(), templateContext); - // 静态化文件地址 - this.setContentStaticPath(site, catalog, content, templateContext); - // 静态化 - this.staticizeService.process(templateContext); - logger.debug("[ {} ]内容详情页模板解析[ {}#{} ]:{},耗时:{}ms", publishPipeCode, site.getName(), - catalog.getName(), content.getTitle(), (System.currentTimeMillis() - s)); - } catch (TemplateException | IOException e) { - logger.error(AsyncTaskManager.addErrMessage(StringUtils.messageFormat("[{0}]内容详情页解析失败:[{1}]{2}", - publishPipeCode, catalog.getName(), content.getTitle())), e); - } - } - - private void setContentStaticPath(CmsSite site, CmsCatalog catalog, CmsContent content, TemplateContext context) { - String siteRoot = SiteUtils.getSiteRoot(site, context.getPublishPipeCode()); - if (StringUtils.isNotBlank(content.getStaticPath())) { - String dir = ""; - String filename = content.getStaticPath(); - if (filename.indexOf("/") > 0) { - dir = filename.substring(0, filename.lastIndexOf("/") + 1); - filename = filename.substring(filename.lastIndexOf("/") + 1); - } - context.setDirectory(siteRoot + dir); - context.setFirstFileName(filename); - String name = filename.substring(0, filename.lastIndexOf(".")); - String suffix = filename.substring(filename.lastIndexOf(".")); - context.setOtherFileName(name + "_" + TemplateContext.PlaceHolder_PageNo + suffix); - } else { - context.setDirectory(siteRoot + catalog.getPath()); - String suffix = site.getStaticSuffix(context.getPublishPipeCode()); - context.setFirstFileName(content.getContentId() + StringUtils.DOT + suffix); - context.setOtherFileName( - content.getContentId() + "_" + TemplateContext.PlaceHolder_PageNo + StringUtils.DOT + suffix); - } - } - - private void doContentExStaticize(CmsContent content, String publishPipeCode) { - CmsSite site = this.siteService.getSite(content.getSiteId()); - CmsCatalog catalog = this.catalogService.getCatalog(content.getCatalogId()); - if (!catalog.isStaticize()) { - logger.warn("[{}]栏目设置不静态化[{}#{}]:{}", publishPipeCode, site.getName(), catalog.getName(), content.getTitle()); - return; // 不静态化直接跳过 - } - if (content.isLinkContent()) { - logger.warn("[{}]标题内容不需要静态化[ {}#{} ]:{}", publishPipeCode, site.getName(), catalog.getName(), content.getTitle()); - return; // 标题内容不需要静态化 - } - String exTemplate = ContentUtils.getContentExTemplate(content, catalog, publishPipeCode); - if (StringUtils.isEmpty(exTemplate)) { - return; // 未设置扩展模板直接跳过 - } - File templateFile = this.templateService.findTemplateFile(site, exTemplate, publishPipeCode); - if (templateFile == null) { - logger.warn("[{}]内容扩展模板未设置或文件不存在[ {}#{} ]:{}", publishPipeCode, site.getName(), catalog.getName(), content.getTitle()); - return; - } - try { - long s = System.currentTimeMillis(); - // 自定义模板上下文 - String templateKey = SiteUtils.getTemplateKey(site, publishPipeCode, exTemplate); - TemplateContext templateContext = new TemplateContext(templateKey, false, publishPipeCode); - // init template datamode - TemplateUtils.initGlobalVariables(site, templateContext); - // init templateType data to datamode - ITemplateType templateType = this.templateService.getTemplateType(ContentTemplateType.TypeId); - templateType.initTemplateData(content.getContentId(), templateContext); - // 静态化文件地址 - String siteRoot = SiteUtils.getSiteRoot(site, publishPipeCode); - templateContext.setDirectory(siteRoot + catalog.getPath()); - String fileName = ContentUtils.getContextExFileName(content.getContentId(), site.getStaticSuffix(publishPipeCode)); - templateContext.setFirstFileName(fileName); - // 静态化 - this.staticizeService.process(templateContext); - logger.debug("[{}]内容扩展模板解析[ {}#{} ]:{},耗时:{}ms", publishPipeCode, site.getName(), - catalog.getName(), content.getTitle(), (System.currentTimeMillis() - s)); - } catch (TemplateException | IOException e) { - logger.error(AsyncTaskManager.addErrMessage(StringUtils.messageFormat("[{0}] 内容扩展模板解析失败 [{1}#{2}]:{3}", - publishPipeCode, site.getName(), catalog.getName(), content.getTitle())), e); - } - } - - private String getDetailTemplate(CmsSite site, CmsCatalog catalog, CmsContent content, String publishPipeCode) { - String detailTemplate = PublishPipeProp_ContentTemplate.getValue(publishPipeCode, - content.getPublishPipeProps()); - if (StringUtils.isEmpty(detailTemplate)) { - // 无内容独立模板取栏目配置 - detailTemplate = this.publishPipeService.getPublishPipePropValue( - IPublishPipeProp.DetailTemplatePropPrefix + content.getContentType(), publishPipeCode, - catalog.getPublishPipeProps()); - if (StringUtils.isEmpty(detailTemplate)) { - // 无栏目配置去站点默认模板配置 - detailTemplate = this.publishPipeService.getPublishPipePropValue( - IPublishPipeProp.DefaultDetailTemplatePropPrefix + content.getContentType(), publishPipeCode, - site.getPublishPipeProps()); - } - } - return detailTemplate; - } -} diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/staticize/SiteStaticizeType.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/staticize/SiteStaticizeType.java deleted file mode 100644 index 3c5fe841..00000000 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/staticize/SiteStaticizeType.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2022-2024 兮玥(190785909@qq.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.chestnut.contentcore.publish.staticize; - -import com.chestnut.common.async.AsyncTaskManager; -import com.chestnut.common.staticize.StaticizeService; -import com.chestnut.common.staticize.core.TemplateContext; -import com.chestnut.common.utils.IdUtils; -import com.chestnut.common.utils.StringUtils; -import com.chestnut.contentcore.domain.CmsSite; -import com.chestnut.contentcore.publish.IStaticizeType; -import com.chestnut.contentcore.service.IPublishPipeService; -import com.chestnut.contentcore.service.ISiteService; -import com.chestnut.contentcore.service.ITemplateService; -import com.chestnut.contentcore.template.ITemplateType; -import com.chestnut.contentcore.template.impl.SiteTemplateType; -import com.chestnut.contentcore.util.SiteUtils; -import com.chestnut.contentcore.util.TemplateUtils; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Component; - -import java.io.File; -import java.util.Objects; - -/** - * SiteStaticizeType - * - * @author 兮玥 - * @email 190785909@qq.com - */ -@RequiredArgsConstructor -@Component(IStaticizeType.BEAN_PREFIX + SiteStaticizeType.TYPE) -public class SiteStaticizeType implements IStaticizeType { - - public static final String TYPE = "site"; - - private final ISiteService siteService; - - private final IPublishPipeService publishPipeService; - - private final ITemplateService templateService; - - private final StaticizeService staticizeService; - - @Override - public String getType() { - return TYPE; - } - - @Override - public void staticize(String dataId) { - Long siteId = Long.valueOf(dataId); - if (IdUtils.validate(siteId)) { - CmsSite site = this.siteService.getSite(siteId); - if (Objects.nonNull(site)) { - this.siteStaticize(site); - } - } - } - - public void siteStaticize(CmsSite site) { - this.publishPipeService.getPublishPipes(site.getSiteId()) - .forEach(pp -> doSiteStaticize(site, pp.getCode())); - } - - private void doSiteStaticize(CmsSite site, String publishPipeCode) { - try { - AsyncTaskManager - .setTaskMessage(StringUtils.messageFormat("[{0}]正在发布站点首页:{1}", publishPipeCode, site.getName())); - - String indexTemplate = site.getIndexTemplate(publishPipeCode); - File templateFile = this.templateService.findTemplateFile(site, indexTemplate, publishPipeCode); - if (Objects.isNull(templateFile)) { - logger.warn(AsyncTaskManager.addErrMessage(StringUtils.messageFormat("[{0}]站点首页模板未配置或不存在:{1}", - publishPipeCode, site.getSiteId() + "#" + site.getName()))); - return; - } - // 模板ID = 通道:站点目录:模板文件名 - String templateKey = SiteUtils.getTemplateKey(site, publishPipeCode, indexTemplate); - TemplateContext context = new TemplateContext(templateKey, false, publishPipeCode); - // init template datamode - TemplateUtils.initGlobalVariables(site, context); - // init templateType data to datamode - ITemplateType templateType = templateService.getTemplateType(SiteTemplateType.TypeId); - templateType.initTemplateData(site.getSiteId(), context); - - long s = System.currentTimeMillis(); - context.setDirectory(SiteUtils.getSiteRoot(site, publishPipeCode)); - context.setFirstFileName("index" + StringUtils.DOT + site.getStaticSuffix(publishPipeCode)); - this.staticizeService.process(context); - logger.debug("[{}]首页模板解析:{},耗时:{}ms", publishPipeCode, site.getName(), (System.currentTimeMillis() - s)); - } catch (Exception e) { - logger.error(AsyncTaskManager.addErrMessage(StringUtils.messageFormat("[{0}][{1}]站点首页解析失败:{2}", - publishPipeCode, site.getName(), e.getMessage())), e); - } - } -} diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/strategies/PublishTaskReceiver.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/strategies/PublishTaskReceiver.java deleted file mode 100644 index 6743c3ec..00000000 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/strategies/PublishTaskReceiver.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2022-2024 兮玥(190785909@qq.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.chestnut.contentcore.publish.strategies; - -import com.chestnut.contentcore.publish.CmsStaticizeService; -import com.chestnut.contentcore.publish.IStaticizeType; -import com.chestnut.contentcore.publish.strategies.RedisStreamPublishStrategy; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import lombok.Setter; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections4.MapUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.data.redis.connection.stream.Consumer; -import org.springframework.data.redis.connection.stream.MapRecord; -import org.springframework.data.redis.core.StringRedisTemplate; -import org.springframework.data.redis.stream.StreamListener; - -import java.util.Map; -import java.util.Objects; - -/** - * 发布任务消费监听 - * - * @author 兮玥 - * @email 190785909@qq.com - */ -@Slf4j -@RequiredArgsConstructor -public class PublishTaskReceiver implements StreamListener> { - - private final static Logger logger = LoggerFactory.getLogger("publish"); - - private final CmsStaticizeService cmsStaticizeService; - - private final StringRedisTemplate redisTemplate; - - @Setter - @Getter - private Consumer consumer; - - @Override - public void onMessage(MapRecord message) { - String stream = message.getStream(); - if (Objects.nonNull(stream)) { - try { - Map map = message.getValue(); - String type = MapUtils.getString(map, "type"); - - IStaticizeType staticizeType = cmsStaticizeService.getStaticizeType(type); - if (Objects.nonNull(staticizeType)) { - staticizeType.staticize(map.get("id")); - } - } catch(Exception e) { - logger.error("Publish err.", e); - } finally { - redisTemplate.opsForStream().acknowledge( - stream, - RedisStreamPublishStrategy.PublishConsumerGroup, - message.getId().getValue() - ); - redisTemplate.opsForStream().delete(stream, message.getId().getValue()); - } - } - } -} diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/strategies/RedisSetPublishStrategy.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/strategies/RedisSetPublishStrategy.java deleted file mode 100644 index d0ae6034..00000000 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/strategies/RedisSetPublishStrategy.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2022-2024 兮玥(190785909@qq.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.chestnut.contentcore.publish.strategies; - -import com.chestnut.common.async.AsyncTask; -import com.chestnut.contentcore.config.properties.CMSPublishProperties; -import com.chestnut.contentcore.publish.CmsStaticizeService; -import com.chestnut.contentcore.publish.IPublishStrategy; -import com.chestnut.contentcore.publish.IStaticizeType; -import lombok.RequiredArgsConstructor; -import org.springframework.boot.CommandLineRunner; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.data.redis.core.StringRedisTemplate; -import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; -import org.springframework.scheduling.support.PeriodicTrigger; -import org.springframework.stereotype.Component; - -import java.time.Duration; -import java.util.Objects; - -/** - * 发布策略:Redis Set - * - * @author 兮玥 - * @email 190785909@qq.com - */ -@Component -@RequiredArgsConstructor -@ConditionalOnProperty(prefix = CMSPublishProperties.PREFIX, name = "strategy", havingValue = RedisSetPublishStrategy.ID) -public class RedisSetPublishStrategy implements IPublishStrategy, CommandLineRunner { - - public static final String ID = "RedisSet"; - - static final String CACHE_NAME = "cms:publish:list"; - - private final StringRedisTemplate redisTemplate; - - private final CMSPublishProperties properties; - - private final CmsStaticizeService cmsStaticizeService; - - private final ThreadPoolTaskScheduler threadPoolTaskScheduler; - - @Override - public String getId() { - return ID; - } - - @Override - public void publish(String dataType, String dataId) { - redisTemplate.opsForSet().add(CACHE_NAME, dataType+"-"+dataId); - } - - @Override - public long getTaskCount() { - Long size = redisTemplate.opsForSet().size(CACHE_NAME); - return Objects.requireNonNullElse(size, 0L); - } - - @Override - public void cleanTasks() { - redisTemplate.opsForSet().remove(CACHE_NAME); - } - - @Override - public void run(String... args) throws Exception { - for (int i = 1; i <= properties.getConsumerCount(); i++) { - // 创建一个3秒间隔执行的定时任务 - PeriodicTrigger periodicTrigger = new PeriodicTrigger(Duration.ofSeconds(3L)); - periodicTrigger.setFixedRate(false); - - AsyncTask task = new AsyncTask() { - - @Override - public void run0() { - String data = null; - do { - try { - data = redisTemplate.opsForSet().pop(CACHE_NAME); - if (Objects.nonNull(data)) { - String[] split = data.split("-"); - String dataType = split[0]; - String dataId = split[1]; - - IStaticizeType staticizeType = cmsStaticizeService.getStaticizeType(dataType); - if (Objects.nonNull(staticizeType)) { - staticizeType.staticize(dataId); - } - } - } catch (Exception e) { - IStaticizeType.logger.error("静态化失败", e); - } - } while(Objects.nonNull(data)); - } - }; - task.setTaskId("cms-publish-" + i); - task.setType("CMS-PUBLISH"); - threadPoolTaskScheduler.schedule(task, periodicTrigger); - } - } -} diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/strategies/RedisStreamPublishStrategy.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/strategies/RedisStreamPublishStrategy.java deleted file mode 100644 index 9691460c..00000000 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/strategies/RedisStreamPublishStrategy.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2022-2024 兮玥(190785909@qq.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.chestnut.contentcore.publish.strategies; - -import com.chestnut.contentcore.config.properties.CMSPublishProperties; -import com.chestnut.contentcore.publish.CmsStaticizeService; -import com.chestnut.contentcore.publish.IPublishStrategy; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Bean; -import org.springframework.data.redis.connection.stream.*; -import org.springframework.data.redis.core.StringRedisTemplate; -import org.springframework.data.redis.stream.StreamMessageListenerContainer; -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; -import org.springframework.stereotype.Component; - -import java.time.Duration; -import java.util.Map; - -/** - * 发布策略:Redis Stream - * - * @author 兮玥 - * @email 190785909@qq.com - */ -@Slf4j -@Component -@RequiredArgsConstructor -@ConditionalOnProperty(prefix = CMSPublishProperties.PREFIX, name = "strategy", havingValue = RedisStreamPublishStrategy.ID) -public class RedisStreamPublishStrategy implements IPublishStrategy { - - public static final String ID = "RedisStream"; - - public static final String PublishStreamName = "ChestnutCMSPublishStream"; - - public static final String PublishConsumerGroup = "ChestnutCMSPublishConsumerGroup"; - - private final CMSPublishProperties properties; - - private final StringRedisTemplate redisTemplate; - - private final CmsStaticizeService cmsStaticizeService; - - @Override - public String getId() { - return ID; - } - - @Override - public void publish(String dataType, String dataId) { - MapRecord record = MapRecord.create(PublishStreamName, Map.of( - "type", dataType, - "id", dataId - )); - redisTemplate.opsForStream().add(record); - } - - @Override - public long getTaskCount() { - StreamInfo.XInfoStream info = redisTemplate.opsForStream().info(PublishStreamName); - return info.streamLength(); - } - - @Override - public void cleanTasks() { - try { - redisTemplate.delete(PublishStreamName); - redisTemplate.opsForStream().createGroup(PublishStreamName, PublishConsumerGroup); - } catch (Exception ignored) { - } - } - - @Bean - public StreamMessageListenerContainer> streamMessageListenerContainer() { - // 启动清理消息队列数据 - if (properties.isClearOnStart()) { - redisTemplate.delete(PublishStreamName); - } - // 监听容器配置 - StreamMessageListenerContainer.StreamMessageListenerContainerOptions> streamMessageListenerContainerOptions = StreamMessageListenerContainer.StreamMessageListenerContainerOptions - .builder() - .batchSize(10) // 一次拉取消息数量 - .pollTimeout(Duration.ofSeconds(2)) // 拉取消息超时时间 - .executor(cmsPublishThreadPoolTaskExecutor()) - .build(); - // 创建监听容器 - StreamMessageListenerContainer> container = StreamMessageListenerContainer - .create(redisTemplate.getRequiredConnectionFactory(), streamMessageListenerContainerOptions); - //创建消费者组 - try { - redisTemplate.opsForStream().createGroup(PublishStreamName, PublishConsumerGroup); - } catch (Exception e) { - log.info("消费者组:{} 已存在", PublishConsumerGroup); - } - // 添加消费者 - for (int i = 0; i < properties.getConsumerCount(); i++) { - Consumer consumer = Consumer.from(PublishConsumerGroup, "cms-publish-consumer-" + i); - PublishTaskReceiver publishTaskReceiver = new PublishTaskReceiver(cmsStaticizeService, redisTemplate); - publishTaskReceiver.setConsumer(consumer); - container.receive(consumer, StreamOffset.create(PublishStreamName, ReadOffset.lastConsumed()), publishTaskReceiver); - } - container.start(); - return container; - } - - @Bean - ThreadPoolTaskExecutor cmsPublishThreadPoolTaskExecutor() { - ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); - executor.setThreadNamePrefix(properties.getPool().getThreadNamePrefix()); - executor.setCorePoolSize(properties.getPool().getCoreSize()); - executor.setQueueCapacity(properties.getPool().getQueueCapacity()); - executor.setMaxPoolSize(properties.getPool().getMaxSize()); - executor.setKeepAliveSeconds((int) properties.getPool().getKeepAlive().getSeconds()); - executor.setAllowCoreThreadTimeOut(this.properties.getPool().isAllowCoreThreadTimeout()); - executor.setWaitForTasksToCompleteOnShutdown(properties.getShutdown().isAwaitTermination()); - executor.setAwaitTerminationSeconds((int) properties.getShutdown().getAwaitTerminationPeriod().toSeconds()); - log.info("Cms publish task executor initialize: {}", executor.getThreadNamePrefix()); - executor.initialize(); - return executor; - } -} diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/strategies/ThreadPoolPublishStrategy.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/strategies/ThreadPoolPublishStrategy.java deleted file mode 100644 index 491514b1..00000000 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/publish/strategies/ThreadPoolPublishStrategy.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2022-2024 兮玥(190785909@qq.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.chestnut.contentcore.publish.strategies; - -import com.chestnut.contentcore.config.properties.CMSPublishProperties; -import com.chestnut.contentcore.publish.CmsStaticizeService; -import com.chestnut.contentcore.publish.IPublishStrategy; -import com.chestnut.contentcore.publish.IStaticizeType; -import lombok.RequiredArgsConstructor; -import org.springframework.boot.CommandLineRunner; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; -import org.springframework.stereotype.Component; - -import java.util.Objects; -import java.util.concurrent.ThreadPoolExecutor; - -/** - * 发布策略:ThreadPool - * - * @author 兮玥 - * @email 190785909@qq.com - */ -@Component -@RequiredArgsConstructor -@ConditionalOnProperty(prefix = CMSPublishProperties.PREFIX, name = "strategy", havingValue = ThreadPoolPublishStrategy.ID) -public class ThreadPoolPublishStrategy implements IPublishStrategy, CommandLineRunner { - - public static final String ID = "ThreadPool"; - - private final CMSPublishProperties properties; - - private final CmsStaticizeService cmsStaticizeService; - - private ThreadPoolTaskExecutor threadPoolTaskExecutor; - - @Override - public String getId() { - return ID; - } - - @Override - public void publish(String dataType, String dataId) { - IStaticizeType staticizeType = cmsStaticizeService.getStaticizeType(dataType); - if (Objects.nonNull(staticizeType)) { - threadPoolTaskExecutor.execute(() -> staticizeType.staticize(dataId)); - } - } - - @Override - public long getTaskCount() { - // 返回线程池队列信息 - return threadPoolTaskExecutor.getQueueSize(); - } - - @Override - public void cleanTasks() { - // 清空线程池队列 - threadPoolTaskExecutor.getThreadPoolExecutor().getQueue().clear(); - } - - @Override - public void run(String... args) throws Exception { - ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); - executor.setThreadNamePrefix(properties.getPool().getThreadNamePrefix()); - executor.setCorePoolSize(properties.getPool().getCoreSize()); - executor.setQueueCapacity(properties.getPool().getQueueCapacity()); - executor.setMaxPoolSize(properties.getPool().getMaxSize()); - executor.setKeepAliveSeconds((int) properties.getPool().getKeepAlive().getSeconds()); - executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 默认池满使用调用线程执行 - executor.setAllowCoreThreadTimeOut(this.properties.getPool().isAllowCoreThreadTimeout()); - executor.setWaitForTasksToCompleteOnShutdown(properties.getShutdown().isAwaitTermination()); - executor.setAwaitTerminationSeconds((int) properties.getShutdown().getAwaitTerminationPeriod().toSeconds()); - executor.initialize(); - this.threadPoolTaskExecutor = executor; - } -} diff --git a/chestnut-cms/chestnut-cms-exmodel/src/main/java/com/chestnut/exmodel/domain/dto/XModelFieldDataDTO.java b/chestnut-cms/chestnut-cms-exmodel/src/main/java/com/chestnut/exmodel/domain/dto/XModelFieldDataDTO.java deleted file mode 100644 index 2ea8804e..00000000 --- a/chestnut-cms/chestnut-cms-exmodel/src/main/java/com/chestnut/exmodel/domain/dto/XModelFieldDataDTO.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.chestnut.exmodel.domain.dto; - -import com.chestnut.exmodel.CmsExtendMetaModelType; -import com.chestnut.xmodel.domain.XModelField; -import lombok.Getter; -import lombok.Setter; - -import java.util.List; -import java.util.Map; - -@Getter -@Setter -public class XModelFieldDataDTO { - - private String label; - - private String fieldName; - - private String controlType; - - private List> validations; - - private List> options; - - private Object value; - - private String valueSrc; - - public static XModelFieldDataDTO newInstance(XModelField field, String value) { - XModelFieldDataDTO dto = new XModelFieldDataDTO(); - dto.setLabel(field.getName()); - dto.setFieldName(CmsExtendMetaModelType.DATA_FIELD_PREFIX + field.getCode()); - dto.setControlType(field.getControlType()); - dto.setValidations(field.getValidations()); - dto.setValue(value); - return dto; - } -} \ No newline at end of file diff --git a/chestnut-cms/chestnut-cms-stat/src/main/java/com/chestnut/cms/stat/core/CmsStat.java b/chestnut-cms/chestnut-cms-stat/src/main/java/com/chestnut/cms/stat/core/CmsStat.java deleted file mode 100644 index 8afa7d2c..00000000 --- a/chestnut-cms/chestnut-cms-stat/src/main/java/com/chestnut/cms/stat/core/CmsStat.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.chestnut.cms.stat.core; - -import com.chestnut.cms.stat.domain.CmsSiteVisitLog; - -/** - * - * - * @author 兮玥 - * @email 190785909@qq.com - */ -public interface CmsStat { - - void deal(CmsSiteVisitLog log); -} \ No newline at end of file diff --git a/chestnut-cms/chestnut-cms-stat/src/main/java/com/chestnut/cms/stat/core/impl/CmsContentViewStat.java b/chestnut-cms/chestnut-cms-stat/src/main/java/com/chestnut/cms/stat/core/impl/CmsContentViewStat.java deleted file mode 100644 index fb71146f..00000000 --- a/chestnut-cms/chestnut-cms-stat/src/main/java/com/chestnut/cms/stat/core/impl/CmsContentViewStat.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.chestnut.cms.stat.core.impl; - -import com.chestnut.cms.stat.core.CmsStat; -import com.chestnut.cms.stat.domain.CmsSiteVisitLog; -import com.chestnut.contentcore.service.impl.ContentDynamicDataService; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Component; - -/** - * 内容动态浏览量统计 - * - * @author 兮玥 - * @email 190785909@qq.com - */ -@Component -@RequiredArgsConstructor -public class CmsContentViewStat implements CmsStat { - - private final ContentDynamicDataService contentDynamicDataService; - - @Override - public void deal(final CmsSiteVisitLog log) { - this.contentDynamicDataService.increaseViewCount(log.getContentId()); - } -} \ No newline at end of file diff --git a/chestnut-common/chestnut-common-core/src/main/java/com/chestnut/common/async/AsyncTaskExceptionHandler.java b/chestnut-common/chestnut-common-core/src/main/java/com/chestnut/common/async/AsyncTaskExceptionHandler.java deleted file mode 100644 index c87b4989..00000000 --- a/chestnut-common/chestnut-common-core/src/main/java/com/chestnut/common/async/AsyncTaskExceptionHandler.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.chestnut.common.async; - -import java.lang.reflect.Method; -import java.time.LocalDateTime; - -import org.apache.commons.lang3.ArrayUtils; -import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; - -import com.chestnut.common.async.enums.TaskStatus; - -import lombok.extern.slf4j.Slf4j; - -/** - * 异步任务异常处理器 - * - * @author 兮玥 - * @email 190785909@qq.com - */ -@Slf4j -public class AsyncTaskExceptionHandler implements AsyncUncaughtExceptionHandler { - - @Override - public void handleUncaughtException(Throwable ex, Method method, Object... params) { - if (ArrayUtils.isNotEmpty(params) && params[0] instanceof AsyncTask task) { - task.setStatus(TaskStatus.FAILED); - task.setEndTime(LocalDateTime.now()); - task.addErrorMessage(ex.getMessage()); - AsyncTaskManager.setTaskMessage("Async task failed:" + ex.getMessage()); - log.error("Async task failed:{}", ex.getMessage()); - } - } -} \ No newline at end of file diff --git a/chestnut-modules/chestnut-stat/src/main/java/com/chestnut/stat/IStatType.java b/chestnut-modules/chestnut-stat/src/main/java/com/chestnut/stat/IStatType.java deleted file mode 100644 index 4a3bb382..00000000 --- a/chestnut-modules/chestnut-stat/src/main/java/com/chestnut/stat/IStatType.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.chestnut.stat; - -import java.util.List; - -/** - * 统计类型 - * - *

- * 每一个统计类型对应一种统计数据的存储及展示,前端根据统计类型进行分类展示 - *

- * - * @author 兮玥 - * @email 190785909@qq.com - */ -public interface IStatType { - - /** - * 统计菜单树 - */ - public List getStatMenus(); -} \ No newline at end of file diff --git a/chestnut-modules/chestnut-stat/src/main/java/com/chestnut/stat/RequestEvent.java b/chestnut-modules/chestnut-stat/src/main/java/com/chestnut/stat/RequestEvent.java deleted file mode 100644 index 848f598a..00000000 --- a/chestnut-modules/chestnut-stat/src/main/java/com/chestnut/stat/RequestEvent.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.chestnut.stat; - -import java.time.LocalDateTime; - -import com.chestnut.common.utils.IP2RegionUtils; -import com.chestnut.common.utils.ServletUtils; -import com.chestnut.common.utils.StringUtils; - -import eu.bitwalker.useragentutils.UserAgent; -import jakarta.servlet.http.HttpServletRequest; -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -public class RequestEvent { - - /** - * 请求域 - */ - private String host; - - /** - * IP地址 - */ - private String ip; - - /** - * IP所属地区 - */ - private String address; - - /** - * 来源地址 - */ - private String referer; - - /** - * 浏览器类型 - */ - private String browser; - - /** - * UserAgent - */ - private String userAgent; - - /** - * 操作系统 - */ - private String os; - - /** - * 设备类型 - */ - private String deviceType; - - /** - * 语言 - */ - private String locale; - - /** - * 事件发生时间 - */ - private LocalDateTime evtTime; - - /** - * 提取request请求信息到RequestEvent - * - * @param request - */ - public void fill(HttpServletRequest request) { - this.setHost(request.getRemoteHost()); - this.setIp(ServletUtils.getIpAddr(request)); - this.setAddress(IP2RegionUtils.ip2Region(this.getIp())); - this.setReferer(ServletUtils.getReferer(request)); - this.setLocale(StringUtils.substringBefore(ServletUtils.getAcceptLanaguage(request), ",")); - - this.setUserAgent(ServletUtils.getUserAgent(request)); - UserAgent ua = ServletUtils.parseUserAgent(request); - this.setBrowser(ua.getBrowser().getName()); - this.setOs(ua.getOperatingSystem().getName()); - this.setDeviceType(ua.getOperatingSystem().getDeviceType().getName()); - } -} \ No newline at end of file diff --git a/chestnut-modules/chestnut-stat/src/main/java/com/chestnut/stat/StatMenu.java b/chestnut-modules/chestnut-stat/src/main/java/com/chestnut/stat/StatMenu.java deleted file mode 100644 index 4e71d3b6..00000000 --- a/chestnut-modules/chestnut-stat/src/main/java/com/chestnut/stat/StatMenu.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.chestnut.stat; - -/** - * 统计菜单 - * - * @author 兮玥 - * @email 190785909@qq.com - */ -public record StatMenu(String menuId, String parentId, String name, int sort) { - -} \ No newline at end of file diff --git a/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/intercepter/DemoModeIntercepter.java b/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/intercepter/DemoModeIntercepter.java deleted file mode 100644 index 3f5c2da4..00000000 --- a/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/intercepter/DemoModeIntercepter.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.chestnut.system.intercepter; - -import java.util.Objects; - -import org.springframework.http.HttpMethod; -import org.springframework.web.method.HandlerMethod; -import org.springframework.web.servlet.HandlerInterceptor; - -import com.chestnut.common.security.SecurityUtils; -import com.chestnut.common.security.exception.SecurityErrorCode; -import com.chestnut.system.annotation.IgnoreDemoMode; -import com.chestnut.system.security.StpAdminUtil; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import lombok.RequiredArgsConstructor; - -/** - * 演示模式拦截器 - */ -@RequiredArgsConstructor -public class DemoModeIntercepter implements HandlerInterceptor { - - @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) - throws Exception { - String method = request.getMethod(); - if (StpAdminUtil.isLogin() && SecurityUtils.isSuperAdmin(StpAdminUtil.getLoginIdAsLong())) { - return true; // 超级管理员允许操作 - } - // 非Get且无忽略演示模式注解则抛出异常 - if (HttpMethod.POST.matches(method) || HttpMethod.PUT.matches(method) || HttpMethod.DELETE.matches(method)) { - if (handler instanceof HandlerMethod handlerMethod) { - IgnoreDemoMode ignoreDemoMode = handlerMethod.getMethodAnnotation(IgnoreDemoMode.class); - if (Objects.isNull(ignoreDemoMode)) { - throw SecurityErrorCode.DEMO_EXCEPTION.exception(); - } - } - } - return true; - } -} \ No newline at end of file diff --git a/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/mapper/DataBaseMapper.java b/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/mapper/DataBaseMapper.java deleted file mode 100644 index 1ed25b32..00000000 --- a/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/mapper/DataBaseMapper.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2022-2024 兮玥(190785909@qq.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.chestnut.system.mapper; - -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Select; -import org.apache.ibatis.annotations.Update; - -public interface DataBaseMapper { - - /** - * 表字段是否存在 - * - * @param tableName - * @param columnName - * @return - */ - @Select("select count(*) from information_schema.columns where table_name = #{tableName} and column_name = #{columnName}") - public Integer isTableColumnExists(@Param("tableName") String tableName, @Param("columnName") String columnName); - - /** - * 添加表字段 - * - * @param tableName 表明 - * @param columnName 字段名 - * @param columnType 字段类型 - */ - @Update("alter table #{tableName} add column #{columnName} #{columnType}") - public void addTableColumn(@Param("tableName") String tableName, @Param("columnName") String columnName, - @Param("columnType") String columnType); - - /** - * 重命名表 - * - * @param oldName - * @param newName - */ - @Update("alter table #{oldTableName} rename #{newTableName}") - public void renameTable(String oldTableName, String newTableName); - - /** - * 清空表数据,自增清零 - * - * @param tableName - */ - @Update("truncate table ${tableName}") - public void truncateTable(@Param("tableName") String tableName); - - /** - * 当前数据库名 - */ - @Select("select database()") - public void getDatabaseName(); -} diff --git a/chestnut-ui/src/assets/images/alipay.png b/chestnut-ui/src/assets/images/alipay.png deleted file mode 100644 index 43b37926..00000000 Binary files a/chestnut-ui/src/assets/images/alipay.png and /dev/null differ diff --git a/chestnut-ui/src/assets/images/wxpay.png b/chestnut-ui/src/assets/images/wxpay.png deleted file mode 100644 index bf667605..00000000 Binary files a/chestnut-ui/src/assets/images/wxpay.png and /dev/null differ