refactor(admin): 调整项目配置移除context-path前缀

- 移除调度中心默认context-path配置 /xxl-job-admin
- 更新数据库脚本中的AI模型配置从 qwen3.5:2b 到 qwen3.5:0.8b
- 升级多项Maven依赖版本包括Spring Boot、Netty、MySQL连接器等
- 修改应用配置文件中的服务器上下文路径为根路径
- 更新测试代码中的地址URL配置
- 添加Git忽略文件配置支持前端和AI相关文件
- 更新AI聊天客户端配置以支持对话记忆功能
3.4.1-release
xuxueli 3 months ago
parent 71530beac2
commit 4259125060

19
.gitignore vendored

@ -1,7 +1,20 @@
.idea # for backend
*.iml
/.idea
**/target/
.classpath .classpath
.project .project
*.iml
target/
.DS_Store .DS_Store
.gitattributes .gitattributes
# for fontend
node_modules/
dist/
package-lock.json
# for ai
.opencode
.omo
.claude
.specify
specs

@ -881,7 +881,7 @@ The concrete contet describe as follows:
#### Step 2:Deploy: #### Step 2:Deploy:
If you has finished step 1,then you can compile the project in maven and deploy the war package to tomcat. If you has finished step 1,then you can compile the project in maven and deploy the war package to tomcat.
the url to visit is :http://localhost:8080/xxl-job-admin (this address will be used by executor and use it as callback url),the index page after login in is as follow the url to visit is :http://localhost:8080 (this address will be used by executor and use it as callback url),the index page after login in is as follow
![index page after login in](https://www.xuxueli.com/project/static/xxl-job/images/img_6yC0.png "index page after login in") ![index page after login in](https://www.xuxueli.com/project/static/xxl-job/images/img_6yC0.png "index page after login in")
@ -910,7 +910,7 @@ Relative path of the executor configuration file is as follows:
The concret content of configuration file as follows: The concret content of configuration file as follows:
### xxl-job admin address listxxl-job-admin address list: Multiple addresses are separated by commas,this address is used for "heart beat and register" and "task execution result callback" between the executor and xxl-job-admin. ### xxl-job admin address listxxl-job-admin address list: Multiple addresses are separated by commas,this address is used for "heart beat and register" and "task execution result callback" between the executor and xxl-job-admin.
xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin xxl.job.admin.addresses=http://127.0.0.1:8080
### xxl.job.executor.appname is used to group by executors ### xxl.job.executor.appname is used to group by executors
xxl.job.executor.appname=xxl-job-executor-sample xxl.job.executor.appname=xxl-job-executor-sample

@ -940,7 +940,7 @@ xxl.job.logretentiondays=30
#### 步骤二:部署项目: #### 步骤二:部署项目:
如果已经正确进行上述配置,可将项目编译打包部署。 如果已经正确进行上述配置,可将项目编译打包部署。
调度中心访问地址http://localhost:8080/xxl-job-admin (该地址执行器将会使用到,作为回调地址) 调度中心访问地址http://localhost:8080 (该地址执行器将会使用到,作为回调地址)
默认登录账号 "admin/123456", 登录后运行界面如下图所示。 默认登录账号 "admin/123456", 登录后运行界面如下图所示。
@ -1006,7 +1006,7 @@ xuxueli/xxl-job-admin:{指定版本}
``` ```
### 调度中心部署根地址 [选填]:如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册; ### 调度中心部署根地址 [选填]:如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册;
xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin xxl.job.admin.addresses=http://127.0.0.1:8080
### 调度中心通讯TOKEN [选填]:非空时启用; ### 调度中心通讯TOKEN [选填]:非空时启用;
xxl.job.admin.accessToken=default_token xxl.job.admin.accessToken=default_token
### 调度中心通讯超时时间[选填]单位秒默认3s ### 调度中心通讯超时时间[选填]单位秒默认3s
@ -1277,7 +1277,7 @@ public void demoJobHandler() throws Exception {
{ {
"input": "{输入信息,必填信息}", "input": "{输入信息,必填信息}",
"prompt": "{模型prompt可选信息}", "prompt": "{模型prompt可选信息}",
"model": "{模型实现如qwen3.5:2b可选信息}" "model": "{模型实现如qwen3.5:0.8b可选信息}"
} }
``` ```
@ -2840,8 +2840,12 @@ alter table xxl_job_log
``` ```
### 7.45 版本 v3.4.1 Release Notes[ING] ### 7.45 版本 v3.4.1 Release Notes[ING]
- 1、【TODO】调度中心OpenAPI完善提供任务管理能力封装Agent Skill并推送ClawHub - 1、【重构】项目结构AI Ready重构将业务逻辑与数据访问逻辑分离提升项目可读性与可维护性
- 2、【TODO】AccessToken升级执行器维度隔离支持线上化配置升级双端OpenApi适配AccessToken升级 - 2、【调整】消息中心移除context-path前缀配置项简化客户端配置
(存量客户端升级需要注意:升级后需要将配置项 "xxl.job.admin.addresses" 中的 context-path 前缀移除)
- 3、【升级】升级多项maven依赖至较新版本如 spring、netty 等;
- 4、【TODO】调度中心OpenAPI完善提供任务管理能力封装Agent Skill并推送ClawHub
- 5、【TODO】AccessToken升级执行器维度隔离支持线上化配置升级双端OpenApi适配AccessToken升级
### TODO LIST ### TODO LIST

@ -161,7 +161,7 @@ VALUES (1, 1, '示例任务01', now(), now(), 'XXL', '', 'CRON', '0 0 0 * * ? *'
'DO_NOTHING', 'FIRST', 'ollamaJobHandler', '{ 'DO_NOTHING', 'FIRST', 'ollamaJobHandler', '{
"input": "Java实现二叉树层序遍历", "input": "Java实现二叉树层序遍历",
"prompt": "你是一个研发工程师,擅长解决技术类问题。", "prompt": "你是一个研发工程师,擅长解决技术类问题。",
"model": "qwen3.5:2b" "model": "qwen3.5:0.8b"
}', 'SERIAL_EXECUTION', 0, 0, 'BEAN', '', 'GLUE', }', 'SERIAL_EXECUTION', 0, 0, 'BEAN', '', 'GLUE',
now(), ''), now(), ''),
(3, 2, 'Dify示例任务', now(), now(), 'XXL', '', 'NONE', '', (3, 2, 'Dify示例任务', now(), now(), 'XXL', '', 'NONE', '',

@ -2,7 +2,7 @@
# xxl-job, admin # xxl-job, admin
XXL_JOB_ADMIN_PORT=8080 XXL_JOB_ADMIN_PORT=8080
XXL_JOB_ADMIN_CONTEXT_PATH=/xxl-job-admin XXL_JOB_ADMIN_CONTEXT_PATH=/
# xxl-job, database # xxl-job, database
MYSQL_ROOT_PASSWORD=root_pwd MYSQL_ROOT_PASSWORD=root_pwd

@ -31,35 +31,35 @@
<maven-gpg-plugin.version>3.2.8</maven-gpg-plugin.version> <maven-gpg-plugin.version>3.2.8</maven-gpg-plugin.version>
<central-publishing-maven-plugin.version>0.10.0</central-publishing-maven-plugin.version> <central-publishing-maven-plugin.version>0.10.0</central-publishing-maven-plugin.version>
<!-- base --> <!-- base -->
<slf4j-api.version>2.0.17</slf4j-api.version> <slf4j-api.version>2.0.18</slf4j-api.version>
<junit-jupiter.version>6.0.3</junit-jupiter.version> <junit-jupiter.version>6.1.0</junit-jupiter.version>
<!-- jakarta.annotation-api --> <!-- jakarta.annotation-api -->
<jakarta.annotation-api.version>3.0.0</jakarta.annotation-api.version> <jakarta.annotation-api.version>3.0.0</jakarta.annotation-api.version>
<!-- spring --> <!-- spring -->
<spring-boot.version>4.0.5</spring-boot.version> <spring-boot.version>4.0.6</spring-boot.version>
<spring.version>7.0.6</spring.version> <spring.version>7.0.7</spring.version>
<!-- mybatis & db --> <!-- mybatis & db -->
<mybatis-spring-boot-starter.version>4.0.1</mybatis-spring-boot-starter.version> <mybatis-spring-boot-starter.version>4.0.1</mybatis-spring-boot-starter.version>
<mysql-connector-j.version>9.6.0</mysql-connector-j.version> <mysql-connector-j.version>9.7.0</mysql-connector-j.version>
<!-- net --> <!-- net -->
<netty.version>4.2.12.Final</netty.version> <netty.version>4.2.15.Final</netty.version>
<!-- groovy --> <!-- groovy -->
<groovy.version>5.0.5</groovy.version> <groovy.version>5.0.6</groovy.version>
<!-- xxl-sso --> <!-- xxl-sso -->
<xxl-sso.version>2.4.0</xxl-sso.version> <xxl-sso.version>2.4.0</xxl-sso.version>
<!-- xxl-tool --> <!-- xxl-tool -->
<xxl-tool.version>2.5.0</xxl-tool.version> <xxl-tool.version>2.5.0</xxl-tool.version>
<!-- gson --> <!-- gson -->
<gson.version>2.13.2</gson.version> <gson.version>2.14.0</gson.version>
<!-- spring-ai --> <!-- spring-ai -->
<spring-ai.version>2.0.0-M4</spring-ai.version> <spring-ai.version>2.0.0-M8</spring-ai.version>
<!-- dify --> <!-- dify -->
<dify-java-client.version>1.2.5</dify-java-client.version> <dify-java-client.version>1.2.7</dify-java-client.version>
</properties> </properties>
<dependencyManagement> <dependencyManagement>

@ -1,9 +1,13 @@
### web ### web
server.port=8080 server.port=8080
server.servlet.context-path=/xxl-job-admin server.servlet.context-path=/
### actuator ### web config: actuator、error page、controller-format
management.endpoints.web.base-path=/actuator management.server.base-path=/actuator
spring.web.error.whitelabel.enabled=false
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
### mail health
management.health.mail.enabled=false management.health.mail.enabled=false
### resources ### resources
@ -20,7 +24,7 @@ spring.freemarker.settings.number_format=0.##########
spring.freemarker.settings.new_builtin_class_resolver=safer spring.freemarker.settings.new_builtin_class_resolver=safer
### mybatis ### mybatis
mybatis.mapper-locations=classpath:/mapper/*Mapper.xml mybatis.mapper-locations=classpath:/mapper/**/*Mapper.xml
### datasource-pool ### datasource-pool
spring.datasource.type=com.zaxxer.hikari.HikariDataSource spring.datasource.type=com.zaxxer.hikari.HikariDataSource

@ -25,7 +25,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
public class AdminBizTest { public class AdminBizTest {
private static final Logger logger = LoggerFactory.getLogger(AdminBizTest.class); private static final Logger logger = LoggerFactory.getLogger(AdminBizTest.class);
private static String addressUrl = "http://127.0.0.1:8080/xxl-job-admin"; private static String addressUrl = "http://127.0.0.1:8080";
private static String accessToken = "default_token"; private static String accessToken = "default_token";
private AdminBiz buildClient(){ private AdminBiz buildClient(){

@ -1,5 +1,5 @@
### xxl-job admin address list, such as "http://address" or "http://address01,http://address02" ### xxl-job admin address list, such as "http://address" or "http://address01,http://address02"
xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin xxl.job.admin.addresses=http://127.0.0.1:8080
### xxl-job access token ### xxl-job access token
xxl.job.admin.accessToken=default_token xxl.job.admin.accessToken=default_token
### xxl-job timeout by second, default 3s ### xxl-job timeout by second, default 3s

@ -16,6 +16,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor; import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor; import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.memory.MessageWindowChatMemory; import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.ollama.OllamaChatModel; import org.springframework.ai.ollama.OllamaChatModel;
import org.springframework.ai.ollama.api.OllamaChatOptions; import org.springframework.ai.ollama.api.OllamaChatOptions;
@ -50,7 +51,7 @@ public class IndexController {
@Resource @Resource
private OllamaChatModel ollamaChatModel; private OllamaChatModel ollamaChatModel;
private String prompt = "你好,你是一个研发工程师,擅长解决技术类问题。"; private String prompt = "你好,你是一个研发工程师,擅长解决技术类问题。";
private String modle = "qwen3.5:2b"; private String modle = "qwen3.5:0.8b";
/** /**
* ChatClient * ChatClient
@ -64,12 +65,13 @@ public class IndexController {
.builder(ollamaChatModel) .builder(ollamaChatModel)
.defaultAdvisors(MessageChatMemoryAdvisor.builder(MessageWindowChatMemory.builder().build()).build()) // add memory .defaultAdvisors(MessageChatMemoryAdvisor.builder(MessageWindowChatMemory.builder().build()).build()) // add memory
.defaultAdvisors(SimpleLoggerAdvisor.builder().build()) // add logger .defaultAdvisors(SimpleLoggerAdvisor.builder().build()) // add logger
.defaultOptions(OllamaChatOptions.builder().model(modle).build()) // assign model .defaultOptions(OllamaChatOptions.builder().model(modle)) // assign model
.build(); .build();
// call ollama // call ollama
String response = ollamaChatClient String response = ollamaChatClient
.prompt(prompt) .prompt(prompt)
.advisors(a -> a.param(ChatMemory.CONVERSATION_ID, "conversationId-default"))
.user(input) .user(input)
.call() .call()
.content(); .content();
@ -90,12 +92,13 @@ public class IndexController {
.builder(ollamaChatModel) .builder(ollamaChatModel)
.defaultAdvisors(MessageChatMemoryAdvisor.builder(MessageWindowChatMemory.builder().build()).build()) .defaultAdvisors(MessageChatMemoryAdvisor.builder(MessageWindowChatMemory.builder().build()).build())
.defaultAdvisors(SimpleLoggerAdvisor.builder().build()) .defaultAdvisors(SimpleLoggerAdvisor.builder().build())
.defaultOptions(OllamaChatOptions.builder().model(modle).build()) .defaultOptions(OllamaChatOptions.builder().model(modle))
.build(); .build();
// call ollama // call ollama
return ollamaChatClient return ollamaChatClient
.prompt(prompt) .prompt(prompt)
.advisors(a -> a.param(ChatMemory.CONVERSATION_ID, "conversationId-default"))
.user(input) .user(input)
.stream() .stream()
.content(); .content();

@ -12,6 +12,7 @@ import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor; import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor; import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.memory.MessageWindowChatMemory; import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.ollama.OllamaChatModel; import org.springframework.ai.ollama.OllamaChatModel;
import org.springframework.ai.ollama.api.OllamaChatOptions; import org.springframework.ai.ollama.api.OllamaChatOptions;
@ -73,7 +74,7 @@ public class AIXxlJob {
return; return;
} }
if (ollamaParam.getModel()==null || ollamaParam.getModel().isBlank()) { if (ollamaParam.getModel()==null || ollamaParam.getModel().isBlank()) {
ollamaParam.setModel("qwen3.5:2b"); ollamaParam.setModel("qwen3.5:0.8b");
} }
} catch (Exception e) { } catch (Exception e) {
XxlJobHelper.log(new RuntimeException("OllamaParam parse error", e)); XxlJobHelper.log(new RuntimeException("OllamaParam parse error", e));
@ -89,12 +90,13 @@ public class AIXxlJob {
.builder(ollamaChatModel) .builder(ollamaChatModel)
.defaultAdvisors(MessageChatMemoryAdvisor.builder(MessageWindowChatMemory.builder().build()).build()) .defaultAdvisors(MessageChatMemoryAdvisor.builder(MessageWindowChatMemory.builder().build()).build())
.defaultAdvisors(SimpleLoggerAdvisor.builder().build()) .defaultAdvisors(SimpleLoggerAdvisor.builder().build())
.defaultOptions(OllamaChatOptions.builder().model(ollamaParam.getModel()).build()) .defaultOptions(OllamaChatOptions.builder().model(ollamaParam.getModel()))
.build(); .build();
// call ollama // call ollama
String response = ollamaChatClient String response = ollamaChatClient
.prompt(ollamaParam.getPrompt()) .prompt(ollamaParam.getPrompt())
.advisors(a -> a.param(ChatMemory.CONVERSATION_ID, "conversationId-default"))
.user(ollamaParam.getInput()) .user(ollamaParam.getInput())
.call() .call()
.content(); .content();
@ -312,6 +314,7 @@ public class AIXxlJob {
// call opencalw // call opencalw
String response = openclawChatClient String response = openclawChatClient
.prompt(openClawParam.getPrompt()) .prompt(openClawParam.getPrompt())
.advisors(a -> a.param(ChatMemory.CONVERSATION_ID, "conversationId-default"))
.user(openClawParam.getInput()) .user(openClawParam.getInput())
.call() .call()
.content(); .content();

@ -10,7 +10,7 @@ logging.config=classpath:logback.xml
### xxl-job admin address list, such as "http://address" or "http://address01,http://address02" ### xxl-job admin address list, such as "http://address" or "http://address01,http://address02"
xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin xxl.job.admin.addresses=http://127.0.0.1:8080
### xxl-job access token ### xxl-job access token
xxl.job.admin.accessToken=default_token xxl.job.admin.accessToken=default_token
### xxl-job timeout by second, default 3s ### xxl-job timeout by second, default 3s

@ -8,6 +8,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor; import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor; import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.memory.MessageWindowChatMemory; import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.ollama.OllamaChatModel; import org.springframework.ai.ollama.OllamaChatModel;
import org.springframework.ai.ollama.api.OllamaChatOptions; import org.springframework.ai.ollama.api.OllamaChatOptions;
@ -32,7 +33,7 @@ public class OllamaTest {
@Test @Test
public void chatTest() { public void chatTest() {
String model = "qwen3.5:2b"; String model = "qwen3.5:0.8b";
String prompt = "你是一个研发工程师,擅长解决技术类问题。"; String prompt = "你是一个研发工程师,擅长解决技术类问题。";
String input = "Java实现二叉树层序遍历"; String input = "Java实现二叉树层序遍历";
@ -42,12 +43,13 @@ public class OllamaTest {
.builder(ollamaChatModel) .builder(ollamaChatModel)
.defaultAdvisors(MessageChatMemoryAdvisor.builder(MessageWindowChatMemory.builder().build()).build()) .defaultAdvisors(MessageChatMemoryAdvisor.builder(MessageWindowChatMemory.builder().build()).build())
.defaultAdvisors(SimpleLoggerAdvisor.builder().build()) .defaultAdvisors(SimpleLoggerAdvisor.builder().build())
.defaultOptions(OllamaChatOptions.builder().model(model).build()) .defaultOptions(OllamaChatOptions.builder().model(model))
.build(); .build();
// call ollama // call ollama
String response = ollamaChatClient String response = ollamaChatClient
.prompt(prompt) .prompt(prompt)
.advisors(a -> a.param(ChatMemory.CONVERSATION_ID, "conversationId-default"))
.user(input) .user(input)
.call() .call()
.content(); .content();
@ -59,7 +61,7 @@ public class OllamaTest {
@Test @Test
public void chatStreamTest() throws InterruptedException { public void chatStreamTest() throws InterruptedException {
String model = "qwen3.5:2b"; String model = "qwen3.5:0.8b";
String prompt = "你是一个研发工程师,擅长解决技术类问题。"; String prompt = "你是一个研发工程师,擅长解决技术类问题。";
String input = "Java实现二叉树层序遍历"; String input = "Java实现二叉树层序遍历";
@ -69,13 +71,14 @@ public class OllamaTest {
.builder(ollamaChatModel) .builder(ollamaChatModel)
.defaultAdvisors(MessageChatMemoryAdvisor.builder(MessageWindowChatMemory.builder().build()).build()) .defaultAdvisors(MessageChatMemoryAdvisor.builder(MessageWindowChatMemory.builder().build()).build())
.defaultAdvisors(SimpleLoggerAdvisor.builder().build()) .defaultAdvisors(SimpleLoggerAdvisor.builder().build())
.defaultOptions(OllamaChatOptions.builder().model(model).build()) .defaultOptions(OllamaChatOptions.builder().model(model))
.build(); .build();
// call ollama // call ollama
logger.info("input: {}", input); logger.info("input: {}", input);
Flux<String> flux = ollamaChatClient Flux<String> flux = ollamaChatClient
.prompt(prompt) .prompt(prompt)
.advisors(a -> a.param(ChatMemory.CONVERSATION_ID, "conversationId-default"))
.user(input) .user(input)
.stream() .stream()
.content(); .content();

@ -7,6 +7,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor; import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor; import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.memory.MessageWindowChatMemory; import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.openai.OpenAiChatModel; import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;

@ -8,7 +8,7 @@ logging.config=classpath:logback.xml
### xxl-job admin address list, such as "http://address" or "http://address01,http://address02" ### xxl-job admin address list, such as "http://address" or "http://address01,http://address02"
xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin xxl.job.admin.addresses=http://127.0.0.1:8080
### xxl-job access token ### xxl-job access token
xxl.job.admin.accessToken=default_token xxl.job.admin.accessToken=default_token
### xxl-job timeout by second, default 3s ### xxl-job timeout by second, default 3s

Loading…
Cancel
Save