Merge remote-tracking branch 'base-version/main' into dev

# Conflicts:
#	zt-framework/zt-spring-boot-starter-job/src/main/java/com/zt/plat/framework/quartz/config/ZtXxlJobAutoConfiguration.java
This commit is contained in:
chenbowen
2025-09-25 12:06:26 +08:00
9 changed files with 536 additions and 2 deletions

View File

@@ -44,6 +44,10 @@
<groupId>jakarta.validation</groupId> <groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId> <artifactId>jakarta.validation-api</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.zt.plat</groupId>
<artifactId>zt-spring-boot-starter-security</artifactId>
</dependency>
</dependencies> </dependencies>

View File

@@ -35,6 +35,11 @@ public class XxlJobProperties {
@NotNull(message = "执行器配置不能为空") @NotNull(message = "执行器配置不能为空")
private ExecutorProperties executor; private ExecutorProperties executor;
/**
* 系统用户配置
*/
private SystemUserProperties systemUser = new SystemUserProperties();
/** /**
* XXL-Job 调度器配置类 * XXL-Job 调度器配置类
*/ */
@@ -96,4 +101,37 @@ public class XxlJobProperties {
} }
/**
* XXL-Job 系统用户配置类
*/
@Data
public static class SystemUserProperties {
/**
* 系统用户 ID
*/
private Long userId = 0L;
/**
* 系统用户昵称
*/
private String nickname = "job";
/**
* 系统租户 ID
*/
private Long tenantId = 1L;
/**
* 系统公司 ID可选
*/
private Long companyId;
/**
* 系统部门 ID可选
*/
private Long deptId;
}
} }

View File

@@ -1,5 +1,6 @@
package com.zt.plat.framework.quartz.config; package com.zt.plat.framework.quartz.config;
import com.zt.plat.framework.quartz.core.handler.XxlJobSystemAuthenticationAspect;
import com.xxl.job.core.executor.XxlJobExecutor; import com.xxl.job.core.executor.XxlJobExecutor;
import com.xxl.job.core.executor.impl.XxlJobSpringExecutor; import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -9,6 +10,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.EnableScheduling;
/** /**
@@ -21,6 +23,7 @@ import org.springframework.scheduling.annotation.EnableScheduling;
@ConditionalOnProperty(prefix = "xxl.job", name = "enabled", havingValue = "true", matchIfMissing = true) @ConditionalOnProperty(prefix = "xxl.job", name = "enabled", havingValue = "true", matchIfMissing = true)
@EnableConfigurationProperties({XxlJobProperties.class}) @EnableConfigurationProperties({XxlJobProperties.class})
@EnableScheduling // 开启 Spring 自带的定时任务 @EnableScheduling // 开启 Spring 自带的定时任务
@EnableAspectJAutoProxy // 开启 AOP
@Slf4j @Slf4j
public class ZtXxlJobAutoConfiguration { public class ZtXxlJobAutoConfiguration {
@@ -43,4 +46,17 @@ public class ZtXxlJobAutoConfiguration {
return xxlJobExecutor; return xxlJobExecutor;
} }
/**
* 配置 XXL-Job 系统认证切面
*
* 为 @XxlJob 注解的方法提供系统用户认证上下文
*/
@Bean
@ConditionalOnMissingBean
public XxlJobSystemAuthenticationAspect xxlJobSystemAuthenticationAspect(XxlJobProperties properties) {
log.info("[ZtXxlJobAutoConfiguration][注册 XXL-Job 系统认证切面] systemUserId=[{}], systemTenantId=[{}]",
properties.getSystemUser().getUserId(), properties.getSystemUser().getTenantId());
return new XxlJobSystemAuthenticationAspect(properties.getSystemUser());
}
} }

View File

@@ -47,7 +47,7 @@ public class DefaultDBFieldHandler implements MetaObjectHandler {
baseDO.setUpdateTime(current); baseDO.setUpdateTime(current);
} }
Long userId = WebFrameworkUtils.getLoginUserId(); Long userId = getUserId();
String userNickname = SecurityFrameworkUtils.getLoginUserNickname(); String userNickname = SecurityFrameworkUtils.getLoginUserNickname();
// 当前登录用户不为空,创建人为空,则当前登录用户为创建人 // 当前登录用户不为空,创建人为空,则当前登录用户为创建人
if (Objects.nonNull(userId) && Objects.isNull(baseDO.getCreator())) { if (Objects.nonNull(userId) && Objects.isNull(baseDO.getCreator())) {
@@ -81,7 +81,7 @@ public class DefaultDBFieldHandler implements MetaObjectHandler {
// 当前登录用户不为空,更新人为空,则当前登录用户为更新人 // 当前登录用户不为空,更新人为空,则当前登录用户为更新人
Object modifier = getFieldValByName("updater", metaObject); Object modifier = getFieldValByName("updater", metaObject);
Long userId = WebFrameworkUtils.getLoginUserId(); Long userId = getUserId();
String userNickname = SecurityFrameworkUtils.getLoginUserNickname(); String userNickname = SecurityFrameworkUtils.getLoginUserNickname();
if (Objects.nonNull(userId) && Objects.isNull(modifier)) { if (Objects.nonNull(userId) && Objects.isNull(modifier)) {
setFieldValByName("updater", userId.toString(), metaObject); setFieldValByName("updater", userId.toString(), metaObject);
@@ -96,6 +96,15 @@ public class DefaultDBFieldHandler implements MetaObjectHandler {
} }
} }
private static Long getUserId() {
Long userId = WebFrameworkUtils.getLoginUserId();
if (userId == null) {
// 如果不是 http 请求发起的操作,获取不到用户,从认证中获取
userId = SecurityFrameworkUtils.getLoginUserId();
}
return userId;
}
private void autoFillUserNames(BusinessBaseDO businessBaseDO) { private void autoFillUserNames(BusinessBaseDO businessBaseDO) {
String userNickname = SecurityFrameworkUtils.getLoginUserNickname(); String userNickname = SecurityFrameworkUtils.getLoginUserNickname();
if (Objects.nonNull(userNickname)) { if (Objects.nonNull(userNickname)) {

View File

@@ -88,6 +88,7 @@ public class ZtWebAutoConfiguration implements WebMvcConfigurer {
config.addAllowedOriginPattern("*"); // 设置访问源地址 config.addAllowedOriginPattern("*"); // 设置访问源地址
config.addAllowedHeader("*"); // 设置访问源请求头 config.addAllowedHeader("*"); // 设置访问源请求头
config.addAllowedMethod("*"); // 设置访问源请求方法 config.addAllowedMethod("*"); // 设置访问源请求方法
config.addExposedHeader("content-disposition"); // 暴露 content-disposition 头,用于文件下载
// 创建 UrlBasedCorsConfigurationSource 对象 // 创建 UrlBasedCorsConfigurationSource 对象
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config); // 对接口配置跨域设置 source.registerCorsConfiguration("/**", config); // 对接口配置跨域设置

View File

@@ -37,6 +37,7 @@ public class CorsFilter implements WebFilter {
headers.add("Access-Control-Allow-Origin", ALL); headers.add("Access-Control-Allow-Origin", ALL);
headers.add("Access-Control-Allow-Methods", ALL); headers.add("Access-Control-Allow-Methods", ALL);
headers.add("Access-Control-Allow-Headers", ALL); headers.add("Access-Control-Allow-Headers", ALL);
headers.add("Access-Control-Expose-Headers", "content-disposition"); // 暴露 content-disposition 头,用于文件下载
headers.add("Access-Control-Max-Age", MAX_AGE); headers.add("Access-Control-Max-Age", MAX_AGE);
if (request.getMethod() == HttpMethod.OPTIONS) { if (request.getMethod() == HttpMethod.OPTIONS) {
response.setStatusCode(HttpStatus.OK); response.setStatusCode(HttpStatus.OK);