新增分页条模板标签<@page_bar>,异步任务优化

This commit is contained in:
兮玥 2023-10-15 00:26:40 +08:00
parent 322ec7e856
commit d4c14db946
23 changed files with 467 additions and 393 deletions

View File

@ -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);
}
};

View File

@ -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<CmsContent> 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<CmsContent> 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<CmsContent> 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<CmsContent> 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);
});
}
}

View File

@ -202,7 +202,7 @@ public class ContentServiceImpl extends ServiceImpl<CmsContentMapper, CmsContent
aopProxy.addContent0(content);
}
};
task.setType("SaveContent");
task.setType("SaveContent-" + content.getContentEntity().getContentId());
asyncTaskManager.execute(task);
return task;
}
@ -224,7 +224,7 @@ public class ContentServiceImpl extends ServiceImpl<CmsContentMapper, CmsContent
saveContent0(content);
}
};
task.setType("SaveContent");
task.setType("SaveContent-" + content.getContentEntity().getContentId());
asyncTaskManager.execute(task);
return task;
}

View File

@ -99,7 +99,6 @@ public class PublishServiceImpl implements IPublishService, ApplicationContextAw
@Override
public AsyncTask publishAll(CmsSite site, final String contentStatus, final LoginUser operator) {
String taskId = "Publish-Site-" + site.getSiteId();
AsyncTask asyncTask = new AsyncTask() {
@Override
@ -164,7 +163,8 @@ public class PublishServiceImpl implements IPublishService, ApplicationContextAw
}
};
asyncTask.setType("Publish");
asyncTask.setTaskId(taskId);
asyncTask.setTaskId("Publish-Site-" + site.getSiteId());
asyncTask.setInterruptible(true);
this.asyncTaskManager.execute(asyncTask);
return asyncTask;
}
@ -335,6 +335,7 @@ public class PublishServiceImpl implements IPublishService, ApplicationContextAw
};
asyncTask.setType("Publish");
asyncTask.setTaskId("Publish-Catalog-" + catalog.getCatalogId());
asyncTask.setInterruptible(true);
this.asyncTaskManager.execute(asyncTask);
return asyncTask;
}
@ -459,16 +460,6 @@ public class PublishServiceImpl implements IPublishService, ApplicationContextAw
return detailTemplate;
}
private String getContentExTemplate(CmsSite site, CmsCatalog catalog, CmsContent content, String publishPipeCode) {
String exTemplate = PublishPipeProp_ContentExTemplate.getValue(publishPipeCode,
content.getPublishPipeProps());
if (StringUtils.isEmpty(exTemplate)) {
// 无内容独立扩展模板取栏目配置
exTemplate = PublishPipeProp_ContentExTemplate.getValue(publishPipeCode, catalog.getPublishPipeProps());
}
return exTemplate;
}
@Override
public String getContentPageData(CmsContent content, int pageIndex, String publishPipeCode, boolean isPreview)
throws IOException, TemplateException {
@ -517,46 +508,39 @@ public class PublishServiceImpl implements IPublishService, ApplicationContextAw
if (list.isEmpty()) {
return;
}
AsyncTask asyncTask = new AsyncTask() {
asyncTaskManager.execute(() -> {
// 发布内容
Set<Long> 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<Long> 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<Long, CmsCatalog> 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<Long, CmsCatalog> 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);

View File

@ -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<String> 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;
}

View File

@ -223,6 +223,7 @@ public class ContentIndexService implements CommandLineRunner {
};
asyncTask.setTaskId("RebuildAllContentIndex");
asyncTask.setType("ContentCore");
asyncTask.setInterruptible(true);
this.asyncTaskManager.execute(asyncTask);
return asyncTask;
}

View File

@ -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<String, Integer> dataMap = catalogContentStatMapper.statContentByStatus(catalogId)
.stream().collect(Collectors.toMap(ContentStatusTotal::getStatus, ContentStatusTotal::getTotal));
asyncTaskManager.execute(() -> {
long s = System.currentTimeMillis();
Map<String, Integer> 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<String, Integer> dataMap = userContentStatMapper.statContentByStatus(siteId, user.getUserName())
.stream().collect(Collectors.toMap(ContentStatusTotal::getStatus, ContentStatusTotal::getTotal));
asyncTaskManager.execute(() -> {
long s = System.currentTimeMillis();
Map<String, Integer> 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");
});
}
}

View File

@ -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;
}
}

View File

@ -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<AsyncTask> CURRENT = new ThreadLocal<>();
private ConcurrentHashMap<String, AsyncTask> asyncTaskMap = new ConcurrentHashMap<>();
private static final ConcurrentHashMap<String, AsyncTask> 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<AsyncTask> 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() {

View File

@ -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();
}
}

View File

@ -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<TagAttr> getTagAttrs() {
List<TagAttr> 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<String, TemplateModel> execute0(Environment env, Map<String, String> 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);
}
/**
* <a href="#" class="page_link page_active" target="_blank">1</a>
* [首页]...[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 = "<a href=\"{0}\" class=\"page_link{1}\" target=\"{2}\">{3}</a>";
StringBuilder sb = new StringBuilder();
sb.append("<div class=\"pagination\">");
if (withFirstAndLast && startPage > 1) {
sb.append(StringUtils.messageFormat(temp, firstPageLink, "", target, "首页"));
sb.append("<a href=\"javascript:;\" class=\"page_white\">...</a>");
}
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("<a href=\"javascript:;\" class=\"page_white\">...</a>");
sb.append(StringUtils.messageFormat(temp, StringUtils.messageFormat(otherPageLink, pageCount), "", target, "末页"));
}
sb.append("</div>");
return sb.toString();
}
private enum PageBarType {
Mini("极简(页码)"),
Simple("简单(页码+首末页)");
private final String desc;
PageBarType(String desc) {
this.desc = desc;
}
static List<TagAttrOption> 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<TagAttrOption> toTagAttrOptions() {
return List.of(
new TagAttrOption(_blank.name(), _blank.desc),
new TagAttrOption(_self.name(), _self.desc)
);
}
}
}

View File

@ -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=末页

View File

@ -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

View File

@ -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) {
}

View File

@ -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();
}

View File

@ -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) {

View File

@ -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());

View File

@ -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();
});
}

View File

@ -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);
}
/**

View File

@ -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<SysLogininfor> {
/**
* 清空系统登录日志
*/
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);
}

View File

@ -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<SysOperLog> {
/**
* 清空操作日志
*/
public void cleanOperLog();
void cleanOperLog();
/**
* 操作日志记录
*
* @param operLog
* 操作日志信息
* @return 任务task
*
* @param operLog 操作日志信息
*/
public AsyncTask recordOper(SysOperLog operLog);
void recordOper(SysOperLog operLog);
}

View File

@ -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<SysLogininforMapper, S
private static final Logger logger = LoggerFactory.getLogger(SysLogininforServiceImpl.class);
private final AsyncTaskManager asyncTaskManager;
private final SysLogininforMapper logininforMapper;
/**
@ -43,50 +45,41 @@ public class SysLogininforServiceImpl extends ServiceImpl<SysLogininforMapper, S
}
@Override
public AsyncTask recordLogininfor(String userType, Object userId, String username, String logType, String status, String message, Object... args) {
public void recordLogininfor(String userType, Object userId, String username, String logType, String status, String message, Object... args) {
final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getUserAgent());
final String ip = ServletUtils.getIpAddr(ServletUtils.getRequest());
return new AsyncTask() {
@Override
public String getType() {
return "LoginLog";
asyncTaskManager.execute(() -> {
// 打印信息到日志
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);
});
}
}

View File

@ -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<SysOperLogMapper, SysOper
private final SysOperLogMapper operLogMapper;
private final AsyncTaskManager asyncTaskManager;
/**
* 清空操作日志
*/
@ -30,26 +32,14 @@ public class SysOperLogServiceImpl extends ServiceImpl<SysOperLogMapper, SysOper
/**
* 操作日志记录
*
* @param operLog
* 操作日志信息
* @return 任务task
*
* @param operLog 操作日志信息
*/
@Override
public AsyncTask recordOper(final SysOperLog operLog) {
return new AsyncTask() {
@Override
public String getType() {
return "OpLog";
}
@Override
public void run0() {
// 远程查询操作地点
operLog.setOperLocation(IP2RegionUtils.ip2Region(operLog.getOperIp()));
save(operLog);
}
};
public void recordOper(final SysOperLog operLog) {
asyncTaskManager.execute(() -> {
operLog.setOperLocation(IP2RegionUtils.ip2Region(operLog.getOperIp()));
save(operLog);
});
}
}