{
+
+ /**
+ * ID
+ */
+ @ApiModelProperty("ID")
+ private String id;
+
+ /**
+ * 名称
+ */
+ @ApiModelProperty("名称")
+ private String name;
+
+ /**
+ * 文件大小
+ */
+ @ApiModelProperty("文件大小")
+ private String fileSize;
+
+ /**
+ * 上传记录ID
+ */
+ @ApiModelProperty("上传记录ID")
+ private String recordId;
+
+ /**
+ * 总数据条数
+ */
+ @ApiModelProperty("总数据条数")
+ private Long totalCount;
+
+ /**
+ * 创建时间
+ */
+ @ApiModelProperty("创建时间")
+ private LocalDateTime createTime;
+
+ /**
+ * 完成时间
+ */
+ @ApiModelProperty("完成时间")
+ private LocalDateTime finishTime;
+
+ public SuccessExportTaskBo(ExportTask dto) {
+ super(dto);
+ }
+}
diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/components/export/ExportTaskWorker.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/components/export/ExportTaskWorker.java
new file mode 100644
index 0000000000000000000000000000000000000000..4abf075dc93aa3cf6ab0b6833c698d8da94f14e5
--- /dev/null
+++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/components/export/ExportTaskWorker.java
@@ -0,0 +1,47 @@
+package com.lframework.starter.mq.core.components.export;
+
+import com.lframework.starter.web.core.components.excel.ExcelModel;
+import com.lframework.starter.web.core.components.resp.PageResult;
+
+public interface ExportTaskWorker {
+
+ /**
+ * 解析传入参数
+ *
+ * @param json
+ * @return
+ */
+ P parseParams(String json);
+
+ /**
+ * 查询数据
+ *
+ * @param pageIndex
+ * @param pageSize
+ * @param params
+ * @return
+ */
+ PageResult getDataList(int pageIndex, int pageSize, P params);
+
+ /**
+ * 导出数据
+ *
+ * @param data
+ */
+ M exportData(D data);
+
+ /**
+ * 处理异常
+ *
+ * @param e
+ */
+ default void handleError(Exception e) {
+ }
+
+ /**
+ * 获取导出模型类
+ *
+ * @return
+ */
+ Class getModelClass();
+}
diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/config/MqBeanAutoConfiguration.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/config/MqBeanAutoConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..a039b13d72e9d12cd49d355c924bc6b7daf73706
--- /dev/null
+++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/config/MqBeanAutoConfiguration.java
@@ -0,0 +1,25 @@
+package com.lframework.starter.mq.core.config;
+
+import com.lframework.starter.mq.core.controller.ExportTaskController;
+import com.lframework.starter.mq.core.impl.ExportTaskServiceImpl;
+import lombok.extern.slf4j.Slf4j;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.context.EnvironmentAware;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import org.springframework.core.env.Environment;
+
+@Slf4j
+@Configuration
+@Import({
+ ExportTaskServiceImpl.class,
+ ExportTaskController.class,
+})
+@MapperScan("com.lframework.starter.mq.core.**.mappers")
+public class MqBeanAutoConfiguration implements EnvironmentAware {
+
+ @Override
+ public void setEnvironment(Environment environment) {
+ log.info("mq-core加载完成");
+ }
+}
diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/config/MqSwaggerAutoConfiguration.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/config/MqSwaggerAutoConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..b60335413ed43681e63459564629a32900e3e7fd
--- /dev/null
+++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/config/MqSwaggerAutoConfiguration.java
@@ -0,0 +1,31 @@
+package com.lframework.starter.mq.core.config;
+
+import com.github.xiaoymin.knife4j.spring.extension.OpenApiExtensionResolver;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+
+@Configuration
+public class MqSwaggerAutoConfiguration {
+
+ @Bean("mqApiDocket")
+ public Docket mqApiDocket(ApiInfo info, OpenApiExtensionResolver openApiExtensionResolver) {
+
+ // 除了描述 其他全与info保持一致
+ ApiInfo apiInfo = new ApiInfo(info.getTitle(), "消息队列模块", info.getVersion(),
+ info.getTermsOfServiceUrl(),
+ info.getContact(), info.getLicense(), info.getLicenseUrl(), info.getVendorExtensions());
+
+ Docket docket = new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo).groupName("消息队列模块")
+ .select()
+ .apis(RequestHandlerSelectors.basePackage("com.lframework.starter.mq.core"))
+ .paths(PathSelectors.any())
+ .build()
+ .extensions(openApiExtensionResolver.buildSettingExtensions());
+ return docket;
+ }
+}
diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/controller/ExportTaskController.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/controller/ExportTaskController.java
new file mode 100644
index 0000000000000000000000000000000000000000..560e378580978316d57bc7015bc5f53d4c0a3987
--- /dev/null
+++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/controller/ExportTaskController.java
@@ -0,0 +1,106 @@
+package com.lframework.starter.mq.core.controller;
+
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.lframework.starter.common.utils.StringUtil;
+import com.lframework.starter.web.core.components.security.SecurityUtil;
+import com.lframework.starter.web.core.controller.DefaultBaseController;
+import com.lframework.starter.web.core.components.resp.InvokeResult;
+import com.lframework.starter.web.core.components.resp.InvokeResultBuilder;
+import com.lframework.starter.web.core.components.resp.PageResult;
+import com.lframework.starter.web.core.utils.PageResultUtil;
+import com.lframework.starter.mq.core.bo.ExportingExportTaskBo;
+import com.lframework.starter.mq.core.bo.FailExportTaskBo;
+import com.lframework.starter.mq.core.bo.SuccessExportTaskBo;
+import com.lframework.starter.mq.core.entity.ExportTask;
+import com.lframework.starter.mq.core.enums.ExportTaskStatus;
+import com.lframework.starter.mq.core.service.ExportTaskService;
+import com.lframework.starter.mq.core.vo.QueryFailExportTaskVo;
+import com.lframework.starter.mq.core.vo.QuerySuccessExportTaskVo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.validation.Valid;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 导出任务
+ *
+ * @author zmj
+ */
+@Api(tags = "导出任务")
+@Validated
+@RestController
+@RequestMapping("/export/task")
+public class ExportTaskController extends DefaultBaseController {
+
+ @Autowired
+ private ExportTaskService exportTaskService;
+
+ /**
+ * 正在导出列表
+ */
+ @ApiOperation("正在导出列表")
+ @GetMapping("/exporting")
+ public InvokeResult> queryExporting() {
+
+ Wrapper queryWrapper = Wrappers.lambdaQuery(ExportTask.class)
+ .eq(ExportTask::getCreateById, SecurityUtil.getCurrentUser().getId())
+ .in(ExportTask::getStatus, ExportTaskStatus.CREATED, ExportTaskStatus.EXPORTING)
+ .orderByDesc(ExportTask::getCreateTime);
+ List datas = exportTaskService.list(queryWrapper);
+
+ List results = datas.stream().map(ExportingExportTaskBo::new)
+ .collect(Collectors.toList());
+
+ return InvokeResultBuilder.success(results);
+ }
+
+ @ApiOperation("导出成功列表")
+ @GetMapping("/success")
+ public InvokeResult> querySuccess(
+ @Valid QuerySuccessExportTaskVo vo) {
+ Wrapper queryWrapper = Wrappers.lambdaQuery(ExportTask.class)
+ .eq(ExportTask::getCreateById, SecurityUtil.getCurrentUser().getId())
+ .eq(ExportTask::getStatus, ExportTaskStatus.SUCCESS)
+ .like(StringUtil.isNotBlank(vo.getName()), ExportTask::getName, vo.getName())
+ .orderByDesc(ExportTask::getCreateTime);
+
+ Page page = new Page<>(getPageIndex(vo), getPageSize(vo));
+
+ Page pageList = exportTaskService.page(page, queryWrapper);
+ PageResult pageResult = PageResultUtil.convert(pageList);
+ List datas = pageResult.getDatas();
+ List results = datas.stream().map(SuccessExportTaskBo::new)
+ .collect(Collectors.toList());
+
+ return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results));
+ }
+
+ @ApiOperation("导出失败列表")
+ @GetMapping("/fail")
+ public InvokeResult> queryFail(
+ @Valid QueryFailExportTaskVo vo) {
+ Wrapper queryWrapper = Wrappers.lambdaQuery(ExportTask.class)
+ .eq(ExportTask::getCreateById, SecurityUtil.getCurrentUser().getId())
+ .eq(ExportTask::getStatus, ExportTaskStatus.FAIL)
+ .like(StringUtil.isNotBlank(vo.getName()), ExportTask::getName, vo.getName())
+ .orderByDesc(ExportTask::getCreateTime);
+
+ Page page = new Page<>(getPageIndex(vo), getPageSize(vo));
+
+ Page pageList = exportTaskService.page(page, queryWrapper);
+ PageResult pageResult = PageResultUtil.convert(pageList);
+ List datas = pageResult.getDatas();
+ List results = datas.stream().map(FailExportTaskBo::new)
+ .collect(Collectors.toList());
+
+ return InvokeResultBuilder.success(PageResultUtil.rebuild(pageResult, results));
+ }
+}
diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/dto/AddExportTaskDto.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/dto/AddExportTaskDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..ffb24319d558115389c62535e260c5a43baab19c
--- /dev/null
+++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/dto/AddExportTaskDto.java
@@ -0,0 +1,30 @@
+package com.lframework.starter.mq.core.dto;
+
+import java.io.Serializable;
+import lombok.Data;
+
+@Data
+public class AddExportTaskDto implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 名称
+ */
+ private String name;
+
+ /**
+ * 请求类名
+ */
+ private String reqClassName;
+
+ /**
+ * 请求类方法参数
+ */
+ private String reqParams;
+
+ /**
+ * 用户Token
+ */
+ private String token;
+}
diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/dto/ExecuteExportTaskDto.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/dto/ExecuteExportTaskDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..a4ed0b7c8a1c86a820d4f4adcb3c700371fe149f
--- /dev/null
+++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/dto/ExecuteExportTaskDto.java
@@ -0,0 +1,15 @@
+package com.lframework.starter.mq.core.dto;
+
+import com.lframework.starter.web.core.dto.BaseDto;
+import java.io.Serializable;
+import lombok.Data;
+
+@Data
+public class ExecuteExportTaskDto implements BaseDto, Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ private String taskId;
+
+ private String token;
+}
diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/dto/ExportTaskSummaryDto.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/dto/ExportTaskSummaryDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..1bb2276c4015905f7e45581c398fd0c92f42ce92
--- /dev/null
+++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/dto/ExportTaskSummaryDto.java
@@ -0,0 +1,17 @@
+package com.lframework.starter.mq.core.dto;
+
+import com.lframework.starter.web.core.dto.BaseDto;
+import java.io.Serializable;
+import lombok.Data;
+
+@Data
+public class ExportTaskSummaryDto implements BaseDto, Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ private Integer unFinishedCount;
+
+ private Integer successCount;
+
+ private Integer failCount;
+}
diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/entity/ExportTask.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/entity/ExportTask.java
new file mode 100644
index 0000000000000000000000000000000000000000..3b951fd12717e2a78c0c1e12768ecc3f180f4b79
--- /dev/null
+++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/entity/ExportTask.java
@@ -0,0 +1,106 @@
+package com.lframework.starter.mq.core.entity;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.lframework.starter.web.core.dto.BaseDto;
+import com.lframework.starter.web.core.entity.BaseEntity;
+import com.lframework.starter.mq.core.enums.ExportTaskStatus;
+import java.time.LocalDateTime;
+import lombok.Data;
+
+/**
+ *
+ * 导出任务
+ *
+ *
+ * @author zmj
+ * @since 2025-04-10
+ */
+@Data
+@TableName("tbl_export_task")
+public class ExportTask extends BaseEntity implements BaseDto {
+
+ public static final String CACHE_NAME = "ExportTask";
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * ID
+ */
+ private String id;
+
+ /**
+ * 名称
+ */
+ private String name;
+
+ /**
+ * 上传记录ID
+ */
+ private String recordId;
+
+ /**
+ * 状态
+ */
+ private ExportTaskStatus status;
+
+ /**
+ * 错误信息
+ */
+ private String errorMsg;
+
+ /**
+ * 请求类名
+ */
+ private String reqClassName;
+
+
+ /**
+ * 请求类方法参数
+ */
+ private String reqParams;
+
+ /**
+ * 请求类方法参数签名
+ */
+ private String reqParamsSign;
+
+ /**
+ * 总数据条数
+ */
+ private Long totalCount;
+
+ /**
+ * 当前完成数据条数
+ */
+ private Long curCount;
+
+ /**
+ * 文件大小
+ */
+ private String fileSize;
+
+ /**
+ * 创建人ID 新增时赋值
+ */
+ @TableField(fill = FieldFill.INSERT)
+ private String createById;
+
+ /**
+ * 创建人 新增时赋值
+ */
+ @TableField(fill = FieldFill.INSERT)
+ private String createBy;
+
+ /**
+ * 创建时间 新增时赋值
+ */
+ @TableField(fill = FieldFill.INSERT)
+ private LocalDateTime createTime;
+
+ /**
+ * 结束时间
+ */
+ private LocalDateTime finishTime;
+}
diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/enums/ExportTaskStatus.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/enums/ExportTaskStatus.java
new file mode 100644
index 0000000000000000000000000000000000000000..0eac865f142cf50fa8816a41110be09166fab1b1
--- /dev/null
+++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/enums/ExportTaskStatus.java
@@ -0,0 +1,34 @@
+package com.lframework.starter.mq.core.enums;
+
+import com.baomidou.mybatisplus.annotation.EnumValue;
+import com.lframework.starter.web.core.enums.BaseEnum;
+
+public enum ExportTaskStatus implements BaseEnum {
+ CREATED(0, "等待导出"),
+ EXPORTING(1, "正在导出"),
+ SUCCESS(2, "导出成功"),
+ FAIL(3, "导出失败");
+
+ @EnumValue
+ private final Integer code;
+
+ private final String desc;
+
+ ExportTaskStatus(Integer code, String desc) {
+
+ this.code = code;
+ this.desc = desc;
+ }
+
+ @Override
+ public Integer getCode() {
+
+ return this.code;
+ }
+
+ @Override
+ public String getDesc() {
+
+ return this.desc;
+ }
+}
diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/events/ExportTaskNotifyEvent.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/events/ExportTaskNotifyEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..5f4bb5d4d2a5b2d5a5da0493e9359245dd2c8bc4
--- /dev/null
+++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/events/ExportTaskNotifyEvent.java
@@ -0,0 +1,15 @@
+package com.lframework.starter.mq.core.events;
+
+import lombok.Getter;
+import org.springframework.context.ApplicationEvent;
+
+public class ExportTaskNotifyEvent extends ApplicationEvent {
+
+ @Getter
+ private String createById;
+
+ public ExportTaskNotifyEvent(Object source, String createById) {
+ super(source);
+ this.createById = createById;
+ }
+}
diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/handlers/ExportTaskHandler.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/handlers/ExportTaskHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..edbbecf8863a3ed38854e07c611a3e162ae31c8c
--- /dev/null
+++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/handlers/ExportTaskHandler.java
@@ -0,0 +1,147 @@
+package com.lframework.starter.mq.core.handlers;
+
+import com.lframework.starter.common.exceptions.ClientException;
+import com.lframework.starter.common.exceptions.impl.DefaultClientException;
+import com.lframework.starter.common.utils.CollectionUtil;
+import com.lframework.starter.common.utils.FileUtil;
+import com.lframework.starter.common.utils.StringUtil;
+import com.lframework.starter.mq.core.components.export.ExportTaskWorker;
+import com.lframework.starter.mq.core.entity.ExportTask;
+import com.lframework.starter.mq.core.service.ExportTaskService;
+import com.lframework.starter.web.core.components.excel.ExcelModel;
+import com.lframework.starter.web.core.components.excel.ExcelMultipartWriterSheetBuilder;
+import com.lframework.starter.web.core.components.resp.PageResult;
+import com.lframework.starter.web.core.components.security.AbstractUserDetails;
+import com.lframework.starter.web.core.components.security.SecurityUtil;
+import com.lframework.starter.web.core.components.upload.client.dto.UploadDto;
+import com.lframework.starter.web.core.utils.ApplicationUtil;
+import com.lframework.starter.web.core.utils.ExcelUtil;
+import com.lframework.starter.web.core.utils.UploadUtil;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class ExportTaskHandler {
+
+ // 每页条数
+ private static final int PER_PAGE_SIZE = 10000;
+
+ // 上报处理条数的攒批数量
+ private static final int COUNT_BATCH_SIZE = 100;
+
+ private ExportTaskWorker
exportTaskWorker;
+
+ private long timeout;
+
+ private int curCount;
+
+ private String taskId;
+
+ public ExportTaskHandler(String taskId, ExportTaskWorker
exportTaskWorker,
+ long timeout) {
+ this.taskId = taskId;
+ this.exportTaskWorker = exportTaskWorker;
+ this.timeout = timeout;
+ }
+
+ public void execute(String json) {
+
+ ExportTaskService exportTaskService = ApplicationUtil.getBean(ExportTaskService.class);
+
+ ExportTask exportTask = exportTaskService.getById(taskId);
+
+ String tmpLocation = ApplicationUtil.getEnv().getProperty("spring.servlet.multipart.location");
+ tmpLocation = tmpLocation.endsWith(File.separator) ? tmpLocation : tmpLocation + File.separator;
+ try {
+ // 将导出任务状态置为正在导出
+ exportTaskService.setExporting(taskId);
+
+ P params = exportTaskWorker.parseParams(json);
+
+ long beginTs = System.currentTimeMillis();
+ int pageIndex = 1;
+ File xlsxFile = FileUtil.newFile(tmpLocation + taskId + ".xlsx");
+ ExcelMultipartWriterSheetBuilder builder = ExcelUtil.multipartExportXlsx(xlsxFile, "Sheet1",
+ exportTaskWorker.getModelClass());
+ boolean setTotalCount = false;
+ try {
+ while (true) {
+ PageResult pageResult = exportTaskWorker.getDataList(pageIndex, PER_PAGE_SIZE, params);
+ this.checkCurrentUser();
+ if (!setTotalCount) {
+ long totalCount = pageResult.getTotalCount();
+ // 上报总数据条数
+ exportTaskService.setTotalCount(taskId, totalCount);
+ setTotalCount = true;
+ }
+ long calcTs = System.currentTimeMillis() - beginTs;
+ if (calcTs > timeout * 1000L) {
+ throw new DefaultClientException(
+ "导出任务已执行" + (calcTs / 1000) + "秒,已超出最大执行时间" + timeout
+ + "秒,无法导出。");
+ }
+ List dataList = pageResult.getDatas();
+ List modelList = new ArrayList<>(dataList.size());
+ for (D data : dataList) {
+ M model = exportTaskWorker.exportData(data);
+ modelList.add(model);
+ // 上报处理条数
+ this.reportCurCount();
+ }
+
+ builder.doWrite(modelList);
+ if (!pageResult.isHasNext()) {
+ break;
+ }
+ }
+ } finally {
+ builder.finish();
+ }
+
+ UploadDto uploadDto = UploadUtil.upload(xlsxFile,
+ CollectionUtil.toList("export-task", exportTask.getCreateById()), true);
+
+ // 将导出任务状态置为导出完成
+ exportTaskService.setSuccess(taskId, uploadDto.getSecurityUploadRecordId(),
+ FileUtil.readableFileSize(xlsxFile.length()));
+ } catch (ClientException e) {
+ this.handleError(e);
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ this.handleError(e);
+ }
+ }
+
+ protected void reportCurCount() {
+ this.curCount++;
+ if (this.curCount >= COUNT_BATCH_SIZE) {
+ ExportTaskService exportTaskService = ApplicationUtil.getBean(ExportTaskService.class);
+ exportTaskService.addCurCount(taskId, this.curCount);
+ this.curCount = 0;
+ }
+ }
+
+ /**
+ * 处理异常
+ *
+ * @param e
+ */
+ protected void handleError(Exception e) {
+ ExportTaskService exportTaskService = ApplicationUtil.getBean(ExportTaskService.class);
+ // 将导出任务状态置为失败
+ exportTaskService.setFail(taskId,
+ StringUtil.isBlank(e.getMessage()) ? e.toString() : e.getMessage());
+
+ exportTaskWorker.handleError(e);
+ }
+
+ protected void checkCurrentUser() {
+ // 必须一直检测session是否在线,否则可能会导致查出的数据超出了当前用户可访问的数据
+ AbstractUserDetails currentUser = SecurityUtil.getCurrentUser();
+ if (currentUser == null || SecurityUtil.getSessionByLoginId(currentUser.getLoginId()) == null) {
+ throw new DefaultClientException("导出用户已退出登录,无法导出");
+ }
+ }
+}
diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/impl/ExportTaskServiceImpl.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/impl/ExportTaskServiceImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..80d490aa3fbf3bc0f31f13134ef411eb716652ac
--- /dev/null
+++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/impl/ExportTaskServiceImpl.java
@@ -0,0 +1,127 @@
+package com.lframework.starter.mq.core.impl;
+
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.lframework.starter.common.exceptions.impl.DefaultSysException;
+import com.lframework.starter.mq.core.dto.ExportTaskSummaryDto;
+import com.lframework.starter.mq.core.entity.ExportTask;
+import com.lframework.starter.mq.core.enums.ExportTaskStatus;
+import com.lframework.starter.mq.core.events.ExportTaskNotifyEvent;
+import com.lframework.starter.mq.core.mappers.ExportTaskMapper;
+import com.lframework.starter.mq.core.service.ExportTaskService;
+import com.lframework.starter.web.core.impl.BaseMpServiceImpl;
+import com.lframework.starter.web.core.utils.ApplicationUtil;
+import java.time.LocalDateTime;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@Slf4j
+@Service
+public class ExportTaskServiceImpl extends BaseMpServiceImpl
+ implements ExportTaskService {
+
+ @Transactional(rollbackFor = Exception.class)
+ @Override
+ public String create(ExportTask task) {
+ this.save(task);
+
+ ApplicationUtil.publishEvent(new ExportTaskNotifyEvent(this, task.getCreateById()));
+ return task.getId();
+ }
+
+ @Transactional(rollbackFor = Exception.class)
+ @Override
+ public void setExporting(String id) {
+
+ ExportTask task = this.getById(id);
+
+ Wrapper updateWrapper = Wrappers.lambdaUpdate(ExportTask.class)
+ .eq(ExportTask::getId, id)
+ .eq(ExportTask::getStatus, ExportTaskStatus.CREATED)
+ .set(ExportTask::getStatus, ExportTaskStatus.EXPORTING);
+
+ if (!this.update(updateWrapper)) {
+ log.error("导出任务 ID {} 设置为 正在导出 失败", id);
+ throw new DefaultSysException(
+ "导出任务设置为“" + ExportTaskStatus.EXPORTING.getDesc() + "”失败");
+ }
+
+ ApplicationUtil.publishEvent(new ExportTaskNotifyEvent(this, task.getCreateById()));
+ }
+
+ @Transactional(rollbackFor = Exception.class)
+ @Override
+ public void setSuccess(String id, String securityUploadRecordId, String fileSize) {
+
+ ExportTask task = this.getById(id);
+ String recordId = securityUploadRecordId;
+
+ Wrapper updateWrapper = Wrappers.lambdaUpdate(ExportTask.class)
+ .eq(ExportTask::getId, id)
+ .in(ExportTask::getStatus, ExportTaskStatus.CREATED, ExportTaskStatus.EXPORTING)
+ .set(ExportTask::getRecordId, recordId)
+ .set(ExportTask::getStatus, ExportTaskStatus.SUCCESS)
+ .set(ExportTask::getFinishTime, LocalDateTime.now())
+ .set(ExportTask::getFileSize, fileSize)
+ .setSql("cur_count = total_count");
+ if (!this.update(updateWrapper)) {
+ log.error("导出任务 ID {} 设置为 导出成功 失败", id);
+ throw new DefaultSysException(
+ "导出任务设置为“" + ExportTaskStatus.SUCCESS.getDesc() + "”失败");
+ }
+ ApplicationUtil.publishEvent(new ExportTaskNotifyEvent(this, task.getCreateById()));
+ }
+
+ @Transactional(rollbackFor = Exception.class)
+ @Override
+ public void setFail(String id, String errorMsg) {
+ ExportTask task = this.getById(id);
+ Wrapper updateWrapper = Wrappers.lambdaUpdate(ExportTask.class)
+ .eq(ExportTask::getId, id)
+ .set(ExportTask::getStatus, ExportTaskStatus.FAIL)
+ .set(ExportTask::getErrorMsg, errorMsg)
+ .set(ExportTask::getFinishTime, LocalDateTime.now());
+ if (!this.update(updateWrapper)) {
+ log.error("导出任务 ID {} 设置为 导出失败 失败", id);
+ throw new DefaultSysException(
+ "导出任务设置为“" + ExportTaskStatus.FAIL.getDesc() + "”失败");
+ }
+ ApplicationUtil.publishEvent(new ExportTaskNotifyEvent(this, task.getCreateById()));
+ }
+
+ @Transactional(rollbackFor = Exception.class)
+ @Override
+ public void setTotalCount(String id, Long totalCount) {
+ Wrapper updateWrapper = Wrappers.lambdaUpdate(ExportTask.class)
+ .eq(ExportTask::getId, id)
+ .eq(ExportTask::getStatus, ExportTaskStatus.EXPORTING)
+ .set(ExportTask::getTotalCount, totalCount);
+
+ if (!this.update(updateWrapper)) {
+ log.error("导出任务 ID {} 设置 数据总条数 失败", id);
+ throw new DefaultSysException(
+ "导出任务设置数据总条数失败");
+ }
+ }
+
+ @Transactional(rollbackFor = Exception.class)
+ @Override
+ public void addCurCount(String id, int addCount) {
+ Wrapper updateWrapper = Wrappers.lambdaUpdate(ExportTask.class)
+ .eq(ExportTask::getId, id)
+ .eq(ExportTask::getStatus, ExportTaskStatus.EXPORTING)
+ .setSql("cur_count = cur_count + " + addCount);
+
+ if (!this.update(updateWrapper)) {
+ log.error("导出任务 ID {} 设置 当前导出条数 失败", id);
+ throw new DefaultSysException(
+ "导出任务设置当前导出条数失败");
+ }
+ }
+
+ @Override
+ public ExportTaskSummaryDto getSummaryByUserId(String userId) {
+ return getBaseMapper().getSummaryByUserId(userId);
+ }
+}
diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/mappers/ExportTaskMapper.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/mappers/ExportTaskMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..27308dfd1d6fc36221e54dae3c4a0b0851b27cea
--- /dev/null
+++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/mappers/ExportTaskMapper.java
@@ -0,0 +1,24 @@
+package com.lframework.starter.mq.core.mappers;
+
+import com.lframework.starter.web.core.mapper.BaseMapper;
+import com.lframework.starter.mq.core.dto.ExportTaskSummaryDto;
+import com.lframework.starter.mq.core.entity.ExportTask;
+
+/**
+ *
+ * ExportTaskMapper 接口
+ *
+ *
+ * @author zmj
+ * @since 2025-04-10
+ */
+public interface ExportTaskMapper extends BaseMapper {
+
+ /**
+ * 根据用户ID统计导出任务
+ *
+ * @param userId
+ * @return
+ */
+ ExportTaskSummaryDto getSummaryByUserId(String userId);
+}
diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/producer/MqProducer.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/producer/MqProducer.java
new file mode 100644
index 0000000000000000000000000000000000000000..b74df9f1b3d2f3b8a4d6b496dd13eae4b8f359b7
--- /dev/null
+++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/producer/MqProducer.java
@@ -0,0 +1,82 @@
+package com.lframework.starter.mq.core.producer;
+
+import com.lframework.starter.mq.core.queue.QueueDefinition;
+import java.io.Serializable;
+
+/**
+ * MQ生产者
+ *
+ * @author zmj
+ * @since 2022/8/25
+ */
+public interface MqProducer {
+
+ /**
+ * 发送延时消息
+ *
+ * @param definition 队列
+ * @param data 数据
+ * @param millis 毫秒
+ */
+ void sendDelayMessage(QueueDefinition definition, Serializable data, long millis);
+
+ /**
+ * 发送即时消息
+ *
+ * @param definition 队列
+ * @param data 数据
+ */
+ void sendMessage(QueueDefinition definition, Serializable data);
+
+ /**
+ * 发送延时消息
+ *
+ * @param definition 队列
+ * @param millis 毫秒
+ */
+ void sendDelayMessage(QueueDefinition definition, long millis);
+
+ /**
+ * 发送即时消息
+ *
+ * @param definition 队列
+ */
+ void sendMessage(QueueDefinition definition);
+
+ /**
+ * 发送延时消息
+ *
+ * @param definition 队列
+ * @param data 数据
+ * @param millis 毫秒
+ * @param tenantId 租户ID
+ */
+ void sendDelayMessage(QueueDefinition definition, Serializable data, long millis,
+ Integer tenantId);
+
+ /**
+ * 发送即时消息
+ *
+ * @param definition 队列
+ * @param data 数据
+ * @param tenantId 租户ID
+ */
+ void sendMessage(QueueDefinition definition, Serializable data, Integer tenantId);
+
+ /**
+ * 发送延时消息
+ *
+ * @param definition 队列
+ * @param millis 毫秒
+ * @param tenantId 租户ID
+ */
+ void sendDelayMessage(QueueDefinition definition, long millis, Integer tenantId);
+
+ /**
+ * 发送即时消息
+ *
+ * @param definition 队列
+ * @param tenantId 租户ID
+ */
+ void sendMessage(QueueDefinition definition, Integer tenantId);
+}
diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/queue/QueueDefinition.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/queue/QueueDefinition.java
new file mode 100644
index 0000000000000000000000000000000000000000..9f8a1c2c1e5763f98f52fd8d1811109e6e747d7a
--- /dev/null
+++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/queue/QueueDefinition.java
@@ -0,0 +1,8 @@
+package com.lframework.starter.mq.core.queue;
+
+/**
+ * 队列定义
+ */
+public interface QueueDefinition {
+
+}
diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/service/ExportTaskService.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/service/ExportTaskService.java
new file mode 100644
index 0000000000000000000000000000000000000000..c5e93cb0250cb298631c3906483ad5cb9c540dad
--- /dev/null
+++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/service/ExportTaskService.java
@@ -0,0 +1,67 @@
+package com.lframework.starter.mq.core.service;
+
+import com.lframework.starter.web.core.service.BaseMpService;
+import com.lframework.starter.mq.core.dto.ExportTaskSummaryDto;
+import com.lframework.starter.mq.core.entity.ExportTask;
+
+/**
+ * 导出任务 Service
+ *
+ * @author zmj
+ */
+public interface ExportTaskService extends BaseMpService {
+
+ /**
+ * 新增
+ *
+ * @param task
+ * @return
+ */
+ String create(ExportTask task);
+
+ /**
+ * 设置为正在导出
+ *
+ * @param id
+ */
+ void setExporting(String id);
+
+ /**
+ * 设置为成功
+ *
+ * @param id
+ */
+ void setSuccess(String id, String securityUploadRecordId, String fileSize);
+
+ /**
+ * 设置为失败
+ *
+ * @param id
+ * @param errorMsg
+ */
+ void setFail(String id, String errorMsg);
+
+ /**
+ * 设置数据总条数
+ *
+ * @param id
+ * @param totalCount
+ */
+ void setTotalCount(String id, Long totalCount);
+
+ /**
+ * 增加当前导出条数
+ *
+ * @param id
+ * @param addCount
+ */
+ void addCurCount(String id, int addCount);
+
+ /**
+ * 根据用户ID统计导出任务
+ *
+ * @param userId
+ * @return
+ */
+ ExportTaskSummaryDto getSummaryByUserId(String userId);
+}
diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/service/MqProducerService.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/service/MqProducerService.java
new file mode 100644
index 0000000000000000000000000000000000000000..d537d7fa7bde09ee57863279f4fbbdb607bb9385
--- /dev/null
+++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/service/MqProducerService.java
@@ -0,0 +1,46 @@
+package com.lframework.starter.mq.core.service;
+
+import com.lframework.starter.mq.core.dto.AddExportTaskDto;
+import com.lframework.starter.mq.core.dto.ExecuteExportTaskDto;
+import com.lframework.starter.web.core.service.BaseService;
+import com.lframework.starter.web.inner.dto.message.SysMailMessageDto;
+import com.lframework.starter.web.inner.dto.message.SysSiteMessageDto;
+import com.lframework.starter.web.inner.dto.notify.SysNotifyDto;
+
+public interface MqProducerService extends BaseService {
+
+ /**
+ * 发送消息通知
+ *
+ * @param dto
+ */
+ void createSysNotify(SysNotifyDto dto);
+
+ /**
+ * 发送邮件消息
+ *
+ * @param dto
+ */
+ void createSysMailMessage(SysMailMessageDto dto);
+
+ /**
+ * 发送站内信
+ *
+ * @param dto
+ */
+ void createSysSiteMessage(SysSiteMessageDto dto);
+
+ /**
+ * 新增导出任务
+ *
+ * @param dto
+ */
+ void addExportTask(AddExportTaskDto dto);
+
+ /**
+ * 执行导出任务
+ *
+ * @param dto
+ */
+ void executeExportTask(ExecuteExportTaskDto dto);
+}
diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/utils/ExportTaskUtil.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/utils/ExportTaskUtil.java
new file mode 100644
index 0000000000000000000000000000000000000000..5b741090eebff9dcd5c65a46b4b71fd9656cc0cc
--- /dev/null
+++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/utils/ExportTaskUtil.java
@@ -0,0 +1,27 @@
+package com.lframework.starter.mq.core.utils;
+
+import com.lframework.starter.common.utils.DateUtil;
+import com.lframework.starter.mq.core.components.export.ExportTaskWorker;
+import com.lframework.starter.mq.core.service.MqProducerService;
+import com.lframework.starter.web.core.components.security.UserTokenResolver;
+import com.lframework.starter.web.core.utils.ApplicationUtil;
+import com.lframework.starter.web.core.utils.JsonUtil;
+import com.lframework.starter.mq.core.dto.AddExportTaskDto;
+import java.time.LocalDateTime;
+
+public class ExportTaskUtil {
+
+ public static void exportTask(String taskName,
+ Class extends ExportTaskWorker, ?, ?>> clazz,
+ Object params) {
+ MqProducerService mqProducerService = ApplicationUtil.getBean(MqProducerService.class);
+ UserTokenResolver userTokenResolver = ApplicationUtil.getBean(UserTokenResolver.class);
+ AddExportTaskDto dto = new AddExportTaskDto();
+ dto.setName(taskName + "_" + DateUtil.formatDateTime(LocalDateTime.now(), "yyyyMMddHHmmss"));
+ dto.setReqClassName(clazz.getName());
+ dto.setReqParams(JsonUtil.toJsonString(params));
+ dto.setToken(userTokenResolver.getToken());
+
+ mqProducerService.addExportTask(dto);
+ }
+}
diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/vo/QueryFailExportTaskVo.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/vo/QueryFailExportTaskVo.java
new file mode 100644
index 0000000000000000000000000000000000000000..237c23ba1ada4afb8c422cf214ba54fa51cfc6dc
--- /dev/null
+++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/vo/QueryFailExportTaskVo.java
@@ -0,0 +1,15 @@
+package com.lframework.starter.mq.core.vo;
+
+import com.lframework.starter.web.core.vo.PageVo;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+public class QueryFailExportTaskVo extends PageVo {
+
+ /**
+ * 名称
+ */
+ @ApiModelProperty("名称")
+ private String name;
+}
diff --git a/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/vo/QuerySuccessExportTaskVo.java b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/vo/QuerySuccessExportTaskVo.java
new file mode 100644
index 0000000000000000000000000000000000000000..cd66eef074e3cdc81e2690c85896c6079dbeb690
--- /dev/null
+++ b/mq-starter/mq-core/src/main/java/com/lframework/starter/mq/core/vo/QuerySuccessExportTaskVo.java
@@ -0,0 +1,15 @@
+package com.lframework.starter.mq.core.vo;
+
+import com.lframework.starter.web.core.vo.PageVo;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+public class QuerySuccessExportTaskVo extends PageVo {
+
+ /**
+ * 名称
+ */
+ @ApiModelProperty("名称")
+ private String name;
+}
diff --git a/websocket-starter/src/main/resources/META-INF/spring.factories b/mq-starter/mq-core/src/main/resources/META-INF/spring.factories
similarity index 33%
rename from websocket-starter/src/main/resources/META-INF/spring.factories
rename to mq-starter/mq-core/src/main/resources/META-INF/spring.factories
index 2caf5ff67847a4a26c9dcae07b5aa7ded824d4a0..d7c42dd94ce9cbe3ad5432c8ab16d558ee2c11d7 100644
--- a/websocket-starter/src/main/resources/META-INF/spring.factories
+++ b/mq-starter/mq-core/src/main/resources/META-INF/spring.factories
@@ -1 +1,2 @@
-org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.lframework.starter.websocket.config.WsAutoConfiguration
\ No newline at end of file
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.lframework.starter.mq.core.config.MqBeanAutoConfiguration,\
+ com.lframework.starter.mq.core.config.MqSwaggerAutoConfiguration
\ No newline at end of file
diff --git a/mq-starter/mq-core/src/main/resources/mappers/ExportTaskMapper.xml b/mq-starter/mq-core/src/main/resources/mappers/ExportTaskMapper.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1c3e8d1c74f64d11e39e797ab4e8992e93f404d8
--- /dev/null
+++ b/mq-starter/mq-core/src/main/resources/mappers/ExportTaskMapper.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
diff --git a/mq-starter/pom.xml b/mq-starter/pom.xml
index b80250d0bb47f6ce21daab53e41363c02a75fba8..080578e33cdbc6f322c0e3fb5a7d56f6a3c9f19f 100644
--- a/mq-starter/pom.xml
+++ b/mq-starter/pom.xml
@@ -5,28 +5,37 @@
parent
com.lframework
- 3.1.3
+ 4.0.5
mq-starter
4.0.0
- 【${project.artifactId}】集成MQ通用能力
+ 【${project.artifactId}】集成MQ能力
+ pom
-
-
- org.springframework.boot
- spring-boot-configuration-processor
- true
-
+
+ mq-core
+ activemq-starter
+ rabbitmq-starter
+
-
- web-starter
- com.lframework
-
-
-
- pooled-jms
- org.messaginghub
-
-
+
+
+
+ com.lframework
+ mq-core
+ ${jugg.version}
+
+
+ com.lframework
+ activemq-starter
+ ${jugg.version}
+
+
+ com.lframework
+ rabbitmq-starter
+ ${jugg.version}
+
+
+
\ No newline at end of file
diff --git a/web-common/pom.xml b/mq-starter/rabbitmq-starter/pom.xml
similarity index 41%
rename from web-common/pom.xml
rename to mq-starter/rabbitmq-starter/pom.xml
index 45807767b35aa53a76b4aa07b50403a36903258f..09c80862fc77a806d8ec00c020651642e2961644 100644
--- a/web-common/pom.xml
+++ b/mq-starter/rabbitmq-starter/pom.xml
@@ -3,45 +3,30 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- parent
+ mq-starter
com.lframework
- 3.1.3
+ 4.0.5
- 4.0.0
- web-common
- 【${project.artifactId}】需要提供给外部系统使用的依赖
+ rabbitmq-starter
+ 4.0.0
+ 【${project.artifactId}】集成RabbitMQ能力
-
- org.projectlombok
- lombok
-
-
org.springframework.boot
- spring-boot-starter
+ spring-boot-configuration-processor
+ true
- org.apache.commons
- commons-pool2
+ com.lframework
+ mq-core
- cn.dev33
- sa-token-spring-boot-starter
-
-
-
- cn.dev33
- sa-token-dao-redis-jackson
-
-
-
- cn.dev33
- sa-token-alone-redis
+ org.springframework.boot
+ spring-boot-starter-amqp
-
\ No newline at end of file
diff --git a/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/config/RabbitMqAutoConfiguration.java b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/config/RabbitMqAutoConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..a74c842ffcd9ef999bfa78f8904b83f40e554c7f
--- /dev/null
+++ b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/config/RabbitMqAutoConfiguration.java
@@ -0,0 +1,98 @@
+package com.lframework.starter.mq.rabbitmq.config;
+
+import com.lframework.starter.common.utils.ArrayUtil;
+import com.lframework.starter.mq.rabbitmq.impl.RabbitMqProducerServiceImpl;
+import com.lframework.starter.mq.rabbitmq.listeners.app.ExportTaskNotifyListener;
+import com.lframework.starter.mq.rabbitmq.listeners.mq.ExportTaskListener;
+import com.lframework.starter.mq.rabbitmq.listeners.mq.SysMailMessageListener;
+import com.lframework.starter.mq.rabbitmq.listeners.mq.SysNotifyListener;
+import com.lframework.starter.mq.rabbitmq.listeners.mq.SysSiteMessageListener;
+import com.lframework.starter.mq.rabbitmq.producer.RabbitMqProducer;
+import org.aopalliance.aop.Advice;
+import org.springframework.amqp.rabbit.annotation.EnableRabbit;
+import org.springframework.amqp.rabbit.config.DirectRabbitListenerContainerFactory;
+import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
+import org.springframework.amqp.rabbit.connection.ConnectionFactory;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.amqp.rabbit.retry.MessageRecoverer;
+import org.springframework.amqp.support.converter.MessageConverter;
+import org.springframework.beans.factory.ObjectProvider;
+import org.springframework.boot.autoconfigure.amqp.DirectRabbitListenerContainerFactoryConfigurer;
+import org.springframework.boot.autoconfigure.amqp.RabbitProperties;
+import org.springframework.boot.autoconfigure.amqp.RabbitRetryTemplateCustomizer;
+import org.springframework.boot.autoconfigure.amqp.SimpleRabbitListenerContainerFactoryConfigurer;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+
+@EnableRabbit
+@Configuration
+@Import({
+ RabbitMqProducerServiceImpl.class,
+ SysMailMessageListener.class,
+ SysNotifyListener.class,
+ SysSiteMessageListener.class,
+ ExportTaskNotifyListener.class,
+ ExportTaskListener.class,
+})
+public class RabbitMqAutoConfiguration {
+
+ private final ObjectProvider messageConverter;
+
+ private final ObjectProvider messageRecoverer;
+
+ private final ObjectProvider retryTemplateCustomizers;
+
+ private final RabbitProperties properties;
+
+ RabbitMqAutoConfiguration(ObjectProvider messageConverter,
+ ObjectProvider messageRecoverer,
+ ObjectProvider retryTemplateCustomizers,
+ RabbitProperties properties) {
+ this.messageConverter = messageConverter;
+ this.messageRecoverer = messageRecoverer;
+ this.retryTemplateCustomizers = retryTemplateCustomizers;
+ this.properties = properties;
+ }
+
+ @Bean
+ public RabbitMqProducer activeMQProducer(RabbitTemplate rabbitTemplate) {
+ return new RabbitMqProducer(rabbitTemplate);
+ }
+
+ @Bean(name = "rabbitListenerContainerFactory")
+ @ConditionalOnProperty(prefix = "spring.rabbitmq.listener", name = "type", havingValue = "simple",
+ matchIfMissing = true)
+ SimpleRabbitListenerContainerFactory simpleRabbitListenerContainerFactory(
+ SimpleRabbitListenerContainerFactoryConfigurer configurer,
+ ConnectionFactory connectionFactory) {
+ SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
+ configurer.configure(factory, connectionFactory);
+ factory.setAdviceChain(combineAdvice(factory.getAdviceChain()));
+ return factory;
+ }
+
+ @Bean(name = "rabbitListenerContainerFactory")
+ @ConditionalOnProperty(prefix = "spring.rabbitmq.listener", name = "type", havingValue = "direct")
+ DirectRabbitListenerContainerFactory directRabbitListenerContainerFactory(
+ DirectRabbitListenerContainerFactoryConfigurer configurer,
+ ConnectionFactory connectionFactory) {
+ DirectRabbitListenerContainerFactory factory = new DirectRabbitListenerContainerFactory();
+ configurer.configure(factory, connectionFactory);
+ factory.setAdviceChain(combineAdvice(factory.getAdviceChain()));
+ return factory;
+ }
+
+ private Advice[] combineAdvice(Advice[] advices) {
+ Advice[] result = new Advice[(ArrayUtil.isEmpty(advices) ? 0 : advices.length) + 1];
+ if (!ArrayUtil.isEmpty(advices)) {
+ for (int i = 0; i < advices.length; i++) {
+ result[i] = advices[i];
+ }
+ }
+
+ result[result.length - 1] = new TenantMethodInterceptor();
+ return result;
+ }
+}
diff --git a/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/config/TenantMethodInterceptor.java b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/config/TenantMethodInterceptor.java
new file mode 100644
index 0000000000000000000000000000000000000000..2c46e0841a642adb8cf50d6737e8632bb1485906
--- /dev/null
+++ b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/config/TenantMethodInterceptor.java
@@ -0,0 +1,63 @@
+package com.lframework.starter.mq.rabbitmq.config;
+
+import com.lframework.starter.common.utils.ArrayUtil;
+import com.lframework.starter.web.core.components.tenant.TenantContextHolder;
+import com.lframework.starter.web.core.utils.TenantUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+import org.springframework.amqp.core.Message;
+
+@Slf4j
+public class TenantMethodInterceptor implements MethodInterceptor {
+
+ @Override
+ public Object invoke(MethodInvocation invocation) throws Throwable {
+ boolean isTenantEnabled = TenantUtil.enableTenant();
+ Integer tenantId = null;
+
+ if (isTenantEnabled) {
+ log.debug("RabbitMq开始处理TenantId");
+ tenantId = convertTenantId(invocation);
+ log.debug("TenantId = {}", tenantId);
+ if (tenantId != null) {
+ TenantContextHolder.setTenantId(tenantId);
+ }
+ }
+
+ try {
+ return invocation.proceed();
+ } catch (Throwable e) {
+ log.error(e.getMessage(), e);
+ throw e;
+ } finally {
+ TenantContextHolder.clearTenantId();
+ }
+ }
+
+ private Integer convertTenantId(MethodInvocation invocation) {
+ Object[] args = invocation.getArguments();
+
+ if (ArrayUtil.isEmpty(args)) {
+ return null;
+ }
+
+ for (Object arg : args) {
+ if (arg instanceof Message) {
+ Message message = (Message) arg;
+ Object headerValue = message.getMessageProperties().getHeader("tenantId");
+ if (headerValue instanceof Integer) {
+ return (Integer) headerValue;
+ } else if (headerValue != null) {
+ try {
+ return Integer.parseInt(headerValue.toString());
+ } catch (NumberFormatException e) {
+ return null;
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/constants/RabbitMqConstants.java b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/constants/RabbitMqConstants.java
new file mode 100644
index 0000000000000000000000000000000000000000..05f24c98edc2c8dd460b573aa5f42c44d3ac1704
--- /dev/null
+++ b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/constants/RabbitMqConstants.java
@@ -0,0 +1,40 @@
+package com.lframework.starter.mq.rabbitmq.constants;
+
+import com.lframework.starter.mq.core.queue.QueueDefinition;
+import com.lframework.starter.mq.rabbitmq.queue.RabbitMQQueueDefinition;
+
+public class RabbitMqConstants {
+
+ /**
+ * 消息通知
+ */
+ public static final QueueDefinition SYS_NOTIFY = new RabbitMQQueueDefinition(
+ RabbitMqStringPool.SYS_NOTIFY_EXCHANGE, RabbitMqStringPool.SYS_NOTIFY_ROUTING_KEY);
+
+ /**
+ * 邮件消息
+ */
+ public static final QueueDefinition SYS_MAIL_MESSAGE = new RabbitMQQueueDefinition(
+ RabbitMqStringPool.SYS_MAIL_MESSAGE_EXCHANGE,
+ RabbitMqStringPool.SYS_MAIL_MESSAGE_ROUTING_KEY);
+
+ /**
+ * 站内信
+ */
+ public static final QueueDefinition SYS_SITE_MESSAGE = new RabbitMQQueueDefinition(
+ RabbitMqStringPool.SYS_SITE_MESSAGE_EXCHANGE,
+ RabbitMqStringPool.SYS_SITE_MESSAGE_ROUTING_KEY);
+
+ /**
+ * 新增导出任务
+ */
+ public static final QueueDefinition ADD_EXPORT_TASK = new RabbitMQQueueDefinition(
+ RabbitMqStringPool.ADD_EXPORT_TASK_EXCHANGE, RabbitMqStringPool.ADD_EXPORT_TASK_ROUTING_KEY);
+
+ /**
+ * 执行导出任务
+ */
+ public static final QueueDefinition EXECUTE_EXPORT_TASK = new RabbitMQQueueDefinition(
+ RabbitMqStringPool.EXECUTE_EXPORT_TASK_EXCHANGE,
+ RabbitMqStringPool.EXECUTE_EXPORT_TASK_ROUTING_KEY);
+}
diff --git a/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/constants/RabbitMqStringPool.java b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/constants/RabbitMqStringPool.java
new file mode 100644
index 0000000000000000000000000000000000000000..4d609e82248ec336763a4ee33822e0cbeb4f1bb2
--- /dev/null
+++ b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/constants/RabbitMqStringPool.java
@@ -0,0 +1,39 @@
+package com.lframework.starter.mq.rabbitmq.constants;
+
+public interface RabbitMqStringPool {
+
+ // 增加库存
+ String ADD_STOCK_EXCHANGE = "add_stock.fanout";
+
+ // 扣减库存
+ String SUB_STOCK_EXCHANGE = "sub_stock.fanout";
+
+ // 审核通过订单
+ String APPROVE_PASS_ORDER_EXCHANGE = "approve_pass_order.fanout";
+
+ // 消息通知
+ String SYS_NOTIFY_EXCHANGE = "sys_notify.direct";
+ String SYS_NOTIFY_ROUTING_KEY = "sys_notify_routing_key";
+ String SYS_NOTIFY_QUEUE = "sys_notify";
+
+ // 邮件消息
+ String SYS_MAIL_MESSAGE_EXCHANGE = "sys_mail_message.direct";
+ String SYS_MAIL_MESSAGE_ROUTING_KEY = "sys_mail_message_routing_key";
+ String SYS_MAIL_MESSAGE_QUEUE = "sys_mail_message";
+
+ // 站内信
+ String SYS_SITE_MESSAGE_EXCHANGE = "sys_site_message.direct";
+ String SYS_SITE_MESSAGE_ROUTING_KEY = "sys_site_message_routing_key";
+ String SYS_SITE_MESSAGE_QUEUE = "sys_site_message";
+
+ // 新增导出任务
+ String ADD_EXPORT_TASK_EXCHANGE = "add_export_task.direct";
+ String ADD_EXPORT_TASK_ROUTING_KEY = "add_export_task_routing_key";
+ String ADD_EXPORT_TASK_QUEUE = "add_export_task";
+
+ // 执行导出任务
+ String EXECUTE_EXPORT_TASK_EXCHANGE = "execute_export_task.direct";
+ String EXECUTE_EXPORT_TASK_ROUTING_KEY = "execute_export_task_routing_key";
+ String EXECUTE_EXPORT_TASK_QUEUE = "execute_export_task";
+
+}
diff --git a/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/impl/RabbitMqProducerServiceImpl.java b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/impl/RabbitMqProducerServiceImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..fa62aa6b1d2fb41d8fb8f99e5cfa1dd70b2cc19a
--- /dev/null
+++ b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/impl/RabbitMqProducerServiceImpl.java
@@ -0,0 +1,42 @@
+package com.lframework.starter.mq.rabbitmq.impl;
+
+import com.lframework.starter.mq.core.dto.ExecuteExportTaskDto;
+import com.lframework.starter.mq.core.producer.MqProducer;
+import com.lframework.starter.mq.core.service.MqProducerService;
+import com.lframework.starter.mq.rabbitmq.constants.RabbitMqConstants;
+import com.lframework.starter.mq.core.dto.AddExportTaskDto;
+import com.lframework.starter.web.inner.dto.message.SysMailMessageDto;
+import com.lframework.starter.web.inner.dto.message.SysSiteMessageDto;
+import com.lframework.starter.web.inner.dto.notify.SysNotifyDto;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class RabbitMqProducerServiceImpl implements MqProducerService {
+
+ @Autowired
+ private MqProducer mqProducer;
+
+ @Override
+ public void createSysNotify(SysNotifyDto dto) {
+ mqProducer.sendMessage(RabbitMqConstants.SYS_NOTIFY, dto);
+ }
+
+ @Override
+ public void createSysMailMessage(SysMailMessageDto dto) {
+ mqProducer.sendMessage(RabbitMqConstants.SYS_MAIL_MESSAGE, dto);
+ }
+
+ @Override
+ public void createSysSiteMessage(SysSiteMessageDto dto) {
+ mqProducer.sendMessage(RabbitMqConstants.SYS_SITE_MESSAGE, dto);
+ }
+
+ @Override
+ public void addExportTask(AddExportTaskDto dto) {
+ mqProducer.sendMessage(RabbitMqConstants.ADD_EXPORT_TASK, dto);
+ }
+
+ @Override
+ public void executeExportTask(ExecuteExportTaskDto dto) {
+ mqProducer.sendMessage(RabbitMqConstants.EXECUTE_EXPORT_TASK, dto);
+ }
+}
diff --git a/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/listeners/app/ExportTaskNotifyListener.java b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/listeners/app/ExportTaskNotifyListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..91c5d070a82d84917145d6cea034dd27139c92fb
--- /dev/null
+++ b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/listeners/app/ExportTaskNotifyListener.java
@@ -0,0 +1,41 @@
+package com.lframework.starter.mq.rabbitmq.listeners.app;
+
+import com.lframework.starter.web.websocket.dto.WsPushData;
+import com.lframework.starter.web.websocket.components.WsDataPusher;
+import com.lframework.starter.web.websocket.events.UserConnectEvent;
+import com.lframework.starter.mq.core.events.ExportTaskNotifyEvent;
+import com.lframework.starter.mq.core.service.ExportTaskService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationListener;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.event.TransactionalEventListener;
+
+@Component
+public class ExportTaskNotifyListener implements ApplicationListener {
+
+ @Autowired
+ private WsDataPusher wsDataPusher;
+
+ @Autowired
+ private ExportTaskService exportTaskService;
+
+ @TransactionalEventListener
+ public void execute(ExportTaskNotifyEvent event) {
+ this.notify(event.getCreateById());
+ }
+
+ @Override
+ public void onApplicationEvent(UserConnectEvent event) {
+ this.notify(event.getUser().getId());
+ }
+
+ private void notify(String userId) {
+ // 发送广播
+ WsPushData pushData = new WsPushData();
+ pushData.setBizType("exportTask");
+ pushData.setDataObj(exportTaskService.getSummaryByUserId(userId));
+ pushData.setIncludeUserId(userId);
+
+ wsDataPusher.push(pushData);
+ }
+}
diff --git a/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/listeners/mq/ExportTaskListener.java b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/listeners/mq/ExportTaskListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..18b3522acbaa0008094f6b36b3673eb8fadcaa37
--- /dev/null
+++ b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/listeners/mq/ExportTaskListener.java
@@ -0,0 +1,125 @@
+package com.lframework.starter.mq.rabbitmq.listeners.mq;
+
+import cn.hutool.crypto.SecureUtil;
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.lframework.starter.common.exceptions.ClientException;
+import com.lframework.starter.common.exceptions.impl.DefaultClientException;
+import com.lframework.starter.common.utils.ReflectUtil;
+import com.lframework.starter.common.utils.StringUtil;
+import com.lframework.starter.mq.core.dto.AddExportTaskDto;
+import com.lframework.starter.mq.core.dto.ExecuteExportTaskDto;
+import com.lframework.starter.mq.core.entity.ExportTask;
+import com.lframework.starter.mq.core.enums.ExportTaskStatus;
+import com.lframework.starter.mq.core.handlers.ExportTaskHandler;
+import com.lframework.starter.mq.core.service.ExportTaskService;
+import com.lframework.starter.mq.core.service.MqProducerService;
+import com.lframework.starter.mq.rabbitmq.constants.RabbitMqStringPool;
+import com.lframework.starter.web.core.components.security.AbstractUserDetails;
+import com.lframework.starter.web.core.components.security.SecurityUtil;
+import com.lframework.starter.web.core.utils.IdUtil;
+import com.lframework.starter.web.inner.service.SysConfService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.amqp.rabbit.annotation.Exchange;
+import org.springframework.amqp.rabbit.annotation.Queue;
+import org.springframework.amqp.rabbit.annotation.QueueBinding;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.messaging.Message;
+import org.springframework.stereotype.Component;
+
+@Slf4j
+@Component("exportTaskListener")
+public class ExportTaskListener {
+
+ @Autowired
+ private ExportTaskService exportTaskService;
+
+ @Autowired
+ private MqProducerService mqProducerService;
+
+ @Autowired
+ private SysConfService sysConfService;
+
+ @RabbitListener(bindings = {
+ @QueueBinding(value = @Queue(value = RabbitMqStringPool.ADD_EXPORT_TASK_QUEUE), key = RabbitMqStringPool.ADD_EXPORT_TASK_ROUTING_KEY, exchange = @Exchange(value = RabbitMqStringPool.ADD_EXPORT_TASK_EXCHANGE))}, concurrency = "2")
+ public void addExportTask(Message message) {
+
+ AddExportTaskDto dto = message.getPayload();
+
+ log.info("接收到新增导出任务MQ message = {}", dto);
+
+ AbstractUserDetails currentUser = SecurityUtil.getUserByToken(dto.getToken());
+ if (currentUser == null) {
+ log.info("导出用户已退出登录,无法导出");
+ return;
+ }
+
+ try {
+ SecurityUtil.setCurrentUser(currentUser);
+
+ // 新增导出任务
+ ExportTask task = new ExportTask();
+ task.setId(IdUtil.getId());
+ task.setName(dto.getName());
+ task.setStatus(ExportTaskStatus.CREATED);
+ task.setReqClassName(dto.getReqClassName());
+ task.setReqParams(dto.getReqParams());
+
+ task.setReqParamsSign(SecureUtil.md5(dto.getReqClassName() + ":" + dto.getReqParams()));
+
+ exportTaskService.create(task);
+
+ ExecuteExportTaskDto taskDto = new ExecuteExportTaskDto();
+ taskDto.setTaskId(task.getId());
+ taskDto.setToken(dto.getToken());
+
+ mqProducerService.executeExportTask(taskDto);
+
+ } finally {
+ SecurityUtil.removeCurrentUser();
+ }
+ }
+
+ @RabbitListener(bindings = {
+ @QueueBinding(value = @Queue(value = RabbitMqStringPool.EXECUTE_EXPORT_TASK_QUEUE), key = RabbitMqStringPool.EXECUTE_EXPORT_TASK_ROUTING_KEY, exchange = @Exchange(value = RabbitMqStringPool.EXECUTE_EXPORT_TASK_EXCHANGE))})
+ public void executeExportTask(Message message) {
+
+ ExecuteExportTaskDto dto = message.getPayload();
+
+ log.info("接收到执行导出任务MQ message = {}", dto);
+
+ ExportTask task = exportTaskService.getById(dto.getTaskId());
+ AbstractUserDetails currentUser = SecurityUtil.getUserByToken(dto.getToken());
+
+ try {
+ if (currentUser == null) {
+ throw new DefaultClientException("导出用户已退出登录,无法导出");
+ }
+
+ SecurityUtil.setCurrentUser(currentUser);
+
+ Wrapper checkWrapper = Wrappers.lambdaQuery(ExportTask.class)
+ .eq(ExportTask::getReqParamsSign, task.getReqParamsSign())
+ .in(ExportTask::getStatus, ExportTaskStatus.CREATED, ExportTaskStatus.EXPORTING)
+ .ne(ExportTask::getId, task.getId());
+ if (exportTaskService.count(checkWrapper) > 0) {
+ throw new DefaultClientException("导出任务重复,请勿重复导出。");
+ }
+
+ ExportTaskHandler exportTaskHandler = new ExportTaskHandler(task.getId(),
+ ReflectUtil.newInstance(task.getReqClassName()),
+ sysConfService.getLong("export.timeout", 600L));
+ exportTaskHandler.execute(task.getReqParams());
+ } catch (ClientException e) {
+ exportTaskService.setFail(task.getId(),
+ StringUtil.isBlank(e.getMessage()) ? e.toString() : e.getMessage());
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ exportTaskService.setFail(task.getId(),
+ StringUtil.isBlank(e.getMessage()) ? e.toString() : e.getMessage());
+ } finally {
+ SecurityUtil.removeCurrentUser();
+ }
+ }
+}
diff --git a/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/listeners/mq/SysMailMessageListener.java b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/listeners/mq/SysMailMessageListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..8a548b99da6e21d8f02b64dae486a2200da2fd82
--- /dev/null
+++ b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/listeners/mq/SysMailMessageListener.java
@@ -0,0 +1,130 @@
+package com.lframework.starter.mq.rabbitmq.listeners.mq;
+
+import cn.hutool.extra.mail.MailException;
+import com.lframework.starter.common.constants.PatternPool;
+import com.lframework.starter.common.utils.CollectionUtil;
+import com.lframework.starter.common.utils.RegUtil;
+import com.lframework.starter.common.utils.StringUtil;
+import com.lframework.starter.mq.rabbitmq.constants.RabbitMqStringPool;
+import com.lframework.starter.web.core.utils.ApplicationUtil;
+import com.lframework.starter.web.core.utils.IdUtil;
+import com.lframework.starter.web.inner.dto.message.SysMailMessageDto;
+import com.lframework.starter.web.inner.entity.SysMailMessage;
+import com.lframework.starter.web.inner.entity.SysUser;
+import com.lframework.starter.web.inner.enums.system.SysMailMessageSendStatus;
+import com.lframework.starter.web.inner.service.MailService;
+import com.lframework.starter.web.inner.service.system.SysMailMessageService;
+import com.lframework.starter.web.inner.service.system.SysUserService;
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.mail.Address;
+import javax.mail.SendFailedException;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.amqp.rabbit.annotation.Exchange;
+import org.springframework.amqp.rabbit.annotation.Queue;
+import org.springframework.amqp.rabbit.annotation.QueueBinding;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.messaging.Message;
+import org.springframework.stereotype.Component;
+
+@Slf4j
+@Component
+public class SysMailMessageListener {
+
+ @Autowired
+ private SysMailMessageService sysMailMessageService;
+
+ @Autowired
+ private SysUserService sysUserService;
+
+ @RabbitListener(bindings = {
+ @QueueBinding(value = @Queue(value = RabbitMqStringPool.SYS_MAIL_MESSAGE_QUEUE), key = RabbitMqStringPool.SYS_MAIL_MESSAGE_ROUTING_KEY, exchange = @Exchange(value = RabbitMqStringPool.SYS_MAIL_MESSAGE_EXCHANGE))})
+ public void execute(Message message) {
+
+ SysMailMessageDto dto = message.getPayload();
+ log.info("接收到发送邮件消息 {}", dto);
+
+ if (CollectionUtil.isNotEmpty(dto.getMailList())) {
+ dto.setMailList(
+ dto.getMailList().stream().filter(t -> RegUtil.isMatch(PatternPool.EMAIL, t)).collect(
+ Collectors.toList()));
+ }
+
+ if (CollectionUtil.isEmpty(dto.getMailList())) {
+ log.info("邮箱地址为空,不发送");
+ return;
+ }
+
+ String title = dto.getTitle();
+ String content = dto.getContent();
+ if (StringUtil.isBlank(title) || StringUtil.isBlank(content) || StringUtil.isBlank(
+ dto.getBizKey())) {
+ log.info("标题、内容、业务键不能为空,不发送");
+ return;
+ }
+
+ SysUser createBy = StringUtil.isBlank(dto.getCreateUserId()) ? null
+ : sysUserService.findById(dto.getCreateUserId());
+
+ List recordList = dto.getMailList().stream().distinct().map(t -> {
+ SysMailMessage record = new SysMailMessage();
+ record.setId(IdUtil.getId());
+ record.setTitle(title);
+ record.setContent(content);
+ record.setMail(t);
+ record.setBizKey(dto.getBizKey());
+ record.setSendStatus(SysMailMessageSendStatus.UN_SEND);
+ if (createBy != null) {
+ record.setCreateById(createBy.getId());
+ record.setCreateBy(createBy.getName());
+ record.setUpdateBy(createBy.getName());
+ record.setUpdateById(createBy.getId());
+ }
+
+ return record;
+ }).collect(Collectors.toList());
+
+ sysMailMessageService.saveBatch(recordList);
+
+ try {
+ MailService mailService = ApplicationUtil.getBean(MailService.class);
+ mailService.send(
+ recordList.stream().map(SysMailMessage::getMail).collect(Collectors.toList()),
+ title, content);
+
+ // 全部成功
+ recordList.forEach(t -> t.setSendStatus(SysMailMessageSendStatus.SENDED));
+
+ } catch (MailException e) {
+ Throwable throwable = e.getCause();
+ if (throwable instanceof SendFailedException) {
+ //部分失败
+ Address[] invalidAddresses = ((SendFailedException) throwable).getInvalidAddresses();
+ for (Address invalidAddress : invalidAddresses) {
+ String mail = invalidAddress.toString();
+ recordList.stream().filter(t -> mail.equals(t.getMail()))
+ .findFirst().ifPresent(record -> record.setSendStatus(SysMailMessageSendStatus.FAIL));
+ recordList.stream().filter(t -> t.getSendStatus() == SysMailMessageSendStatus.UN_SEND
+ ).forEach(record -> record.setSendStatus(SysMailMessageSendStatus.SENDED));
+ }
+ } else {
+ // 全部失败
+ recordList.forEach(t -> t.setSendStatus(SysMailMessageSendStatus.FAIL));
+ log.error(e.getMessage(), e);
+ }
+ }
+
+ sysMailMessageService.updateBatchById(recordList.stream().map(t -> {
+ SysMailMessage record = new SysMailMessage();
+ record.setId(t.getId());
+ record.setSendStatus(t.getSendStatus());
+ record.setCreateById(t.getCreateById());
+ record.setCreateBy(t.getCreateBy());
+ record.setUpdateById(t.getUpdateById());
+ record.setUpdateBy(t.getUpdateBy());
+
+ return record;
+ }).collect(Collectors.toList()));
+ }
+}
diff --git a/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/listeners/mq/SysNotifyListener.java b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/listeners/mq/SysNotifyListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..f13462edcd821a76adf739baf4fa781137554eff
--- /dev/null
+++ b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/listeners/mq/SysNotifyListener.java
@@ -0,0 +1,174 @@
+package com.lframework.starter.mq.rabbitmq.listeners.mq;
+
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.lframework.starter.common.constants.StringPool;
+import com.lframework.starter.common.exceptions.impl.DefaultSysException;
+import com.lframework.starter.common.utils.CollectionUtil;
+import com.lframework.starter.mq.core.service.MqProducerService;
+import com.lframework.starter.mq.rabbitmq.constants.RabbitMqStringPool;
+import com.lframework.starter.web.core.components.notify.SysNotifyRuleEmail;
+import com.lframework.starter.web.core.components.notify.SysNotifyRuleSys;
+import com.lframework.starter.web.core.utils.ApplicationUtil;
+import com.lframework.starter.web.core.utils.EnumUtil;
+import com.lframework.starter.web.core.utils.IdUtil;
+import com.lframework.starter.web.inner.dto.message.SysMailMessageDto;
+import com.lframework.starter.web.inner.dto.message.SysSiteMessageDto;
+import com.lframework.starter.web.inner.dto.notify.SysNotifyDto;
+import com.lframework.starter.web.inner.dto.notify.SysNotifyParamsDto;
+import com.lframework.starter.web.inner.entity.SysNotifyGroup;
+import com.lframework.starter.web.inner.entity.SysUser;
+import com.lframework.starter.web.inner.enums.system.SysNotifyMessageType;
+import com.lframework.starter.web.inner.service.system.SysNotifyGroupService;
+import com.lframework.starter.web.inner.service.system.SysUserService;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.amqp.rabbit.annotation.Exchange;
+import org.springframework.amqp.rabbit.annotation.Queue;
+import org.springframework.amqp.rabbit.annotation.QueueBinding;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.messaging.Message;
+import org.springframework.stereotype.Component;
+
+@Slf4j
+@Component
+public class SysNotifyListener {
+
+ @Autowired
+ private SysNotifyGroupService sysNotifyGroupService;
+
+ @Autowired
+ private SysUserService sysUserService;
+
+ @Autowired
+ private MqProducerService mqProducerService;
+
+ private static final int BATCH_SIZE = 100;
+
+ @RabbitListener(bindings = {
+ @QueueBinding(value = @Queue(value = RabbitMqStringPool.SYS_NOTIFY_QUEUE), key = RabbitMqStringPool.SYS_NOTIFY_ROUTING_KEY, exchange = @Exchange(value = RabbitMqStringPool.SYS_NOTIFY_EXCHANGE))})
+ public void execute(Message message) {
+ SysNotifyDto dto = message.getPayload();
+ log.debug("接收到消息:{}", dto);
+
+ SysNotifyGroup notifyGroup = sysNotifyGroupService.findById(dto.getNotifyGroupId());
+ if (notifyGroup == null) {
+ log.info("消息通知组不存在,通知组ID:{}", dto.getNotifyGroupId());
+ return;
+ }
+ if (!notifyGroup.getAvailable()) {
+ log.info("消息通知组不可用,通知组ID:{}", dto.getNotifyGroupId());
+ return;
+ }
+
+ Set userIds = sysNotifyGroupService.getReceiveUserIds(notifyGroup.getId());
+ if (CollectionUtil.isEmpty(userIds)) {
+ log.info("消息通知组不存在接收人,通知组ID:{}", dto.getNotifyGroupId());
+ return;
+ }
+
+ List messageTypeCodes = Arrays.stream(
+ notifyGroup.getMessageType().split(StringPool.STR_SPLIT)).map(Integer::valueOf).collect(
+ Collectors.toList());
+ for (Integer messageTypeCode : messageTypeCodes) {
+ SysNotifyMessageType messageType = EnumUtil.getByCode(SysNotifyMessageType.class,
+ messageTypeCode);
+ switch (messageType) {
+ case EMAIL: {
+ Map ruleMap = ApplicationUtil.getBeansOfType(
+ SysNotifyRuleEmail.class);
+
+ for (SysNotifyRuleEmail rule : ruleMap.values()) {
+ if (!rule.match(dto.getBizType())) {
+ continue;
+ }
+
+ log.info("匹配到rule,开始发送邮件");
+ Wrapper queryWrapper = Wrappers.lambdaQuery(SysUser.class)
+ .select(SysUser::getEmail)
+ .in(SysUser::getId, userIds)
+ .eq(SysUser::getAvailable, true)
+ .isNotNull(SysUser::getEmail)
+ .ne(SysUser::getEmail, StringPool.EMPTY_STR);
+ List userList = sysUserService.list(queryWrapper);
+ if (CollectionUtil.isNotEmpty(userList)) {
+ SysNotifyParamsDto paramsDto = new SysNotifyParamsDto();
+ paramsDto.setVariables(dto.getVariables());
+
+ String title = rule.getTitle(paramsDto);
+ String content = rule.getContent(paramsDto);
+
+ List allMailList = userList.stream().map(SysUser::getEmail).distinct()
+ .collect(
+ Collectors.toList());
+ List> splitMailList = CollectionUtil.split(allMailList, BATCH_SIZE);
+ for (List mailList : splitMailList) {
+ SysMailMessageDto messageDto = new SysMailMessageDto();
+ messageDto.setMailList(mailList);
+ messageDto.setTitle(title);
+ messageDto.setContent(content);
+ messageDto.setBizKey(IdUtil.getId());
+ messageDto.setCreateUserId(dto.getCreateUserId());
+
+ mqProducerService.createSysMailMessage(messageDto);
+ }
+ }
+ break;
+ }
+ break;
+ }
+
+ case SYS: {
+ Map ruleMap = ApplicationUtil.getBeansOfType(
+ SysNotifyRuleSys.class);
+
+ for (SysNotifyRuleSys rule : ruleMap.values()) {
+ if (!rule.match(dto.getBizType())) {
+ continue;
+ }
+
+ log.info("匹配到rule,开始发送站内信");
+ Wrapper queryWrapper = Wrappers.lambdaQuery(SysUser.class)
+ .select(SysUser::getId)
+ .in(SysUser::getId, userIds)
+ .eq(SysUser::getAvailable, true);
+ List userList = sysUserService.list(queryWrapper);
+ if (CollectionUtil.isNotEmpty(userList)) {
+ SysNotifyParamsDto paramsDto = new SysNotifyParamsDto();
+ paramsDto.setVariables(dto.getVariables());
+
+ String title = rule.getTitle(paramsDto);
+ String content = rule.getContent(paramsDto);
+
+ List allUserIdList = userList.stream().map(SysUser::getId).distinct()
+ .collect(
+ Collectors.toList());
+ List> splitUserIdList = CollectionUtil.split(allUserIdList, BATCH_SIZE);
+ for (List userIdList : splitUserIdList) {
+ SysSiteMessageDto messageDto = new SysSiteMessageDto();
+ messageDto.setUserIdList(userIdList);
+ messageDto.setTitle(title);
+ messageDto.setContent(content);
+ messageDto.setBizKey(IdUtil.getId());
+ messageDto.setCreateUserId(dto.getCreateUserId());
+
+ mqProducerService.createSysSiteMessage(messageDto);
+ }
+ }
+ break;
+ }
+ break;
+ }
+
+ default: {
+ throw new DefaultSysException("未知的MessageType: " + messageTypeCode);
+ }
+ }
+ }
+ }
+}
diff --git a/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/listeners/mq/SysSiteMessageListener.java b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/listeners/mq/SysSiteMessageListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..49adcf95057e134afe7bcee2159b6d59c5e373d0
--- /dev/null
+++ b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/listeners/mq/SysSiteMessageListener.java
@@ -0,0 +1,91 @@
+package com.lframework.starter.mq.rabbitmq.listeners.mq;
+
+import com.lframework.starter.common.utils.CollectionUtil;
+import com.lframework.starter.common.utils.StringUtil;
+import com.lframework.starter.mq.rabbitmq.constants.RabbitMqStringPool;
+import com.lframework.starter.web.core.utils.IdUtil;
+import com.lframework.starter.web.inner.dto.message.SysSiteMessageDto;
+import com.lframework.starter.web.inner.entity.SysSiteMessage;
+import com.lframework.starter.web.inner.entity.SysUser;
+import com.lframework.starter.web.inner.service.system.SysSiteMessageService;
+import com.lframework.starter.web.inner.service.system.SysUserService;
+import com.lframework.starter.web.websocket.components.WsDataPusher;
+import com.lframework.starter.web.websocket.dto.WsPushData;
+import java.util.List;
+import java.util.stream.Collectors;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.amqp.rabbit.annotation.Exchange;
+import org.springframework.amqp.rabbit.annotation.Queue;
+import org.springframework.amqp.rabbit.annotation.QueueBinding;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.messaging.Message;
+import org.springframework.stereotype.Component;
+
+@Slf4j
+@Component
+public class SysSiteMessageListener {
+
+ @Autowired
+ private SysSiteMessageService sysSiteMessageService;
+
+ @Autowired
+ private SysUserService sysUserService;
+
+ @Autowired
+ private WsDataPusher wsDataPusher;
+
+ @RabbitListener(bindings = {
+ @QueueBinding(value = @Queue(value = RabbitMqStringPool.SYS_SITE_MESSAGE_QUEUE), key = RabbitMqStringPool.SYS_SITE_MESSAGE_ROUTING_KEY, exchange = @Exchange(value = RabbitMqStringPool.SYS_SITE_MESSAGE_EXCHANGE))})
+ public void execute(Message message) {
+
+ SysSiteMessageDto dto = message.getPayload();
+ log.info("接收到发送站内信消息 {}", dto);
+
+ if (CollectionUtil.isEmpty(dto.getUserIdList())) {
+ log.info("接收人为空,不发送");
+ return;
+ }
+
+ String title = dto.getTitle();
+ String content = dto.getContent();
+ if (StringUtil.isBlank(title) || StringUtil.isBlank(content) || StringUtil.isBlank(
+ dto.getBizKey())) {
+ log.info("标题、内容、业务键不能为空,不发送");
+ return;
+ }
+
+ SysUser createBy = StringUtil.isBlank(dto.getCreateUserId()) ? null
+ : sysUserService.findById(dto.getCreateUserId());
+
+ List recordList = dto.getUserIdList().stream().distinct().map(t -> {
+ SysSiteMessage record = new SysSiteMessage();
+ record.setId(IdUtil.getId());
+ record.setTitle(title);
+ record.setContent(content);
+ record.setReceiverId(t);
+ record.setBizKey(dto.getBizKey());
+ if (createBy != null) {
+ record.setCreateById(createBy.getId());
+ record.setCreateBy(createBy.getName());
+ record.setUpdateBy(createBy.getName());
+ record.setUpdateById(createBy.getId());
+ }
+
+ return record;
+ }).collect(Collectors.toList());
+
+ sysSiteMessageService.saveBatch(recordList);
+
+ for (SysSiteMessage sysSiteMessage : recordList) {
+ try {
+ WsPushData pushData = new WsPushData();
+ pushData.setBizType("siteMessage");
+ pushData.setIncludeUserId(sysSiteMessage.getReceiverId());
+ wsDataPusher.push(pushData);
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ }
+ }
+ }
+}
diff --git a/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/producer/RabbitMqProducer.java b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/producer/RabbitMqProducer.java
new file mode 100644
index 0000000000000000000000000000000000000000..8bb4a0ce53784c31265c5edcdfa650666fc41607
--- /dev/null
+++ b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/producer/RabbitMqProducer.java
@@ -0,0 +1,138 @@
+package com.lframework.starter.mq.rabbitmq.producer;
+
+import com.lframework.starter.common.exceptions.impl.DefaultSysException;
+import com.lframework.starter.common.utils.Assert;
+import com.lframework.starter.mq.core.producer.MqProducer;
+import com.lframework.starter.mq.core.queue.QueueDefinition;
+import com.lframework.starter.mq.rabbitmq.queue.RabbitMQQueueDefinition;
+import com.lframework.starter.web.core.components.tenant.TenantContextHolder;
+import com.lframework.starter.web.core.utils.TenantUtil;
+import java.io.Serializable;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+
+/**
+ * RabbitMQ生产者
+ *
+ * @author zmj
+ * @since 2022/8/25
+ */
+public class RabbitMqProducer implements MqProducer {
+
+ private final RabbitTemplate rabbitTemplate;
+
+ private final Object EMPTY_MSG = new Object();
+
+ public RabbitMqProducer(RabbitTemplate rabbitTemplate) {
+ this.rabbitTemplate = rabbitTemplate;
+ }
+
+ @Override
+ public void sendDelayMessage(QueueDefinition definition, Serializable data, long millis) {
+
+ sendDelayMessage(definition, data, millis, TenantContextHolder.getTenantId());
+ }
+
+ @Override
+ public void sendMessage(QueueDefinition definition, Serializable data) {
+
+ sendMessage(definition, data, TenantContextHolder.getTenantId());
+ }
+
+ @Override
+ public void sendDelayMessage(QueueDefinition definition, long millis) {
+ sendDelayMessage(definition, millis, TenantContextHolder.getTenantId());
+ }
+
+ @Override
+ public void sendMessage(QueueDefinition definition) {
+ sendMessage(definition, TenantContextHolder.getTenantId());
+ }
+
+ @Override
+ public void sendDelayMessage(QueueDefinition definition, Serializable data, long millis,
+ Integer tenantId) {
+ Assert.isTrue(millis <= Integer.MAX_VALUE && millis >= 0);
+ rabbitTemplate.convertAndSend(
+ convertExchange(definition),
+ convertRoutingKey(definition),
+ data,
+ m -> {
+ m.getMessageProperties().setDelay((int) millis);
+ if (TenantUtil.enableTenant() && tenantId != null) {
+ m.getMessageProperties().setHeader("tenantId", tenantId);
+ }
+
+ return m;
+ }
+ );
+ }
+
+ @Override
+ public void sendMessage(QueueDefinition definition, Serializable data, Integer tenantId) {
+ rabbitTemplate.convertAndSend(convertExchange(definition), convertRoutingKey(definition), data,
+ m -> {
+ if (TenantUtil.enableTenant() && tenantId != null) {
+ m.getMessageProperties().setHeader("tenantId", tenantId);
+ }
+
+ return m;
+ });
+ }
+
+ @Override
+ public void sendDelayMessage(QueueDefinition definition, long millis, Integer tenantId) {
+ Assert.isTrue(millis <= Integer.MAX_VALUE && millis >= 0);
+ rabbitTemplate.convertAndSend(
+ convertExchange(definition),
+ convertRoutingKey(definition),
+ EMPTY_MSG,
+ m -> {
+ m.getMessageProperties().setDelay((int) millis);
+
+ if (TenantUtil.enableTenant() && tenantId != null) {
+ m.getMessageProperties().setHeader("tenantId", tenantId);
+ }
+
+ return m;
+ }
+ );
+ }
+
+ @Override
+ public void sendMessage(QueueDefinition definition, Integer tenantId) {
+ rabbitTemplate.convertAndSend(convertExchange(definition), convertRoutingKey(definition),
+ EMPTY_MSG, m -> {
+ if (TenantUtil.enableTenant() && tenantId != null) {
+ m.getMessageProperties().setHeader("tenantId", tenantId);
+ }
+
+ return m;
+ });
+ }
+
+ private String convertExchange(QueueDefinition definition) {
+ if (definition == null) {
+ throw new DefaultSysException("definition不能为空!");
+ }
+
+ if (definition instanceof RabbitMQQueueDefinition) {
+ return ((RabbitMQQueueDefinition) definition).getExchange();
+ } else {
+ throw new DefaultSysException(
+ "没有找到" + definition.getClass().getName() + "对应的QueueDefinition");
+ }
+ }
+
+ private String convertRoutingKey(QueueDefinition definition) {
+ if (definition == null) {
+ throw new DefaultSysException("definition不能为空!");
+ }
+
+ if (definition instanceof RabbitMQQueueDefinition) {
+ return ((RabbitMQQueueDefinition) definition).getRoutingKey();
+ } else {
+ throw new DefaultSysException(
+ "没有找到" + definition.getClass().getName() + "对应的QueueDefinition");
+ }
+ }
+}
diff --git a/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/queue/RabbitMQQueueDefinition.java b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/queue/RabbitMQQueueDefinition.java
new file mode 100644
index 0000000000000000000000000000000000000000..707109ab7ca17dcec5de72f724aedc0d7d9483c5
--- /dev/null
+++ b/mq-starter/rabbitmq-starter/src/main/java/com/lframework/starter/mq/rabbitmq/queue/RabbitMQQueueDefinition.java
@@ -0,0 +1,27 @@
+package com.lframework.starter.mq.rabbitmq.queue;
+
+import com.lframework.starter.mq.core.queue.QueueDefinition;
+import lombok.Getter;
+
+@Getter
+public class RabbitMQQueueDefinition implements QueueDefinition {
+
+ /**
+ * 交换机名
+ */
+ private final String exchange;
+
+ /**
+ * 路由键
+ */
+ private String routingKey;
+
+ public RabbitMQQueueDefinition(String exchange) {
+ this.exchange = exchange;
+ }
+
+ public RabbitMQQueueDefinition(String exchange, String routingKey) {
+ this.exchange = exchange;
+ this.routingKey = routingKey;
+ }
+}
diff --git a/websocket-starter/src/main/java/lombok.config b/mq-starter/rabbitmq-starter/src/main/java/lombok.config
similarity index 100%
rename from websocket-starter/src/main/java/lombok.config
rename to mq-starter/rabbitmq-starter/src/main/java/lombok.config
diff --git a/web-common/src/main/resources/META-INF/spring.factories b/mq-starter/rabbitmq-starter/src/main/resources/META-INF/spring.factories
similarity index 50%
rename from web-common/src/main/resources/META-INF/spring.factories
rename to mq-starter/rabbitmq-starter/src/main/resources/META-INF/spring.factories
index 2d31cb33cdf822c530ce27390b3db10f2a188fce..258ac18ebf6ab47cb180fb58c2a1a4033d7bb758 100644
--- a/web-common/src/main/resources/META-INF/spring.factories
+++ b/mq-starter/rabbitmq-starter/src/main/resources/META-INF/spring.factories
@@ -1 +1 @@
-org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.lframework.starter.web.common.config.WebCommonAutoConfiguration
\ No newline at end of file
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.lframework.starter.mq.rabbitmq.config.RabbitMqAutoConfiguration
\ No newline at end of file
diff --git a/mq-starter/src/main/java/com/lframework/starter/mq/listener/MqListener.java b/mq-starter/src/main/java/com/lframework/starter/mq/listener/MqListener.java
deleted file mode 100644
index 8d9493478372651e2db48e18ed47e2dc0509be83..0000000000000000000000000000000000000000
--- a/mq-starter/src/main/java/com/lframework/starter/mq/listener/MqListener.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.lframework.starter.mq.listener;
-
-public interface MqListener {
-
-}
diff --git a/mq-starter/src/main/java/com/lframework/starter/mq/producer/MqProducer.java b/mq-starter/src/main/java/com/lframework/starter/mq/producer/MqProducer.java
deleted file mode 100644
index fb3e3ebb5fdb480485cd678635f2c12d04a52202..0000000000000000000000000000000000000000
--- a/mq-starter/src/main/java/com/lframework/starter/mq/producer/MqProducer.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.lframework.starter.mq.producer;
-
-import java.io.Serializable;
-
-/**
- * MQ生产者
- *
- * @author zmj
- * @since 2022/8/25
- */
-public interface MqProducer {
-
- /**
- * 发送延时消息
- *
- * @param queue 队列名
- * @param data 数据
- * @param millis 毫秒
- */
- void sendDelayMessage(String queue, Serializable data, long millis);
-
- /**
- * 发送即时消息
- *
- * @param queue 队列名
- * @param data 数据
- */
- void sendMessage(String queue, Serializable data);
-
- /**
- * 发送延时消息
- *
- * @param queue 队列名
- * @param millis 毫秒
- */
- void sendDelayMessage(String queue, long millis);
-
- /**
- * 发送即时消息
- *
- * @param queue 队列名
- */
- void sendMessage(String queue);
-}
diff --git a/pom.xml b/pom.xml
index 02d5d9beeecfa09934b0edf025b3180d687a4579..66b796793df87df3cf1de0d265b4b17e1bb8e07d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,7 +7,7 @@
com.lframework
parent
【${project.artifactId}】Jugg基础框架
- 3.1.3
+ 4.0.5
pom
https://gitee.com/lframework/jugg
@@ -21,7 +21,7 @@
UTF-8
3.8.0
2.2.2.RELEASE
- 3.1.3
+ 4.0.5
1.18.10
1.7.21
1.1.7
@@ -40,8 +40,6 @@
1.6.2
2.0.9
1.29.0
- 2.8.4-release
- 2.8.0-release
2.2.0.RELEASE
1.4.4
1.5.2
@@ -51,16 +49,15 @@
3.16.3
3.19.7
5.6.133
+ 1.7.4
common
web-starter
- web-common
cloud-starter
mq-starter
- activemq-starter
- websocket-starter
+ bpm-starter
@@ -85,19 +82,6 @@
https://gitee.com/lframework/jugg
-
-
- sonatype_snapshots
- https://s01.oss.sonatype.org/content/repositories/snapshots/
- default
-
-
- sonatype_releases
- https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/
- default
-
-
-
@@ -130,12 +114,6 @@
${jugg.version}
-
- com.lframework
- web-common
- ${jugg.version}
-
-
com.lframework
web-starter
@@ -156,13 +134,7 @@
com.lframework
- activemq-starter
- ${jugg.version}
-
-
-
- com.lframework
- websocket-starter
+ bpm-starter
${jugg.version}
@@ -314,18 +286,6 @@
${sa-token.version}
-
- net.oschina.j2cache
- j2cache-core
- ${j2cache.version}
-
-
-
- net.oschina.j2cache
- j2cache-springcache
- ${j2cache-spring.version}
-
-
spring-cloud-starter-alibaba-nacos-discovery
@@ -405,6 +365,31 @@
cos_api
${cos_api.version}
+
+
+
+ org.dromara.warm
+ warm-flow-mybatis-plus-sb-starter
+ ${warm-flow.version}
+
+
+ com.baomidou
+ mybatis-plus-extension
+
+
+
+
+
+ org.dromara.warm
+ warm-flow-plugin-ui-sb-web
+ ${warm-flow.version}
+
+
+
+ org.dromara.warm
+ warm-flow-plugin-ui-core
+ ${warm-flow.version}
+
@@ -486,6 +471,16 @@
+
+ org.sonatype.central
+ central-publishing-maven-plugin
+ 0.7.0
+ true
+
+ central
+ true
+
+
diff --git a/web-starter/pom.xml b/web-starter/pom.xml
index 8499b7eb4537441eeda2b27acf65f597e8e10636..48db0c551ee9547bc3e935532594cb76c0c4caa2 100644
--- a/web-starter/pom.xml
+++ b/web-starter/pom.xml
@@ -5,7 +5,7 @@
parent
com.lframework
- 3.1.3
+ 4.0.5
4.0.0
@@ -48,11 +48,6 @@
common
-
- com.lframework
- web-common
-
-
org.springframework.boot
spring-boot-starter-web
@@ -161,11 +156,6 @@
sa-token-dao-redis-jackson
-
- cn.dev33
- sa-token-alone-redis
-
-
com.github.xiaoymin
knife4j-spring-boot-starter
@@ -190,5 +180,18 @@
org.springframework.cloud
spring-cloud-sleuth-core
+
+
+ org.freemarker
+ freemarker
+
+
+ org.ssssssss
+ magic-api-spring-boot-starter
+
+
+ org.ssssssss
+ magic-api-plugin-cluster
+
diff --git a/web-starter/src/main/java/com/lframework/starter/web/annotations/constants/EncryType.java b/web-starter/src/main/java/com/lframework/starter/web/annotations/constants/EncryType.java
deleted file mode 100644
index 8b90a46892075b7f366463cce75cc690383ee8fd..0000000000000000000000000000000000000000
--- a/web-starter/src/main/java/com/lframework/starter/web/annotations/constants/EncryType.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.lframework.starter.web.annotations.constants;
-
-public enum EncryType {
- // 自动
- AUTO,
- // 密码
- PASSWORD,
-}
diff --git a/web-starter/src/main/java/com/lframework/starter/web/bo/BasePrintBo.java b/web-starter/src/main/java/com/lframework/starter/web/bo/BasePrintBo.java
deleted file mode 100644
index 981b660d16b5347bb5dc06f4846bc3e497a1e055..0000000000000000000000000000000000000000
--- a/web-starter/src/main/java/com/lframework/starter/web/bo/BasePrintBo.java
+++ /dev/null
@@ -1,84 +0,0 @@
-package com.lframework.starter.web.bo;
-
-import com.lframework.starter.web.dto.BaseDto;
-import com.lframework.starter.web.utils.PrintUtil;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-/**
- * 打印数据Bo
- *
- * @param
- */
-@Data
-public abstract class BasePrintBo> {
-
- /**
- * 打印方向及纸张类型 1---纵向打印,固定纸张; 2---横向打印,固定纸张; 3---纵向打印,宽度固定,高度按打印内容的高度自适应;
- * 0---方向不定,由操作者自行选择或按打印机缺省设置。
- */
- @ApiModelProperty("打印方向及纸张类型 1---纵向打印,固定纸张; 2---横向打印,固定纸张; 3---纵向打印,宽度固定,高度按打印内容的高度自适应;0---方向不定,由操作者自行选择或按打印机缺省设置。")
- private Integer orient;
-
- /**
- * 纸张宽,单位为0.1mm 譬如该参数值为45,则表示4.5mm,计量精度是0.1mm。
- */
- @ApiModelProperty("纸张宽,单位为0.1mm 譬如该参数值为45,则表示4.5mm,计量精度是0.1mm。")
- private Integer pageWidth;
-
- /**
- * 固定纸张时该参数是纸张高;高度自适应时该参数是纸张底边的空白高,计量单位与纸张宽一样。
- */
- @ApiModelProperty("固定纸张时该参数是纸张高;高度自适应时该参数是纸张底边的空白高,计量单位与纸张宽一样。")
- private Integer pageHeight;
-
- /**
- * 纸张类型名, pageWidth等于零时本参数才有效,具体名称参见操作系统打印服务属性中的格式定义。 关键字“CreateCustomPage”会在系统内建立一个名称为“LodopCustomPage”自定义纸张类型。
- */
- @ApiModelProperty("纸张类型名, pageWidth等于零时本参数才有效,具体名称参见操作系统打印服务属性中的格式定义。 关键字“CreateCustomPage”会在系统内建立一个名称为“LodopCustomPage”自定义纸张类型。")
- private String pageName;
-
- /**
- * 上边距 单位:mm
- */
- @ApiModelProperty("上边距 单位:mm")
- private Double marginTop;
-
- /**
- * 左边距 单位:mm
- */
- @ApiModelProperty("左边距 单位:mm")
- private Double marginLeft;
-
- /**
- * 右边距 单位:mm
- */
- @ApiModelProperty("右边距 单位:mm")
- private Double marginRight;
-
- /**
- * 下边距 单位:mm
- */
- @ApiModelProperty("下边距 单位:mm")
- private Double marginBottom;
-
- /**
- * 打印html内容
- */
- @ApiModelProperty("打印html内容")
- private String html;
-
- public BasePrintBo() {
-
- }
-
- public BasePrintBo(String templateName) {
-
- this(templateName, null);
- }
-
- public BasePrintBo(String templateName, T data) {
-
- this.html = PrintUtil.generate(templateName, data);
- }
-}
diff --git a/web-starter/src/main/java/com/lframework/starter/web/bo/BasePrintDataBo.java b/web-starter/src/main/java/com/lframework/starter/web/bo/BasePrintDataBo.java
deleted file mode 100644
index 5d1d4661efcb5fde93bdadc17701ad1492084a67..0000000000000000000000000000000000000000
--- a/web-starter/src/main/java/com/lframework/starter/web/bo/BasePrintDataBo.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.lframework.starter.web.bo;
-
-import com.lframework.starter.web.dto.BaseDto;
-import lombok.Data;
-
-@Data
-public class BasePrintDataBo extends BaseBo {
-
- public BasePrintDataBo() {
-
- }
-
- public BasePrintDataBo(T dto) {
-
- super(dto);
- }
-}
diff --git a/web-starter/src/main/java/com/lframework/starter/web/components/code/DefaultFlowGenerateCodeType.java b/web-starter/src/main/java/com/lframework/starter/web/components/code/DefaultFlowGenerateCodeType.java
deleted file mode 100644
index 5cb06787a3dc9ab3620ea414d0301524c8864577..0000000000000000000000000000000000000000
--- a/web-starter/src/main/java/com/lframework/starter/web/components/code/DefaultFlowGenerateCodeType.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.lframework.starter.web.components.code;
-
-public class DefaultFlowGenerateCodeType implements GenerateCodeType {
-
- private static final long serialVersionUID = 1L;
-}
diff --git a/web-starter/src/main/java/com/lframework/starter/web/components/code/DefaultGenerateCodeType.java b/web-starter/src/main/java/com/lframework/starter/web/components/code/DefaultGenerateCodeType.java
deleted file mode 100644
index fa8738007f061a8390eb1924aea96cee45056968..0000000000000000000000000000000000000000
--- a/web-starter/src/main/java/com/lframework/starter/web/components/code/DefaultGenerateCodeType.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.lframework.starter.web.components.code;
-
-/**
- * 默认生成类型
- *
- * @author zmj
- */
-public class DefaultGenerateCodeType implements GenerateCodeType {
-
- private static final long serialVersionUID = 1L;
-
-}
diff --git a/web-starter/src/main/java/com/lframework/starter/web/components/code/DefaultSnowFlakeGenerateCodeType.java b/web-starter/src/main/java/com/lframework/starter/web/components/code/DefaultSnowFlakeGenerateCodeType.java
deleted file mode 100644
index 7b68b680153525ccaa8f9968a9283d120e32a0c7..0000000000000000000000000000000000000000
--- a/web-starter/src/main/java/com/lframework/starter/web/components/code/DefaultSnowFlakeGenerateCodeType.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.lframework.starter.web.components.code;
-
-public class DefaultSnowFlakeGenerateCodeType implements GenerateCodeType {
-
- private static final long serialVersionUID = 1L;
-}
diff --git a/web-starter/src/main/java/com/lframework/starter/web/components/code/GenerateCodeType.java b/web-starter/src/main/java/com/lframework/starter/web/components/code/GenerateCodeType.java
deleted file mode 100644
index 66a27b455e64ef77b369e422714db6740a7a1d04..0000000000000000000000000000000000000000
--- a/web-starter/src/main/java/com/lframework/starter/web/components/code/GenerateCodeType.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.lframework.starter.web.components.code;
-
-import java.io.Serializable;
-
-/**
- * 单号生成类型
- *
- * @author zmj
- */
-public interface GenerateCodeType extends Serializable {
-
- /**
- * 默认的单号生成类型
- */
- GenerateCodeType DEFAULT = new DefaultGenerateCodeType();
-
- /**
- * 流水号类型的单号生成类型
- */
- GenerateCodeType FLOW = new DefaultFlowGenerateCodeType();
-
- /**
- * 雪花算法的单号生成类型
- */
- GenerateCodeType SNOW_FLAKE = new DefaultSnowFlakeGenerateCodeType();
-}
diff --git a/web-starter/src/main/java/com/lframework/starter/web/components/generator/GenerateCodeFactory.java b/web-starter/src/main/java/com/lframework/starter/web/components/generator/GenerateCodeFactory.java
deleted file mode 100644
index 62883d7647463ff8b794cb4b060d3186515afb8a..0000000000000000000000000000000000000000
--- a/web-starter/src/main/java/com/lframework/starter/web/components/generator/GenerateCodeFactory.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package com.lframework.starter.web.components.generator;
-
-
-import com.lframework.starter.common.exceptions.impl.DefaultSysException;
-import com.lframework.starter.web.components.code.GenerateCodeType;
-import com.lframework.starter.web.common.utils.ApplicationUtil;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * 单号生成器Factory
- *
- * @author zmj
- */
-public class GenerateCodeFactory {
-
- public static final Map, Generator> GENERATOR_POOL = new ConcurrentHashMap<>();
-
- public static Generator getInstance(GenerateCodeType type) {
-
- Generator generator = GENERATOR_POOL.get(type.getClass());
- if (generator == null) {
- synchronized (GenerateCodeFactory.class) {
- generator = GENERATOR_POOL.get(type.getClass());
- if (generator == null) {
-
- generator = getGenrator(type);
- if (generator == null) {
- //如果未找到generator就使用默认generator
- generator = getGenrator(GenerateCodeType.DEFAULT);
- }
-
- if (generator == null) {
- throw new DefaultSysException("未找到" + type + "单号生成器!");
- }
-
- GENERATOR_POOL.put(type.getClass(), generator);
- }
- }
- }
-
- return generator;
- }
-
- private static Generator getGenrator(GenerateCodeType type) {
-
- Map generators = ApplicationUtil.getBeansOfType(Generator.class);
- for (Generator value : generators.values()) {
- if (!value.isSpecial()) {
- // 优先匹配自定义生成器
- if (value.getType().getClass() == type.getClass()) {
- return value;
- }
- }
- }
-
- for (Generator value : generators.values()) {
- if (value.isSpecial()) {
- // 匹配内置生成器
- if (value.getType().getClass() == type.getClass()) {
- return value;
- }
- }
- }
-
- return null;
- }
-}
diff --git a/web-starter/src/main/java/com/lframework/starter/web/components/generator/Generator.java b/web-starter/src/main/java/com/lframework/starter/web/components/generator/Generator.java
deleted file mode 100644
index 90efb6d80900380bfba481eb441509c09774ff79..0000000000000000000000000000000000000000
--- a/web-starter/src/main/java/com/lframework/starter/web/components/generator/Generator.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.lframework.starter.web.components.generator;
-
-import com.lframework.starter.web.components.code.GenerateCodeType;
-
-/**
- * 单号生成器 根据#getType进行类型比对 比对成功后,#generate进行单号生成 如果需要自定义单号生成器规则,步骤如下: 1、实现GenerateCodeType接口,定义类型
- *
- * @see GenerateCodeType 2、实现Generator接口,定义生成器,然后注册成Bean
- */
-public interface Generator {
-
- /**
- * 获取类型
- *
- * @return
- */
- GenerateCodeType getType();
-
- /**
- * 生成code
- *
- * @return
- */
- String generate();
-
- /**
- * 是否内置生成器 用于区分是内置的还是自定义的生成器
- *
- * @return
- */
- boolean isSpecial();
-}
diff --git a/web-starter/src/main/java/com/lframework/starter/web/components/generator/impl/AbstractFlowGenerator.java b/web-starter/src/main/java/com/lframework/starter/web/components/generator/impl/AbstractFlowGenerator.java
deleted file mode 100644
index dd18433e7483a8a0c63f13ee128513615423382a..0000000000000000000000000000000000000000
--- a/web-starter/src/main/java/com/lframework/starter/web/components/generator/impl/AbstractFlowGenerator.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package com.lframework.starter.web.components.generator.impl;
-
-import com.lframework.starter.common.exceptions.impl.DefaultClientException;
-import com.lframework.starter.common.exceptions.impl.DefaultSysException;
-import com.lframework.starter.common.locker.LockBuilder;
-import com.lframework.starter.common.locker.Locker;
-import com.lframework.starter.common.utils.DateUtil;
-import com.lframework.starter.web.common.tenant.TenantContextHolder;
-import com.lframework.starter.web.components.code.GenerateCodeType;
-import com.lframework.starter.web.components.generator.Generator;
-import com.lframework.starter.web.components.redis.RedisHandler;
-import com.lframework.starter.web.utils.TenantUtil;
-import java.time.LocalDate;
-import org.springframework.beans.factory.annotation.Autowired;
-
-/**
- * 流水号生成器
- *
- * @author zmj
- */
-public abstract class AbstractFlowGenerator extends AbstractGenerator implements Generator {
-
- private static final String LOCK_KEY = "flow_generator_index";
-
- @Autowired
- private RedisHandler redisHandler;
-
- @Autowired
- private LockBuilder lockBuilder;
-
- @Override
- public String generate() {
-
- GenerateCodeType type = getType();
- if (type == null) {
- throw new DefaultSysException("code为null!");
- }
- String lockerName = LOCK_KEY + type.getClass().getName();
- String nowStr = DateUtil.formatDate(LocalDate.now(), "yyyyMMdd");
- String redisKey =
- nowStr + "_" + (TenantUtil.enableTenant() ? TenantContextHolder.getTenantId() : "noTenant")
- + "_" + lockerName;
- Locker locker = lockBuilder.buildLocker(redisKey + "_Locker", 60000L, 5000L);
- long no;
-
- if (locker.lock()) {
- try {
- no = redisHandler.incr(redisKey, 1L);
- } finally {
- locker.unLock();
- }
- } else {
- throw new DefaultClientException("生成单号失败,请稍后重试!");
- }
- redisHandler.expire(redisKey, 86400000L);
-
- String noStr = String.valueOf(no);
- if (noStr.length() > getCodeLength()) {
- throw new DefaultSysException("单号超长!");
- }
-
- StringBuilder builder = new StringBuilder();
- builder.append(getPreffix()).append(nowStr);
- for (int i = 0, len = getCodeLength() - noStr.length(); i < len; i++) {
- builder.append("0");
- }
-
- return builder.append(noStr).toString();
- }
-
- /**
- * 获取流水号长度
- *
- * @return
- */
- protected int getCodeLength() {
-
- return 10;
- }
-
- protected String getPreffix() {
-
- return "";
- }
-}
diff --git a/web-starter/src/main/java/com/lframework/starter/web/components/generator/impl/AbstractGenerator.java b/web-starter/src/main/java/com/lframework/starter/web/components/generator/impl/AbstractGenerator.java
deleted file mode 100644
index f1818e5828bc34453fe70b05d95bd19c0896498f..0000000000000000000000000000000000000000
--- a/web-starter/src/main/java/com/lframework/starter/web/components/generator/impl/AbstractGenerator.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.lframework.starter.web.components.generator.impl;
-
-import com.lframework.starter.web.components.generator.Generator;
-
-public abstract class AbstractGenerator implements Generator {
-
- @Override
- public boolean isSpecial() {
-
- return false;
- }
-}
diff --git a/web-starter/src/main/java/com/lframework/starter/web/components/generator/impl/AbstractSnowFlakeGenerator.java b/web-starter/src/main/java/com/lframework/starter/web/components/generator/impl/AbstractSnowFlakeGenerator.java
deleted file mode 100644
index d94421eb3c06c3cb87ef11f8a308cde5ddb692f0..0000000000000000000000000000000000000000
--- a/web-starter/src/main/java/com/lframework/starter/web/components/generator/impl/AbstractSnowFlakeGenerator.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.lframework.starter.web.components.generator.impl;
-
-import com.lframework.starter.common.utils.IdWorker;
-import com.lframework.starter.web.components.generator.Generator;
-import org.springframework.beans.factory.annotation.Autowired;
-
-/**
- * 单号生成器
- *
- * @author zmj
- */
-public abstract class AbstractSnowFlakeGenerator extends AbstractGenerator implements Generator {
-
- @Autowired
- private IdWorker idWorker;
-
- @Override
- public String generate() {
-
- return getPreffix() + idWorker.nextIdStr();
- }
-
- protected String getPreffix() {
-
- return "";
- }
-}
diff --git a/web-starter/src/main/java/com/lframework/starter/web/components/generator/impl/DefaultFlowGenerator.java b/web-starter/src/main/java/com/lframework/starter/web/components/generator/impl/DefaultFlowGenerator.java
deleted file mode 100644
index 5e957073b4ea16096bfe57815af8ee6688fbad86..0000000000000000000000000000000000000000
--- a/web-starter/src/main/java/com/lframework/starter/web/components/generator/impl/DefaultFlowGenerator.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.lframework.starter.web.components.generator.impl;
-
-import com.lframework.starter.web.components.code.GenerateCodeType;
-import com.lframework.starter.web.components.generator.Generator;
-import org.springframework.stereotype.Component;
-
-/**
- * 默认流水号生成器 流水号位数是10位,即:yyyyMMdd0000000001格式
- */
-public class DefaultFlowGenerator extends AbstractFlowGenerator implements Generator {
-
- @Override
- public GenerateCodeType getType() {
-
- return GenerateCodeType.FLOW;
- }
-
- @Override
- protected int getCodeLength() {
-
- return 10;
- }
-
- @Override
- public boolean isSpecial() {
-
- return true;
- }
-}
diff --git a/web-starter/src/main/java/com/lframework/starter/web/components/generator/impl/DefaultGenerator.java b/web-starter/src/main/java/com/lframework/starter/web/components/generator/impl/DefaultGenerator.java
deleted file mode 100644
index 74f0e1311959d3056a0532912e7498eea7e01e69..0000000000000000000000000000000000000000
--- a/web-starter/src/main/java/com/lframework/starter/web/components/generator/impl/DefaultGenerator.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.lframework.starter.web.components.generator.impl;
-
-import com.lframework.starter.web.components.code.GenerateCodeType;
-import com.lframework.starter.web.components.generator.Generator;
-import com.lframework.starter.web.config.properties.DefaultSettingProperties;
-import org.springframework.beans.factory.annotation.Autowired;
-
-/**
- * 默认单号生成器
- *
- * @author zmj
- */
-public class DefaultGenerator extends AbstractSnowFlakeGenerator implements Generator {
-
- private DefaultSettingProperties defaultSettingProperties;
-
- @Autowired
- private DefaultFlowGenerator defaultFlowGenerator;
-
- @Autowired
- private DefaultSnowFlakeGenerator defaultSnowFlakeGenerator;
-
- @Override
- public GenerateCodeType getType() {
-
- return GenerateCodeType.DEFAULT;
- }
-
- @Override
- public String generate() {
-
- if (defaultSettingProperties.getGeneratorType() == GeneratorType.FLOW) {
- return defaultFlowGenerator.generate();
- } else {
- return defaultSnowFlakeGenerator.generate();
- }
- }
-
- @Override
- public boolean isSpecial() {
-
- return true;
- }
-
- public enum GeneratorType {
- FLOW, SNOW_FLAKE
- }
-}
diff --git a/web-starter/src/main/java/com/lframework/starter/web/components/generator/impl/DefaultSnowFlakeGenerator.java b/web-starter/src/main/java/com/lframework/starter/web/components/generator/impl/DefaultSnowFlakeGenerator.java
deleted file mode 100644
index 9fde0349fbda366dcf30c8449ed06aa719e04e93..0000000000000000000000000000000000000000
--- a/web-starter/src/main/java/com/lframework/starter/web/components/generator/impl/DefaultSnowFlakeGenerator.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.lframework.starter.web.components.generator.impl;
-
-import com.lframework.starter.web.components.code.GenerateCodeType;
-import com.lframework.starter.web.components.generator.Generator;
-
-/**
- * 默认雪花算法单号生成器
- *
- * @author zmj
- */
-public class DefaultSnowFlakeGenerator extends AbstractSnowFlakeGenerator implements Generator {
-
- @Override
- public GenerateCodeType getType() {
-
- return GenerateCodeType.SNOW_FLAKE;
- }
-
- @Override
- public boolean isSpecial() {
-
- return true;
- }
-}
diff --git a/web-starter/src/main/java/com/lframework/starter/web/components/redis/locker/RedisLockConditional.java b/web-starter/src/main/java/com/lframework/starter/web/components/redis/locker/RedisLockConditional.java
deleted file mode 100644
index 59962524b5e39c903e54a57d1abe899bd2b302cb..0000000000000000000000000000000000000000
--- a/web-starter/src/main/java/com/lframework/starter/web/components/redis/locker/RedisLockConditional.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.lframework.starter.web.components.redis.locker;
-
-import org.springframework.context.annotation.Condition;
-import org.springframework.context.annotation.ConditionContext;
-import org.springframework.core.type.AnnotatedTypeMetadata;
-
-public class RedisLockConditional implements Condition {
-
- @Override
- public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
-
- String lockerType = context.getEnvironment().getProperty("jugg.locker.type");
- return "redis".equalsIgnoreCase(lockerType);
- }
-}
diff --git a/web-starter/src/main/java/com/lframework/starter/web/components/upload/handler/impl/ObsUploadHandler.java b/web-starter/src/main/java/com/lframework/starter/web/components/upload/handler/impl/ObsUploadHandler.java
deleted file mode 100644
index 4d778526e619353c44b30fa7cc94105108867f29..0000000000000000000000000000000000000000
--- a/web-starter/src/main/java/com/lframework/starter/web/components/upload/handler/impl/ObsUploadHandler.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package com.lframework.starter.web.components.upload.handler.impl;
-
-import cn.hutool.core.util.URLUtil;
-import com.lframework.starter.common.constants.StringPool;
-import com.lframework.starter.common.exceptions.impl.DefaultSysException;
-import com.lframework.starter.common.utils.Assert;
-import com.lframework.starter.common.utils.StringUtil;
-import com.lframework.starter.web.components.upload.handler.UploadHandler;
-import com.lframework.starter.web.service.SysParameterService;
-import com.lframework.starter.web.utils.JsonUtil;
-import com.obs.services.ObsClient;
-import com.obs.services.model.PutObjectResult;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.List;
-import lombok.Data;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-@Slf4j
-public class ObsUploadHandler implements UploadHandler {
-
- @Autowired
- private SysParameterService sysParameterService;
-
- @Override
- public String getType() {
- return "OBS";
- }
-
- @Override
- public String upload(InputStream is, List locations, String fileName) {
- String configStr = sysParameterService.findRequiredByKey("upload.obs.config");
- ObsConfig config = JsonUtil.parseObject(configStr, ObsConfig.class);
-
- Assert.notBlank(config.getEndpoint());
- Assert.notBlank(config.getBucketName());
- Assert.notBlank(config.getAk());
- Assert.notBlank(config.getSk());
-
- String objectName = StringUtil.join("/", locations) + fileName;
-
- try (ObsClient obsClient = new ObsClient(config.getAk(), config.getSk(),
- config.getEndpoint())) {
- // 不判断桶是否存在,建议桶在控台创建
- PutObjectResult result = obsClient.putObject(config.getBucketName(), objectName, is);
-
- if (StringUtil.isNotBlank(config.getCustomUrl())) {
- return config.getCustomUrl() + (config.getCustomUrl().endsWith("/") ? StringPool.EMPTY_STR
- : "/") + objectName;
- }
-
- return URLUtil.decode(result.getObjectUrl());
- } catch (IOException e) {
- log.error(e.getMessage(), e);
- throw new DefaultSysException(e.getMessage());
- }
- }
-
- @Data
- public static class ObsConfig {
-
- private String customUrl;
-
- private String endpoint;
-
- private String ak;
-
- private String sk;
-
- private String bucketName;
- }
-}
diff --git a/web-starter/src/main/java/com/lframework/starter/web/components/upload/handler/impl/OssUploadHandler.java b/web-starter/src/main/java/com/lframework/starter/web/components/upload/handler/impl/OssUploadHandler.java
deleted file mode 100644
index 94ef68d7f1793c2c79062ea5a1498eea6d95cd56..0000000000000000000000000000000000000000
--- a/web-starter/src/main/java/com/lframework/starter/web/components/upload/handler/impl/OssUploadHandler.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package com.lframework.starter.web.components.upload.handler.impl;
-
-import com.aliyun.oss.OSS;
-import com.aliyun.oss.OSSClientBuilder;
-import com.lframework.starter.common.constants.StringPool;
-import com.lframework.starter.common.utils.Assert;
-import com.lframework.starter.common.utils.StringUtil;
-import com.lframework.starter.web.components.upload.handler.UploadHandler;
-import com.lframework.starter.web.service.SysParameterService;
-import com.lframework.starter.web.utils.JsonUtil;
-import java.io.InputStream;
-import java.util.List;
-import lombok.Data;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-public class OssUploadHandler implements UploadHandler {
-
- @Autowired
- private SysParameterService sysParameterService;
-
- @Override
- public String getType() {
- return "OSS";
- }
-
- @Override
- public String upload(InputStream is, List locations, String fileName) {
- String configStr = sysParameterService.findRequiredByKey("upload.oss.config");
- OssConfig config = JsonUtil.parseObject(configStr, OssConfig.class);
-
- Assert.notBlank(config.getEndpoint());
- Assert.notBlank(config.getBucketName());
- Assert.notBlank(config.getAccessKeyId());
- Assert.notBlank(config.getAccessKeySecret());
-
- OSS ossClient = new OSSClientBuilder().build(
- StringUtil.isBlank(config.getInternalEndPoint()) ? config.getEndpoint()
- : config.getInternalEndPoint(), config.getAccessKeyId(),
- config.getAccessKeySecret());
-
- String objectName = StringUtil.join("/", locations) + fileName;
- try {
- // 这里不判断桶是否存在,通过控台创建
- ossClient.putObject(config.getBucketName(), objectName, is);
-
- if (StringUtil.isNotBlank(config.getCustomUrl())) {
- return config.getCustomUrl() + (config.getCustomUrl().endsWith("/") ? StringPool.EMPTY_STR
- : "/") + objectName;
- }
-
- return "https://" + config.getBucketName() + "." + config.getEndpoint() + "/" + objectName;
- } finally {
- if (ossClient != null) {
- ossClient.shutdown();
- }
- }
- }
-
- @Data
- public static class OssConfig {
-
- private String customUrl;
-
- private String endpoint;
-
- private String internalEndPoint;
-
- private String accessKeyId;
-
- private String accessKeySecret;
-
- private String bucketName;
- }
-}
diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/GenAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/GenAutoConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..c78d4d3c04f0848bd86c0273e4822478ee27c77a
--- /dev/null
+++ b/web-starter/src/main/java/com/lframework/starter/web/config/GenAutoConfiguration.java
@@ -0,0 +1,227 @@
+package com.lframework.starter.web.config;
+
+import com.lframework.starter.web.gen.builders.CustomListBuilder;
+import com.lframework.starter.web.gen.builders.CustomPageBuilder;
+import com.lframework.starter.web.gen.builders.CustomSelectorBuilder;
+import com.lframework.starter.web.gen.builders.DataEntityBuilder;
+import com.lframework.starter.web.gen.builders.DataObjectBuilder;
+import com.lframework.starter.web.gen.controller.GenController;
+import com.lframework.starter.web.gen.controller.GenCustomListCategoryController;
+import com.lframework.starter.web.gen.controller.GenCustomListController;
+import com.lframework.starter.web.gen.controller.GenCustomPageCategoryController;
+import com.lframework.starter.web.gen.controller.GenCustomPageController;
+import com.lframework.starter.web.gen.controller.GenCustomSelectorCategoryController;
+import com.lframework.starter.web.gen.controller.GenCustomSelectorController;
+import com.lframework.starter.web.gen.controller.GenDataEntityCategoryController;
+import com.lframework.starter.web.gen.controller.GenDataEntityController;
+import com.lframework.starter.web.gen.controller.GenDataObjCategoryController;
+import com.lframework.starter.web.gen.controller.GenDataObjController;
+import com.lframework.starter.web.gen.controller.GenSelectorController;
+import com.lframework.starter.web.gen.converters.GenMysqlDataTypeConverter;
+import com.lframework.starter.web.gen.converters.GenViewTypeConverter;
+import com.lframework.starter.web.gen.impl.GenCreateColumnConfigServiceImpl;
+import com.lframework.starter.web.gen.impl.GenCustomListCategoryServiceImpl;
+import com.lframework.starter.web.gen.impl.GenCustomListDetailServiceImpl;
+import com.lframework.starter.web.gen.impl.GenCustomListHandleColumnServiceImpl;
+import com.lframework.starter.web.gen.impl.GenCustomListQueryParamsServiceImpl;
+import com.lframework.starter.web.gen.impl.GenCustomListServiceImpl;
+import com.lframework.starter.web.gen.impl.GenCustomListToolbarServiceImpl;
+import com.lframework.starter.web.gen.impl.GenCustomPageCategoryServiceImpl;
+import com.lframework.starter.web.gen.impl.GenCustomPageServiceImpl;
+import com.lframework.starter.web.gen.impl.GenCustomSelectorCategoryServiceImpl;
+import com.lframework.starter.web.gen.impl.GenCustomSelectorServiceImpl;
+import com.lframework.starter.web.gen.impl.GenDataEntityCategoryServiceImpl;
+import com.lframework.starter.web.gen.impl.GenDataEntityDetailServiceImpl;
+import com.lframework.starter.web.gen.impl.GenDataEntityServiceImpl;
+import com.lframework.starter.web.gen.impl.GenDataObjCategoryServiceImpl;
+import com.lframework.starter.web.gen.impl.GenDataObjDetailServiceImpl;
+import com.lframework.starter.web.gen.impl.GenDataObjQueryDetailServiceImpl;
+import com.lframework.starter.web.gen.impl.GenDataObjServiceImpl;
+import com.lframework.starter.web.gen.impl.GenDetailColumnConfigServiceImpl;
+import com.lframework.starter.web.gen.impl.GenQueryColumnConfigServiceImpl;
+import com.lframework.starter.web.gen.impl.GenQueryParamsColumnConfigServiceImpl;
+import com.lframework.starter.web.gen.impl.GenUpdateColumnConfigServiceImpl;
+import com.lframework.starter.web.gen.impl.GenerateInfoServiceImpl;
+import com.lframework.starter.web.gen.impl.SimpleDBServiceImpl;
+import com.lframework.starter.web.gen.impl.SimpleTableColumnServiceImpl;
+import com.lframework.starter.web.gen.listeners.CreateColumnConfigListener;
+import com.lframework.starter.web.gen.listeners.DetailColumnConfigListener;
+import com.lframework.starter.web.gen.listeners.GenCustomListListener;
+import com.lframework.starter.web.gen.listeners.GenCustomSelectorListener;
+import com.lframework.starter.web.gen.listeners.GenDataObjListener;
+import com.lframework.starter.web.gen.listeners.GenTenantListener;
+import com.lframework.starter.web.gen.listeners.GenerateInfoListener;
+import com.lframework.starter.web.gen.listeners.QueryColumnConfigListener;
+import com.lframework.starter.web.gen.listeners.QueryParamsColumnConfigListener;
+import com.lframework.starter.web.gen.listeners.UpdateColumnConfigListener;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+
+@Configuration
+@Import({
+ GenController.class,
+ GenCustomListCategoryController.class,
+ GenCustomListController.class,
+ GenCustomPageCategoryController.class,
+ GenCustomPageController.class,
+ GenCustomSelectorCategoryController.class,
+ GenCustomSelectorController.class,
+ GenDataEntityCategoryController.class,
+ GenDataEntityController.class,
+ GenDataObjCategoryController.class,
+ GenDataObjController.class,
+ GenSelectorController.class,
+ GenCreateColumnConfigServiceImpl.class,
+ GenCustomListCategoryServiceImpl.class,
+ GenCustomListDetailServiceImpl.class,
+ GenCustomListHandleColumnServiceImpl.class,
+ GenCustomListQueryParamsServiceImpl.class,
+ GenCustomListServiceImpl.class,
+ GenCustomListToolbarServiceImpl.class,
+ GenCustomPageCategoryServiceImpl.class,
+ GenCustomPageServiceImpl.class,
+ GenCustomSelectorCategoryServiceImpl.class,
+ GenCustomSelectorServiceImpl.class,
+ GenDataEntityCategoryServiceImpl.class,
+ GenDataEntityDetailServiceImpl.class,
+ GenDataEntityServiceImpl.class,
+ GenDataObjCategoryServiceImpl.class,
+ GenDataObjDetailServiceImpl.class,
+ GenDataObjQueryDetailServiceImpl.class,
+ GenDataObjServiceImpl.class,
+ GenDetailColumnConfigServiceImpl.class,
+ GenerateInfoServiceImpl.class,
+ GenQueryColumnConfigServiceImpl.class,
+ GenQueryParamsColumnConfigServiceImpl.class,
+ GenUpdateColumnConfigServiceImpl.class,
+ SimpleDBServiceImpl.class,
+ SimpleTableColumnServiceImpl.class
+})
+public class GenAutoConfiguration {
+
+ @Bean
+ public CustomListBuilder customListBuilder() {
+ return new CustomListBuilder();
+ }
+
+ @Bean
+ public CustomPageBuilder customPageBuilder() {
+ return new CustomPageBuilder();
+ }
+
+ @Bean
+ public CustomSelectorBuilder customSelectorBuilder() {
+ return new CustomSelectorBuilder();
+ }
+
+ @Bean
+ public DataEntityBuilder dataEntityBuilder() {
+ return new DataEntityBuilder();
+ }
+
+ @Bean
+ public DataObjectBuilder dataObjectBuilder() {
+ return new DataObjectBuilder();
+ }
+
+ @Bean
+ public GenMysqlDataTypeConverter genMysqlDataTypeConverter() {
+ return new GenMysqlDataTypeConverter();
+ }
+
+ @Bean
+ public GenViewTypeConverter genViewTypeConverter() {
+ return new GenViewTypeConverter();
+ }
+
+ @Bean
+ public CreateColumnConfigListener.DeleteEntityDetailListener createColumnConfigDeleteEntityDetailListener() {
+ return new CreateColumnConfigListener.DeleteEntityDetailListener();
+ }
+
+ @Bean
+ public CreateColumnConfigListener.DeleteEntityListener deleteEntityListener() {
+ return new CreateColumnConfigListener.DeleteEntityListener();
+ }
+
+ @Bean
+ public DetailColumnConfigListener.DeleteEntityDetailListener detailColumnConfigDeleteEntityDetailListener() {
+ return new DetailColumnConfigListener.DeleteEntityDetailListener();
+ }
+
+ @Bean
+ public DetailColumnConfigListener.DeleteEntityListener detailColumnConfigDeleteEntityListener() {
+ return new DetailColumnConfigListener.DeleteEntityListener();
+ }
+
+ @Bean
+ public GenCustomListListener.DataEntityDetailDeleteListener genCustomListDataEntityDetailDeleteListener() {
+ return new GenCustomListListener.DataEntityDetailDeleteListener();
+ }
+
+ @Bean
+ public GenCustomListListener.DataObjDeleteListener genCustomListDataObjDeleteListener() {
+ return new GenCustomListListener.DataObjDeleteListener();
+ }
+
+ @Bean
+ public GenCustomListListener.DataObjQueryDetailDeleteListener genCustomListDataObjQueryDetailDeleteListener() {
+ return new GenCustomListListener.DataObjQueryDetailDeleteListener();
+ }
+
+ @Bean
+ public GenCustomSelectorListener.CustomListDeleteListener genCustomSelectorCustomListDeleteListener() {
+ return new GenCustomSelectorListener.CustomListDeleteListener();
+ }
+
+ @Bean
+ public GenDataObjListener.DataEntityDeleteListener genDataObjDataEntityDeleteListener() {
+ return new GenDataObjListener.DataEntityDeleteListener();
+ }
+
+ @Bean
+ public GenDataObjListener.DataEntityDetailDeleteListener genDataObjDataEntityDetailDeleteListener() {
+ return new GenDataObjListener.DataEntityDetailDeleteListener();
+ }
+
+ @Bean
+ public GenerateInfoListener.DeleteEntityListener generateInfoDeleteEntityListener() {
+ return new GenerateInfoListener.DeleteEntityListener();
+ }
+
+ @Bean
+ public GenTenantListener.ReloadTenantListener genTenantReloadTenantListener() {
+ return new GenTenantListener.ReloadTenantListener();
+ }
+
+ @Bean
+ public QueryColumnConfigListener.DeleteEntityDetailListener queryColumnConfigDeleteEntityDetailListener() {
+ return new QueryColumnConfigListener.DeleteEntityDetailListener();
+ }
+
+ @Bean
+ public QueryColumnConfigListener.DeleteEntityListener queryColumnConfigDeleteEntityListener() {
+ return new QueryColumnConfigListener.DeleteEntityListener();
+ }
+
+ @Bean
+ public QueryParamsColumnConfigListener.DeleteEntityDetailListener queryParamsColumnConfigDeleteEntityDetailListener() {
+ return new QueryParamsColumnConfigListener.DeleteEntityDetailListener();
+ }
+
+ @Bean
+ public QueryParamsColumnConfigListener.DeleteEntityListener queryParamsColumnConfigDeleteEntityListener() {
+ return new QueryParamsColumnConfigListener.DeleteEntityListener();
+ }
+
+ @Bean
+ public UpdateColumnConfigListener.DeleteEntityDetailListener updateColumnConfigDeleteEntityDetailListener() {
+ return new UpdateColumnConfigListener.DeleteEntityDetailListener();
+ }
+
+ @Bean
+ public UpdateColumnConfigListener.DeleteEntityListener updateColumnConfigDeleteEntityListener() {
+ return new UpdateColumnConfigListener.DeleteEntityListener();
+ }
+}
diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/LettuceAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/LettuceAutoConfiguration.java
index c01028330d54bd8fedf06f0bfd89f5185720045b..309e7e81d2041c881fee5a8ad79d2c2d501b3af1 100644
--- a/web-starter/src/main/java/com/lframework/starter/web/config/LettuceAutoConfiguration.java
+++ b/web-starter/src/main/java/com/lframework/starter/web/config/LettuceAutoConfiguration.java
@@ -1,22 +1,86 @@
package com.lframework.starter.web.config;
+import io.lettuce.core.resource.ClientResources;
+import io.lettuce.core.resource.NettyCustomizer;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelDuplexHandler;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.timeout.IdleStateEvent;
+import io.netty.handler.timeout.IdleStateHandler;
import org.springframework.beans.factory.InitializingBean;
-import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.data.redis.LettuceClientConfigurationBuilderCustomizer;
+import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration.LettuceClientConfigurationBuilder;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
-import org.springframework.stereotype.Component;
-@Component
-public class LettuceAutoConfiguration implements InitializingBean {
+public class LettuceAutoConfiguration {
- @Autowired
- private RedisConnectionFactory redisConnectionFactory;
+ @Value("${spring.redis.lettuce.reader-idle-time-seconds:30}")
+ private Integer readerIdleTimeSeconds;
- @Override
- public void afterPropertiesSet() throws Exception {
- if (redisConnectionFactory instanceof LettuceConnectionFactory) {
- LettuceConnectionFactory c = (LettuceConnectionFactory) redisConnectionFactory;
- c.setValidateConnection(true);
+ // @Bean
+ public LettuceInitializingBean lettuceInitializingBean(RedisConnectionFactory redisConnectionFactory) {
+ return new LettuceInitializingBean(redisConnectionFactory);
+ }
+
+ @Bean
+ public ClientResources clientResources() {
+ NettyCustomizer nettyCustomizer = new NettyCustomizer() {
+ @Override
+ public void afterChannelInitialized(Channel channel) {
+ channel.pipeline().addLast(
+ //第一个参数readerIdleTimeSeconds设置为小于超时时间timeout,单位为秒,
+ //每隔readerIdleTimeSeconds会进行重连,在超时之前重连就能避免命令超时报错。
+ new IdleStateHandler(readerIdleTimeSeconds, 0, 0));
+ channel.pipeline().addLast(new ChannelDuplexHandler() {
+ @Override
+ public void userEventTriggered(ChannelHandlerContext ctx, Object isEvt) throws Exception {
+ if (isEvt instanceof IdleStateEvent) {
+ ctx.disconnect();
+ }
+ }
+ });
+ }
+ };
+ return ClientResources.builder().nettyCustomizer(nettyCustomizer).build();
+ }
+
+ @Bean
+ public CustomLettuceClientConfigurationBuilderCustomizer customLettuceClientConfigurationBuilderCustomizer() {
+ return new CustomLettuceClientConfigurationBuilderCustomizer(clientResources());
+ }
+
+ public static class CustomLettuceClientConfigurationBuilderCustomizer implements
+ LettuceClientConfigurationBuilderCustomizer {
+
+ private ClientResources clientResources;
+
+ public CustomLettuceClientConfigurationBuilderCustomizer(ClientResources clientResources) {
+ this.clientResources = clientResources;
+ }
+
+ @Override
+ public void customize(LettuceClientConfigurationBuilder clientConfigurationBuilder) {
+ clientConfigurationBuilder.clientResources(clientResources);
+ }
+ }
+
+ public static class LettuceInitializingBean implements InitializingBean {
+
+ private RedisConnectionFactory redisConnectionFactory;
+
+ public LettuceInitializingBean(RedisConnectionFactory redisConnectionFactory) {
+ this.redisConnectionFactory = redisConnectionFactory;
+ }
+
+ @Override
+ public void afterPropertiesSet() throws Exception {
+ if (redisConnectionFactory instanceof LettuceConnectionFactory) {
+ LettuceConnectionFactory c = (LettuceConnectionFactory) redisConnectionFactory;
+ c.setValidateConnection(true);
+ }
}
}
}
diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/LockAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/LockAutoConfiguration.java
index 9d64918b9e572973f1deab1eac7ced581412fb0a..488fffe914b67b0cb3e41d6507d1d0f272bd1f6a 100644
--- a/web-starter/src/main/java/com/lframework/starter/web/config/LockAutoConfiguration.java
+++ b/web-starter/src/main/java/com/lframework/starter/web/config/LockAutoConfiguration.java
@@ -1,10 +1,10 @@
package com.lframework.starter.web.config;
import com.lframework.starter.common.locker.LockBuilder;
-import com.lframework.starter.web.annotations.locker.EnableLock;
-import com.lframework.starter.web.annotations.locker.LockType;
-import com.lframework.starter.web.components.locker.DefaultLockBuilder;
-import com.lframework.starter.web.components.redis.locker.RedisLockBuilder;
+import com.lframework.starter.web.core.annotations.locker.EnableLock;
+import com.lframework.starter.web.core.annotations.locker.LockType;
+import com.lframework.starter.web.core.components.locker.DefaultLockBuilder;
+import com.lframework.starter.web.core.components.locker.RedisLockBuilder;
import java.util.Map;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ImportSelector;
diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/MagicCustomAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/MagicCustomAutoConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..ece53fc4543dc3c8a7d94035941ad4082e61dfa2
--- /dev/null
+++ b/web-starter/src/main/java/com/lframework/starter/web/config/MagicCustomAutoConfiguration.java
@@ -0,0 +1,72 @@
+package com.lframework.starter.web.config;
+
+import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
+import com.baomidou.dynamic.datasource.creator.BasicDataSourceCreator;
+import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
+import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.lframework.starter.web.config.properties.SecretProperties;
+import com.lframework.starter.web.gen.components.magic.MagicCustomAuthorizationInterceptor;
+import com.lframework.starter.web.gen.components.magic.MagicCustomJsonValueProvider;
+import com.lframework.starter.web.gen.components.magic.MagicCustomMagicFunction;
+import com.lframework.starter.web.gen.components.magic.MagicCustomSqlCache;
+import com.lframework.starter.web.inner.entity.Tenant;
+import com.lframework.starter.web.inner.service.TenantService;
+import com.lframework.starter.web.core.utils.DataSourceUtil;
+import com.lframework.starter.web.core.utils.EncryptUtil;
+import java.util.List;
+import java.util.Map;
+import javax.sql.DataSource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import org.springframework.scheduling.TaskScheduler;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
+import org.ssssssss.magicapi.datasource.model.MagicDynamicDataSource;
+
+@Configuration
+@Import({
+ MagicCustomAuthorizationInterceptor.class,
+ MagicCustomJsonValueProvider.class,
+ MagicCustomMagicFunction.class,
+ MagicCustomSqlCache.class
+})
+public class MagicCustomAutoConfiguration {
+
+ @Autowired
+ private DynamicDataSourceProperties dynamicDataSourceProperties;
+
+ @Bean
+ public TaskScheduler taskScheduler() {
+ ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
+ taskScheduler.setPoolSize(10);
+ taskScheduler.initialize();
+ return taskScheduler;
+ }
+
+ @Bean
+ public MagicDynamicDataSource magicDynamicDataSource(DynamicRoutingDataSource dataSource,
+ TenantService tenantService, BasicDataSourceCreator basicDataSourceCreator, SecretProperties secretProperties) {
+ Map dataSourceMap = dataSource.getDataSources();
+ MagicDynamicDataSource dynamicDataSource = new MagicDynamicDataSource();
+ dynamicDataSource.setDefault(dataSourceMap.get("master"));
+
+ DataSourceProperty dataSourceProperty = dynamicDataSourceProperties.getDatasource()
+ .get("master");
+ // 这里只加载启用的租户
+ Wrapper queryWrapper = Wrappers.lambdaQuery(Tenant.class)
+ .eq(Tenant::getAvailable, Boolean.TRUE);
+ List tenants = tenantService.list(queryWrapper);
+
+ for (Tenant tenant : tenants) {
+ dynamicDataSource.add(String.valueOf(tenant.getId()),
+ basicDataSourceCreator.createDataSource(
+ DataSourceUtil.createDataSourceProperty(dataSourceProperty, tenant.getJdbcUrl(),
+ tenant.getJdbcUsername(), EncryptUtil.decrypt(tenant.getJdbcPassword(), secretProperties))));
+ }
+
+ return dynamicDataSource;
+ }
+}
diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/MailAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/MailAutoConfiguration.java
index 5e1f16ddd25058c9415f2a38f6f2385e9312eaf0..76b86803f3dd6d9ecf5784b09d2485c70df23579 100644
--- a/web-starter/src/main/java/com/lframework/starter/web/config/MailAutoConfiguration.java
+++ b/web-starter/src/main/java/com/lframework/starter/web/config/MailAutoConfiguration.java
@@ -2,10 +2,10 @@ package com.lframework.starter.web.config;
import cn.hutool.extra.mail.MailAccount;
import com.lframework.starter.web.config.properties.MailProperties;
-import com.lframework.starter.web.impl.MailServiceImpl;
-import com.lframework.starter.web.service.MailService;
-import com.lframework.starter.web.service.SysParameterService;
-import com.lframework.starter.web.utils.JsonUtil;
+import com.lframework.starter.web.inner.impl.MailServiceImpl;
+import com.lframework.starter.web.inner.service.MailService;
+import com.lframework.starter.web.inner.service.SysConfService;
+import com.lframework.starter.web.core.utils.JsonUtil;
import com.sun.mail.util.MailSSLSocketFactory;
import java.security.GeneralSecurityException;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@@ -19,10 +19,10 @@ public class MailAutoConfiguration {
@Bean
@Scope("prototype")
@ConditionalOnMissingBean(MailService.class)
- public MailService getMailService(SysParameterService sysParameterService)
+ public MailService getMailService(SysConfService sysConfService)
throws GeneralSecurityException {
- String configStr = sysParameterService.findRequiredByKey("mail");
+ String configStr = sysConfService.findRequiredByKey("mail");
MailProperties properties = JsonUtil.parseObject(configStr, MailProperties.class);
MailAccount account = new MailAccount();
account.setHost(properties.getHost());
diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/MybatisAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/MybatisAutoConfiguration.java
index 4c9f34851e78e3d3dd5f49785f9418ddc0a76cb4..f12bb662257eab24b75429a8a56b1b46631d5f9d 100644
--- a/web-starter/src/main/java/com/lframework/starter/web/config/MybatisAutoConfiguration.java
+++ b/web-starter/src/main/java/com/lframework/starter/web/config/MybatisAutoConfiguration.java
@@ -1,12 +1,18 @@
package com.lframework.starter.web.config;
import com.baomidou.mybatisplus.annotation.DbType;
+import com.baomidou.mybatisplus.autoconfigure.MybatisPlusProperties;
+import com.baomidou.mybatisplus.autoconfigure.MybatisPlusPropertiesCustomizer;
+import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.DataPermissionInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
-import com.lframework.starter.web.handlers.DefaultBaseEntityFillHandler;
-import com.lframework.starter.web.injectors.MybatisPlusUpdateAllColumnInjector;
+import com.lframework.starter.web.core.components.permission.DataPermissionHandlerImpl;
+import com.lframework.starter.web.core.handlers.DefaultBaseEntityFillHandler;
+import com.lframework.starter.web.core.injectors.MybatisPlusUpdateAllColumnInjector;
+import com.lframework.starter.web.core.interceptors.CustomSortInterceptor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -25,8 +31,11 @@ public class MybatisAutoConfiguration {
@ConditionalOnMissingBean(MybatisPlusInterceptor.class)
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
- interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
+ interceptor.addInnerInterceptor(
+ new DataPermissionInterceptor(new DataPermissionHandlerImpl()));
+ interceptor.addInnerInterceptor(new CustomSortInterceptor());
interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
+ interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/MybatisBeanAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/MybatisBeanAutoConfiguration.java
index 03b8e2a5e5027625f0a2f6b5de94b562cf76cb66..282b07cf74e03b64b428199d5709b104b9052f08 100644
--- a/web-starter/src/main/java/com/lframework/starter/web/config/MybatisBeanAutoConfiguration.java
+++ b/web-starter/src/main/java/com/lframework/starter/web/config/MybatisBeanAutoConfiguration.java
@@ -1,6 +1,6 @@
package com.lframework.starter.web.config;
-import com.lframework.starter.web.components.CaptchaValidator;
+import com.lframework.starter.web.core.components.captcha.CaptchaValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/PasswordEncoderAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/PasswordEncoderAutoConfiguration.java
index 3a1643338788e35ab88ae3715eed4246afbec439..db8f1b793fcfa5e87ee755d792c9df95a51e97d7 100644
--- a/web-starter/src/main/java/com/lframework/starter/web/config/PasswordEncoderAutoConfiguration.java
+++ b/web-starter/src/main/java/com/lframework/starter/web/config/PasswordEncoderAutoConfiguration.java
@@ -1,6 +1,6 @@
package com.lframework.starter.web.config;
-import com.lframework.starter.web.components.security.PasswordEncoderWrapper;
+import com.lframework.starter.web.core.components.security.PasswordEncoderWrapper;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/RedisAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/RedisAutoConfiguration.java
index feaac5e0262f4231f00304f84faeb68b4541206f..6cb1e0d98b6e6986e058b1e790bf071992207c1a 100644
--- a/web-starter/src/main/java/com/lframework/starter/web/config/RedisAutoConfiguration.java
+++ b/web-starter/src/main/java/com/lframework/starter/web/config/RedisAutoConfiguration.java
@@ -7,7 +7,7 @@ import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
-import com.lframework.starter.web.components.redis.RedisHandler;
+import com.lframework.starter.web.core.components.redis.RedisHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/SaTokenAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/SaTokenAutoConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..37616638eb4edec96e78f9148a31e0d305b0f613
--- /dev/null
+++ b/web-starter/src/main/java/com/lframework/starter/web/config/SaTokenAutoConfiguration.java
@@ -0,0 +1,136 @@
+package com.lframework.starter.web.config;
+
+import cn.dev33.satoken.dao.SaTokenDao;
+import cn.dev33.satoken.dao.SaTokenDaoDefaultImpl;
+import cn.dev33.satoken.dao.SaTokenDaoRedisJackson;
+import io.lettuce.core.resource.ClientResources;
+import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
+import org.springframework.beans.factory.ObjectProvider;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.data.redis.LettuceClientConfigurationBuilderCustomizer;
+import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.context.properties.bind.Binder;
+import org.springframework.context.EnvironmentAware;
+import org.springframework.context.annotation.Bean;
+import org.springframework.core.env.Environment;
+import org.springframework.data.redis.connection.RedisPassword;
+import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
+import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
+import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
+import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
+
+class SaTokenAutoConfiguration {
+
+ @Bean
+ public SaAloneRedisInject saAloneRedisInject(
+ @Autowired(required = false) SaTokenDao saTokenDao,
+ ObjectProvider builderCustomizers,
+ ClientResources clientResources) {
+ return new SaAloneRedisInject(saTokenDao, builderCustomizers, clientResources);
+ }
+
+ public static class SaAloneRedisInject implements EnvironmentAware {
+
+ /**
+ * 配置信息的前缀
+ */
+ public static final String ALONE_PREFIX = "sa-token.alone-redis";
+
+ /**
+ * Sa-Token 持久层接口
+ */
+ private SaTokenDao saTokenDao;
+
+ private ObjectProvider builderCustomizers;
+
+ private ClientResources clientResources;
+
+ public SaAloneRedisInject(SaTokenDao saTokenDao,
+ ObjectProvider builderCustomizers,
+ ClientResources clientResources) {
+ this.saTokenDao = saTokenDao;
+ this.builderCustomizers = builderCustomizers;
+ this.clientResources = clientResources;
+ }
+
+ /**
+ * 开始注入
+ */
+ @Override
+ public void setEnvironment(Environment environment) {
+ try {
+ // 如果为空或者默认实现,则不进行任何操作
+ if (saTokenDao == null || saTokenDao instanceof SaTokenDaoDefaultImpl) {
+ return;
+ }
+ // 如果配置文件不包含相关配置,则不进行任何操作
+ if (environment.getProperty(ALONE_PREFIX + ".host") == null) {
+ return;
+ }
+
+ // ------------------- 开始注入
+
+ // 获取cfg对象
+ RedisProperties cfg = Binder.get(environment).bind(ALONE_PREFIX, RedisProperties.class)
+ .get();
+
+ // 1. Redis配置
+ RedisStandaloneConfiguration redisConfig = new RedisStandaloneConfiguration();
+ redisConfig.setHostName(cfg.getHost());
+ redisConfig.setPort(cfg.getPort());
+ redisConfig.setDatabase(cfg.getDatabase());
+ redisConfig.setPassword(RedisPassword.of(cfg.getPassword()));
+
+ // 2. 连接池配置
+ GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
+ // pool配置
+ RedisProperties.Lettuce lettuce = cfg.getLettuce();
+ if (lettuce.getPool() != null) {
+ RedisProperties.Pool pool = cfg.getLettuce().getPool();
+ // 连接池最大连接数
+ poolConfig.setMaxTotal(pool.getMaxActive());
+ // 连接池中的最大空闲连接
+ poolConfig.setMaxIdle(pool.getMaxIdle());
+ // 连接池中的最小空闲连接
+ poolConfig.setMinIdle(pool.getMinIdle());
+ // 连接池最大阻塞等待时间(使用负值表示没有限制)
+ poolConfig.setMaxWaitMillis(pool.getMaxWait().toMillis());
+ }
+ LettucePoolingClientConfiguration.LettucePoolingClientConfigurationBuilder builder = LettucePoolingClientConfiguration.builder();
+ // timeout
+ if (cfg.getTimeout() != null) {
+ builder.commandTimeout(cfg.getTimeout());
+ }
+ // shutdownTimeout
+ if (lettuce.getShutdownTimeout() != null) {
+ builder.shutdownTimeout(lettuce.getShutdownTimeout());
+ }
+ builder.clientResources(clientResources);
+ builderCustomizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
+ // 创建Factory对象
+ LettuceClientConfiguration clientConfig = builder.poolConfig(poolConfig).build();
+ LettuceConnectionFactory factory = new LettuceConnectionFactory(redisConfig, clientConfig);
+ factory.afterPropertiesSet();
+
+ // 3. 开始初始化 SaTokenDao
+ SaTokenDaoRedisJackson dao = (SaTokenDaoRedisJackson) saTokenDao;
+ dao.isInit = false;
+ dao.init(factory);
+ return;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 骗过编辑器,增加配置文件代码提示
+ *
+ * @return 配置对象
+ */
+ @ConfigurationProperties(prefix = ALONE_PREFIX)
+ public RedisProperties getSaAloneRedisConfig() {
+ return new RedisProperties();
+ }
+ }
+}
diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/SecurityAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/SecurityAutoConfiguration.java
index 21f193b9517bf068f88afc08db6ab0ac97b1bdca..8821013cf3f34ace3261655367a933991b0626b4 100644
--- a/web-starter/src/main/java/com/lframework/starter/web/config/SecurityAutoConfiguration.java
+++ b/web-starter/src/main/java/com/lframework/starter/web/config/SecurityAutoConfiguration.java
@@ -1,9 +1,9 @@
package com.lframework.starter.web.config;
-import com.lframework.starter.web.components.security.LoginInterceptor;
-import com.lframework.starter.web.components.security.PermitAllService;
-import com.lframework.starter.web.components.tenant.DefaultTenantInterceptor;
-import com.lframework.starter.web.components.tenant.TenantInterceptor;
+import com.lframework.starter.web.core.interceptors.LoginInterceptor;
+import com.lframework.starter.web.core.components.security.PermitAllService;
+import com.lframework.starter.web.core.components.tenant.DefaultTenantInterceptor;
+import com.lframework.starter.web.core.components.tenant.TenantInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/SwaggerAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/SwaggerAutoConfiguration.java
index f444e0cb523ef77baae93b3296416dfd99ec3b4b..be353feadefca73b80e50fe7487552a8b78bc06a 100644
--- a/web-starter/src/main/java/com/lframework/starter/web/config/SwaggerAutoConfiguration.java
+++ b/web-starter/src/main/java/com/lframework/starter/web/config/SwaggerAutoConfiguration.java
@@ -1,6 +1,6 @@
package com.lframework.starter.web.config;
-import com.lframework.starter.web.common.utils.ApplicationUtil;
+import com.lframework.starter.web.core.utils.ApplicationUtil;
import java.net.InetAddress;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/TenantConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/TenantAutoConfiguration.java
similarity index 83%
rename from web-starter/src/main/java/com/lframework/starter/web/config/TenantConfiguration.java
rename to web-starter/src/main/java/com/lframework/starter/web/config/TenantAutoConfiguration.java
index de39f5365ef349025f041b93ef8df7799161c845..70761a75fbe1a6fb8d7f62440de1d4a36f122479 100644
--- a/web-starter/src/main/java/com/lframework/starter/web/config/TenantConfiguration.java
+++ b/web-starter/src/main/java/com/lframework/starter/web/config/TenantAutoConfiguration.java
@@ -4,13 +4,13 @@ import com.baomidou.dynamic.datasource.provider.AbstractJdbcDataSourceProvider;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
import com.lframework.starter.web.config.properties.SecretProperties;
-import com.lframework.starter.web.utils.DataSourceUtil;
-import com.lframework.starter.web.interceptors.TenantInterceptorImpl;
-import com.lframework.starter.web.listeners.TenantListener.ClearTenantListener;
-import com.lframework.starter.web.listeners.TenantListener.ReloadTenantListener;
-import com.lframework.starter.web.listeners.TenantListener.SetTenantListener;
-import com.lframework.starter.web.components.tenant.TenantInterceptor;
-import com.lframework.starter.web.utils.EncryptUtil;
+import com.lframework.starter.web.core.utils.DataSourceUtil;
+import com.lframework.starter.web.core.interceptors.TenantInterceptorImpl;
+import com.lframework.starter.web.core.listeners.TenantListener.ClearTenantListener;
+import com.lframework.starter.web.core.listeners.TenantListener.ReloadTenantListener;
+import com.lframework.starter.web.core.listeners.TenantListener.SetTenantListener;
+import com.lframework.starter.web.core.components.tenant.TenantInterceptor;
+import com.lframework.starter.web.core.utils.EncryptUtil;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
@@ -25,7 +25,7 @@ import org.springframework.context.annotation.Configuration;
@Slf4j
@Configuration
@ConditionalOnProperty(prefix = "jugg.tenant", value = "enabled", matchIfMissing = false, havingValue = "true")
-public class TenantConfiguration {
+public class TenantAutoConfiguration {
@Autowired
private DynamicDataSourceProperties dynamicDataSourceProperties;
diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/TenantDynamicDataSourceAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/TenantDynamicDataSourceAutoConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..01f6eb4361d2a2895275478dea15a55d86cec086
--- /dev/null
+++ b/web-starter/src/main/java/com/lframework/starter/web/config/TenantDynamicDataSourceAutoConfiguration.java
@@ -0,0 +1,66 @@
+package com.lframework.starter.web.config;
+
+import com.baomidou.dynamic.datasource.processor.DsHeaderProcessor;
+import com.baomidou.dynamic.datasource.processor.DsProcessor;
+import com.baomidou.dynamic.datasource.processor.DsSessionProcessor;
+import com.baomidou.dynamic.datasource.processor.DsSpelExpressionProcessor;
+import com.baomidou.dynamic.datasource.processor.jakarta.DsJakartaHeaderProcessor;
+import com.baomidou.dynamic.datasource.processor.jakarta.DsJakartaSessionProcessor;
+import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration;
+import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
+import com.lframework.starter.web.core.components.tenant.TenantContextHolder;
+import com.lframework.starter.web.core.constants.MyBatisStringPool;
+import com.lframework.starter.web.core.utils.TenantUtil;
+import org.aopalliance.intercept.MethodInvocation;
+import org.springframework.boot.SpringBootVersion;
+import org.springframework.boot.autoconfigure.AutoConfigureBefore;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@AutoConfigureBefore(value = DynamicDataSourceAutoConfiguration.class)
+public class TenantDynamicDataSourceAutoConfiguration {
+
+ public class DsCurTenantProcessor extends DsProcessor {
+
+ private String primary;
+
+ public DsCurTenantProcessor(String primary) {
+ this.primary = primary;
+ }
+
+ @Override
+ public boolean matches(String key) {
+ return key.equals(MyBatisStringPool.DS_KEY_CUR_TENANT);
+ }
+
+ @Override
+ public String doDetermineDatasource(MethodInvocation invocation, String key) {
+
+ if (TenantUtil.enableTenant()) {
+ return TenantContextHolder.getTenantIdStr();
+ }
+ return this.primary;
+ }
+ }
+
+ @Bean
+ public DsProcessor dsProcessor(DynamicDataSourceProperties properties) {
+ String version = SpringBootVersion.getVersion();
+ DsProcessor headerProcessor;
+ DsProcessor sessionProcessor;
+ if (version.startsWith("3")) {
+ headerProcessor = new DsJakartaHeaderProcessor();
+ sessionProcessor = new DsJakartaSessionProcessor();
+ } else {
+ headerProcessor = new DsHeaderProcessor();
+ sessionProcessor = new DsSessionProcessor();
+ }
+ DsCurTenantProcessor curTenantProcessor = new DsCurTenantProcessor(properties.getPrimary());
+ DsSpelExpressionProcessor spelExpressionProcessor = new DsSpelExpressionProcessor();
+ headerProcessor.setNextProcessor(sessionProcessor);
+ sessionProcessor.setNextProcessor(spelExpressionProcessor);
+ spelExpressionProcessor.setNextProcessor(curTenantProcessor);
+ return headerProcessor;
+ }
+}
diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/UploadAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/UploadAutoConfiguration.java
index 042212db5028241dacead899b8c537115c4b6fa5..2af5037280b70092c274f339f30db658a9dc9dc6 100644
--- a/web-starter/src/main/java/com/lframework/starter/web/config/UploadAutoConfiguration.java
+++ b/web-starter/src/main/java/com/lframework/starter/web/config/UploadAutoConfiguration.java
@@ -1,6 +1,7 @@
package com.lframework.starter.web.config;
import com.lframework.starter.common.utils.StringUtil;
+import com.lframework.starter.web.config.properties.SecurityUploadProperties;
import com.lframework.starter.web.config.properties.UploadProperties;
import java.io.File;
import org.springframework.beans.factory.annotation.Autowired;
@@ -10,7 +11,7 @@ import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
-@EnableConfigurationProperties(UploadProperties.class)
+@EnableConfigurationProperties({UploadProperties.class, SecurityUploadProperties.class})
public class UploadAutoConfiguration implements WebMvcConfigurer {
@Autowired
diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/WebAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/WebAutoConfiguration.java
index 1a6f0eebec9e8443d35ccad35c24e794f123019c..cf064b9d465173f7035b3f43fc7e4e4c75952430 100644
--- a/web-starter/src/main/java/com/lframework/starter/web/config/WebAutoConfiguration.java
+++ b/web-starter/src/main/java/com/lframework/starter/web/config/WebAutoConfiguration.java
@@ -21,16 +21,16 @@ import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
import com.lframework.starter.common.constants.StringPool;
import com.lframework.starter.common.utils.IdWorker;
import com.lframework.starter.common.utils.StringUtil;
-import com.lframework.starter.web.components.security.CheckPermissionHandler;
-import com.lframework.starter.web.components.security.CheckPermissionHandlerImpl;
-import com.lframework.starter.web.components.security.PermitAllService;
-import com.lframework.starter.web.components.trace.DefaultTraceBuilder;
-import com.lframework.starter.web.components.trace.TraceBuilder;
+import com.lframework.starter.web.core.components.security.CheckPermissionHandler;
+import com.lframework.starter.web.core.components.security.CheckPermissionHandlerImpl;
+import com.lframework.starter.web.core.components.security.PermitAllService;
+import com.lframework.starter.web.core.components.trace.DefaultTraceBuilder;
+import com.lframework.starter.web.core.components.trace.TraceBuilder;
import com.lframework.starter.web.config.properties.DefaultSettingProperties;
import com.lframework.starter.web.config.properties.SecretProperties;
import com.lframework.starter.web.config.properties.WebProperties;
-import com.lframework.starter.web.sign.CheckSignHandler;
-import com.lframework.starter.web.sign.DefaultCheckSignHandler;
+import com.lframework.starter.web.core.components.sign.CheckSignHandler;
+import com.lframework.starter.web.core.components.sign.handler.DefaultCheckSignHandler;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/WebBeanAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/WebBeanAutoConfiguration.java
index 62d48cc5a99ee0b0a4403b1181871e7fa630d0d7..872d4c377ebee20d8b836a13684677f75b53837e 100644
--- a/web-starter/src/main/java/com/lframework/starter/web/config/WebBeanAutoConfiguration.java
+++ b/web-starter/src/main/java/com/lframework/starter/web/config/WebBeanAutoConfiguration.java
@@ -1,30 +1,205 @@
package com.lframework.starter.web.config;
-import com.lframework.starter.web.aop.ControllerAspector;
-import com.lframework.starter.web.aop.OpenApiAspect;
-import com.lframework.starter.web.aop.PermissionAspect;
-import com.lframework.starter.web.components.cache.CacheVariables;
-import com.lframework.starter.web.components.generator.Generator;
-import com.lframework.starter.web.components.generator.impl.DefaultFlowGenerator;
-import com.lframework.starter.web.components.generator.impl.DefaultGenerator;
-import com.lframework.starter.web.components.generator.impl.DefaultSnowFlakeGenerator;
-import com.lframework.starter.web.components.security.UserTokenResolver;
-import com.lframework.starter.web.components.upload.handler.UploadHandler;
-import com.lframework.starter.web.components.upload.handler.impl.CosUploadHandler;
-import com.lframework.starter.web.components.upload.handler.impl.LocalUploadHandler;
-import com.lframework.starter.web.components.upload.handler.impl.ObsUploadHandler;
-import com.lframework.starter.web.components.upload.handler.impl.OssUploadHandler;
-import com.lframework.starter.web.impl.GenerateCodeServiceImpl;
-import com.lframework.starter.web.resp.InvokeResultErrorBuilderWrapper;
-import com.lframework.starter.web.resp.ResponseErrorBuilder;
-import com.lframework.starter.web.service.GenerateCodeService;
-import com.lframework.starter.web.sign.CheckSignFactory;
-import com.lframework.starter.web.sign.DefaultCheckSignFactory;
+import com.lframework.starter.web.core.aop.ControllerAspector;
+import com.lframework.starter.web.core.aop.OpLogAspector;
+import com.lframework.starter.web.core.aop.OpenApiAspect;
+import com.lframework.starter.web.core.aop.OrderTimeLineLogAspect;
+import com.lframework.starter.web.core.aop.PermissionAspect;
+import com.lframework.starter.web.core.components.cache.CacheVariables;
+import com.lframework.starter.web.core.components.generator.handler.impl.CurrentDateTimeRuleGenerateCodeHandler;
+import com.lframework.starter.web.core.components.generator.handler.impl.CustomRandomStrGenerateCodeRuleHandler;
+import com.lframework.starter.web.core.components.generator.handler.impl.FlowGenerateCodeRuleHandler;
+import com.lframework.starter.web.core.components.generator.handler.impl.SnowFlakeGenerateCodeRuleHandler;
+import com.lframework.starter.web.core.components.generator.handler.impl.StaticStrGenerateCodeRuleHandler;
+import com.lframework.starter.web.core.components.generator.handler.impl.UUIDGenerateCodeRuleHandler;
+import com.lframework.starter.web.core.components.resp.InvokeResultErrorBuilderWrapper;
+import com.lframework.starter.web.core.components.resp.ResponseErrorBuilder;
+import com.lframework.starter.web.core.components.security.UserTokenResolverImpl;
+import com.lframework.starter.web.core.components.sign.CheckSignFactory;
+import com.lframework.starter.web.core.components.sign.DefaultCheckSignFactory;
+import com.lframework.starter.web.core.components.sign.handler.DefaultCheckSignHandler;
+import com.lframework.starter.web.core.components.upload.handler.SecurityUploadHandler;
+import com.lframework.starter.web.core.components.upload.handler.UploadHandler;
+import com.lframework.starter.web.core.components.upload.handler.impl.CosSecurityUploadHandler;
+import com.lframework.starter.web.core.components.upload.handler.impl.CosUploadHandler;
+import com.lframework.starter.web.core.components.upload.handler.impl.LocalSecurityUploadHandler;
+import com.lframework.starter.web.core.components.upload.handler.impl.LocalUploadHandler;
+import com.lframework.starter.web.core.components.upload.handler.impl.ObsSecurityUploadHandler;
+import com.lframework.starter.web.core.components.upload.handler.impl.ObsUploadHandler;
+import com.lframework.starter.web.core.components.upload.handler.impl.OssSecurityUploadHandler;
+import com.lframework.starter.web.core.components.upload.handler.impl.OssUploadHandler;
+import com.lframework.starter.web.core.handlers.exception.WebExceptionHandler;
+import com.lframework.starter.web.inner.components.oplog.AuthOpLogType;
+import com.lframework.starter.web.inner.components.oplog.OtherOpLogType;
+import com.lframework.starter.web.inner.components.oplog.SystemOpLogType;
+import com.lframework.starter.web.inner.components.permission.OrderDataPermissionDataPermissionType;
+import com.lframework.starter.web.inner.components.permission.ProductDataPermissionDataPermissionType;
+import com.lframework.starter.web.inner.components.timeline.ApprovePassOrderTimeLineBizType;
+import com.lframework.starter.web.inner.components.timeline.ApproveReturnOrderTimeLineBizType;
+import com.lframework.starter.web.inner.components.timeline.CancelApproveOrderTimeLineBizType;
+import com.lframework.starter.web.inner.components.timeline.CreateOrderTimeLineBizType;
+import com.lframework.starter.web.inner.components.timeline.NormalOrderTimeLineBizType;
+import com.lframework.starter.web.inner.components.timeline.SendOrderTimeLineBizType;
+import com.lframework.starter.web.inner.components.timeline.UpdateOrderTimeLineBizType;
+import com.lframework.starter.web.inner.controller.AuthController;
+import com.lframework.starter.web.inner.controller.QrtzController;
+import com.lframework.starter.web.inner.controller.UserCenterController;
+import com.lframework.starter.web.inner.controller.system.DefaultSysSelectorController;
+import com.lframework.starter.web.inner.controller.system.OpLogController;
+import com.lframework.starter.web.inner.controller.system.SysDataDicCategoryController;
+import com.lframework.starter.web.inner.controller.system.SysDataDicController;
+import com.lframework.starter.web.inner.controller.system.SysDataDicItemController;
+import com.lframework.starter.web.inner.controller.system.SysDataPermissionDataController;
+import com.lframework.starter.web.inner.controller.system.SysDataPermissionModelDetailController;
+import com.lframework.starter.web.inner.controller.system.SysDeptController;
+import com.lframework.starter.web.inner.controller.system.SysGenerateCodeController;
+import com.lframework.starter.web.inner.controller.system.SysMailMessageController;
+import com.lframework.starter.web.inner.controller.system.SysMenuController;
+import com.lframework.starter.web.inner.controller.system.SysModuleController;
+import com.lframework.starter.web.inner.controller.system.SysNoticeController;
+import com.lframework.starter.web.inner.controller.system.SysNotifyGroupController;
+import com.lframework.starter.web.inner.controller.system.SysOpenDomainController;
+import com.lframework.starter.web.inner.controller.system.SysParameterController;
+import com.lframework.starter.web.inner.controller.system.SysRoleCategoryController;
+import com.lframework.starter.web.inner.controller.system.SysRoleController;
+import com.lframework.starter.web.inner.controller.system.SysRoleMenuController;
+import com.lframework.starter.web.inner.controller.system.SysSiteMessageController;
+import com.lframework.starter.web.inner.controller.system.SysUserController;
+import com.lframework.starter.web.inner.controller.system.SysUserGroupController;
+import com.lframework.starter.web.inner.controller.system.SysUserRoleController;
+import com.lframework.starter.web.inner.controller.system.TenantController;
+import com.lframework.starter.web.inner.enums.system.SysDeptNodeType;
+import com.lframework.starter.web.inner.handlers.exception.AccessDeniedExceptionConverter;
+import com.lframework.starter.web.inner.handlers.exception.BindExceptionConverter;
+import com.lframework.starter.web.inner.handlers.exception.ClientExceptionConverter;
+import com.lframework.starter.web.inner.handlers.exception.ConstraintViolationExceptionConverter;
+import com.lframework.starter.web.inner.handlers.exception.ExceptionConverter;
+import com.lframework.starter.web.inner.handlers.exception.FileUploadExceptionConverter;
+import com.lframework.starter.web.inner.handlers.exception.HttpMessageNotReadableExceptionConverter;
+import com.lframework.starter.web.inner.handlers.exception.HttpRequestMethodNotSupportedExceptionConverter;
+import com.lframework.starter.web.inner.handlers.exception.MethodArgumentNotValidExceptionConverter;
+import com.lframework.starter.web.inner.handlers.exception.NotPermissionExceptionConverter;
+import com.lframework.starter.web.inner.handlers.exception.SysExceptionConverter;
+import com.lframework.starter.web.inner.handlers.exception.TypeMismatchExceptionConverter;
+import com.lframework.starter.web.inner.handlers.exception.UnexpectedTypeExceptionConverter;
+import com.lframework.starter.web.inner.impl.DefaultUserDetailsService;
+import com.lframework.starter.web.inner.impl.DicCityServiceImpl;
+import com.lframework.starter.web.inner.impl.GenerateCodeServiceImpl;
+import com.lframework.starter.web.inner.impl.OpLogsServiceImpl;
+import com.lframework.starter.web.inner.impl.OrderTimeLineServiceImpl;
+import com.lframework.starter.web.inner.impl.QrtzServiceImpl;
+import com.lframework.starter.web.inner.impl.RecursionMappingServiceImpl;
+import com.lframework.starter.web.inner.impl.SecurityUploadRecordServiceImpl;
+import com.lframework.starter.web.inner.impl.SysModuleServiceImpl;
+import com.lframework.starter.web.inner.impl.SysModuleTenantServiceImpl;
+import com.lframework.starter.web.inner.impl.TenantServiceImpl;
+import com.lframework.starter.web.inner.impl.system.SysDataDicCategoryServiceImpl;
+import com.lframework.starter.web.inner.impl.system.SysDataDicItemServiceImpl;
+import com.lframework.starter.web.inner.impl.system.SysDataDicServiceImpl;
+import com.lframework.starter.web.inner.impl.system.SysDataPermissionDataServiceImpl;
+import com.lframework.starter.web.inner.impl.system.SysDataPermissionModelDetailServiceImpl;
+import com.lframework.starter.web.inner.impl.system.SysDeptServiceImpl;
+import com.lframework.starter.web.inner.impl.system.SysGenerateCodeServiceImpl;
+import com.lframework.starter.web.inner.impl.system.SysMailMessageServiceImpl;
+import com.lframework.starter.web.inner.impl.system.SysMenuServiceImpl;
+import com.lframework.starter.web.inner.impl.system.SysNoticeLogServiceImpl;
+import com.lframework.starter.web.inner.impl.system.SysNoticeServiceImpl;
+import com.lframework.starter.web.inner.impl.system.SysNotifyGroupReceiverServiceImpl;
+import com.lframework.starter.web.inner.impl.system.SysNotifyGroupServiceImpl;
+import com.lframework.starter.web.inner.impl.system.SysOpenDomainServiceImpl;
+import com.lframework.starter.web.inner.impl.system.SysParameterServiceImpl;
+import com.lframework.starter.web.inner.impl.system.SysRoleCategoryServiceImpl;
+import com.lframework.starter.web.inner.impl.system.SysRoleMenuServiceImpl;
+import com.lframework.starter.web.inner.impl.system.SysRoleServiceImpl;
+import com.lframework.starter.web.inner.impl.system.SysSiteMessageServiceImpl;
+import com.lframework.starter.web.inner.impl.system.SysUserDeptServiceImpl;
+import com.lframework.starter.web.inner.impl.system.SysUserGroupDetailServiceImpl;
+import com.lframework.starter.web.inner.impl.system.SysUserGroupServiceImpl;
+import com.lframework.starter.web.inner.impl.system.SysUserRoleServiceImpl;
+import com.lframework.starter.web.inner.impl.system.SysUserServiceImpl;
+import com.lframework.starter.web.inner.impl.system.SysUserTelephoneServiceImpl;
+import com.lframework.starter.web.inner.listeners.OpLogTimerListener;
+import lombok.extern.slf4j.Slf4j;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import org.springframework.core.env.Environment;
+@Slf4j
@Configuration
-public class WebBeanAutoConfiguration {
+@Import({
+ WebExceptionHandler.class,
+ DicCityServiceImpl.class,
+ GenerateCodeServiceImpl.class,
+ OpLogsServiceImpl.class,
+ OrderTimeLineServiceImpl.class,
+ RecursionMappingServiceImpl.class,
+ SecurityUploadRecordServiceImpl.class,
+ DefaultSysSelectorController.class,
+ OpLogController.class,
+ SysDataDicCategoryController.class,
+ SysDataDicController.class,
+ SysDataDicItemController.class,
+ SysDataPermissionDataController.class,
+ SysDataPermissionModelDetailController.class,
+ SysDeptController.class,
+ SysGenerateCodeController.class,
+ SysMailMessageController.class,
+ SysMenuController.class,
+ SysModuleController.class,
+ SysNoticeController.class,
+ SysNotifyGroupController.class,
+ SysOpenDomainController.class,
+ SysParameterController.class,
+ SysRoleCategoryController.class,
+ SysRoleController.class,
+ SysRoleMenuController.class,
+ SysSiteMessageController.class,
+ SysUserController.class,
+ SysUserGroupController.class,
+ SysUserRoleController.class,
+ TenantController.class,
+ AuthController.class,
+ QrtzController.class,
+ UserCenterController.class,
+ SysDataDicCategoryServiceImpl.class,
+ SysDataDicItemServiceImpl.class,
+ SysDataDicServiceImpl.class,
+ SysDataPermissionDataServiceImpl.class,
+ SysDataPermissionModelDetailServiceImpl.class,
+ SysDeptServiceImpl.class,
+ SysGenerateCodeServiceImpl.class,
+ SysMailMessageServiceImpl.class,
+ SysMenuServiceImpl.class,
+ SysNoticeLogServiceImpl.class,
+ SysNoticeServiceImpl.class,
+ SysNoticeServiceImpl.ReloadNoticeListener.class,
+ SysNotifyGroupReceiverServiceImpl.class,
+ SysNotifyGroupServiceImpl.class,
+ SysOpenDomainServiceImpl.class,
+ SysParameterServiceImpl.class,
+ SysRoleCategoryServiceImpl.class,
+ SysRoleMenuServiceImpl.class,
+ SysRoleServiceImpl.class,
+ SysSiteMessageServiceImpl.class,
+ SysSiteMessageServiceImpl.ReloadSiteMessageListener.class,
+ SysUserDeptServiceImpl.class,
+ SysUserGroupDetailServiceImpl.class,
+ SysUserGroupServiceImpl.class,
+ SysUserRoleServiceImpl.class,
+ SysUserServiceImpl.class,
+ SysUserTelephoneServiceImpl.class,
+ QrtzServiceImpl.class,
+ SysModuleServiceImpl.class,
+ SysModuleTenantServiceImpl.class,
+ TenantServiceImpl.class,
+ DefaultUserDetailsService.class
+})
+@MapperScan("com.lframework.starter.web.**.mappers")
+public class WebBeanAutoConfiguration implements EnvironmentAware {
@Bean
public ControllerAspector controllerAspector() {
@@ -43,43 +218,43 @@ public class WebBeanAutoConfiguration {
}
@Bean
- public Generator defaultFlowGenerator() {
- return new DefaultFlowGenerator();
+ public UploadHandler cosUploadHandler() {
+ return new CosUploadHandler();
}
@Bean
- public Generator defaultSnowFlakeGenerator() {
- return new DefaultSnowFlakeGenerator();
+ public UploadHandler localUploadHandler() {
+ return new LocalUploadHandler();
}
@Bean
- public Generator defaultGenerator() {
- return new DefaultGenerator();
+ public UploadHandler obsUploadHandler() {
+ return new ObsUploadHandler();
}
@Bean
- public UploadHandler cosUploadHandler() {
- return new CosUploadHandler();
+ public UploadHandler ossUploadHandler() {
+ return new OssUploadHandler();
}
@Bean
- public UploadHandler localUploadHandler() {
- return new LocalUploadHandler();
+ public SecurityUploadHandler ossSecurityUploadHandler() {
+ return new OssSecurityUploadHandler();
}
@Bean
- public UploadHandler obsUploadHandler() {
- return new ObsUploadHandler();
+ public SecurityUploadHandler cosSecurityUploadHandler() {
+ return new CosSecurityUploadHandler();
}
@Bean
- public UploadHandler ossUploadHandler() {
- return new OssUploadHandler();
+ public SecurityUploadHandler localSecurityUploadHandler() {
+ return new LocalSecurityUploadHandler();
}
@Bean
- public GenerateCodeService generateCodeService() {
- return new GenerateCodeServiceImpl();
+ public SecurityUploadHandler obsSecurityUploadHandler() {
+ return new ObsSecurityUploadHandler();
}
@Bean
@@ -98,7 +273,188 @@ public class WebBeanAutoConfiguration {
}
@Bean
- public UserTokenResolver userTokenResolver() {
- return new UserTokenResolver();
+ public UserTokenResolverImpl userTokenResolver() {
+ return new UserTokenResolverImpl();
+ }
+
+ @Bean
+ public CurrentDateTimeRuleGenerateCodeHandler currentDateTimeRuleGenerateHandler() {
+ return new CurrentDateTimeRuleGenerateCodeHandler();
+ }
+
+ @Bean
+ public CustomRandomStrGenerateCodeRuleHandler customRandomStrGenerateRuleHandler() {
+ return new CustomRandomStrGenerateCodeRuleHandler();
+ }
+
+ @Bean
+ public FlowGenerateCodeRuleHandler flowGenerateRuleHandler() {
+ return new FlowGenerateCodeRuleHandler();
+ }
+
+ @Bean
+ public SnowFlakeGenerateCodeRuleHandler snowFlakeGenerateRuleHandler() {
+ return new SnowFlakeGenerateCodeRuleHandler();
+ }
+
+ @Bean
+ public StaticStrGenerateCodeRuleHandler staticStrGenerateRuleHandler() {
+ return new StaticStrGenerateCodeRuleHandler();
+ }
+
+ @Bean
+ public UUIDGenerateCodeRuleHandler uuidGenerateRuleHandler() {
+ return new UUIDGenerateCodeRuleHandler();
+ }
+
+ @Bean
+ public OrderDataPermissionDataPermissionType orderDataPermissionDataPermissionType() {
+ return new OrderDataPermissionDataPermissionType();
+ }
+
+ @Bean
+ public ProductDataPermissionDataPermissionType productDataPermissionDataPermissionType() {
+ return new ProductDataPermissionDataPermissionType();
+ }
+
+ @Bean
+ public ApprovePassOrderTimeLineBizType approvePassOrderTimeLineBizType() {
+ return new ApprovePassOrderTimeLineBizType();
+ }
+
+ @Bean
+ public ApproveReturnOrderTimeLineBizType approveReturnOrderTimeLineBizType() {
+ return new ApproveReturnOrderTimeLineBizType();
+ }
+
+ @Bean
+ public CancelApproveOrderTimeLineBizType cancelApproveOrderTimeLineBizType() {
+ return new CancelApproveOrderTimeLineBizType();
+ }
+
+ @Bean
+ public CreateOrderTimeLineBizType createOrderTimeLineBizType() {
+ return new CreateOrderTimeLineBizType();
+ }
+
+ @Bean
+ public NormalOrderTimeLineBizType normalOrderTimeLineBizType() {
+ return new NormalOrderTimeLineBizType();
+ }
+
+ @Bean
+ public SendOrderTimeLineBizType sendOrderTimeLineBizType() {
+ return new SendOrderTimeLineBizType();
+ }
+
+ @Bean
+ public UpdateOrderTimeLineBizType updateOrderTimeLineBizType() {
+ return new UpdateOrderTimeLineBizType();
+ }
+
+ @Bean
+ public AccessDeniedExceptionConverter accessDeniedExceptionConverter() {
+ return new AccessDeniedExceptionConverter();
+ }
+
+ @Bean
+ public BindExceptionConverter bindExceptionConverter() {
+ return new BindExceptionConverter();
+ }
+
+ @Bean
+ public ClientExceptionConverter clientExceptionConverter() {
+ return new ClientExceptionConverter();
+ }
+
+ @Bean
+ public ConstraintViolationExceptionConverter constraintViolationExceptionConverter() {
+ return new ConstraintViolationExceptionConverter();
+ }
+
+ @Bean
+ public ExceptionConverter exceptionConverter() {
+ return new ExceptionConverter();
+ }
+
+ @Bean
+ public FileUploadExceptionConverter fileUploadExceptionConverter() {
+ return new FileUploadExceptionConverter();
+ }
+
+ @Bean
+ public HttpMessageNotReadableExceptionConverter httpMessageNotReadableExceptionConverter() {
+ return new HttpMessageNotReadableExceptionConverter();
+ }
+
+ @Bean
+ public HttpRequestMethodNotSupportedExceptionConverter httpRequestMethodNotSupportedExceptionConverter() {
+ return new HttpRequestMethodNotSupportedExceptionConverter();
+ }
+
+ @Bean
+ public MethodArgumentNotValidExceptionConverter methodArgumentNotValidExceptionConverter() {
+ return new MethodArgumentNotValidExceptionConverter();
+ }
+
+ @Bean
+ public NotPermissionExceptionConverter notPermissionExceptionConverter() {
+ return new NotPermissionExceptionConverter();
+ }
+
+ @Bean
+ public SysExceptionConverter sysExceptionConverter() {
+ return new SysExceptionConverter();
+ }
+
+ @Bean
+ public TypeMismatchExceptionConverter typeMismatchExceptionConverter() {
+ return new TypeMismatchExceptionConverter();
+ }
+
+ @Bean
+ public UnexpectedTypeExceptionConverter unexpectedTypeExceptionConverter() {
+ return new UnexpectedTypeExceptionConverter();
+ }
+
+ @Bean
+ @ConditionalOnProperty(value = "op-logs.enabled", matchIfMissing = true)
+ public OpLogAspector opLogAspector() {
+ return new OpLogAspector();
+ }
+
+ @Bean
+ public OrderTimeLineLogAspect orderTimeLineLogAspect() {
+ return new OrderTimeLineLogAspect();
+ }
+
+ @Bean
+ public OpLogTimerListener opLogTimerListener() {
+ return new OpLogTimerListener();
+ }
+
+ @Bean
+ public AuthOpLogType authOpLogType() {
+ return new AuthOpLogType();
+ }
+
+ @Bean
+ public SystemOpLogType systemOpLogType() {
+ return new SystemOpLogType();
+ }
+
+ @Bean
+ public OtherOpLogType otherOpLogType() {
+ return new OtherOpLogType();
+ }
+
+ @Override
+ public void setEnvironment(Environment environment) {
+ log.info("web-starter加载完成");
+ }
+
+ @Bean
+ public SysDeptNodeType sysDeptNodeType() {
+ return new SysDeptNodeType();
}
}
diff --git a/web-common/src/main/java/com/lframework/starter/web/common/config/WebCommonAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/WebCommonAutoConfiguration.java
similarity index 70%
rename from web-common/src/main/java/com/lframework/starter/web/common/config/WebCommonAutoConfiguration.java
rename to web-starter/src/main/java/com/lframework/starter/web/config/WebCommonAutoConfiguration.java
index fd9a83f443c7b38e2b41fb9483ba1b15d19c9e81..7d33af973e05fda771511135a87c54129d3d6fbe 100644
--- a/web-common/src/main/java/com/lframework/starter/web/common/config/WebCommonAutoConfiguration.java
+++ b/web-starter/src/main/java/com/lframework/starter/web/config/WebCommonAutoConfiguration.java
@@ -1,6 +1,6 @@
-package com.lframework.starter.web.common.config;
+package com.lframework.starter.web.config;
-import com.lframework.starter.web.common.utils.ApplicationUtil;
+import com.lframework.starter.web.core.utils.ApplicationUtil;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/WebMvcAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/WebMvcAutoConfiguration.java
index 657d523c497cc466a5f0cf7cc3cc6fa5bed9e238..508ecd2632d2a230f07280879c06995856e6f98d 100644
--- a/web-starter/src/main/java/com/lframework/starter/web/config/WebMvcAutoConfiguration.java
+++ b/web-starter/src/main/java/com/lframework/starter/web/config/WebMvcAutoConfiguration.java
@@ -1,7 +1,7 @@
package com.lframework.starter.web.config;
import cn.dev33.satoken.interceptor.SaAnnotationInterceptor;
-import com.lframework.starter.web.components.security.PermitAllService;
+import com.lframework.starter.web.core.components.security.PermitAllService;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/WebSwaggerAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/WebSwaggerAutoConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..e7333f4b83a1c1c26c0d6ce7a23e1eb2231723b1
--- /dev/null
+++ b/web-starter/src/main/java/com/lframework/starter/web/config/WebSwaggerAutoConfiguration.java
@@ -0,0 +1,48 @@
+package com.lframework.starter.web.config;
+
+import com.github.xiaoymin.knife4j.spring.extension.OpenApiExtensionResolver;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+
+@Configuration
+public class WebSwaggerAutoConfiguration {
+
+ @Bean("webApiDocket")
+ public Docket webApiDocket(ApiInfo info, OpenApiExtensionResolver openApiExtensionResolver) {
+
+ // 除了描述 其他全与info保持一致
+ ApiInfo apiInfo = new ApiInfo(info.getTitle(), "系统功能模块", info.getVersion(),
+ info.getTermsOfServiceUrl(),
+ info.getContact(), info.getLicense(), info.getLicenseUrl(), info.getVendorExtensions());
+
+ Docket docket = new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo).groupName("系统功能模块")
+ .select()
+ .apis(RequestHandlerSelectors.basePackage("com.lframework.starter.web.inner"))
+ .paths(PathSelectors.any())
+ .build()
+ .extensions(openApiExtensionResolver.buildSettingExtensions());
+ return docket;
+ }
+
+ @Bean("genApiDocket")
+ public Docket genApiDocket(ApiInfo info, OpenApiExtensionResolver openApiExtensionResolver) {
+
+ // 除了描述 其他全与info保持一致
+ ApiInfo apiInfo = new ApiInfo(info.getTitle(), "代码生成模块", info.getVersion(),
+ info.getTermsOfServiceUrl(),
+ info.getContact(), info.getLicense(), info.getLicenseUrl(), info.getVendorExtensions());
+
+ Docket docket = new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo).groupName("代码生成模块")
+ .select()
+ .apis(RequestHandlerSelectors.basePackage("com.lframework.starter.web.gen"))
+ .paths(PathSelectors.any())
+ .build()
+ .extensions(openApiExtensionResolver.buildSettingExtensions());
+ return docket;
+ }
+}
diff --git a/websocket-starter/src/main/java/com/lframework/starter/websocket/config/WsAutoConfiguration.java b/web-starter/src/main/java/com/lframework/starter/web/config/WsAutoConfiguration.java
similarity index 78%
rename from websocket-starter/src/main/java/com/lframework/starter/websocket/config/WsAutoConfiguration.java
rename to web-starter/src/main/java/com/lframework/starter/web/config/WsAutoConfiguration.java
index 071c304eabf0b6c293077443ccf19571ceabce63..091e5380421c45e117b769e6794e06ec95aa7ace 100644
--- a/websocket-starter/src/main/java/com/lframework/starter/websocket/config/WsAutoConfiguration.java
+++ b/web-starter/src/main/java/com/lframework/starter/web/config/WsAutoConfiguration.java
@@ -1,15 +1,16 @@
-package com.lframework.starter.websocket.config;
+package com.lframework.starter.web.config;
import com.lframework.starter.common.utils.StringUtil;
-import com.lframework.starter.web.dto.WsPushData;
-import com.lframework.starter.web.utils.JsonUtil;
-import com.lframework.starter.websocket.components.WsDataPushWorker;
-import com.lframework.starter.websocket.components.WsDataPusher;
-import com.lframework.starter.websocket.components.WsDataPusherImpl;
-import com.lframework.starter.websocket.handler.WsHandler;
-import com.lframework.starter.websocket.interceptor.WsHandshakeInterceptor;
-import com.lframework.starter.websocket.listener.WsUserConnectListener;
-import com.lframework.starter.websocket.listener.WsUserDisConnectListener;
+import com.lframework.starter.web.config.properties.WsProperties;
+import com.lframework.starter.web.websocket.dto.WsPushData;
+import com.lframework.starter.web.core.utils.JsonUtil;
+import com.lframework.starter.web.websocket.components.WsDataPushWorker;
+import com.lframework.starter.web.websocket.components.WsDataPusher;
+import com.lframework.starter.web.websocket.components.WsDataPusherImpl;
+import com.lframework.starter.web.websocket.handler.WsHandler;
+import com.lframework.starter.web.websocket.interceptor.WsHandshakeInterceptor;
+import com.lframework.starter.web.websocket.listener.WsUserConnectListener;
+import com.lframework.starter.web.websocket.listener.WsUserDisConnectListener;
import java.nio.charset.StandardCharsets;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/properties/DefaultSettingProperties.java b/web-starter/src/main/java/com/lframework/starter/web/config/properties/DefaultSettingProperties.java
index fba98363d71d425aefc9bfe64bb4a6e0a43a1d8f..59a8a67db66354ed59959009561fbf589cff4523 100644
--- a/web-starter/src/main/java/com/lframework/starter/web/config/properties/DefaultSettingProperties.java
+++ b/web-starter/src/main/java/com/lframework/starter/web/config/properties/DefaultSettingProperties.java
@@ -1,6 +1,5 @@
package com.lframework.starter.web.config.properties;
-import com.lframework.starter.web.components.generator.impl.DefaultGenerator.GeneratorType;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@@ -17,9 +16,4 @@ public class DefaultSettingProperties {
* 默认的用户姓名,用于写入数据库时的createBy和updateBy的自动赋值,如果有登录人则取登录人姓名,如果没有则取默认用户姓名,如果不配置,默认是系统管理员
*/
private String defaultUserName = "系统管理员";
-
- /**
- * 默认单号生成类型 FLOW:流水号 SNOW_FLAKE:雪花算法,如果不配置,默认是SNOW_FLAKE
- */
- private GeneratorType generatorType = GeneratorType.SNOW_FLAKE;
}
diff --git a/web-starter/src/main/java/com/lframework/starter/web/config/properties/SecurityUploadProperties.java b/web-starter/src/main/java/com/lframework/starter/web/config/properties/SecurityUploadProperties.java
new file mode 100644
index 0000000000000000000000000000000000000000..c5b19a9861cd885a223997fc5d204e5f81f3078e
--- /dev/null
+++ b/web-starter/src/main/java/com/lframework/starter/web/config/properties/SecurityUploadProperties.java
@@ -0,0 +1,19 @@
+package com.lframework.starter.web.config.properties;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+@Data
+@ConfigurationProperties(prefix = "jugg.security-upload")
+public class SecurityUploadProperties {
+
+ /**
+ * 下载时的域名
+ */
+ private String domain;
+
+ /**
+ * 上传文件的路径
+ */
+ private String location;
+}
diff --git a/websocket-starter/src/main/java/com/lframework/starter/websocket/config/WsProperties.java b/web-starter/src/main/java/com/lframework/starter/web/config/properties/WsProperties.java
similarity index 81%
rename from websocket-starter/src/main/java/com/lframework/starter/websocket/config/WsProperties.java
rename to web-starter/src/main/java/com/lframework/starter/web/config/properties/WsProperties.java
index ef8ff2123a0ea6d583e250571aecb30b87018239..01b64ea4774b7a35fc6480611ebe61324e26e7a1 100644
--- a/websocket-starter/src/main/java/com/lframework/starter/websocket/config/WsProperties.java
+++ b/web-starter/src/main/java/com/lframework/starter/web/config/properties/WsProperties.java
@@ -1,6 +1,5 @@
-package com.lframework.starter.websocket.config;
+package com.lframework.starter.web.config.properties;
-import com.lframework.starter.web.utils.IdUtil;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/annotations/constants/EncryType.java b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/constants/EncryType.java
new file mode 100644
index 0000000000000000000000000000000000000000..85ace72b0705f1471087ce141b5ed233f78e1c89
--- /dev/null
+++ b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/constants/EncryType.java
@@ -0,0 +1,22 @@
+package com.lframework.starter.web.core.annotations.constants;
+
+public enum EncryType {
+ // 自动
+ AUTO,
+ // 密码
+ PASSWORD,
+ //中文名
+ CHINESE_NAME,
+ //身份证号
+ ID_CARD,
+ //座机号
+ FIXED_PHONE,
+ //手机号
+ MOBILE_PHONE,
+ //电子邮件
+ EMAIL,
+ //中国大陆车牌,包含普通车辆、新能源车辆
+ CAR_LICENSE,
+ //银行卡
+ BANK_CARD
+}
diff --git a/web-starter/src/main/java/com/lframework/starter/web/annotations/convert/EncryptConvert.java b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/convert/EncryptConvert.java
similarity index 78%
rename from web-starter/src/main/java/com/lframework/starter/web/annotations/convert/EncryptConvert.java
rename to web-starter/src/main/java/com/lframework/starter/web/core/annotations/convert/EncryptConvert.java
index 8c731a8e596fe880dec7596e1765a60a2505733e..d079c24b2c729aded8e41edb64e7a19c859c0d48 100644
--- a/web-starter/src/main/java/com/lframework/starter/web/annotations/convert/EncryptConvert.java
+++ b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/convert/EncryptConvert.java
@@ -1,6 +1,6 @@
-package com.lframework.starter.web.annotations.convert;
+package com.lframework.starter.web.core.annotations.convert;
-import com.lframework.starter.web.annotations.constants.EncryType;
+import com.lframework.starter.web.core.annotations.constants.EncryType;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
diff --git a/web-starter/src/main/java/com/lframework/starter/web/annotations/convert/EnumConvert.java b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/convert/EnumConvert.java
similarity index 86%
rename from web-starter/src/main/java/com/lframework/starter/web/annotations/convert/EnumConvert.java
rename to web-starter/src/main/java/com/lframework/starter/web/core/annotations/convert/EnumConvert.java
index e825fd10094f6b6144353f6163c3098e658dfdfd..ba1ec978cc5d2e6aa5463f79618240264bfbbab3 100644
--- a/web-starter/src/main/java/com/lframework/starter/web/annotations/convert/EnumConvert.java
+++ b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/convert/EnumConvert.java
@@ -1,4 +1,4 @@
-package com.lframework.starter.web.annotations.convert;
+package com.lframework.starter.web.core.annotations.convert;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
diff --git a/web-starter/src/main/java/com/lframework/starter/web/annotations/convert/IgnoreConvert.java b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/convert/IgnoreConvert.java
similarity index 85%
rename from web-starter/src/main/java/com/lframework/starter/web/annotations/convert/IgnoreConvert.java
rename to web-starter/src/main/java/com/lframework/starter/web/core/annotations/convert/IgnoreConvert.java
index 4b1e56e3393d31fb0b077355372364a58b777fbe..202befce701bafc57b512e075aa9f07f05452afa 100644
--- a/web-starter/src/main/java/com/lframework/starter/web/annotations/convert/IgnoreConvert.java
+++ b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/convert/IgnoreConvert.java
@@ -1,4 +1,4 @@
-package com.lframework.starter.web.annotations.convert;
+package com.lframework.starter.web.core.annotations.convert;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/annotations/ds/CurTenantDs.java b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/ds/CurTenantDs.java
new file mode 100644
index 0000000000000000000000000000000000000000..14df40e41d37170821fd3efe7c4a2bab9204d497
--- /dev/null
+++ b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/ds/CurTenantDs.java
@@ -0,0 +1,17 @@
+package com.lframework.starter.web.core.annotations.ds;
+
+import com.baomidou.dynamic.datasource.annotation.DS;
+import com.lframework.starter.web.core.constants.MyBatisStringPool;
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target({ElementType.TYPE, ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@DS(MyBatisStringPool.DS_KEY_CUR_TENANT)
+public @interface CurTenantDs {
+
+}
diff --git a/web-starter/src/main/java/com/lframework/starter/web/annotations/excel/ExcelRequired.java b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/excel/ExcelRequired.java
similarity index 84%
rename from web-starter/src/main/java/com/lframework/starter/web/annotations/excel/ExcelRequired.java
rename to web-starter/src/main/java/com/lframework/starter/web/core/annotations/excel/ExcelRequired.java
index 3a78104615c3f7dba6c6b977854a74a4f60667e8..4778de2a2e7167dd3ecd56bee7e08145495ad7d7 100644
--- a/web-starter/src/main/java/com/lframework/starter/web/annotations/excel/ExcelRequired.java
+++ b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/excel/ExcelRequired.java
@@ -1,4 +1,4 @@
-package com.lframework.starter.web.annotations.excel;
+package com.lframework.starter.web.core.annotations.excel;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
diff --git a/web-starter/src/main/java/com/lframework/starter/web/annotations/locker/EnableLock.java b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/locker/EnableLock.java
similarity index 91%
rename from web-starter/src/main/java/com/lframework/starter/web/annotations/locker/EnableLock.java
rename to web-starter/src/main/java/com/lframework/starter/web/core/annotations/locker/EnableLock.java
index fdddbbfb89670864f008928240ce78872f7ef26c..7e1b78e66eac16dde421df79941d23c3b87d7cb6 100644
--- a/web-starter/src/main/java/com/lframework/starter/web/annotations/locker/EnableLock.java
+++ b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/locker/EnableLock.java
@@ -1,4 +1,4 @@
-package com.lframework.starter.web.annotations.locker;
+package com.lframework.starter.web.core.annotations.locker;
import com.lframework.starter.web.config.LockAutoConfiguration;
import java.lang.annotation.Documented;
diff --git a/web-starter/src/main/java/com/lframework/starter/web/annotations/locker/LockType.java b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/locker/LockType.java
similarity index 42%
rename from web-starter/src/main/java/com/lframework/starter/web/annotations/locker/LockType.java
rename to web-starter/src/main/java/com/lframework/starter/web/core/annotations/locker/LockType.java
index cb19a654c46525774dc78750eb4db152a46674da..e8dea5de51cc59408e61ba171e2b2028934f2ef4 100644
--- a/web-starter/src/main/java/com/lframework/starter/web/annotations/locker/LockType.java
+++ b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/locker/LockType.java
@@ -1,4 +1,4 @@
-package com.lframework.starter.web.annotations.locker;
+package com.lframework.starter.web.core.annotations.locker;
public enum LockType {
DEFAULT, REDIS
diff --git a/web-starter/src/main/java/com/lframework/starter/web/annotations/OpenApi.java b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/openapi/OpenApi.java
similarity index 87%
rename from web-starter/src/main/java/com/lframework/starter/web/annotations/OpenApi.java
rename to web-starter/src/main/java/com/lframework/starter/web/core/annotations/openapi/OpenApi.java
index 37bc627505cde0bee924899bc3d70fc78ba20789..ded0cce4eef6db57dc3c118a9a261d63ea299895 100644
--- a/web-starter/src/main/java/com/lframework/starter/web/annotations/OpenApi.java
+++ b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/openapi/OpenApi.java
@@ -1,4 +1,4 @@
-package com.lframework.starter.web.annotations;
+package com.lframework.starter.web.core.annotations.openapi;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/annotations/oplog/OpLog.java b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/oplog/OpLog.java
new file mode 100644
index 0000000000000000000000000000000000000000..e60a95ca807397e057bfbca51fa3ba99e28e1cf8
--- /dev/null
+++ b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/oplog/OpLog.java
@@ -0,0 +1,54 @@
+package com.lframework.starter.web.core.annotations.oplog;
+
+import com.lframework.starter.web.core.components.oplog.OpLogType;
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 系统日志注解
+ *
+ * @author zmj
+ */
+@Target({ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface OpLog {
+
+ /**
+ * 日志类型 用于做业务区分
+ *
+ * @return
+ */
+ Class extends OpLogType> type();
+
+ /**
+ * 日志名称 需要填充参数部分用{}占位,会根据params的值进行填充
+ *
+ * @return
+ */
+ String name() default "";
+
+ /**
+ * 需要保存的参数 Spel表达式
+ *
+ * @return
+ */
+ String[] params() default {};
+
+ /**
+ * 是否循环填充日志名称 会将params中的collection循环format
+ *
+ * @return
+ */
+ boolean loopFormat() default false;
+
+ /**
+ * 是否自动保存参数
+ *
+ * @return
+ */
+ boolean autoSaveParams() default false;
+}
diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/annotations/permission/DataPermission.java b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/permission/DataPermission.java
new file mode 100644
index 0000000000000000000000000000000000000000..9755045db1a274236f32989cd30e070b035279c5
--- /dev/null
+++ b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/permission/DataPermission.java
@@ -0,0 +1,17 @@
+package com.lframework.starter.web.core.annotations.permission;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface DataPermission {
+
+ String template();
+
+ String alias();
+}
diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/annotations/permission/DataPermissionGroup.java b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/permission/DataPermissionGroup.java
new file mode 100644
index 0000000000000000000000000000000000000000..b98f582957a1f4e1914a413849dced2467097397
--- /dev/null
+++ b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/permission/DataPermissionGroup.java
@@ -0,0 +1,15 @@
+package com.lframework.starter.web.core.annotations.permission;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface DataPermissionGroup {
+
+ DataPermissions[] value();
+}
diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/annotations/permission/DataPermissions.java b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/permission/DataPermissions.java
new file mode 100644
index 0000000000000000000000000000000000000000..15e3e106e117ab811c6491038171071dfe0c7ec1
--- /dev/null
+++ b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/permission/DataPermissions.java
@@ -0,0 +1,18 @@
+package com.lframework.starter.web.core.annotations.permission;
+
+import com.lframework.starter.web.core.components.permission.SysDataPermissionDataPermissionType;
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface DataPermissions {
+
+ Class extends SysDataPermissionDataPermissionType> type();
+
+ DataPermission[] value();
+}
diff --git a/web-starter/src/main/java/com/lframework/starter/web/annotations/security/HasPermission.java b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/security/HasPermission.java
similarity index 77%
rename from web-starter/src/main/java/com/lframework/starter/web/annotations/security/HasPermission.java
rename to web-starter/src/main/java/com/lframework/starter/web/core/annotations/security/HasPermission.java
index 3b21b9f4348c95da59fc3acbc361662d237deae0..49d5ea710142bb9f91abf08b9b62ca01403d1674 100644
--- a/web-starter/src/main/java/com/lframework/starter/web/annotations/security/HasPermission.java
+++ b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/security/HasPermission.java
@@ -1,6 +1,6 @@
-package com.lframework.starter.web.annotations.security;
+package com.lframework.starter.web.core.annotations.security;
-import com.lframework.starter.web.components.security.PermissionCalcType;
+import com.lframework.starter.web.core.components.security.PermissionCalcType;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/annotations/sort/Sort.java b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/sort/Sort.java
new file mode 100644
index 0000000000000000000000000000000000000000..7f49fc2ae85b17ea0740a13495b8158d0a812573
--- /dev/null
+++ b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/sort/Sort.java
@@ -0,0 +1,36 @@
+package com.lframework.starter.web.core.annotations.sort;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface Sort {
+
+ /**
+ * 传入列名
+ *
+ * @return
+ */
+ String value();
+
+ /**
+ * SQL列名
+ *
+ * @return
+ */
+ String alias() default "";
+
+ /**
+ * 是否自动解析
+ *
+ * 如果自动解析,那么alias只需要指定表的别名即可,会直接将alias和转为下划线的value拼接作为SQL列名
+ *
+ * @return
+ */
+ boolean autoParse() default false;
+}
\ No newline at end of file
diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/annotations/sort/Sorts.java b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/sort/Sorts.java
new file mode 100644
index 0000000000000000000000000000000000000000..03a709a36ec8905ff0a53f88516170dae8b0aa59
--- /dev/null
+++ b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/sort/Sorts.java
@@ -0,0 +1,15 @@
+package com.lframework.starter.web.core.annotations.sort;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface Sorts {
+
+ Sort[] value();
+}
diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/annotations/timeline/OrderTimeLineLog.java b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/timeline/OrderTimeLineLog.java
new file mode 100644
index 0000000000000000000000000000000000000000..ce6bad2b0597f73c9d4ab7e13c06cb688e72df70
--- /dev/null
+++ b/web-starter/src/main/java/com/lframework/starter/web/core/annotations/timeline/OrderTimeLineLog.java
@@ -0,0 +1,61 @@
+package com.lframework.starter.web.core.annotations.timeline;
+
+import com.lframework.starter.web.core.components.timeline.OrderTimeLineBizType;
+import com.lframework.starter.web.inner.components.timeline.NormalOrderTimeLineBizType;
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 单据时间轴记录
+ * 如果出现嵌套那么以最外层的为准,不会进行嵌套隔离
+ * @author zmj
+ */
+@Target({ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface OrderTimeLineLog {
+
+ /**
+ * 业务类型
+ *
+ * @return
+ */
+ Class extends OrderTimeLineBizType> type() default NormalOrderTimeLineBizType.class;
+
+ /**
+ * 单据ID
+ * @return
+ */
+ String[] orderId();
+
+ /**
+ * 内容 需要填充参数部分用{}占位,会根据params的值进行填充
+ *
+ * @return
+ */
+ String name() default "";
+
+ /**
+ * 需要保存的参数 Spel表达式
+ *
+ * @return
+ */
+ String[] params() default {};
+
+ /**
+ * 是否循环填充内容 会将params中的collection循环format
+ *
+ * @return
+ */
+ boolean loopFormat() default false;
+
+ /**
+ * 是否为删除操作
+ * 如果为删除操作,那么忽略type、name、loopFormat,直接根据orderId进行删除操作
+ * @return
+ */
+ boolean delete() default false;
+}
diff --git a/web-starter/src/main/java/com/lframework/starter/web/aop/ControllerAspector.java b/web-starter/src/main/java/com/lframework/starter/web/core/aop/ControllerAspector.java
similarity index 95%
rename from web-starter/src/main/java/com/lframework/starter/web/aop/ControllerAspector.java
rename to web-starter/src/main/java/com/lframework/starter/web/core/aop/ControllerAspector.java
index db30c3e941127dc836fdd7cc72e9dab7488efc60..899a1affc0ef5fd460428d4d24d69dd67a81c319 100644
--- a/web-starter/src/main/java/com/lframework/starter/web/aop/ControllerAspector.java
+++ b/web-starter/src/main/java/com/lframework/starter/web/core/aop/ControllerAspector.java
@@ -1,8 +1,8 @@
-package com.lframework.starter.web.aop;
+package com.lframework.starter.web.core.aop;
import com.lframework.starter.common.utils.ArrayUtil;
import com.lframework.starter.common.utils.CollectionUtil;
-import com.lframework.starter.web.utils.JsonUtil;
+import com.lframework.starter.web.core.utils.JsonUtil;
import java.util.LinkedList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
@@ -13,7 +13,6 @@ import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
/**
diff --git a/web-starter/src/main/java/com/lframework/starter/web/core/aop/OpLogAspector.java b/web-starter/src/main/java/com/lframework/starter/web/core/aop/OpLogAspector.java
new file mode 100644
index 0000000000000000000000000000000000000000..36d365f2f42e7e2fc2c597cecbfb878a2131dbb1
--- /dev/null
+++ b/web-starter/src/main/java/com/lframework/starter/web/core/aop/OpLogAspector.java
@@ -0,0 +1,194 @@
+package com.lframework.starter.web.core.aop;
+
+import com.lframework.starter.common.utils.ArrayUtil;
+import com.lframework.starter.common.utils.CollectionUtil;
+import com.lframework.starter.common.utils.StringUtil;
+import com.lframework.starter.web.core.components.oplog.OpLogType;
+import com.lframework.starter.web.core.components.security.AbstractUserDetails;
+import com.lframework.starter.web.core.components.security.SecurityUtil;
+import com.lframework.starter.web.core.utils.ApplicationUtil;
+import com.lframework.starter.web.core.utils.IdUtil;
+import com.lframework.starter.web.core.utils.SpelUtil;
+import com.lframework.starter.web.core.annotations.oplog.OpLog;
+import com.lframework.starter.web.core.utils.OpLogUtil;
+import com.lframework.starter.web.inner.vo.oplogs.CreateOpLogsVo;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import lombok.extern.slf4j.Slf4j;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.springframework.expression.EvaluationContext;
+
+/**
+ * OpLog切面
+ *
+ * @author zmj
+ */
+@Slf4j
+@Aspect
+public class OpLogAspector {
+
+ @Pointcut("@annotation(com.lframework.starter.web.core.annotations.oplog.OpLog)")
+ public void opLogCutPoint() {
+
+ }
+
+ @Around(value = "opLogCutPoint()")
+ public Object opLog(ProceedingJoinPoint joinPoint) throws Throwable {
+
+ try {
+ //生成logId,多层嵌套时,隔离不同bean的数据
+ String logId = IdUtil.getUUID();
+ OpLogUtil.init(logId);
+
+ AbstractUserDetails currentUser = SecurityUtil.getCurrentUser();
+
+ Object value = joinPoint.proceed();
+
+ if (currentUser == null) {
+ currentUser = SecurityUtil.getCurrentUser();
+ }
+
+ if (currentUser != null) {
+ try {
+ //获取方法的参数名和参数值
+ MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
+ List paramNameList = Arrays.asList(methodSignature.getParameterNames());
+ List