diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/controller/CatalogController.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/controller/CatalogController.java index 3f2e1104..2a779630 100644 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/controller/CatalogController.java +++ b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/controller/CatalogController.java @@ -157,7 +157,7 @@ public class CatalogController extends BaseRestController { AsyncTask task = new AsyncTask() { @Override - public void run0() throws Exception { + public void run0() { catalogService.deleteCatalog(catalogId, operator); } }; diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/listener/ContentCoreListener.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/listener/ContentCoreListener.java index 50a5cd27..d3dd6e66 100644 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/listener/ContentCoreListener.java +++ b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/listener/ContentCoreListener.java @@ -181,38 +181,33 @@ public class ContentCoreListener { public void afterContentOffline(AfterContentOfflineEvent event) { final Long contentId = event.getContent().getContentEntity().getContentId(); final String operator = event.getContent().getOperator().getUsername(); - AsyncTask task = new AsyncTask() { - - @Override - public void run0() throws Exception { - // 映射关联内容同步下线 - List mappingList = contentService.lambdaQuery() - .gt(CmsContent::getCopyType, ContentCopyType.Mapping) - .eq(CmsContent::getCopyId, contentId).list(); - for (CmsContent c : mappingList) { - if (ContentStatus.PUBLISHED == c.getStatus()) { - try { - contentService.deleteStaticFiles(c); - } catch (IOException e) { - e.printStackTrace(); - } + asyncTaskManager.execute(() -> { + // 映射关联内容同步下线 + List mappingList = contentService.lambdaQuery() + .gt(CmsContent::getCopyType, ContentCopyType.Mapping) + .eq(CmsContent::getCopyId, contentId).list(); + for (CmsContent c : mappingList) { + if (ContentStatus.PUBLISHED == c.getStatus()) { + try { + contentService.deleteStaticFiles(c); + } catch (IOException e) { + e.printStackTrace(); } - c.setStatus(ContentStatus.OFFLINE); - c.updateBy(operator); } - contentService.updateBatchById(mappingList); - // 标题内容同步下线 - String internalUrl = InternalUrlUtils.getInternalUrl(InternalDataType_Content.ID, contentId); - List linkList = contentService.lambdaQuery().eq(CmsContent::getLinkFlag, YesOrNo.YES) - .eq(CmsContent::getRedirectUrl, internalUrl).list(); - for (CmsContent c : linkList) { - c.setStatus(ContentStatus.OFFLINE); - c.updateBy(operator); - } - mappingList.addAll(linkList); - contentService.updateBatchById(mappingList); + c.setStatus(ContentStatus.OFFLINE); + c.updateBy(operator); } - }; - this.asyncTaskManager.execute(task); + contentService.updateBatchById(mappingList); + // 标题内容同步下线 + String internalUrl = InternalUrlUtils.getInternalUrl(InternalDataType_Content.ID, contentId); + List linkList = contentService.lambdaQuery().eq(CmsContent::getLinkFlag, YesOrNo.YES) + .eq(CmsContent::getRedirectUrl, internalUrl).list(); + for (CmsContent c : linkList) { + c.setStatus(ContentStatus.OFFLINE); + c.updateBy(operator); + } + mappingList.addAll(linkList); + contentService.updateBatchById(mappingList); + }); } } diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/service/impl/ContentServiceImpl.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/service/impl/ContentServiceImpl.java index 853c2ebe..999350d9 100644 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/service/impl/ContentServiceImpl.java +++ b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/service/impl/ContentServiceImpl.java @@ -202,7 +202,7 @@ public class ContentServiceImpl extends ServiceImpl { + // 发布内容 + Set catalogIds = new HashSet<>(); + for (CmsContent cmsContent : list) { + IContentType contentType = ContentCoreUtils.getContentType(cmsContent.getContentType()); + IContent content = contentType.loadContent(cmsContent); + content.setOperator(operator); - @Override - public void run0() { - // 发布内容 - Set catalogIds = new HashSet<>(); - for (CmsContent cmsContent : list) { - IContentType contentType = ContentCoreUtils.getContentType(cmsContent.getContentType()); - IContent content = contentType.loadContent(cmsContent); - content.setOperator(operator); - - catalogIds.add(cmsContent.getCatalogId()); - if (content.publish()) { - applicationContext.publishEvent(new AfterContentPublishEvent(contentType, content)); - } + catalogIds.add(cmsContent.getCatalogId()); + if (content.publish()) { + applicationContext.publishEvent(new AfterContentPublishEvent(contentType, content)); } - // 发布关联栏目:内容所属栏目及其所有父级栏目 - Map catalogMap = new HashMap<>(); - catalogIds.forEach(catalogId -> { - CmsCatalog catalog = catalogService.getCatalog(catalogId); - catalogMap.put(catalog.getCatalogId(), catalog); - long parentId = catalog.getParentId(); - while (parentId > 0) { - CmsCatalog parent = catalogService.getCatalog(parentId); - if (parent == null) { - break; - } - catalogMap.put(parent.getCatalogId(), parent); - parentId = parent.getParentId(); - } - }); - CmsSite site = siteService.getSite(list.get(0).getSiteId()); - catalogMap.values().forEach(c -> asyncPublishCatalog(c)); - // 发布站点首页 - asyncPublishSite(site); } - }; - asyncTask.setType("Publish"); - asyncTask.setTaskId("Publish-Content"); - this.asyncTaskManager.execute(asyncTask); + // 发布关联栏目:内容所属栏目及其所有父级栏目 + Map catalogMap = new HashMap<>(); + catalogIds.forEach(catalogId -> { + CmsCatalog catalog = catalogService.getCatalog(catalogId); + catalogMap.put(catalog.getCatalogId(), catalog); + long parentId = catalog.getParentId(); + while (parentId > 0) { + CmsCatalog parent = catalogService.getCatalog(parentId); + if (parent == null) { + break; + } + catalogMap.put(parent.getCatalogId(), parent); + parentId = parent.getParentId(); + } + }); + CmsSite site = siteService.getSite(list.get(0).getSiteId()); + catalogMap.values().forEach(this::asyncPublishCatalog); + // 发布站点首页 + asyncPublishSite(site); + }); } @Override @@ -792,7 +776,7 @@ public class PublishServiceImpl implements IPublishService, ApplicationContextAw templateType.initTemplateData(site.getSiteId(), templateContext); // staticize this.staticizeService.process(templateContext); - logger.debug("[{0}]页面部件模板解析:{1},耗时:{2}ms", pw.getPublishPipeCode(), pw.getCode(), System.currentTimeMillis() - s); + logger.debug("[{}]页面部件模板解析:{},耗时:{}ms", pw.getPublishPipeCode(), pw.getCode(), System.currentTimeMillis() - s); } catch (TemplateException | IOException e) { logger.error(AsyncTaskManager.addErrMessage(StringUtils.messageFormat("[{0}]页面部件模板解析失败:{1}#{2}", pw.getPublishPipeCode(), pw.getName(), pw.getCode())), e); diff --git a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/service/impl/SiteThemeService.java b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/service/impl/SiteThemeService.java index 5a262714..26d489b8 100644 --- a/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/service/impl/SiteThemeService.java +++ b/chestnut-cms/chestnut-cms-contentcore/src/main/java/com/chestnut/contentcore/service/impl/SiteThemeService.java @@ -67,16 +67,6 @@ public class SiteThemeService implements ApplicationContextAware { private final IPageWidgetService pageWidgetService; public AsyncTask importSiteTheme(CmsSite site, final File zipFile, LoginUser operator) throws IOException { - String taskId = "SiteThemeImport-" + site.getPath(); - AsyncTask task = asyncTaskManager.getTask(taskId); - if (task != null) { - if (!task.isAlive()) { - asyncTaskManager.removeById(task.getTaskId()); - } else { - throw ContentCoreErrorCode.SITE_EXPORT_TASK_EXISTS.exception(); - } - } - AsyncTask asyncTask = new AsyncTask() { @Override @@ -178,8 +168,8 @@ public class SiteThemeService implements ApplicationContextAware { } } }; - asyncTask.setTaskId(taskId); - asyncTask.setType("SiteThemeImport"); + asyncTask.setType("SiteTheme"); + asyncTask.setTaskId("SiteThemeImport-" + site.getSiteId()); this.asyncTaskManager.execute(asyncTask); return asyncTask; } @@ -187,16 +177,6 @@ public class SiteThemeService implements ApplicationContextAware { public static final String ThemeFileName = "SiteTheme.zip"; public AsyncTask exportSiteTheme(CmsSite site, final List directories) { - String taskId = "SiteExportTheme-" + site.getPath(); - AsyncTask task = asyncTaskManager.getTask(taskId); - if (task != null) { - if (!task.isAlive()) { - asyncTaskManager.removeById(task.getTaskId()); - } else { - throw ContentCoreErrorCode.SITE_EXPORT_TASK_EXISTS.exception(); - } - } - AsyncTask asyncTask = new AsyncTask() { @Override @@ -256,8 +236,8 @@ public class SiteThemeService implements ApplicationContextAware { AsyncTaskManager.setTaskProgressInfo(100, "导出成功"); } }; - asyncTask.setTaskId(taskId); - asyncTask.setType("SiteExportTheme"); + asyncTask.setType("SiteTheme"); + asyncTask.setTaskId("SiteThemeExport-" + site.getSiteId()); this.asyncTaskManager.execute(asyncTask); return asyncTask; } diff --git a/chestnut-cms/chestnut-cms-search/src/main/java/com/chestnut/cms/search/service/ContentIndexService.java b/chestnut-cms/chestnut-cms-search/src/main/java/com/chestnut/cms/search/service/ContentIndexService.java index e44e0c36..881935ad 100644 --- a/chestnut-cms/chestnut-cms-search/src/main/java/com/chestnut/cms/search/service/ContentIndexService.java +++ b/chestnut-cms/chestnut-cms-search/src/main/java/com/chestnut/cms/search/service/ContentIndexService.java @@ -223,6 +223,7 @@ public class ContentIndexService implements CommandLineRunner { }; asyncTask.setTaskId("RebuildAllContentIndex"); asyncTask.setType("ContentCore"); + asyncTask.setInterruptible(true); this.asyncTaskManager.execute(asyncTask); return asyncTask; } diff --git a/chestnut-cms/chestnut-cms-stat/src/main/java/com/chestnut/cms/stat/listener/CmsStatEventListener.java b/chestnut-cms/chestnut-cms-stat/src/main/java/com/chestnut/cms/stat/listener/CmsStatEventListener.java index d1243b1b..2e4cc997 100644 --- a/chestnut-cms/chestnut-cms-stat/src/main/java/com/chestnut/cms/stat/listener/CmsStatEventListener.java +++ b/chestnut-cms/chestnut-cms-stat/src/main/java/com/chestnut/cms/stat/listener/CmsStatEventListener.java @@ -5,7 +5,6 @@ import com.chestnut.cms.stat.domain.CmsUserContentStat; import com.chestnut.cms.stat.domain.vo.ContentStatusTotal; import com.chestnut.cms.stat.mapper.CmsCatalogContentStatMapper; import com.chestnut.cms.stat.mapper.CmsUserContentStatMapper; -import com.chestnut.common.async.AsyncTask; import com.chestnut.common.async.AsyncTaskManager; import com.chestnut.common.utils.IdUtils; import com.chestnut.contentcore.fixed.dict.ContentStatus; @@ -13,7 +12,6 @@ import com.chestnut.contentcore.listener.event.*; import com.chestnut.system.domain.SysUser; import com.chestnut.system.service.ISysUserService; import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.event.EventListener; @@ -94,73 +92,63 @@ public class CmsStatEventListener { } private void updateCatalogContentStat(Long siteId, Long catalogId) { - AsyncTask task = new AsyncTask() { - @Override - public void run0() { - long s = System.currentTimeMillis(); - Map dataMap = catalogContentStatMapper.statContentByStatus(catalogId) - .stream().collect(Collectors.toMap(ContentStatusTotal::getStatus, ContentStatusTotal::getTotal)); + asyncTaskManager.execute(() -> { + long s = System.currentTimeMillis(); + Map dataMap = catalogContentStatMapper.statContentByStatus(catalogId) + .stream().collect(Collectors.toMap(ContentStatusTotal::getStatus, ContentStatusTotal::getTotal)); - CmsCatalogContentStat stat = catalogContentStatMapper.selectById(catalogId); - if (Objects.isNull(stat)) { - stat = new CmsCatalogContentStat(); - stat.setCatalogId(catalogId); - stat.setSiteId(siteId); - stat.setDraftTotal(dataMap.get(ContentStatus.DRAFT)); - stat.setToPublishTotal(dataMap.get(ContentStatus.TO_PUBLISHED)); - stat.setPublishedTotal(dataMap.get(ContentStatus.PUBLISHED)); - stat.setOfflineTotal(dataMap.get(ContentStatus.OFFLINE)); - stat.setEditingTotal(dataMap.get(ContentStatus.EDITING)); - catalogContentStatMapper.insert(stat); - } else { - stat.setDraftTotal(dataMap.get(ContentStatus.DRAFT)); - stat.setToPublishTotal(dataMap.get(ContentStatus.TO_PUBLISHED)); - stat.setPublishedTotal(dataMap.get(ContentStatus.PUBLISHED)); - stat.setOfflineTotal(dataMap.get(ContentStatus.OFFLINE)); - stat.setEditingTotal(dataMap.get(ContentStatus.EDITING)); - catalogContentStatMapper.updateById(stat); - } - logger.info("Stat catalog content by status cost: " + (System.currentTimeMillis() - s) + " ms"); + CmsCatalogContentStat stat = catalogContentStatMapper.selectById(catalogId); + if (Objects.isNull(stat)) { + stat = new CmsCatalogContentStat(); + stat.setCatalogId(catalogId); + stat.setSiteId(siteId); + stat.setDraftTotal(dataMap.get(ContentStatus.DRAFT)); + stat.setToPublishTotal(dataMap.get(ContentStatus.TO_PUBLISHED)); + stat.setPublishedTotal(dataMap.get(ContentStatus.PUBLISHED)); + stat.setOfflineTotal(dataMap.get(ContentStatus.OFFLINE)); + stat.setEditingTotal(dataMap.get(ContentStatus.EDITING)); + catalogContentStatMapper.insert(stat); + } else { + stat.setDraftTotal(dataMap.get(ContentStatus.DRAFT)); + stat.setToPublishTotal(dataMap.get(ContentStatus.TO_PUBLISHED)); + stat.setPublishedTotal(dataMap.get(ContentStatus.PUBLISHED)); + stat.setOfflineTotal(dataMap.get(ContentStatus.OFFLINE)); + stat.setEditingTotal(dataMap.get(ContentStatus.EDITING)); + catalogContentStatMapper.updateById(stat); } - }; - task.setTaskId("UpdateCatalogContentStat"); - this.asyncTaskManager.executeIgnoreIfExists(task); + logger.info("Stat catalog content by status cost: " + (System.currentTimeMillis() - s) + " ms"); + }); } private void updateUserContentStat(Long siteId, SysUser user) { - AsyncTask task = new AsyncTask() { - @Override - public void run0() { - long s = System.currentTimeMillis(); - Map dataMap = userContentStatMapper.statContentByStatus(siteId, user.getUserName()) - .stream().collect(Collectors.toMap(ContentStatusTotal::getStatus, ContentStatusTotal::getTotal)); + asyncTaskManager.execute(() -> { + long s = System.currentTimeMillis(); + Map dataMap = userContentStatMapper.statContentByStatus(siteId, user.getUserName()) + .stream().collect(Collectors.toMap(ContentStatusTotal::getStatus, ContentStatusTotal::getTotal)); - String statId = siteId + "-" + user.getUserId(); - CmsUserContentStat stat = userContentStatMapper.selectById(statId); - if (Objects.isNull(stat)) { - stat = new CmsUserContentStat(); - stat.setId(statId); - stat.setUserId(user.getUserId()); - stat.setUserName(user.getUserName()); - stat.setSiteId(siteId); - stat.setDraftTotal(dataMap.get(ContentStatus.DRAFT)); - stat.setToPublishTotal(dataMap.get(ContentStatus.TO_PUBLISHED)); - stat.setPublishedTotal(dataMap.get(ContentStatus.PUBLISHED)); - stat.setOfflineTotal(dataMap.get(ContentStatus.OFFLINE)); - stat.setEditingTotal(dataMap.get(ContentStatus.EDITING)); - userContentStatMapper.insert(stat); - } else { - stat.setDraftTotal(dataMap.get(ContentStatus.DRAFT)); - stat.setToPublishTotal(dataMap.get(ContentStatus.TO_PUBLISHED)); - stat.setPublishedTotal(dataMap.get(ContentStatus.PUBLISHED)); - stat.setOfflineTotal(dataMap.get(ContentStatus.OFFLINE)); - stat.setEditingTotal(dataMap.get(ContentStatus.EDITING)); - userContentStatMapper.updateById(stat); - } - logger.info("Stat user content by status cost: " + (System.currentTimeMillis() - s) + " ms"); + String statId = siteId + "-" + user.getUserId(); + CmsUserContentStat stat = userContentStatMapper.selectById(statId); + if (Objects.isNull(stat)) { + stat = new CmsUserContentStat(); + stat.setId(statId); + stat.setUserId(user.getUserId()); + stat.setUserName(user.getUserName()); + stat.setSiteId(siteId); + stat.setDraftTotal(dataMap.get(ContentStatus.DRAFT)); + stat.setToPublishTotal(dataMap.get(ContentStatus.TO_PUBLISHED)); + stat.setPublishedTotal(dataMap.get(ContentStatus.PUBLISHED)); + stat.setOfflineTotal(dataMap.get(ContentStatus.OFFLINE)); + stat.setEditingTotal(dataMap.get(ContentStatus.EDITING)); + userContentStatMapper.insert(stat); + } else { + stat.setDraftTotal(dataMap.get(ContentStatus.DRAFT)); + stat.setToPublishTotal(dataMap.get(ContentStatus.TO_PUBLISHED)); + stat.setPublishedTotal(dataMap.get(ContentStatus.PUBLISHED)); + stat.setOfflineTotal(dataMap.get(ContentStatus.OFFLINE)); + stat.setEditingTotal(dataMap.get(ContentStatus.EDITING)); + userContentStatMapper.updateById(stat); } - }; - task.setTaskId("UpdateUserContentStat"); - this.asyncTaskManager.executeIgnoreIfExists(task); + logger.info("Stat user content by status cost: " + (System.currentTimeMillis() - s) + " ms"); + }); } } diff --git a/chestnut-common/chestnut-common-core/src/main/java/com/chestnut/common/async/AsyncTask.java b/chestnut-common/chestnut-common-core/src/main/java/com/chestnut/common/async/AsyncTask.java index 343d7427..ebcf920d 100644 --- a/chestnut-common/chestnut-common-core/src/main/java/com/chestnut/common/async/AsyncTask.java +++ b/chestnut-common/chestnut-common-core/src/main/java/com/chestnut/common/async/AsyncTask.java @@ -81,6 +81,11 @@ public abstract class AsyncTask implements Runnable { */ private boolean interrupt = false; + /** + * 是否可被中断 + */ + private boolean interruptible = false; + @Override public void run() { try { @@ -103,6 +108,7 @@ public abstract class AsyncTask implements Runnable { this.setPercent(100); e.printStackTrace(); } finally { + this.setEndTime(LocalDateTime.now()); AsyncTaskManager.removeCurrent(); } } @@ -131,28 +137,24 @@ public abstract class AsyncTask implements Runnable { * 任务完成 */ void completed() { - if (this.getStatus() == TaskStatus.INTERRUPTED) { - return; - } - log.debug("[{}]Task completed: {}", Thread.currentThread().getName(), this.getTaskId()); this.setStatus(TaskStatus.SUCCESS); - this.setEndTime(LocalDateTime.now()); this.setPercent(100); if (this.getCallback() != null) { this.getCallback().complete(this); } + log.debug("[{}]Task completed: {}", Thread.currentThread().getName(), this.getTaskId()); } /** * 执行中断,设置中断标识 */ public void interrupt() { - log.debug("[{}]Task interrupted: {}", Thread.currentThread().getName(), this.getTaskId()); if (this.interrupt) { return; } this.interrupt = true; this.setInterruptTime(LocalDateTime.now()); + log.debug("[{}]Task interrupted: {}", Thread.currentThread().getName(), this.getTaskId()); } /** @@ -164,6 +166,10 @@ public abstract class AsyncTask implements Runnable { Assert.isFalse(this.interrupt, () -> new InterruptedException("The task is interrupted: " + this.taskId)); } + public boolean isExpired(long expireSeconds) { + return this.isEnd() && this.endTime.plusSeconds(expireSeconds).isBefore(LocalDateTime.now()); + } + public String getTaskId() { return taskId; } @@ -274,4 +280,12 @@ public abstract class AsyncTask implements Runnable { public void setInterruptTime(LocalDateTime interruptTime) { this.interruptTime = interruptTime; } + + public boolean isInterruptible() { + return interruptible; + } + + public void setInterruptible(boolean interruptible) { + this.interruptible = interruptible; + } } \ No newline at end of file diff --git a/chestnut-common/chestnut-common-core/src/main/java/com/chestnut/common/async/AsyncTaskManager.java b/chestnut-common/chestnut-common-core/src/main/java/com/chestnut/common/async/AsyncTaskManager.java index 2fb832dd..88da4bc9 100644 --- a/chestnut-common/chestnut-common-core/src/main/java/com/chestnut/common/async/AsyncTaskManager.java +++ b/chestnut-common/chestnut-common-core/src/main/java/com/chestnut/common/async/AsyncTaskManager.java @@ -1,95 +1,83 @@ package com.chestnut.common.async; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; - -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; -import org.springframework.stereotype.Component; - import com.chestnut.common.async.enums.TaskStatus; import com.chestnut.common.config.AsyncConfig; import com.chestnut.common.exception.CommonErrorCode; import com.chestnut.common.utils.Assert; import com.chestnut.common.utils.IdUtils; import com.chestnut.common.utils.StringUtils; - import jakarta.annotation.Resource; -import lombok.RequiredArgsConstructor; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; /** * 异步任务管理器 */ -@RequiredArgsConstructor @Component public class AsyncTaskManager { - + + private final long ExpireSeconds = 60; + private static final ThreadLocal CURRENT = new ThreadLocal<>(); - private ConcurrentHashMap asyncTaskMap = new ConcurrentHashMap<>(); + private static final ConcurrentHashMap asyncTaskMap = new ConcurrentHashMap<>(); @Resource(name = AsyncConfig.COMMON_EXECUTOR_BEAN) private ThreadPoolTaskExecutor taskExecutor; - - public void execute(AsyncTask asyncTask) { - execute(asyncTask, false); - } - - public void executeIgnoreIfExists(AsyncTask asyncTask) { - this.execute(asyncTask, true); + AsyncTaskManager() { + Executors.newScheduledThreadPool(1).scheduleAtFixedRate(() -> { + asyncTaskMap.entrySet().removeIf(next -> next.getValue().isExpired(ExpireSeconds)); + }, ExpireSeconds, ExpireSeconds, TimeUnit.SECONDS); } /** - * 提交异步任务 - * - * @param asyncTask 异步任务构造器 - * @return taskInfo - */ - public synchronized void execute(AsyncTask asyncTask, boolean ignoreExists) { - if (StringUtils.isEmpty(asyncTask.getTaskId())) { - asyncTask.setTaskId(this.generateTaskId()); - } - AsyncTask task = this.asyncTaskMap.get(asyncTask.getTaskId()); - if (task != null && task.isAlive()) { - if (ignoreExists) { - return; - } - throw CommonErrorCode.ASYNC_TASK_RUNNING.exception(asyncTask.getTaskId()); - } - this.asyncTaskMap.put(asyncTask.getTaskId(), asyncTask); + * 提交异步任务,提供任务进度监控,中断操作 + */ + public synchronized void execute(AsyncTask asyncTask) { + if (StringUtils.isEmpty(asyncTask.getTaskId())) { + asyncTask.setTaskId(this.generateTaskId()); + } + AsyncTask task = asyncTaskMap.get(asyncTask.getTaskId()); + if (task != null && task.isAlive()) { + throw CommonErrorCode.ASYNC_TASK_RUNNING.exception(asyncTask.getTaskId()); + } + asyncTaskMap.put(asyncTask.getTaskId(), asyncTask); asyncTask.ready(); - this.taskExecutor.execute(asyncTask); } - - public void execute(Runnable runnable) { - this.execute(new AsyncTask() { - - @Override - public void run0() throws Exception { - runnable.run(); - } - }); + + /** + * 提交异步任务 + */ + public void execute(Runnable runnable) { + this.taskExecutor.execute(runnable); } /** * 获取任务信息 * * @param taskId 任务ID - * @return + * @return AsyncTask */ public AsyncTask getTask(String taskId) { - return this.asyncTaskMap.get(taskId); + return asyncTaskMap.get(taskId); } /** * 获取任务列表 - * @return + * + * @return taskList */ public List getTaskList() { - return new ArrayList<>(this.asyncTaskMap.values()); + return new ArrayList<>(asyncTaskMap.values()); } /** @@ -109,11 +97,11 @@ public class AsyncTaskManager { boolean isRunning = task.getStatus() == TaskStatus.RUNNING || task.getStatus() == TaskStatus.READY; Assert.isFalse(isRunning, () -> CommonErrorCode.ASYNC_TASK_RUNNING.exception(taskId)); - this.asyncTaskMap.remove(taskId); + asyncTaskMap.remove(taskId); } - + public synchronized void cancel(String taskId) { - AsyncTask task = this.asyncTaskMap.get(taskId); + AsyncTask task = asyncTaskMap.get(taskId); if (Objects.nonNull(task)) { task.interrupt(); } @@ -123,51 +111,51 @@ public class AsyncTaskManager { * 获取线程池信息 */ public ThreadPoolTaskExecutor getThreadPool() { - return this.taskExecutor; + return this.taskExecutor; } protected static void setCurrent(AsyncTask task) { - CURRENT.set(task); + CURRENT.set(task); } protected static void removeCurrent() { - CURRENT.remove(); + CURRENT.remove(); } public static void checkInterrupt() throws InterruptedException { - AsyncTask task = CURRENT.get(); - if (Objects.nonNull(task)) { - task.checkInterrupt(); - } + AsyncTask task = CURRENT.get(); + if (Objects.nonNull(task)) { + task.checkInterrupt(); + } } public static String addErrMessage(String message) { - AsyncTask task = CURRENT.get(); - if (Objects.nonNull(task)) { - task.addErrorMessage(message); - } - return message; + AsyncTask task = CURRENT.get(); + if (Objects.nonNull(task)) { + task.addErrorMessage(message); + } + return message; } public static void setTaskPercent(int percent) { - AsyncTask task = CURRENT.get(); - if (Objects.nonNull(task)) { - task.setPercent(percent); - } + AsyncTask task = CURRENT.get(); + if (Objects.nonNull(task)) { + task.setPercent(percent); + } } public static void setTaskMessage(String msg) { - AsyncTask task = CURRENT.get(); - if (Objects.nonNull(task)) { - task.setProgressMessage(msg); - } + AsyncTask task = CURRENT.get(); + if (Objects.nonNull(task)) { + task.setProgressMessage(msg); + } } public static void setTaskProgressInfo(int percent, String msg) { - AsyncTask task = CURRENT.get(); - if (Objects.nonNull(task)) { - task.setProgressInfo(percent, msg); - } + AsyncTask task = CURRENT.get(); + if (Objects.nonNull(task)) { + task.setProgressInfo(percent, msg); + } } public static int getTaskProgressPercent() { diff --git a/chestnut-common/chestnut-common-core/src/main/java/com/chestnut/common/config/AsyncConfig.java b/chestnut-common/chestnut-common-core/src/main/java/com/chestnut/common/config/AsyncConfig.java index 4327559f..ebe8e04f 100644 --- a/chestnut-common/chestnut-common-core/src/main/java/com/chestnut/common/config/AsyncConfig.java +++ b/chestnut-common/chestnut-common-core/src/main/java/com/chestnut/common/config/AsyncConfig.java @@ -1,11 +1,9 @@ package com.chestnut.common.config; -import java.util.concurrent.Executor; -import java.util.concurrent.ThreadPoolExecutor; - +import com.chestnut.common.config.properties.AsyncProperties; +import lombok.RequiredArgsConstructor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -13,10 +11,8 @@ import org.springframework.scheduling.annotation.AsyncConfigurer; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; -import com.chestnut.common.async.AsyncTaskExceptionHandler; -import com.chestnut.common.config.properties.AsyncProperties; - -import lombok.RequiredArgsConstructor; +import java.util.concurrent.Executor; +import java.util.concurrent.ThreadPoolExecutor; /** * 异步任务线程池配置 @@ -66,9 +62,4 @@ public class AsyncConfig implements AsyncConfigurer { executor.initialize(); return executor; } - - @Override - public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { - return new AsyncTaskExceptionHandler(); - } } \ No newline at end of file diff --git a/chestnut-common/chestnut-common-staticize/src/main/java/com/chestnut/common/staticize/tag/impl/PageBarTag.java b/chestnut-common/chestnut-common-staticize/src/main/java/com/chestnut/common/staticize/tag/impl/PageBarTag.java new file mode 100644 index 00000000..52b809be --- /dev/null +++ b/chestnut-common/chestnut-common-staticize/src/main/java/com/chestnut/common/staticize/tag/impl/PageBarTag.java @@ -0,0 +1,160 @@ +package com.chestnut.common.staticize.tag.impl; + +import com.chestnut.common.staticize.FreeMarkerUtils; +import com.chestnut.common.staticize.StaticizeConstants; +import com.chestnut.common.staticize.core.TemplateContext; +import com.chestnut.common.staticize.enums.TagAttrDataType; +import com.chestnut.common.staticize.tag.AbstractTag; +import com.chestnut.common.staticize.tag.TagAttr; +import com.chestnut.common.staticize.tag.TagAttrOption; +import com.chestnut.common.utils.StringUtils; +import freemarker.core.Environment; +import freemarker.template.TemplateException; +import freemarker.template.TemplateModel; +import org.apache.commons.collections4.MapUtils; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@Component +public class PageBarTag extends AbstractTag { + + public final static String TAG_NAME = "page_bar"; + public final static String NAME = "{FREEMARKER.TAG.NAME." + TAG_NAME + "}"; + public final static String DESC = "{FREEMARKER.TAG.DESC." + TAG_NAME + "}"; + + @Override + public String getTagName() { + return TAG_NAME; + } + + @Override + public String getName() { + return NAME; + } + + @Override + public String getDescription() { + return DESC; + } + + final static String TagAttr_Type = "type"; + final static String TagAttr_Target = "target"; + + @Override + public List getTagAttrs() { + List tagAttrs = new ArrayList<>(); + tagAttrs.add(new TagAttr(TagAttr_Type, false, TagAttrDataType.STRING, "类型", + PageBarType.toTagAttrOptions(), PageBarType.Simple.name())); + tagAttrs.add(new TagAttr(TagAttr_Target, false, TagAttrDataType.STRING, "链接打开方式", + LinkTarget.toTagAttrOptions(), LinkTarget._self.name())); + return tagAttrs; + } + + @Override + public Map execute0(Environment env, Map attrs) + throws TemplateException, IOException { + String type = MapUtils.getString(attrs, TagAttr_Type, PageBarType.Simple.name()); + String target = MapUtils.getString(attrs, TagAttr_Target, LinkTarget._self.name()); + + env.getOut().write(switch (PageBarType.valueOf(type)) { + case Mini -> generateMinPageBar(target, env); + case Simple -> generateSimplePageBar(target, env); + }); + return null; + } + + private String generateMinPageBar(String target, Environment env) + throws TemplateException { + return generatePageBar(target, false, env); + } + + private String generateSimplePageBar(String target, Environment env) + throws TemplateException { + return generatePageBar(target, true, env); + } + + /** + * 1 + * [首页]...[2][3][4] 5 [6][7][8]...[末页] + * 最多显示7个页码,当前页前后各三个 + */ + private String generatePageBar(String target, boolean withFirstAndLast, Environment env) + throws TemplateException { + TemplateContext context = FreeMarkerUtils.getTemplateContext(env); + int pageCount = Long.valueOf((context.getPageTotal() + context.getPageSize() - 1 ) / context.getPageSize()).intValue(); + int startPage = 1; + int endPage = 7; + if (context.getPageIndex() > 4) { + int maxMove = Math.max(pageCount - endPage, 0); + startPage += Math.min(context.getPageIndex() - 4, maxMove); + } + endPage = Math.min(startPage + 6, pageCount); + + String firstPageLink = FreeMarkerUtils.evalStringVariable(env, StaticizeConstants.TemplateVariable_FirstPage); + String otherPageLink = FreeMarkerUtils.evalStringVariable(env, StaticizeConstants.TemplateVariable_OtherPage); + String temp = "{3}"; + StringBuilder sb = new StringBuilder(); + sb.append("
"); + if (withFirstAndLast && startPage > 1) { + sb.append(StringUtils.messageFormat(temp, firstPageLink, "", target, "首页")); + sb.append("..."); + } + for (int i = startPage; i <= endPage; i++) { + String pageLink = "javascript:;"; + String active = " page_active"; + if (i != context.getPageIndex()) { + pageLink = i > 1 ? StringUtils.messageFormat(otherPageLink, i) : firstPageLink; + active = ""; + } + sb.append(StringUtils.messageFormat(temp, pageLink, active, target, i)); + } + if (withFirstAndLast && endPage < pageCount) { + sb.append("..."); + sb.append(StringUtils.messageFormat(temp, StringUtils.messageFormat(otherPageLink, pageCount), "", target, "末页")); + } + sb.append("
"); + return sb.toString(); + } + + private enum PageBarType { + + Mini("极简(页码)"), + Simple("简单(页码+首末页)"); + + private final String desc; + + PageBarType(String desc) { + this.desc = desc; + } + + static List toTagAttrOptions() { + return List.of( + new TagAttrOption(Mini.name(), Mini.desc), + new TagAttrOption(Simple.name(), Simple.desc) + ); + } + } + + private enum LinkTarget { + + _blank("新标签页打开"), + _self("当前页打开"); + + private final String desc; + + LinkTarget(String desc) { + this.desc = desc; + } + + static List toTagAttrOptions() { + return List.of( + new TagAttrOption(_blank.name(), _blank.desc), + new TagAttrOption(_self.name(), _self.desc) + ); + } + } +} diff --git a/chestnut-common/chestnut-common-staticize/src/main/resources/i18n/messages.properties b/chestnut-common/chestnut-common-staticize/src/main/resources/i18n/messages.properties index 69d00d3b..54cec961 100644 --- a/chestnut-common/chestnut-common-staticize/src/main/resources/i18n/messages.properties +++ b/chestnut-common/chestnut-common-staticize/src/main/resources/i18n/messages.properties @@ -1,3 +1,8 @@ FREEMARKER.TAG_ATTR.PAGE=是否分页获取数据 FREEMARKER.TAG_ATTR.PAGE_SIZE=分页数据条数,默认:20 FREEMARKER.TAG_ATTR.CONDITION=扩展sql条件语句,例如:title like 'a%' + +FREEMARKER.TAG.NAME.page_bar=分页条标签 +FREEMARKER.TAG.DESC.page_bar=生成固定格式的分页条html代码,样式由模板样式决定 +FREEMARKER.TAG.FIRST_PAGE=首页 +FREEMARKER.TAG.LAST_PAGE=末页 diff --git a/chestnut-common/chestnut-common-staticize/src/main/resources/i18n/messages_en.properties b/chestnut-common/chestnut-common-staticize/src/main/resources/i18n/messages_en.properties index 224e5713..ef7d98fb 100644 --- a/chestnut-common/chestnut-common-staticize/src/main/resources/i18n/messages_en.properties +++ b/chestnut-common/chestnut-common-staticize/src/main/resources/i18n/messages_en.properties @@ -1,3 +1,8 @@ FREEMARKER.TAG_ATTR.PAGE=Pageable FREEMARKER.TAG_ATTR.PAGE_SIZE=Page size, default is: 20. FREEMARKER.TAG_ATTR.CONDITION=Extend sql condition, eg: title like 'a%' + +FREEMARKER.TAG.NAME.page_bar=Pagination bar tag +FREEMARKER.TAG.DESC.page_bar=Generate pagination bar html code, the style is determined by the template style. +FREEMARKER.TAG.FIRST_PAGE=First Page +FREEMARKER.TAG.LAST_PAGE=Last Page diff --git a/chestnut-modules/chestnut-member/src/main/java/com/chestnut/member/controller/front/MemberLoginApiController.java b/chestnut-modules/chestnut-member/src/main/java/com/chestnut/member/controller/front/MemberLoginApiController.java index 68475f10..9a3b3c2c 100644 --- a/chestnut-modules/chestnut-member/src/main/java/com/chestnut/member/controller/front/MemberLoginApiController.java +++ b/chestnut-modules/chestnut-member/src/main/java/com/chestnut/member/controller/front/MemberLoginApiController.java @@ -122,9 +122,9 @@ public class MemberLoginApiController extends BaseRestController { if (StpMemberUtil.isLogin()) { LoginUser loginUser = StpMemberUtil.getLoginUser(); StpMemberUtil.logout(); - asyncTaskManager.execute(this.logininforService.recordLogininfor(loginUser.getUserType(), + this.logininforService.recordLogininfor(loginUser.getUserType(), loginUser.getUserId(), loginUser.getUsername(), LoginLogType.LOGOUT, SuccessOrFail.SUCCESS, - StringUtils.EMPTY)); + StringUtils.EMPTY); } } catch (Exception e) { } diff --git a/chestnut-modules/chestnut-member/src/main/java/com/chestnut/member/security/MemberLoginService.java b/chestnut-modules/chestnut-member/src/main/java/com/chestnut/member/security/MemberLoginService.java index 562a74d6..57712def 100644 --- a/chestnut-modules/chestnut-member/src/main/java/com/chestnut/member/security/MemberLoginService.java +++ b/chestnut-modules/chestnut-member/src/main/java/com/chestnut/member/security/MemberLoginService.java @@ -1,26 +1,19 @@ package com.chestnut.member.security; -import java.time.Instant; -import java.time.LocalDateTime; -import java.util.Objects; - +import cn.dev33.satoken.session.SaSession; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.chestnut.common.exception.GlobalException; -import com.chestnut.common.utils.IdUtils; -import com.chestnut.member.domain.dto.MemberLoginDTO; -import com.chestnut.member.domain.dto.MemberRegisterDTO; -import com.chestnut.member.fixed.dict.MemberStatus; -import org.springframework.stereotype.Component; - -import com.chestnut.common.async.AsyncTaskManager; import com.chestnut.common.security.SecurityUtils; import com.chestnut.common.security.domain.LoginUser; import com.chestnut.common.security.enums.DeviceType; import com.chestnut.common.utils.IP2RegionUtils; -import com.chestnut.common.utils.ServletUtils; +import com.chestnut.common.utils.IdUtils; import com.chestnut.common.utils.StringUtils; import com.chestnut.member.domain.Member; +import com.chestnut.member.domain.dto.MemberLoginDTO; +import com.chestnut.member.domain.dto.MemberRegisterDTO; import com.chestnut.member.exception.MemberErrorCode; +import com.chestnut.member.fixed.dict.MemberStatus; import com.chestnut.member.service.IMemberService; import com.chestnut.system.exception.SysErrorCode; import com.chestnut.system.fixed.dict.LoginLogType; @@ -28,10 +21,13 @@ import com.chestnut.system.fixed.dict.SuccessOrFail; import com.chestnut.system.fixed.dict.UserStatus; import com.chestnut.system.service.ISecurityConfigService; import com.chestnut.system.service.ISysLogininforService; - -import cn.dev33.satoken.session.SaSession; import eu.bitwalker.useragentutils.UserAgent; import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import java.time.Instant; +import java.time.LocalDateTime; +import java.util.Objects; /** * 会员登录校验方法 @@ -49,8 +45,6 @@ public class MemberLoginService { private final ISecurityConfigService securityConfigService; - private final AsyncTaskManager asyncTaskManager; - /** * 登录验证 * @@ -74,8 +68,8 @@ public class MemberLoginService { // 密码错误处理策略 this.securityConfigService.processLoginPasswordError(member); // 记录日志 - asyncTaskManager.execute(this.logininfoService.recordLogininfor(MemberUserType.TYPE, member.getMemberId(), - member.getUserName(), LoginLogType.LOGIN, SuccessOrFail.FAIL, "Invalid password.")); + this.logininfoService.recordLogininfor(MemberUserType.TYPE, member.getMemberId(), + member.getUserName(), LoginLogType.LOGIN, SuccessOrFail.FAIL, "Invalid password."); throw SysErrorCode.PASSWORD_ERROR.exception(); } this.securityConfigService.onLoginSuccess(member); @@ -89,8 +83,8 @@ public class MemberLoginService { loginUser.setToken(StpMemberUtil.getTokenValueByLoginId(member.getUserId())); StpMemberUtil.getTokenSession().set(SaSession.USER, loginUser); // 日志 - asyncTaskManager.execute(this.logininfoService.recordLogininfor(MemberUserType.TYPE, member.getUserId(), - loginUser.getUsername(), LoginLogType.LOGIN, SuccessOrFail.SUCCESS, StringUtils.EMPTY)); + this.logininfoService.recordLogininfor(MemberUserType.TYPE, member.getUserId(), + loginUser.getUsername(), LoginLogType.LOGIN, SuccessOrFail.SUCCESS, StringUtils.EMPTY); return StpMemberUtil.getTokenValue(); } diff --git a/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/controller/SysLoginController.java b/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/controller/SysLoginController.java index d32b38bb..3c64cc92 100644 --- a/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/controller/SysLoginController.java +++ b/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/controller/SysLoginController.java @@ -1,6 +1,5 @@ package com.chestnut.system.controller; -import com.chestnut.common.async.AsyncTaskManager; import com.chestnut.common.domain.R; import com.chestnut.common.i18n.I18nUtils; import com.chestnut.common.security.anno.Priv; @@ -47,12 +46,8 @@ public class SysLoginController extends BaseRestController { private final ISysRoleService roleService; - private final ISysPermissionService permissionService; - private final ISysLogininforService logininfoService; - private final AsyncTaskManager asyncTaskManager; - /** * 登录方法 * @@ -73,9 +68,9 @@ public class SysLoginController extends BaseRestController { if (StpAdminUtil.isLogin()) { LoginUser loginUser = StpAdminUtil.getLoginUser(); StpAdminUtil.logout(); - asyncTaskManager.execute(this.logininfoService.recordLogininfor(loginUser.getUserType(), + this.logininfoService.recordLogininfor(loginUser.getUserType(), loginUser.getUserId(), loginUser.getUsername(), LoginLogType.LOGOUT, SuccessOrFail.SUCCESS, - StringUtils.EMPTY)); + StringUtils.EMPTY); } } catch (Exception e) { diff --git a/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/handler/SysLogHandler.java b/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/handler/SysLogHandler.java index b5de28e7..b60ee791 100644 --- a/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/handler/SysLogHandler.java +++ b/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/handler/SysLogHandler.java @@ -72,7 +72,7 @@ public class SysLogHandler implements ILogHandler { operLog.setOperTime(logDetail.getLogTime()); operLog.setCost(logDetail.getCost()); // 保存数据库 - asyncTaskManager.execute(operLogService.recordOper(operLog)); + operLogService.recordOper(operLog); } catch (Exception exp) { // 记录本地异常日志 logger.error("异常信息:{}", exp.getMessage()); diff --git a/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/security/SysLoginService.java b/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/security/SysLoginService.java index 86ae758c..25345916 100644 --- a/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/security/SysLoginService.java +++ b/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/security/SysLoginService.java @@ -1,7 +1,6 @@ package com.chestnut.system.security; import cn.dev33.satoken.session.SaSession; -import com.chestnut.common.async.AsyncTaskManager; import com.chestnut.common.redis.RedisCache; import com.chestnut.common.security.SecurityUtils; import com.chestnut.common.security.domain.LoginUser; @@ -49,8 +48,6 @@ public class SysLoginService { private final ISysPermissionService permissionService; - private final AsyncTaskManager asyncTaskManager; - /** * 登录验证 * @@ -84,8 +81,8 @@ public class SysLoginService { this.userService.updateById(user); } // 记录日志 - asyncTaskManager.execute(this.logininfoService.recordLogininfor(AdminUserType.TYPE, user.getUserId(), - user.getUserName(), LoginLogType.LOGIN, SuccessOrFail.FAIL, "Invalid password.")); + this.logininfoService.recordLogininfor(AdminUserType.TYPE, user.getUserId(), + user.getUserName(), LoginLogType.LOGIN, SuccessOrFail.FAIL, "Invalid password."); throw SysErrorCode.PASSWORD_ERROR.exception(); } this.securityConfigService.onLoginSuccess(user); @@ -100,8 +97,8 @@ public class SysLoginService { loginUser.setToken(StpAdminUtil.getTokenValueByLoginId(user.getUserId())); StpAdminUtil.getTokenSession().set(SaSession.USER, loginUser); // 日志 - asyncTaskManager.execute(this.logininfoService.recordLogininfor(AdminUserType.TYPE, user.getUserId(), - loginUser.getUsername(), LoginLogType.LOGIN, SuccessOrFail.SUCCESS, StringUtils.EMPTY)); + this.logininfoService.recordLogininfor(AdminUserType.TYPE, user.getUserId(), + loginUser.getUsername(), LoginLogType.LOGIN, SuccessOrFail.SUCCESS, StringUtils.EMPTY); return StpAdminUtil.getTokenValue(); } @@ -130,25 +127,24 @@ public class SysLoginService { * @param username 用户名 * @param code 验证码 * @param uuid 唯一标识 - * @return 结果 */ public void validateCaptcha(String username, String code, String uuid) { - Assert.notEmpty(uuid, () -> SysErrorCode.CAPTCHA_ERR.exception()); + Assert.notEmpty(uuid, SysErrorCode.CAPTCHA_ERR::exception); String verifyKey = SysConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, StringUtils.EMPTY); String captcha = redisCache.getCacheObject(verifyKey); // 过期判断 Assert.notNull(captcha, () -> { - asyncTaskManager.execute(this.logininfoService.recordLogininfor(AdminUserType.TYPE, null, username, - LoginLogType.LOGIN, SuccessOrFail.FAIL, SysErrorCode.CAPTCHA_EXPIRED.name())); + this.logininfoService.recordLogininfor(AdminUserType.TYPE, null, username, + LoginLogType.LOGIN, SuccessOrFail.FAIL, SysErrorCode.CAPTCHA_EXPIRED.name()); return SysErrorCode.CAPTCHA_EXPIRED.exception(); }); // 未过期移除缓存 redisCache.deleteObject(verifyKey); // 判断是否与输入验证码一致 Assert.isTrue(StringUtils.equals(code, captcha), () -> { - asyncTaskManager.execute(this.logininfoService.recordLogininfor(AdminUserType.TYPE, null, username, - LoginLogType.LOGIN, SuccessOrFail.FAIL, SysErrorCode.CAPTCHA_ERR.name())); + this.logininfoService.recordLogininfor(AdminUserType.TYPE, null, username, + LoginLogType.LOGIN, SuccessOrFail.FAIL, SysErrorCode.CAPTCHA_ERR.name()); return SysErrorCode.CAPTCHA_ERR.exception(); }); } diff --git a/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/security/SysRegisterService.java b/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/security/SysRegisterService.java index 18f39927..375d15f9 100644 --- a/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/security/SysRegisterService.java +++ b/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/security/SysRegisterService.java @@ -53,8 +53,8 @@ public class SysRegisterService { user.setPassword(registerBody.getPassword()); user.setNickName(registerBody.getUsername()); userService.registerUser(user); - asyncTaskManager.execute(this.logininfoService.recordLogininfor(AdminUserType.TYPE, user.getUserId(), - user.getUserName(), LoginLogType.REGIST, SuccessOrFail.SUCCESS, StringUtils.EMPTY)); + this.logininfoService.recordLogininfor(AdminUserType.TYPE, user.getUserId(), + user.getUserName(), LoginLogType.REGIST, SuccessOrFail.SUCCESS, StringUtils.EMPTY); } /** diff --git a/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/service/ISysLogininforService.java b/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/service/ISysLogininforService.java index 5f0f3cf3..98b367d4 100644 --- a/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/service/ISysLogininforService.java +++ b/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/service/ISysLogininforService.java @@ -1,7 +1,6 @@ package com.chestnut.system.service; import com.baomidou.mybatisplus.extension.service.IService; -import com.chestnut.common.async.AsyncTask; import com.chestnut.system.domain.SysLogininfor; /** @@ -12,18 +11,17 @@ public interface ISysLogininforService extends IService { /** * 清空系统登录日志 */ - public void cleanLogininfor(); + void cleanLogininfor(); /** * 记录登录日志任务 - * - * @param userType - * @param userId - * @param username - * @param logType - * @param message - * @param args - * @return + * + * @param userType 用户类型 + * @param userId 用户ID + * @param username 用户名 + * @param logType 日志类型 + * @param message 日志详情 + * @param args 参数 */ - AsyncTask recordLogininfor(String userType, Object userId, String username, String logType, String status, String message, Object... args); + void recordLogininfor(String userType, Object userId, String username, String logType, String status, String message, Object... args); } diff --git a/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/service/ISysOperLogService.java b/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/service/ISysOperLogService.java index 30172ad7..0936e905 100644 --- a/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/service/ISysOperLogService.java +++ b/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/service/ISysOperLogService.java @@ -1,7 +1,6 @@ package com.chestnut.system.service; import com.baomidou.mybatisplus.extension.service.IService; -import com.chestnut.common.async.AsyncTask; import com.chestnut.system.domain.SysOperLog; /** @@ -15,14 +14,12 @@ public interface ISysOperLogService extends IService { /** * 清空操作日志 */ - public void cleanOperLog(); + void cleanOperLog(); /** * 操作日志记录 - * - * @param operLog - * 操作日志信息 - * @return 任务task + * + * @param operLog 操作日志信息 */ - public AsyncTask recordOper(SysOperLog operLog); + void recordOper(SysOperLog operLog); } diff --git a/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/service/impl/SysLogininforServiceImpl.java b/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/service/impl/SysLogininforServiceImpl.java index 96ad8e7b..ce705625 100644 --- a/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/service/impl/SysLogininforServiceImpl.java +++ b/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/service/impl/SysLogininforServiceImpl.java @@ -2,12 +2,12 @@ package com.chestnut.system.service.impl; import java.time.LocalDateTime; +import com.chestnut.common.async.AsyncTaskManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.chestnut.common.async.AsyncTask; import com.chestnut.common.utils.ConvertUtils; import com.chestnut.common.utils.IP2RegionUtils; import com.chestnut.common.utils.ServletUtils; @@ -32,6 +32,8 @@ public class SysLogininforServiceImpl extends ServiceImpl { + // 打印信息到日志 + StringBuilder s = new StringBuilder(); + s.append("[").append(ip).append("]"); + s.append("[type:").append(userType).append("]"); + s.append("[uid:").append(userId).append("]"); + s.append("[uname:").append(username).append("]"); + s.append("[").append(logType).append("]"); + s.append("[").append(status).append("]"); + s.append("[").append(message).append("]"); + logger.info(s.toString(), args); + // 获取客户端操作系统 + String os = userAgent.getOperatingSystem().getName(); + // 获取客户端浏览器 + String browser = userAgent.getBrowser().getName(); + // 封装对象 + SysLogininfor logininfor = new SysLogininfor(); + logininfor.setUserType(userType); + logininfor.setUserId(ConvertUtils.toStr(userId)); + logininfor.setUserName(username); + logininfor.setLoginTime(LocalDateTime.now()); + logininfor.setIpaddr(ip); + logininfor.setLoginLocation(IP2RegionUtils.ip2Region(ip)); + logininfor.setBrowser(browser); + logininfor.setOs(os); + if (StringUtils.isNotBlank(message)) { + logininfor.setMsg(message.length() > 2000 ? message.substring(0, 2000) : message); } - - @Override - public void run0() { - // 打印信息到日志 - StringBuilder s = new StringBuilder(); - s.append("[").append(ip).append("]"); - s.append("[type:").append(userType).append("]"); - s.append("[uid:").append(userId).append("]"); - s.append("[uname:").append(username).append("]"); - s.append("[").append(logType).append("]"); - s.append("[").append(status).append("]"); - s.append("[").append(message).append("]"); - logger.info(s.toString(), args); - // 获取客户端操作系统 - String os = userAgent.getOperatingSystem().getName(); - // 获取客户端浏览器 - String browser = userAgent.getBrowser().getName(); - // 封装对象 - SysLogininfor logininfor = new SysLogininfor(); - logininfor.setUserType(userType); - logininfor.setUserId(ConvertUtils.toStr(userId)); - logininfor.setUserName(username); - logininfor.setLoginTime(LocalDateTime.now()); - logininfor.setIpaddr(ip); - logininfor.setLoginLocation(IP2RegionUtils.ip2Region(ip)); - logininfor.setBrowser(browser); - logininfor.setOs(os); - if (StringUtils.isNotBlank(message)) { - logininfor.setMsg(message.length() > 2000 ? message.substring(0, 2000) : message); - } - logininfor.setLogType(logType); - // 日志状态 - logininfor.setStatus(status); - save(logininfor); - } - }; + logininfor.setLogType(logType); + // 日志状态 + logininfor.setStatus(status); + save(logininfor); + }); } } diff --git a/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/service/impl/SysOperLogServiceImpl.java b/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/service/impl/SysOperLogServiceImpl.java index 34fa5909..dc54879a 100644 --- a/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/service/impl/SysOperLogServiceImpl.java +++ b/chestnut-modules/chestnut-system/src/main/java/com/chestnut/system/service/impl/SysOperLogServiceImpl.java @@ -1,9 +1,9 @@ package com.chestnut.system.service.impl; +import com.chestnut.common.async.AsyncTaskManager; import org.springframework.stereotype.Service; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.chestnut.common.async.AsyncTask; import com.chestnut.common.utils.IP2RegionUtils; import com.chestnut.system.domain.SysOperLog; import com.chestnut.system.mapper.SysOperLogMapper; @@ -20,6 +20,8 @@ public class SysOperLogServiceImpl extends ServiceImpl { + operLog.setOperLocation(IP2RegionUtils.ip2Region(operLog.getOperIp())); + save(operLog); + }); } }