Compare commits
4 Commits
master
...
master-jdk
Author | SHA1 | Date | |
---|---|---|---|
![]() |
7295b6a10d | ||
![]() |
7722162bf3 | ||
![]() |
42634c0e3f | ||
![]() |
634ef9b5a8 |
@ -1,51 +0,0 @@
|
||||
kind: pipeline # 定义对象类型,还有secret和signature两种类型
|
||||
|
||||
type: docker # 定义流水线类型,还有kubernetes、exec、ssh等类型
|
||||
|
||||
name: ludu-base-drone # 定义流水线名称
|
||||
|
||||
clone:
|
||||
disable: true
|
||||
|
||||
steps: # 定义流水线执行步骤,这些步骤将顺序执行
|
||||
|
||||
- name: base-build
|
||||
|
||||
image: appleboy/drone-ssh # SSH工具镜像
|
||||
|
||||
settings:
|
||||
|
||||
host: 121.36.203.133 # 远程连接地址
|
||||
|
||||
username: root # 远程连接账号
|
||||
|
||||
password:
|
||||
|
||||
from_secret: ssh_password3 # 从Secret中读取SSH密码
|
||||
|
||||
port: 22 # 远程连接端口
|
||||
|
||||
command_timeout: 20m # 远程执行命令超时时间
|
||||
|
||||
script:
|
||||
- cd /root/ludu-cloud
|
||||
- git fetch origin
|
||||
- git reset --hard origin/master
|
||||
- git clean -fd
|
||||
- /root/apache-maven-3.9.4/bin/mvn package -Dmaven.test.skip=true
|
||||
|
||||
- cd /root/ludu-cloud/yudao-gateway
|
||||
- chmod +x run.sh
|
||||
- ./run.sh || echo "gateway build failed"
|
||||
|
||||
- cd /root/ludu-cloud/yudao-module-system/yudao-module-system-biz
|
||||
- chmod +x run.sh
|
||||
- ./run.sh || echo "system build failed"
|
||||
|
||||
- cd /root/ludu-cloud/yudao-module-infra/yudao-module-infra-biz
|
||||
- chmod +x run.sh
|
||||
- ./run.sh || echo "infra build failed"
|
||||
|
||||
- cd /root/ludu-cloud/ludu-job-admin/ludu-job-admin-biz
|
||||
- chmod +x run.sh
|
||||
- ./run.sh || echo "job build failed"
|
@ -1,38 +0,0 @@
|
||||
kind: pipeline # 定义对象类型,还有secret和signature两种类型
|
||||
|
||||
type: docker # 定义流水线类型,还有kubernetes、exec、ssh等类型
|
||||
|
||||
name: ludu-datacenter-drone # 定义流水线名称
|
||||
|
||||
clone:
|
||||
disable: true
|
||||
|
||||
steps: # 定义流水线执行步骤,这些步骤将顺序执行
|
||||
|
||||
- name: build-new-service
|
||||
|
||||
image: appleboy/drone-ssh # SSH工具镜像
|
||||
|
||||
settings:
|
||||
|
||||
host: 121.36.203.133 # 远程连接地址
|
||||
|
||||
username: root # 远程连接账号
|
||||
|
||||
password:
|
||||
|
||||
from_secret: ssh_password3 # 从Secret中读取SSH密码
|
||||
|
||||
port: 22 # 远程连接端口
|
||||
|
||||
command_timeout: 10m # 远程执行命令超时时间
|
||||
|
||||
script: |
|
||||
cd /root/ludu-cloud
|
||||
git fetch origin
|
||||
git reset --hard origin/master
|
||||
git clean -fd
|
||||
/root/apache-maven-3.9.4/bin/mvn package -Dmaven.test.skip=true
|
||||
cd ludu-module-datacenter/ludu-module-datacenter-biz/
|
||||
chmod +x run.sh
|
||||
./run.sh || echo "ludu-module-datacenter build failed"
|
@ -1,39 +0,0 @@
|
||||
kind: pipeline # 定义对象类型,还有secret和signature两种类型
|
||||
|
||||
type: docker # 定义流水线类型,还有kubernetes、exec、ssh等类型
|
||||
|
||||
name: ludu-gateway-drone # 定义流水线名称
|
||||
|
||||
clone:
|
||||
disable: true
|
||||
|
||||
steps: # 定义流水线执行步骤,这些步骤将顺序执行
|
||||
|
||||
- name: gateway-build
|
||||
|
||||
image: appleboy/drone-ssh # SSH工具镜像
|
||||
|
||||
settings:
|
||||
|
||||
host: 121.36.203.133 # 远程连接地址
|
||||
|
||||
username: root # 远程连接账号
|
||||
|
||||
password:
|
||||
|
||||
from_secret: ssh_password3 # 从Secret中读取SSH密码
|
||||
|
||||
port: 22 # 远程连接端口
|
||||
|
||||
command_timeout: 20m # 远程执行命令超时时间
|
||||
|
||||
script:
|
||||
- cd /root/ludu-cloud
|
||||
- git fetch origin
|
||||
- git reset --hard origin/master
|
||||
- git clean -fd
|
||||
- /root/apache-maven-3.9.4/bin/mvn package -Dmaven.test.skip=true
|
||||
|
||||
- cd /root/ludu-cloud/yudao-gateway
|
||||
- chmod +x run.sh
|
||||
- ./run.sh || echo "gateway build failed"
|
@ -1,46 +0,0 @@
|
||||
kind: pipeline # 定义对象类型,还有secret和signature两种类型
|
||||
|
||||
type: docker # 定义流水线类型,还有kubernetes、exec、ssh等类型
|
||||
|
||||
name: ludu-hiking-drone # 定义流水线名称
|
||||
|
||||
clone:
|
||||
disable: true
|
||||
|
||||
steps: # 定义流水线执行步骤,这些步骤将顺序执行
|
||||
|
||||
- name: hiking-build
|
||||
|
||||
image: appleboy/drone-ssh # SSH工具镜像
|
||||
|
||||
settings:
|
||||
|
||||
host: 121.36.203.133 # 远程连接地址
|
||||
|
||||
username: root # 远程连接账号
|
||||
|
||||
password:
|
||||
|
||||
from_secret: ssh_password3 # 从Secret中读取SSH密码
|
||||
|
||||
port: 22 # 远程连接端口
|
||||
|
||||
command_timeout: 20m # 远程执行命令超时时间
|
||||
|
||||
script:
|
||||
- cd /root/ludu-cloud
|
||||
- git fetch origin
|
||||
- git reset --hard origin/master
|
||||
- git clean -fd
|
||||
- docker rm -f ludu-module-hiking
|
||||
- docker rm -f ludu-module-datacenter
|
||||
|
||||
- /root/apache-maven-3.9.4/bin/mvn package -Dmaven.test.skip=true
|
||||
|
||||
- cd /root/ludu-cloud/ludu-module-hiking/ludu-module-hiking-biz
|
||||
- chmod +x run.sh
|
||||
- ./run.sh || echo "hiking build failed"
|
||||
|
||||
- cd /root/ludu-cloud/ludu-module-datacenter/ludu-module-datacenter-biz/
|
||||
- chmod +x run.sh
|
||||
- ./run.sh || echo "ludu-module-datacenter build failed"
|
@ -1,41 +0,0 @@
|
||||
kind: pipeline # 定义对象类型,还有secret和signature两种类型
|
||||
|
||||
type: docker # 定义流水线类型,还有kubernetes、exec、ssh等类型
|
||||
|
||||
name: ludu-hiking-drone # 定义流水线名称
|
||||
|
||||
clone:
|
||||
disable: true
|
||||
|
||||
steps: # 定义流水线执行步骤,这些步骤将顺序执行
|
||||
|
||||
- name: hiking-build
|
||||
|
||||
image: appleboy/drone-ssh # SSH工具镜像
|
||||
|
||||
settings:
|
||||
|
||||
host: 121.36.203.133 # 远程连接地址
|
||||
|
||||
username: root # 远程连接账号
|
||||
|
||||
password:
|
||||
|
||||
from_secret: ssh_password3 # 从Secret中读取SSH密码
|
||||
|
||||
port: 22 # 远程连接端口
|
||||
|
||||
command_timeout: 20m # 远程执行命令超时时间
|
||||
|
||||
script:
|
||||
- cd /root/ludu-cloud
|
||||
- git fetch origin
|
||||
- git reset --hard origin/master
|
||||
- git clean -fd
|
||||
- docker rm -f ludu-module-hiking
|
||||
|
||||
- /root/apache-maven-3.9.4/bin/mvn package -Dmaven.test.skip=true
|
||||
|
||||
- cd /root/ludu-cloud/ludu-module-hiking/ludu-module-hiking-biz
|
||||
- chmod +x run.sh
|
||||
- ./run.sh || echo "hiking build failed"
|
@ -1,155 +0,0 @@
|
||||
kind: pipeline # 定义对象类型,还有secret和signature两种类型
|
||||
|
||||
type: docker # 定义流水线类型,还有kubernetes、exec、ssh等类型
|
||||
|
||||
name: ludu-drone-images # 定义流水线名称
|
||||
|
||||
|
||||
steps: # 定义流水线执行步骤,这些步骤将顺序执行
|
||||
- name: package # 流水线名称
|
||||
|
||||
image: maven:3-jdk-8 # 定义创建容器的Docker镜像
|
||||
|
||||
volumes: # 将容器内目录挂载到宿主机,仓库需要开启Trusted设置
|
||||
|
||||
- name: maven-cache
|
||||
|
||||
path: /root/.m2 # 将maven下载依赖的目录挂载出来,防止重复下载
|
||||
|
||||
- name: maven-build
|
||||
|
||||
path: /app/build # 将应用打包好的Jar和执行脚本挂载出来
|
||||
|
||||
commands: # 定义在Docker容器中执行的shell命令
|
||||
- mvn package -Dmaven.test.skip=true # 应用打包命令
|
||||
- |
|
||||
if [ "${service}" = "gateway" ] || [ "${service}" = "all" ]; then
|
||||
mkdir -p /app/build/yudao-gateway/target
|
||||
cp ./yudao-gateway/target/yudao-gateway.jar /app/build/yudao-gateway/target/
|
||||
cp ./yudao-gateway/Dockerfile /app/build/yudao-gateway/
|
||||
cp ./yudao-gateway/run.sh /app/build/yudao-gateway/
|
||||
fi
|
||||
if [ "${service}" = "system" ] || [ "${service}" = "all" ]; then
|
||||
mkdir -p /app/build/yudao-module-system/target
|
||||
cp ./yudao-module-system/yudao-module-system-biz/target/yudao-module-system-biz.jar /app/build/yudao-module-system/target/
|
||||
cp ./yudao-module-system/yudao-module-system-biz/Dockerfile /app/build/yudao-module-system/
|
||||
cp ./yudao-module-system/yudao-module-system-biz/run.sh /app/build/yudao-module-system/
|
||||
fi
|
||||
if [ "${service}" = "infra" ] || [ "${service}" = "all" ]; then
|
||||
mkdir -p /app/build/yudao-module-infra/target
|
||||
cp ./yudao-module-infra/yudao-module-infra-biz/target/yudao-module-infra-biz.jar /app/build/yudao-module-infra/target/
|
||||
cp ./yudao-module-infra/yudao-module-infra-biz/Dockerfile /app/build/yudao-module-infra/
|
||||
cp ./yudao-module-infra/yudao-module-infra-biz/run.sh /app/build/yudao-module-infra/
|
||||
fi
|
||||
if [ "${service}" = "job" ] || [ "${service}" = "all" ]; then
|
||||
mkdir -p /app/build/ludu-job-admin/target
|
||||
cp ./ludu-job-admin/ludu-job-admin-biz/target/ludu-job-admin-biz.jar /app/build/ludu-job-admin/target/
|
||||
cp ./ludu-job-admin/ludu-job-admin-biz/Dockerfile /app/build/ludu-job-admin/
|
||||
cp ./ludu-job-admin/ludu-job-admin-biz/run.sh /app/build/ludu-job-admin/
|
||||
fi
|
||||
if [ "${service}" = "ticketing" ] || [ "${service}" = "all" ]; then
|
||||
mkdir -p /app/build/ludu-module-ticketing/target
|
||||
cp ./ludu-module-ticketing/ludu-module-ticketing-biz/target/ludu-module-ticketing-biz.jar /app/build/ludu-module-ticketing/target/
|
||||
cp ./ludu-module-ticketing/ludu-module-ticketing-biz/Dockerfile /app/build/ludu-module-ticketing/
|
||||
cp ./ludu-module-ticketing/ludu-module-ticketing-biz/run.sh /app/build/ludu-module-ticketing/
|
||||
fi
|
||||
if [ "${service}" = "parking" ] || [ "${service}" = "all" ]; then
|
||||
mkdir -p /app/build/ludu-module-parking/target
|
||||
cp ./ludu-module-parking/ludu-module-parking-biz/target/ludu-module-parking-biz.jar /app/build/ludu-module-parking/target/
|
||||
cp ./ludu-module-parking/ludu-module-parking-biz/Dockerfile /app/build/ludu-module-parking/
|
||||
cp ./ludu-module-parking/ludu-module-parking-biz/run.sh /app/build/ludu-module-parking/
|
||||
fi
|
||||
if [ "${service}" = "datacenter" ] || [ "${service}" = "all" ]; then
|
||||
mkdir -p /app/build/ludu-module-datacenter/target
|
||||
cp ./ludu-module-datacenter/ludu-module-datacenter-biz/target/ludu-module-datacenter-biz.jar /app/build/ludu-module-datacenter/target
|
||||
cp ./ludu-module-datacenter/ludu-module-datacenter-biz/Dockerfile /app/build/ludu-module-datacenter/
|
||||
cp ./ludu-module-datacenter/ludu-module-datacenter-biz/run.sh /app/build/ludu-module-datacenter/
|
||||
fi
|
||||
|
||||
- name: push-images
|
||||
|
||||
image: appleboy/drone-ssh # SSH工具镜像
|
||||
|
||||
settings:
|
||||
|
||||
host: 101.43.112.107 # 远程连接地址
|
||||
|
||||
username: root # 远程连接账号
|
||||
|
||||
password:
|
||||
|
||||
from_secret: ssh_password # 从Secret中读取SSH密码
|
||||
|
||||
port: 22 # 远程连接端口
|
||||
|
||||
command_timeout: 30m # 远程执行命令超时时间
|
||||
|
||||
script:
|
||||
- |
|
||||
deploy_service() {
|
||||
local image_name=$1
|
||||
local container_name=$2
|
||||
if [[ -z "${image_name}" || -z "${container_name}" ]]; then
|
||||
echo "Error: image_name or container_name is empty."
|
||||
exit 1
|
||||
fi
|
||||
cd /ludu/build/${image_name}
|
||||
docker stop ${container_name}
|
||||
docker rm ${container_name}
|
||||
docker rmi -f ${image_name}:1.0.0
|
||||
docker buildx build -f Dockerfile -t ${image_name}:1.0.0 .
|
||||
docker tag ${image_name}:1.0.0 120.46.37.243:8080/lundu/${image_name}:1.0.0
|
||||
docker push 120.46.37.243:8080/lundu/${image_name}:1.0.0
|
||||
}
|
||||
if [ "${service}" = "gateway" ] || [ "${service}" = "all" ]; then
|
||||
deploy_service "yudao-gateway" "yudao-gateway"
|
||||
fi
|
||||
if [ "${service}" = "system" ] || [ "${service}" = "all" ]; then
|
||||
deploy_service "yudao-module-system" "yudao-system"
|
||||
fi
|
||||
if [ "${service}" = "infra" ] || [ "${service}" = "all" ]; then
|
||||
deploy_service "yudao-module-infra" "yudao-infra"
|
||||
fi
|
||||
if [ "${service}" = "job" ] || [ "${service}" = "all" ]; then
|
||||
deploy_service "ludu-job-admin" "ludu-job-admin"
|
||||
fi
|
||||
if [ "${service}" = "ticketing" ] || [ "${service}" = "all" ]; then
|
||||
deploy_service "ludu-module-ticketing" "ludu-ticketing"
|
||||
fi
|
||||
if [ "${service}" = "parking" ] || [ "${service}" = "all" ]; then
|
||||
deploy_service "ludu-module-parking" "ludu-parking"
|
||||
fi
|
||||
if [ "${service}" = "datacenter" ] || [ "${service}" = "all" ]; then
|
||||
deploy_service "ludu-module-datacenter" "ludu-datacenter"
|
||||
fi
|
||||
|
||||
- name: pull-image-and-run
|
||||
|
||||
image: appleboy/drone-ssh # SSH工具镜像
|
||||
|
||||
settings:
|
||||
|
||||
host: 121.36.203.133 # 远程连接地址
|
||||
|
||||
username: root # 远程连接账号
|
||||
|
||||
password:
|
||||
|
||||
from_secret: ssh_password3 # 从Secret中读取SSH密码
|
||||
|
||||
port: 22 # 远程连接端口
|
||||
|
||||
command_timeout: 20m # 远程执行命令超时时间
|
||||
|
||||
script:
|
||||
- cd /ludu
|
||||
- ./start_service.sh ${service}
|
||||
volumes: # 定义流水线挂载目录,用于共享数据
|
||||
|
||||
- name: maven-build
|
||||
host:
|
||||
path: /ludu/maven/build # 从宿主机中挂载的目录
|
||||
|
||||
- name: maven-cache
|
||||
host:
|
||||
path: /ludu/maven/cache # 从宿主机中挂载的目录
|
@ -1,40 +0,0 @@
|
||||
kind: pipeline # 定义对象类型,还有secret和signature两种类型
|
||||
|
||||
type: docker # 定义流水线类型,还有kubernetes、exec、ssh等类型
|
||||
|
||||
name: ludu-infra-drone # 定义流水线名称
|
||||
|
||||
clone:
|
||||
disable: true
|
||||
|
||||
steps: # 定义流水线执行步骤,这些步骤将顺序执行
|
||||
|
||||
- name: infra-build
|
||||
|
||||
image: appleboy/drone-ssh # SSH工具镜像
|
||||
|
||||
settings:
|
||||
|
||||
host: 121.36.203.133 # 远程连接地址
|
||||
|
||||
username: root # 远程连接账号
|
||||
|
||||
password:
|
||||
|
||||
from_secret: ssh_password3 # 从Secret中读取SSH密码
|
||||
|
||||
port: 22 # 远程连接端口
|
||||
|
||||
command_timeout: 20m # 远程执行命令超时时间
|
||||
|
||||
script:
|
||||
- cd /root/ludu-cloud
|
||||
- git fetch origin
|
||||
- git reset --hard origin/master
|
||||
- git clean -fd
|
||||
- docker rm -f yudao-module-infra
|
||||
- /root/apache-maven-3.9.4/bin/mvn package -Dmaven.test.skip=true
|
||||
|
||||
- cd /root/ludu-cloud/yudao-module-infra/yudao-module-infra-biz
|
||||
- chmod +x run.sh
|
||||
- ./run.sh || echo "infra build failed"
|
@ -1,39 +0,0 @@
|
||||
kind: pipeline # 定义对象类型,还有secret和signature两种类型
|
||||
|
||||
type: docker # 定义流水线类型,还有kubernetes、exec、ssh等类型
|
||||
|
||||
name: ludu-job-drone # 定义流水线名称
|
||||
|
||||
clone:
|
||||
disable: true
|
||||
|
||||
steps: # 定义流水线执行步骤,这些步骤将顺序执行
|
||||
|
||||
- name: job-build
|
||||
|
||||
image: appleboy/drone-ssh # SSH工具镜像
|
||||
|
||||
settings:
|
||||
|
||||
host: 121.36.203.133 # 远程连接地址
|
||||
|
||||
username: root # 远程连接账号
|
||||
|
||||
password:
|
||||
|
||||
from_secret: ssh_password3 # 从Secret中读取SSH密码
|
||||
|
||||
port: 22 # 远程连接端口
|
||||
|
||||
command_timeout: 20m # 远程执行命令超时时间
|
||||
|
||||
script:
|
||||
- cd /root/ludu-cloud
|
||||
- git fetch origin
|
||||
- git reset --hard origin/master
|
||||
- git clean -fd
|
||||
- /root/apache-maven-3.9.4/bin/mvn package -Dmaven.test.skip=true
|
||||
|
||||
- cd /root/ludu-cloud/ludu-job-admin/ludu-job-admin-biz
|
||||
- chmod +x run.sh
|
||||
- ./run.sh || echo "job build failed"
|
@ -1,39 +0,0 @@
|
||||
kind: pipeline # 定义对象类型,还有secret和signature两种类型
|
||||
|
||||
type: docker # 定义流水线类型,还有kubernetes、exec、ssh等类型
|
||||
|
||||
name: ludu-parking-drone # 定义流水线名称
|
||||
|
||||
clone:
|
||||
disable: true
|
||||
|
||||
steps: # 定义流水线执行步骤,这些步骤将顺序执行
|
||||
|
||||
- name: parking-build
|
||||
|
||||
image: appleboy/drone-ssh # SSH工具镜像
|
||||
|
||||
settings:
|
||||
|
||||
host: 121.36.203.133 # 远程连接地址
|
||||
|
||||
username: root # 远程连接账号
|
||||
|
||||
password:
|
||||
|
||||
from_secret: ssh_password3 # 从Secret中读取SSH密码
|
||||
|
||||
port: 22 # 远程连接端口
|
||||
|
||||
command_timeout: 20m # 远程执行命令超时时间
|
||||
|
||||
script:
|
||||
- cd /root/ludu-cloud
|
||||
- git fetch origin
|
||||
- git reset --hard origin/master
|
||||
- git clean -fd
|
||||
- /root/apache-maven-3.9.4/bin/mvn package -Dmaven.test.skip=true
|
||||
|
||||
- cd /root/ludu-cloud/ludu-module-parking/ludu-module-parking-biz
|
||||
- chmod +x run.sh
|
||||
- ./run.sh || echo "parking build failed"
|
@ -1,39 +0,0 @@
|
||||
kind: pipeline # 定义对象类型,还有secret和signature两种类型
|
||||
|
||||
type: docker # 定义流水线类型,还有kubernetes、exec、ssh等类型
|
||||
|
||||
name: ludu-system-drone # 定义流水线名称
|
||||
|
||||
clone:
|
||||
disable: true
|
||||
|
||||
steps: # 定义流水线执行步骤,这些步骤将顺序执行
|
||||
|
||||
- name: system-build
|
||||
|
||||
image: appleboy/drone-ssh # SSH工具镜像
|
||||
|
||||
settings:
|
||||
|
||||
host: 121.36.203.133 # 远程连接地址
|
||||
|
||||
username: root # 远程连接账号
|
||||
|
||||
password:
|
||||
|
||||
from_secret: ssh_password3 # 从Secret中读取SSH密码
|
||||
|
||||
port: 22 # 远程连接端口
|
||||
|
||||
command_timeout: 20m # 远程执行命令超时时间
|
||||
|
||||
script:
|
||||
- cd /root/ludu-cloud
|
||||
- git fetch origin
|
||||
- git reset --hard origin/master
|
||||
- git clean -fd
|
||||
- /root/apache-maven-3.9.4/bin/mvn package -Dmaven.test.skip=true
|
||||
|
||||
- cd /root/ludu-cloud/yudao-module-system/yudao-module-system-biz
|
||||
- chmod +x run.sh
|
||||
- ./run.sh || echo "system build failed"
|
@ -1,39 +0,0 @@
|
||||
kind: pipeline # 定义对象类型,还有secret和signature两种类型
|
||||
|
||||
type: docker # 定义流水线类型,还有kubernetes、exec、ssh等类型
|
||||
|
||||
name: ludu-ticketing-drone # 定义流水线名称
|
||||
|
||||
clone:
|
||||
disable: true
|
||||
|
||||
steps: # 定义流水线执行步骤,这些步骤将顺序执行
|
||||
|
||||
- name: ticketing-build
|
||||
|
||||
image: appleboy/drone-ssh # SSH工具镜像
|
||||
|
||||
settings:
|
||||
|
||||
host: 121.36.203.133 # 远程连接地址
|
||||
|
||||
username: root # 远程连接账号
|
||||
|
||||
password:
|
||||
|
||||
from_secret: ssh_password3 # 从Secret中读取SSH密码
|
||||
|
||||
port: 22 # 远程连接端口
|
||||
|
||||
command_timeout: 20m # 远程执行命令超时时间
|
||||
|
||||
script:
|
||||
- cd /root/ludu-cloud
|
||||
- git fetch origin
|
||||
- git reset --hard origin/master
|
||||
- git clean -fd
|
||||
- /root/apache-maven-3.9.4/bin/mvn package -Dmaven.test.skip=true
|
||||
|
||||
- cd /root/ludu-cloud/ludu-module-ticketing/ludu-module-ticketing-biz
|
||||
- chmod +x run.sh
|
||||
- ./run.sh || echo "ticketing build failed"
|
67
.drone.yml
67
.drone.yml
@ -1,67 +0,0 @@
|
||||
kind: pipeline # 定义对象类型,还有secret和signature两种类型
|
||||
|
||||
type: docker # 定义流水线类型,还有kubernetes、exec、ssh等类型
|
||||
|
||||
name: ludu-total-drone # 定义流水线名称
|
||||
|
||||
clone:
|
||||
disable: true
|
||||
|
||||
steps: # 定义流水线执行步骤,这些步骤将顺序执行
|
||||
|
||||
- name: total-build
|
||||
|
||||
image: appleboy/drone-ssh # SSH工具镜像
|
||||
|
||||
settings:
|
||||
|
||||
host: 121.36.203.133 # 远程连接地址
|
||||
|
||||
username: root # 远程连接账号
|
||||
|
||||
password:
|
||||
|
||||
from_secret: ssh_password3 # 从Secret中读取SSH密码
|
||||
|
||||
port: 22 # 远程连接端口
|
||||
|
||||
command_timeout: 20m # 远程执行命令超时时间
|
||||
|
||||
script:
|
||||
- cd /root/ludu-cloud
|
||||
- git fetch origin
|
||||
- git reset --hard origin/master
|
||||
- git clean -fd
|
||||
- /root/apache-maven-3.9.4/bin/mvn package -Dmaven.test.skip=true
|
||||
|
||||
- cd /root/ludu-cloud/yudao-gateway
|
||||
- chmod +x run.sh
|
||||
- ./run.sh || echo "gateway build failed"
|
||||
|
||||
- cd /root/ludu-cloud/yudao-module-system/yudao-module-system-biz
|
||||
- chmod +x run.sh
|
||||
- ./run.sh || echo "system build failed"
|
||||
|
||||
- cd /root/ludu-cloud/yudao-module-infra/yudao-module-infra-biz
|
||||
- chmod +x run.sh
|
||||
- ./run.sh || echo "infra build failed"
|
||||
|
||||
- cd /root/ludu-cloud/ludu-job-admin/ludu-job-admin-biz
|
||||
- chmod +x run.sh
|
||||
- ./run.sh || echo "job build failed"
|
||||
|
||||
- cd /root/ludu-cloud/ludu-module-datacenter/ludu-module-datacenter-biz/
|
||||
- chmod +x run.sh
|
||||
- ./run.sh || echo "datacenter build failed"
|
||||
|
||||
- cd /root/ludu-cloud/ludu-module-ticketing/ludu-module-ticketing-biz
|
||||
- chmod +x run.sh
|
||||
- ./run.sh || echo "ticketing build failed"
|
||||
|
||||
- cd /root/ludu-cloud/ludu-module-parking/ludu-module-parking-biz
|
||||
- chmod +x run.sh
|
||||
- ./run.sh || echo "parking build failed"
|
||||
|
||||
- cd /root/ludu-cloud/ludu-module-hiking/ludu-module-hiking-biz
|
||||
- chmod +x run.sh
|
||||
- ./run.sh || echo "hiking build failed"
|
317
README.md
317
README.md
@ -1,6 +1,254 @@
|
||||
智慧轮渡大数据平台
|
||||
<p align="center">
|
||||
<img src="https://img.shields.io/badge/Spring%20Cloud-2023-blue.svg" alt="Coverage Status">
|
||||
<img src="https://img.shields.io/badge/Spring%20Boot-3.2-blue.svg" alt="Downloads">
|
||||
<img src="https://img.shields.io/badge/Vue-3.2-blue.svg" alt="Downloads">
|
||||
<img src="https://img.shields.io/github/license/YunaiV/yudao-cloud" alt="Downloads" />
|
||||
</p>
|
||||
|
||||
**严肃声明:现在、未来都不会有商业版本,所有代码全部开源!**
|
||||
|
||||
**「我喜欢写代码,乐此不疲」**
|
||||
**「我喜欢做开源,以此为乐」**
|
||||
|
||||
我 🐶 在上海艰苦奋斗,早中晚在 top3 大厂认真搬砖,夜里为开源做贡献。
|
||||
|
||||
如果这个项目让你有所收获,记得 Star 关注哦,这对我是非常不错的鼓励与支持。
|
||||
|
||||
## 🐰 版本说明
|
||||
|
||||
| 版本 | JDK 8 + Spring Boot 2.7 | JDK 17/21 + Spring Boot 3.2 |
|
||||
|-----------------------------------------------------------------------|--------------------------------------------------------------------------|--------------------------------------------------------------------------------------|
|
||||
| 【完整版】[yudao-cloud](https://gitee.com/zhijiantianya/yudao-cloud) | [`master`](https://gitee.com/zhijiantianya/yudao-cloud/tree/master/) 分支 | [`master-jdk17`](https://gitee.com/zhijiantianya/yudao-cloud/tree/master-jdk17/) 分支 |
|
||||
| 【精简版】[yudao-cloud-mini](https://gitee.com/yudaocode/yudao-cloud-mini) | [`master`](https://gitee.com/yudaocode/yudao-cloud-mini/tree/master/) 分支 | [`master-jdk17`](https://gitee.com/yudaocode/yudao-cloud-mini/tree/master-jdk17/) 分支 |
|
||||
|
||||
* 【完整版】:包括系统功能、基础设施、会员中心、数据报表、工作流程、商城系统、微信公众号、CRM、ERP 等功能
|
||||
* 【精简版】:只包括系统功能、基础设施功能,不包括会员中心、数据报表、工作流程、商城系统、微信公众号、CRM、ERP 等功能
|
||||
|
||||
可参考 [《迁移文档》](https://cloud.iocoder.cn/migrate-module/) ,只需要 5-10 分钟,即可将【完整版】按需迁移到【精简版】
|
||||
|
||||
## 🐶 新手必读
|
||||
|
||||
* 演示地址【Vue3 + element-plus】:<http://dashboard-vue3.yudao.iocoder.cn>
|
||||
* 演示地址【Vue3 + vben(ant-design-vue)】:<http://dashboard-vben.yudao.iocoder.cn>
|
||||
* 演示地址【Vue2 + element-ui】:<http://dashboard.yudao.iocoder.cn>
|
||||
* 启动文档:<https://cloud.iocoder.cn/quick-start/>
|
||||
* 视频教程:<https://cloud.iocoder.cn/video/>
|
||||
|
||||
## 🐯 平台简介
|
||||
|
||||
**芋道**,以开发者为中心,打造中国第一流的快速开发平台,全部开源,个人与企业可 100% 免费使用。
|
||||
|
||||
> 有任何问题,或者想要的功能,可以在 _Issues_ 中提给艿艿。
|
||||
>
|
||||
> 😜 给项目点点 Star 吧,这对我们真的很重要!
|
||||
|
||||

|
||||
|
||||
* Java 后端:`master` 分支为 JDK 8 + Spring Boot 2.7,`master-jdk17` 分支为 JDK 17/21 + Spring Boot 3.2
|
||||
* 管理后台的电脑端:Vue3 提供 [element-plus](https://gitee.com/yudaocode/yudao-ui-admin-vue3)、[vben(ant-design-vue)](https://gitee.com/yudaocode/yudao-ui-admin-vben) 两个版本,Vue2 提供 [element-ui](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-ui-admin) 版本
|
||||
* 管理后台的移动端:采用 [uni-app](https://github.com/dcloudio/uni-app) 方案,一份代码多终端适配,同时支持 APP、小程序、H5!
|
||||
* 后端采用 Spring Cloud Alibaba 微服务架构,注册中心 + 配置中心 Nacos,定时任务 XXL-Job,服务保障 Sentinel,服务网关 Gateway,分布式事务 Seata
|
||||
* 数据库可使用 MySQL、Oracle、PostgreSQL、SQL Server、MariaDB、国产达梦 DM、TiDB 等,基于 MyBatis Plus、Redis + Redisson 操作
|
||||
* 消息队列可使用 Event、Redis、RabbitMQ、Kafka、RocketMQ 等
|
||||
* 权限认证使用 Spring Security & Token & Redis,支持多终端、多种用户的认证系统,支持 SSO 单点登录
|
||||
* 支持加载动态权限菜单,按钮级别权限控制,Redis 缓存提升性能
|
||||
* 支持 SaaS 多租户系统,可自定义每个租户的权限,提供透明化的多租户底层封装
|
||||
* 高效率开发,使用代码生成器可以一键生成 Java、Vue 前后端代码、SQL 脚本、接口文档,支持单表、树表、主子表
|
||||
* 实时通信,采用 Spring WebSocket 实现,内置 Token 身份校验,支持 WebSocket 集群
|
||||
* 集成微信小程序、微信公众号、企业微信、钉钉等三方登陆,集成支付宝、微信等支付与退款
|
||||
* 集成阿里云、腾讯云等短信渠道,集成 MinIO、阿里云、腾讯云、七牛云等云存储服务
|
||||
* 集成报表设计器、大屏设计器,通过拖拽即可生成酷炫的报表与大屏
|
||||
|
||||
## 🐳 项目关系
|
||||
|
||||

|
||||
|
||||
三个项目的功能对比,可见社区共同整理的 [国产开源项目对比](https://www.yuque.com/xiatian-bsgny/lm0ec1/wqf8mn) 表格。
|
||||
|
||||
### 后端项目
|
||||
|
||||
| 项目 | Star | 简介 |
|
||||
|-----------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------|
|
||||
| [ruoyi-vue-pro](https://gitee.com/zhijiantianya/ruoyi-vue-pro) | [](https://gitee.com/zhijiantianya/ruoyi-vue-pro) [](https://github.com/YunaiV/ruoyi-vue-pro) | 基于 Spring Boot 多模块架构 |
|
||||
| [yudao-cloud](https://gitee.com/zhijiantianya/yudao-cloud) | [](https://gitee.com/zhijiantianya/yudao-cloud) [](https://github.com/YunaiV/yudao-cloud) | 基于 Spring Cloud 微服务架构 |
|
||||
| [Spring-Boot-Labs](https://gitee.com/yudaocode/SpringBoot-Labs) | [](https://gitee.com/zhijiantianya/yudao-cloud) [](https://github.com/yudaocode/SpringBoot-Labs) | 系统学习 Spring Boot & Cloud 专栏 |
|
||||
|
||||
### 前端项目
|
||||
|
||||
| 项目 | Star | 简介 |
|
||||
|----------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------|
|
||||
| [yudao-ui-admin-vue3](https://gitee.com/yudaocode/yudao-ui-admin-vue3) | [](https://gitee.com/yudaocode/yudao-ui-admin-vue3) [](https://github.com/yudaocode/yudao-ui-admin-vue3) | 基于 Vue3 + element-plus 实现的管理后台 |
|
||||
| [yudao-ui-admin-vben](https://gitee.com/yudaocode/yudao-ui-admin-vben) | [](https://gitee.com/yudaocode/yudao-ui-admin-vben) [](https://github.com/yudaocode/yudao-ui-admin-vben) | 基于 Vue3 + vben(ant-design-vue) 实现的管理后台 |
|
||||
| [yudao-mall-uniapp](https://gitee.com/yudaocode/yudao-mall-uniapp) | [](https://gitee.com/yudaocode/yudao-mall-uniapp) [](https://github.com/yudaocode/yudao-mall-uniapp) | 基于 uni-app 实现的商城小程序 |
|
||||
| [yudao-ui-admin-vue2](https://gitee.com/yudaocode/yudao-ui-admin-vue2) | [](https://gitee.com/yudaocode/yudao-ui-admin-vue2) [](https://github.com/yudaocode/yudao-ui-admin-vue2) | 基于 Vue2 + element-ui 实现的管理后台 |
|
||||
| [yudao-ui-admin-uniapp](https://gitee.com/yudaocode/yudao-ui-admin-uniapp) | [](https://gitee.com/yudaocode/yudao-ui-admin-uniapp) [](https://github.com/yudaocode/yudao-ui-admin-uniapp) | 基于 Vue2 + element-ui 实现的管理后台 |
|
||||
| [yudao-ui-go-view](https://gitee.com/yudaocode/yudao-ui-go-view) | [](https://gitee.com/yudaocode/yudao-ui-go-view) [](https://github.com/yudaocode/yudao-ui-go-view) | 基于 Vue3 + naive-ui 实现的大屏报表 |
|
||||
|
||||
## 😎 开源协议
|
||||
|
||||
**为什么推荐使用本项目?**
|
||||
|
||||
① 本项目采用比 Apache 2.0 更宽松的 [MIT License](https://gitee.com/zhijiantianya/ruoyi-vue-pro/blob/master/LICENSE) 开源协议,个人与企业可 100% 免费使用,不用保留类作者、Copyright 信息。
|
||||
|
||||
② 代码全部开源,不会像其他项目一样,只开源部分代码,让你无法了解整个项目的架构设计。[国产开源项目对比](https://www.yuque.com/xiatian-bsgny/lm0ec1/wqf8mn)
|
||||
|
||||

|
||||
|
||||
③ 代码整洁、架构整洁,遵循《阿里巴巴 Java 开发手册》规范,代码注释详细,57000 行 Java 代码,22000 行代码注释。
|
||||
|
||||
## 🤝 项目外包
|
||||
|
||||
我们也是接外包滴,如果你有项目想要外包,可以微信联系【**Aix9975**】。
|
||||
|
||||
团队包含专业的项目经理、架构师、前端工程师、后端工程师、测试工程师、运维工程师,可以提供全流程的外包服务。
|
||||
|
||||
项目可以是商城、SCRM 系统、OA 系统、物流系统、ERP 系统、CMS 系统、HIS 系统、支付系统、IM 聊天、微信公众号、微信小程序等等。
|
||||
|
||||
## 🐼 内置功能
|
||||
|
||||
系统内置多种多种业务功能,可以用于快速你的业务系统:
|
||||
|
||||

|
||||
|
||||
* 通用模块(必选):系统功能、基础设施
|
||||
* 通用模块(可选):工作流程、支付系统、数据报表、会员中心
|
||||
* 业务系统(按需):ERP 系统、CRM 系统、商城系统、微信公众号
|
||||
|
||||
> 友情提示:本项目基于 RuoYi-Vue 修改,**重构优化**后端的代码,**美化**前端的界面。
|
||||
>
|
||||
> * 额外新增的功能,我们使用 🚀 标记。
|
||||
> * 重新实现的功能,我们使用 ⭐️ 标记。
|
||||
|
||||
🙂 所有功能,都通过 **单元测试** 保证高质量。
|
||||
|
||||
### 系统功能
|
||||
|
||||
| | 功能 | 描述 |
|
||||
|-----|-------|---------------------------------|
|
||||
| | 用户管理 | 用户是系统操作者,该功能主要完成系统用户配置 |
|
||||
| ⭐️ | 在线用户 | 当前系统中活跃用户状态监控,支持手动踢下线 |
|
||||
| | 角色管理 | 角色菜单权限分配、设置角色按机构进行数据范围权限划分 |
|
||||
| | 菜单管理 | 配置系统菜单、操作权限、按钮权限标识等,本地缓存提供性能 |
|
||||
| | 部门管理 | 配置系统组织机构(公司、部门、小组),树结构展现支持数据权限 |
|
||||
| | 岗位管理 | 配置系统用户所属担任职务 |
|
||||
| 🚀 | 租户管理 | 配置系统租户,支持 SaaS 场景下的多租户功能 |
|
||||
| 🚀 | 租户套餐 | 配置租户套餐,自定每个租户的菜单、操作、按钮的权限 |
|
||||
| | 字典管理 | 对系统中经常使用的一些较为固定的数据进行维护 |
|
||||
| 🚀 | 短信管理 | 短信渠道、短息模板、短信日志,对接阿里云、腾讯云等主流短信平台 |
|
||||
| 🚀 | 邮件管理 | 邮箱账号、邮件模版、邮件发送日志,支持所有邮件平台 |
|
||||
| 🚀 | 站内信 | 系统内的消息通知,提供站内信模版、站内信消息 |
|
||||
| 🚀 | 操作日志 | 系统正常操作日志记录和查询,集成 Swagger 生成日志内容 |
|
||||
| ⭐️ | 登录日志 | 系统登录日志记录查询,包含登录异常 |
|
||||
| 🚀 | 错误码管理 | 系统所有错误码的管理,可在线修改错误提示,无需重启服务 |
|
||||
| | 通知公告 | 系统通知公告信息发布维护 |
|
||||
| 🚀 | 敏感词 | 配置系统敏感词,支持标签分组 |
|
||||
| 🚀 | 应用管理 | 管理 SSO 单点登录的应用,支持多种 OAuth2 授权方式 |
|
||||
| 🚀 | 地区管理 | 展示省份、城市、区镇等城市信息,支持 IP 对应城市 |
|
||||
|
||||

|
||||
|
||||
### 工作流程
|
||||
|
||||
| | 功能 | 描述 |
|
||||
|-----|-------|----------------------------------------|
|
||||
| 🚀 | 流程模型 | 配置工作流的流程模型,支持文件导入与在线设计流程图,提供 7 种任务分配规则 |
|
||||
| 🚀 | 流程表单 | 拖动表单元素生成相应的工作流表单,覆盖 Element UI 所有的表单组件 |
|
||||
| 🚀 | 用户分组 | 自定义用户分组,可用于工作流的审批分组 |
|
||||
| 🚀 | 我的流程 | 查看我发起的工作流程,支持新建、取消流程等操作,高亮流程图、审批时间线 |
|
||||
| 🚀 | 待办任务 | 查看自己【未】审批的工作任务,支持通过、不通过、转发、委派、退回等操作 |
|
||||
| 🚀 | 已办任务 | 查看自己【已】审批的工作任务,未来会支持回退操作 |
|
||||
| 🚀 | OA 请假 | 作为业务自定义接入工作流的使用示例,只需创建请求对应的工作流程,即可进行审批 |
|
||||
|
||||

|
||||
|
||||
### 支付系统
|
||||
|
||||
| | 功能 | 描述 |
|
||||
|-----|------|---------------------------|
|
||||
| 🚀 | 应用信息 | 配置商户的应用信息,对接支付宝、微信等多个支付渠道 |
|
||||
| 🚀 | 支付订单 | 查看用户发起的支付宝、微信等的【支付】订单 |
|
||||
| 🚀 | 退款订单 | 查看用户发起的支付宝、微信等的【退款】订单 |
|
||||
| 🚀 | 回调通知 | 查看支付回调业务的【支付】【退款】的通知结果 |
|
||||
| 🚀 | 接入示例 | 提供接入支付系统的【支付】【退款】的功能实战 |
|
||||
|
||||
### 基础设施
|
||||
|
||||
| | 功能 | 描述 |
|
||||
|----|-----------|----------------------------------------------|
|
||||
| 🚀 | 代码生成 | 前后端代码的生成(Java、Vue、SQL、单元测试),支持 CRUD 下载 |
|
||||
| 🚀 | 系统接口 | 基于 Swagger 自动生成相关的 RESTful API 接口文档 |
|
||||
| 🚀 | 数据库文档 | 基于 Screw 自动生成数据库文档,支持导出 Word、HTML、MD 格式 |
|
||||
| | 表单构建 | 拖动表单元素生成相应的 HTML 代码,支持导出 JSON、Vue 文件 |
|
||||
| 🚀 | 配置管理 | 对系统动态配置常用参数,支持 SpringBoot 加载 |
|
||||
| ⭐️ | 定时任务 | 在线(添加、修改、删除)任务调度包含执行结果日志 |
|
||||
| 🚀 | 文件服务 | 支持将文件存储到 S3(MinIO、阿里云、腾讯云、七牛云)、本地、FTP、数据库等 |
|
||||
| 🚀 | WebSocket | 提供 WebSocket 接入示例,支持一对一、一对多发送方式 |
|
||||
| 🚀 | API 日志 | 包括 RESTful API 访问日志、异常日志两部分,方便排查 API 相关的问题 |
|
||||
| | MySQL 监控 | 监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈 |
|
||||
| | Redis 监控 | 监控 Redis 数据库的使用情况,使用的 Redis Key 管理 |
|
||||
| 🚀 | 消息队列 | 基于 Redis 实现消息队列,Stream 提供集群消费,Pub/Sub 提供广播消费 |
|
||||
| 🚀 | Java 监控 | 基于 Spring Boot Admin 实现 Java 应用的监控 |
|
||||
| 🚀 | 链路追踪 | 接入 SkyWalking 组件,实现链路追踪 |
|
||||
| 🚀 | 日志中心 | 接入 SkyWalking 组件,实现日志中心 |
|
||||
| 🚀 | 服务保障 | 基于 Redis 实现分布式锁、幂等、限流功能,满足高并发场景 |
|
||||
| 🚀 | 日志服务 | 轻量级日志中心,查看远程服务器的日志 |
|
||||
| 🚀 | 单元测试 | 基于 JUnit + Mockito 实现单元测试,保证功能的正确性、代码的质量等 |
|
||||
|
||||

|
||||
|
||||
### 数据报表
|
||||
|
||||
| | 功能 | 描述 |
|
||||
|-----|-------|--------------------|
|
||||
| 🚀 | 报表设计器 | 支持数据报表、图形报表、打印设计等 |
|
||||
| 🚀 | 大屏设计器 | 拖拽生成数据大屏,内置几十种图表组件 |
|
||||
|
||||
### 微信公众号
|
||||
|
||||
| | 功能 | 描述 |
|
||||
|-----|--------|-------------------------------|
|
||||
| 🚀 | 账号管理 | 配置接入的微信公众号,可支持多个公众号 |
|
||||
| 🚀 | 数据统计 | 统计公众号的用户增减、累计用户、消息概况、接口分析等数据 |
|
||||
| 🚀 | 粉丝管理 | 查看已关注、取关的粉丝列表,可对粉丝进行同步、打标签等操作 |
|
||||
| 🚀 | 消息管理 | 查看粉丝发送的消息列表,可主动回复粉丝消息 |
|
||||
| 🚀 | 自动回复 | 自动回复粉丝发送的消息,支持关注回复、消息回复、关键字回复 |
|
||||
| 🚀 | 标签管理 | 对公众号的标签进行创建、查询、修改、删除等操作 |
|
||||
| 🚀 | 菜单管理 | 自定义公众号的菜单,也可以从公众号同步菜单 |
|
||||
| 🚀 | 素材管理 | 管理公众号的图片、语音、视频等素材,支持在线播放语音、视频 |
|
||||
| 🚀 | 图文草稿箱 | 新增常用的图文素材到草稿箱,可发布到公众号 |
|
||||
| 🚀 | 图文发表记录 | 查看已发布成功的图文素材,支持删除操作 |
|
||||
|
||||
### 商城系统
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
演示地址:<https://cloud.iocoder.cn/mall-preview/>
|
||||
|
||||
### 会员中心
|
||||
|
||||
| | 功能 | 描述 |
|
||||
|-----|------|----------------------------------|
|
||||
| 🚀 | 会员管理 | 会员是 C 端的消费者,该功能用于会员的搜索与管理 |
|
||||
| 🚀 | 会员标签 | 对会员的标签进行创建、查询、修改、删除等操作 |
|
||||
| 🚀 | 会员等级 | 对会员的等级、成长值进行管理,可用于订单折扣等会员权益 |
|
||||
| 🚀 | 会员分组 | 对会员进行分组,用于用户画像、内容推送等运营手段 |
|
||||
| 🚀 | 积分签到 | 回馈给签到、消费等行为的积分,会员可订单抵现、积分兑换等途径消耗 |
|
||||
|
||||
### ERP 系统
|
||||
|
||||

|
||||
|
||||
演示地址:<https://cloud.iocoder.cn/erp-preview/>
|
||||
|
||||
### ERP 系统
|
||||
|
||||

|
||||
|
||||
演示地址:<https://cloud.iocoder.cn/crm-preview/>
|
||||
|
||||
## 🐨 技术栈
|
||||
|
||||
### 微服务
|
||||
|
||||
@ -8,38 +256,45 @@
|
||||
|--------------------------------------------------------------------------|--------------------|
|
||||
| `yudao-dependencies` | Maven 依赖版本管理 |
|
||||
| `yudao-framework` | Java 框架拓展 |
|
||||
| `yudao-server` | 管理后台 + 用户 APP 的服务端 |
|
||||
| `yudao-module-system` | 系统功能的 Module 模块 |
|
||||
| `yudao-module-member` | 会员中心的 Module 模块 |
|
||||
| `yudao-module-infra` | 基础设施的 Module 模块 |
|
||||
| `yudao-module-bpm` | 工作流程的 Module 模块 |
|
||||
| `yudao-module-pay` | 支付系统的 Module 模块 |
|
||||
| `yudao-module-mall` | 商城系统的 Module 模块 |
|
||||
| `yudao-module-mp` | 微信公众号的 Module 模块 |
|
||||
| `yudao-module-report` | 大屏报表 Module 模块 |
|
||||
|
||||
### 框架
|
||||
|
||||
| 框架 | 说明 | 版本 | 学习指南 |
|
||||
|---------------------------------------------------------------------------------------------|------------------|-------------|---------------------------------------------------------------------|
|
||||
| [Spring Cloud Alibaba](https://github.com/alibaba/spring-cloud-alibaba) | 微服务框架 | 2021.0.4.0 | [文档](https://github.com/YunaiV/SpringBoot-Labs) |
|
||||
| [Nacos](https://github.com/alibaba/nacos) | 配置中心 & 注册中心 | 2.0.4 | [文档](https://www.iocoder.cn/categories/Nacos/?yudao) |
|
||||
| [Spring Cloud Alibaba](https://github.com/alibaba/spring-cloud-alibaba) | 微服务框架 | 2022.0.0.0 | [文档](https://github.com/YunaiV/SpringBoot-Labs) |
|
||||
| [Nacos](https://github.com/alibaba/nacos) | 配置中心 & 注册中心 | 2.2.1 | [文档](https://www.iocoder.cn/categories/Nacos/?yudao) |
|
||||
| [RocketMQ](https://github.com/apache/rocketmq) | 消息队列 | 4.9.4 | [文档](https://www.iocoder.cn/categories/RocketMQ/?yudao) |
|
||||
| [Sentinel](https://github.com/alibaba/sentinel) | 服务保障 | 1.8.6 | [文档](https://www.iocoder.cn/categories/Sentinel/?yudao) |
|
||||
| [XXL Job](https://github.com/xuxueli/xxl-job) | 定时任务 | 2.3.1 | [文档](https://www.iocoder.cn/XXL-JOB/good-collection/?yudao) |
|
||||
| [Spring Cloud Gateway](https://github.com/spring-cloud/spring-cloud-gateway) | 服务网关 | 3.4.1 | [文档](https://www.iocoder.cn/categories/Spring-Cloud-Gateway/?yudao) |
|
||||
| [XXL Job](https://github.com/xuxueli/xxl-job) | 定时任务 | 2.4.0 | [文档](https://www.iocoder.cn/XXL-JOB/good-collection/?yudao) |
|
||||
| [Spring Cloud Gateway](https://github.com/spring-cloud/spring-cloud-gateway) | 服务网关 | 4.1.0 | [文档](https://www.iocoder.cn/categories/Spring-Cloud-Gateway/?yudao) |
|
||||
| [Seata](https://github.com/seata/seata) | 分布式事务 | 1.6.1 | [文档](https://www.iocoder.cn/categories/Seata/?yudao) |
|
||||
| [MySQL](https://www.mysql.com/cn/) | 数据库服务器 | 5.7 / 8.0+ | |
|
||||
| [Druid](https://github.com/alibaba/druid) | JDBC 连接池、监控组件 | 1.2.19 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
|
||||
| [MyBatis Plus](https://mp.baomidou.com/) | MyBatis 增强工具包 | 3.5.3.1 | [文档](http://www.iocoder.cn/Spring-Boot/MyBatis/?yudao) |
|
||||
| [Dynamic Datasource](https://dynamic-datasource.com/) | 动态数据源 | 3.6.0 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
|
||||
| [Druid](https://github.com/alibaba/druid) | JDBC 连接池、监控组件 | 1.2.20 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
|
||||
| [MyBatis Plus](https://mp.baomidou.com/) | MyBatis 增强工具包 | 3.5.4.1 | [文档](http://www.iocoder.cn/Spring-Boot/MyBatis/?yudao) |
|
||||
| [Dynamic Datasource](https://dynamic-datasource.com/) | 动态数据源 | 4.2.0 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
|
||||
| [Redis](https://redis.io/) | key-value 数据库 | 5.0 / 6.0 | |
|
||||
| [Redisson](https://github.com/redisson/redisson) | Redis 客户端 | 3.18.0 | [文档](http://www.iocoder.cn/Spring-Boot/Redis/?yudao) |
|
||||
| [Spring MVC](https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc) | MVC 框架 | 5.3.24 | [文档](http://www.iocoder.cn/SpringMVC/MVC/?yudao) |
|
||||
| [Spring Security](https://github.com/spring-projects/spring-security) | Spring 安全框架 | 5.7.5 | [文档](http://www.iocoder.cn/Spring-Boot/Spring-Security/?yudao) |
|
||||
| [Hibernate Validator](https://github.com/hibernate/hibernate-validator) | 参数校验组件 | 6.2.5 | [文档](http://www.iocoder.cn/Spring-Boot/Validation/?yudao) |
|
||||
| [Flowable](https://github.com/flowable/flowable-engine) | 工作流引擎 | 6.7.2 | [文档](https://doc.iocoder.cn/bpm/) |
|
||||
| [Knife4j](https://gitee.com/xiaoym/knife4j) | Swagger 增强 UI 实现 | 4.0.0 | [文档](http://www.iocoder.cn/Spring-Boot/Swagger/?yudao) |
|
||||
| [SkyWalking](https://skywalking.apache.org/) | 分布式应用追踪系统 | 8.12.0 | [文档](http://www.iocoder.cn/Spring-Boot/SkyWalking/?yudao) |
|
||||
| [Spring Boot Admin](https://github.com/codecentric/spring-boot-admin) | Spring Boot 监控平台 | 2.7.10 | [文档](http://www.iocoder.cn/Spring-Boot/Admin/?yudao) |
|
||||
| [Jackson](https://github.com/FasterXML/jackson) | JSON 工具库 | 2.13.3 | |
|
||||
| [Redisson](https://github.com/redisson/redisson) | Redis 客户端 | 3.25.0 | [文档](http://www.iocoder.cn/Spring-Boot/Redis/?yudao) |
|
||||
| [Spring MVC](https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc) | MVC 框架 | 6.1.1 | [文档](http://www.iocoder.cn/SpringMVC/MVC/?yudao) |
|
||||
| [Spring Security](https://github.com/spring-projects/spring-security) | Spring 安全框架 | 6.2.0 | [文档](http://www.iocoder.cn/Spring-Boot/Spring-Security/?yudao) |
|
||||
| [Hibernate Validator](https://github.com/hibernate/hibernate-validator) | 参数校验组件 | 8.0.1 | [文档](http://www.iocoder.cn/Spring-Boot/Validation/?yudao) |
|
||||
| [Flowable](https://github.com/flowable/flowable-engine) | 工作流引擎 | 7.0.0 | [文档](https://doc.iocoder.cn/bpm/) |
|
||||
| [Knife4j](https://gitee.com/xiaoym/knife4j) | Swagger 增强 UI 实现 | 4.4.0 | [文档](http://www.iocoder.cn/Spring-Boot/Swagger/?yudao) |
|
||||
| [SkyWalking](https://skywalking.apache.org/) | 分布式应用追踪系统 | 9.0.0 | [文档](http://www.iocoder.cn/Spring-Boot/SkyWalking/?yudao) |
|
||||
| [Spring Boot Admin](https://github.com/codecentric/spring-boot-admin) | Spring Boot 监控平台 | 3.6.1 | [文档](http://www.iocoder.cn/Spring-Boot/Admin/?yudao) |
|
||||
| [Jackson](https://github.com/FasterXML/jackson) | JSON 工具库 | 2.15.3 | |
|
||||
| [MapStruct](https://mapstruct.org/) | Java Bean 转换 | 1.5.5.Final | [文档](http://www.iocoder.cn/Spring-Boot/MapStruct/?yudao) |
|
||||
| [Lombok](https://projectlombok.org/) | 消除冗长的 Java 代码 | 1.18.26 | [文档](http://www.iocoder.cn/Spring-Boot/Lombok/?yudao) |
|
||||
| [JUnit](https://junit.org/junit5/) | Java 单元测试框架 | 5.8.2 | - |
|
||||
| [Mockito](https://github.com/mockito/mockito) | Java Mock 框架 | 4.8.0 | - |
|
||||
| [Lombok](https://projectlombok.org/) | 消除冗长的 Java 代码 | 1.18.30 | [文档](http://www.iocoder.cn/Spring-Boot/Lombok/?yudao) |
|
||||
| [JUnit](https://junit.org/junit5/) | Java 单元测试框架 | 5.10.1 | - |
|
||||
| [Mockito](https://github.com/mockito/mockito) | Java Mock 框架 | 5.7.0 | - |
|
||||
|
||||
## 🐷 演示图
|
||||
|
||||
@ -79,3 +334,25 @@
|
||||
| MySQL & Redis |  |  | - |
|
||||
| 监控平台 |  |  |  |
|
||||
|
||||
### 支付系统
|
||||
|
||||
| 模块 | biu | biu | biu |
|
||||
|---------|---------------------------|---------------------------------|---------------------------------|
|
||||
| 商家 & 应用 |  |  |  |
|
||||
| 支付 & 退款 |  |  | --- |
|
||||
### 数据报表
|
||||
|
||||
| 模块 | biu | biu | biu |
|
||||
|-------|---------------------------------|---------------------------------|---------------------------------------|
|
||||
| 报表设计器 |  |  |  |
|
||||
| 大屏设计器 |  |  |  |
|
||||
|
||||
### 移动端(管理后台)
|
||||
|
||||
| biu | biu | biu |
|
||||
|----------------------------------|----------------------------------|----------------------------------|
|
||||
|  |  |  |
|
||||
|  |  |  |
|
||||
|  |  |  |
|
||||
|
||||
目前已经实现登录、我的、工作台、编辑资料、头像修改、密码修改、常见问题、关于我们等基础功能。
|
||||
|
@ -1,52 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
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>
|
||||
<artifactId>xxl-job-admin</artifactId>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>ludu-job-admin-api</artifactId>
|
||||
|
||||
<packaging>jar</packaging> <!-- 2. 新增 packaging 为 jar -->
|
||||
|
||||
<name>${project.artifactId}</name> <!-- 3. 新增 name 为 ${project.artifactId} -->
|
||||
<description> <!-- 4. 新增 description 为该模块的描述 -->
|
||||
xxl-job 模块 API,暴露给其它模块调用
|
||||
</description>
|
||||
|
||||
<dependencies> <!-- 5. 新增 yudao-common 依赖 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-common</artifactId>
|
||||
</dependency>
|
||||
<!-- Web 相关 -->
|
||||
<dependency>
|
||||
<groupId>org.springdoc</groupId>
|
||||
<artifactId>springdoc-openapi-ui</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- 参数校验 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- RPC 远程调用相关 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-excel</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -1,61 +0,0 @@
|
||||
package com.xxl.job.admin.api.info;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import com.xxl.job.admin.api.info.dto.JobInfoDetailRespDTO;
|
||||
import com.xxl.job.admin.api.info.dto.JobInfoRespDTO;
|
||||
import com.xxl.job.admin.api.info.dto.JobInfoSaveReqDTO;
|
||||
import com.xxl.job.admin.enums.ApiConstants;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Description 调度任务信息Api接口
|
||||
*/
|
||||
@FeignClient(name = ApiConstants.NAME, path = "/xxl-job-admin")
|
||||
@Tag(name = "RPC 服务 - 任务信息管理")
|
||||
public interface JobInfoApi {
|
||||
String PREFIX = ApiConstants.PREFIX + "/info";
|
||||
@GetMapping(PREFIX + "/page")
|
||||
@Operation(summary = "获得所有任务列表")
|
||||
@Parameter(name = "pageNo", description = "当前页数", required = true)
|
||||
@Parameter(name = "pageSize", description = "每页显示条数", required = true)
|
||||
@Parameter(name = "name", description = "任务名称", required = false)
|
||||
@Parameter(name = "status", description = "任务状态", required = false)
|
||||
@Parameter(name = "handlerName", description = "处理器名字", required = false)
|
||||
public CommonResult<PageResult<JobInfoRespDTO>> getPage(@RequestParam(value = "pageNo") Integer pageNo, @RequestParam(value = "pageSize") Integer pageSize, @RequestParam(required = false, value = "name") String name, @RequestParam(required = false, value = "status") Integer status, @RequestParam(required = false, value = "handlerName") String handlerName);
|
||||
|
||||
@GetMapping(PREFIX + "/get")
|
||||
@Operation(summary = "获得任务详情")
|
||||
@Parameter(name = "id", description = "任务主键", required = true)
|
||||
CommonResult<JobInfoDetailRespDTO> get(@RequestParam("id") Integer id);
|
||||
|
||||
@PostMapping(PREFIX + "/create")
|
||||
@Operation(summary = "创建任务")
|
||||
CommonResult<Boolean> create(@RequestBody JobInfoSaveReqDTO jobInfoSaveReqDTO);
|
||||
|
||||
@PutMapping(PREFIX + "/update")
|
||||
@Operation(summary = "修改任务")
|
||||
CommonResult<Boolean> update(@RequestBody JobInfoSaveReqDTO jobInfoSaveReqDTO);
|
||||
|
||||
@DeleteMapping(PREFIX + "/delete")
|
||||
@Operation(summary = "删除任务")
|
||||
CommonResult<Boolean> delete(@RequestParam("id") Integer id);
|
||||
@PutMapping(PREFIX + "/update-status")
|
||||
@Operation(summary = "任务状态修改")
|
||||
CommonResult<Boolean> updateStatus(@RequestParam("id") Integer id, @RequestParam("status") Integer status);
|
||||
|
||||
@PutMapping(PREFIX + "/trigger")
|
||||
@Operation(summary = "任务立即执行一次")
|
||||
CommonResult<Object> trigger(@RequestParam("id") Integer id);
|
||||
|
||||
@GetMapping(PREFIX + "/get_next_times")
|
||||
@Operation(summary = "下n次执行时间")
|
||||
CommonResult<List<String>> getNextTimes(@RequestParam("id") Integer id);
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
package com.xxl.job.admin.api.info.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @Description 任务详情
|
||||
*/
|
||||
@Schema(description = "RPC 服务 - 任务信息 Response DTO")
|
||||
@Data
|
||||
public class JobInfoDetailRespDTO {
|
||||
@Schema(description = "任务编号", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Integer id;
|
||||
@Schema(description = "任务名称")
|
||||
private String name;
|
||||
@Schema(description = "处理器的名字")
|
||||
private String handlerName;
|
||||
@Schema(description = "处理器的参数")
|
||||
private String handlerParam;
|
||||
@Schema(description = "CRON 表达式")
|
||||
private String cronExpression;
|
||||
@Schema(description = "重试次数")
|
||||
private Integer retryCount;
|
||||
@Schema(description = "监控超时时间")
|
||||
private Integer monitorTimeout;
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
package com.xxl.job.admin.api.info.dto;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
@Schema(description = "RPC 服务 - 任务列表 Request DTO")
|
||||
@Data
|
||||
public class JobInfoPageReqDTO extends PageParam {
|
||||
@Schema(description = "任务编号", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Integer id;
|
||||
@Schema(description = "任务名称")
|
||||
private String name;
|
||||
@Schema(description = "任务状态")
|
||||
private Integer status;
|
||||
@Schema(description = "处理器的名字")
|
||||
private String handlerName;
|
||||
@Schema(description = "处理器的参数")
|
||||
private String handlerParam;
|
||||
@Schema(description = "CRON 表达式")
|
||||
private String cronExpression;
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
package com.xxl.job.admin.api.info.dto;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @Description 任务列表单个信息
|
||||
*/
|
||||
@Schema(description = "RPC 服务 - 任务信息 Response DTO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class JobInfoRespDTO {
|
||||
@Schema(description = "任务编号", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("任务编号")
|
||||
private Integer id;
|
||||
@Schema(description = "任务名称")
|
||||
@ExcelProperty("任务名称")
|
||||
private String name;
|
||||
@Schema(description = "任务状态")
|
||||
@ExcelProperty("任务状态")
|
||||
private Integer status;
|
||||
@Schema(description = "处理器的名字")
|
||||
@ExcelProperty("处理器的名字")
|
||||
private String handlerName;
|
||||
@Schema(description = "处理器的参数")
|
||||
@ExcelProperty("处理器的参数")
|
||||
private String handlerParam;
|
||||
@Schema(description = "CRON 表达式")
|
||||
@ExcelProperty("CRON 表达式")
|
||||
private String cronExpression;
|
||||
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
package com.xxl.job.admin.api.info.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @Description TODO
|
||||
*/
|
||||
@Schema(description = "RPC 服务 - 新增任务 Request DTO")
|
||||
@Data
|
||||
public class JobInfoSaveReqDTO {
|
||||
@Schema(description = "任务编号")
|
||||
private Integer id;
|
||||
@Schema(description = "任务名称")
|
||||
private String name;
|
||||
@Schema(description = "处理器的名字")
|
||||
private String handlerName;
|
||||
@Schema(description = "处理器的参数")
|
||||
private String handlerParam;
|
||||
@Schema(description = "CRON 表达式")
|
||||
private String cronExpression;
|
||||
@Schema(description = "重试次数")
|
||||
private Integer retryCount;
|
||||
@Schema(description = "监控超时时间")
|
||||
private Integer monitorTimeout;
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
package com.xxl.job.admin.api.log;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import com.xxl.job.admin.api.info.dto.JobInfoRespDTO;
|
||||
import com.xxl.job.admin.api.log.dto.JobLogPageReqDTO;
|
||||
import com.xxl.job.admin.api.log.dto.JobLogRespDTO;
|
||||
import com.xxl.job.admin.enums.ApiConstants;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @Description 调度任务日志Api接口
|
||||
*/
|
||||
@FeignClient(name = ApiConstants.NAME, path = "/xxl-job-admin")
|
||||
@Tag(name = "RPC 服务 - 任务日志管理")
|
||||
public interface JobLogApi {
|
||||
String PREFIX = ApiConstants.PREFIX + "/log";
|
||||
@GetMapping(PREFIX + "/page")
|
||||
@Operation(summary = "获得所有任务列表")
|
||||
public CommonResult<PageResult<JobLogRespDTO>> getPage(@RequestParam(value = "pageNo") Integer pageNo,
|
||||
@RequestParam(value = "pageSize") Integer pageSize,
|
||||
@RequestParam(value = "jobId") Integer jobId,
|
||||
@RequestParam(required = false, value = "handlerName") String handlerName,
|
||||
@RequestParam(required = false, value = "beginTime") String beginTime,
|
||||
@RequestParam(required = false, value = "endTime") String endTime,
|
||||
@RequestParam(required = false, value = "status") Integer status);
|
||||
|
||||
@GetMapping(PREFIX + "/get")
|
||||
@Operation(summary = "获得任务日志详情")
|
||||
CommonResult<JobLogRespDTO> get(@RequestParam("id") Integer id);
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
package com.xxl.job.admin.api.log.dto;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Date;
|
||||
|
||||
@Schema(description = "RPC 服务 - 任务日志 Request DTO")
|
||||
@Data
|
||||
public class JobLogPageReqDTO extends PageParam {
|
||||
@NotNull(message = "任务编号不能为空")
|
||||
@Schema(description = "任务编号")
|
||||
private Integer jobId;
|
||||
@Schema(description = "处理器的名字")
|
||||
private String handlerName;
|
||||
@Schema(description = "开始执行时间")
|
||||
private String beginTime;
|
||||
@Schema(description = "结束执行时间")
|
||||
private String endTime;
|
||||
@Schema(description = "任务状态")
|
||||
private Integer status;
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
package com.xxl.job.admin.api.log.dto;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Schema(description = "RPC 服务 - 任务日志 Response DTO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class JobLogRespDTO {
|
||||
@Schema(description = "日志编号")
|
||||
@ExcelProperty("日志编号")
|
||||
private Integer id;
|
||||
@Schema(description = "任务编号")
|
||||
@ExcelProperty("任务编号")
|
||||
private Integer jobId;
|
||||
@Schema(description = "处理器的名字")
|
||||
@ExcelProperty("处理器的名字")
|
||||
private String handlerName;
|
||||
@Schema(description = "处理器的参数")
|
||||
@ExcelProperty("处理器的参数")
|
||||
private String handlerParam;
|
||||
@Schema(description = "第几次执行")
|
||||
@ExcelProperty("第几次执行")
|
||||
private Integer executeIndex;
|
||||
@Schema(description = "开始执行时间")
|
||||
@ExcelProperty("开始执行时间")
|
||||
private String beginTime;
|
||||
@Schema(description = "结束执行时间")
|
||||
@ExcelProperty("结束执行时间")
|
||||
private String endTime;
|
||||
@Schema(description = "执行时长")
|
||||
@ExcelProperty("执行时长")
|
||||
private Integer duration;
|
||||
@Schema(description = "任务状态")
|
||||
@ExcelProperty("任务状态")
|
||||
private Integer status;
|
||||
@Schema(description = "任务详细结果")
|
||||
private String result;
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
package com.xxl.job.admin.enums;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.RpcConstants;
|
||||
|
||||
/**
|
||||
* API 相关的枚举
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public class ApiConstants {
|
||||
|
||||
/**
|
||||
* 服务名
|
||||
*
|
||||
* 注意,需要保证和 spring.application.name 保持一致
|
||||
*/
|
||||
public static final String NAME = "job-server";
|
||||
|
||||
public static final String PREFIX = RpcConstants.RPC_API_PREFIX + "/job";
|
||||
|
||||
public static final String VERSION = "1.0.0";
|
||||
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
FROM openjdk:8-jre
|
||||
|
||||
## 创建目录,并使用它作为工作目录
|
||||
RUN mkdir -p /ludu-job-admin-biz
|
||||
WORKDIR /ludu-job-admin-biz
|
||||
## 将后端项目的 Jar 文件,复制到镜像中
|
||||
COPY ./target/ludu-job-admin-biz.jar app.jar
|
||||
|
||||
## 设置 TZ 时区
|
||||
ENV TZ=Asia/Shanghai
|
||||
## 设置 JAVA_OPTS 环境变量,可通过 docker run -e "JAVA_OPTS=" 进行覆盖
|
||||
ENV JAVA_OPTS="-Xms256m -Xmx256m -Djava.security.egd=file:/dev/./urandom"
|
||||
|
||||
## 暴露后端项目的 9090 端口
|
||||
EXPOSE 48084
|
||||
|
||||
## 启动后端项目
|
||||
CMD java ${JAVA_OPTS} -jar app.jar --spring.profiles.active=dev
|
@ -1,160 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
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>
|
||||
<artifactId>xxl-job-admin</artifactId>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>ludu-job-admin-biz</artifactId>
|
||||
<packaging>jar</packaging> <!-- 2. 新增 packaging 为 jar -->
|
||||
|
||||
<name>${project.artifactId}</name> <!-- 3. 新增 name 为 ${project.artifactId} -->
|
||||
<description> <!-- 4. 新增 description 为该模块的描述 -->
|
||||
demo 模块,主要实现 XXX、YYY、ZZZ 等功能。
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>ludu-job-core</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<!-- Spring Cloud 基础 -->
|
||||
<!-- Web 相关 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>5.8.22</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>ludu-job-admin-api</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- freemarker-starter -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-freemarker</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- mail-starter -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-mail</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- starter-actuator -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Cloud 基础 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-bootstrap</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-env</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- Web 相关 -->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- DB 相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-mybatis</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- RPC 远程调用相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-rpc</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Registry 注册中心相关 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Config 配置中心相关 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
<!-- Test 测试相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- 工具类相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-excel</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-biz-ip</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 监控相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-monitor</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<!-- 设置构建的 jar 包名 -->
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
<plugins>
|
||||
<!-- 打包 -->
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>${spring.boot.version}</version>
|
||||
<configuration>
|
||||
<fork>true</fork>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal> <!-- 将引入的 jar 打入其中 -->
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
@ -1,16 +0,0 @@
|
||||
app_name='ludu-job-admin'
|
||||
# 定义应用版本
|
||||
app_version='1.0.0'
|
||||
# 定义应用环境
|
||||
#profile_active='prod'
|
||||
# 打包编译docker镜像
|
||||
echo '----build image----'
|
||||
docker build -f Dockerfile -t ${app_name}:${app_version} .
|
||||
echo '----stop container----'
|
||||
docker stop ${app_name}
|
||||
echo '----rm container----'
|
||||
docker rm ${app_name}
|
||||
echo '----rmi none image----'
|
||||
docker rmi $(docker images -f "dangling=true" -q)
|
||||
echo '----start container----'
|
||||
docker run -d -p 48083:9090 --name ${app_name} --restart always ${app_name}:${app_version}
|
@ -1,16 +0,0 @@
|
||||
package com.xxl.job.admin;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
/**
|
||||
* @author xuxueli 2018-10-28 00:38:13
|
||||
*/
|
||||
@SpringBootApplication
|
||||
public class XxlJobAdminApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(XxlJobAdminApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
package com.xxl.job.admin.api.info;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import com.xxl.job.admin.api.info.dto.JobInfoDetailRespDTO;
|
||||
import com.xxl.job.admin.api.info.dto.JobInfoRespDTO;
|
||||
import com.xxl.job.admin.api.info.dto.JobInfoSaveReqDTO;
|
||||
import com.xxl.job.admin.service.XxlJobService;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
/**
|
||||
* @Description 调度任务信息Api实现类
|
||||
*/
|
||||
@RestController // 提供 RESTful API 接口,给 Feign 调用
|
||||
@Validated
|
||||
public class JobInfoApiImpl implements JobInfoApi{
|
||||
@Resource
|
||||
private XxlJobService xxlJobService;
|
||||
|
||||
@Override
|
||||
public CommonResult<PageResult<JobInfoRespDTO>> getPage(Integer pageNo, Integer pageSize, String name, Integer status, String handlerName) {
|
||||
return success(xxlJobService.apiPage(pageNo, pageSize, name, status, handlerName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<JobInfoDetailRespDTO> get(Integer id) {
|
||||
return success(xxlJobService.apiGet(id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<Boolean> create(JobInfoSaveReqDTO jobInfoSaveReqDTO) {
|
||||
return xxlJobService.apiCreate(jobInfoSaveReqDTO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<Boolean> update(JobInfoSaveReqDTO jobInfoSaveReqDTO) {
|
||||
return xxlJobService.apiUpdate(jobInfoSaveReqDTO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<Boolean> delete(Integer id) {
|
||||
return success(xxlJobService.apiDelete(id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<Boolean> updateStatus(Integer id, Integer status) {
|
||||
return success(xxlJobService.apiUpdateStatus(id, status));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<Object> trigger(Integer id) {
|
||||
|
||||
return xxlJobService.apiTrigger(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<List<String>> getNextTimes(Integer id) {
|
||||
return xxlJobService.apiGetNextTimes(id);
|
||||
}
|
||||
}
|
@ -1,119 +0,0 @@
|
||||
package com.xxl.job.admin.api.log;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import com.xxl.job.admin.api.info.dto.JobInfoRespDTO;
|
||||
import com.xxl.job.admin.api.log.dto.JobLogPageReqDTO;
|
||||
import com.xxl.job.admin.api.log.dto.JobLogRespDTO;
|
||||
import com.xxl.job.admin.controller.JobInfoController;
|
||||
import com.xxl.job.admin.controller.JobLogController;
|
||||
import com.xxl.job.admin.core.model.XxlJobLog;
|
||||
import com.xxl.job.admin.core.scheduler.XxlJobScheduler;
|
||||
import com.xxl.job.admin.core.util.I18nUtil;
|
||||
import com.xxl.job.admin.dao.XxlJobGroupDao;
|
||||
import com.xxl.job.admin.dao.XxlJobInfoDao;
|
||||
import com.xxl.job.admin.dao.XxlJobLogDao;
|
||||
import com.xxl.job.core.biz.ExecutorBiz;
|
||||
import com.xxl.job.core.biz.model.LogParam;
|
||||
import com.xxl.job.core.biz.model.LogResult;
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import com.xxl.job.core.util.DateUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.util.HtmlUtils;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Description 调度任务日志Api实现类
|
||||
*/
|
||||
@RestController // 提供 RESTful API 接口,给 Feign 调用
|
||||
@Validated
|
||||
public class JobLogApiImpl implements JobLogApi {
|
||||
private static Logger logger = LoggerFactory.getLogger(JobLogController.class);
|
||||
|
||||
@Resource
|
||||
private XxlJobGroupDao xxlJobGroupDao;
|
||||
@Resource
|
||||
public XxlJobInfoDao xxlJobInfoDao;
|
||||
@Resource
|
||||
public XxlJobLogDao xxlJobLogDao;
|
||||
|
||||
@Override
|
||||
public CommonResult<PageResult<JobLogRespDTO>> getPage(Integer pageNo,
|
||||
Integer pageSize,
|
||||
Integer jobId,
|
||||
String handlerName,
|
||||
String beginTime,
|
||||
String endTime,
|
||||
Integer status) {
|
||||
// 设置默认组为3
|
||||
int jobGroup = 3;
|
||||
// 计算起始页数
|
||||
pageNo = (pageNo - 1) * pageSize;
|
||||
// page query
|
||||
List<JobLogRespDTO> list = xxlJobLogDao.apiPageList(pageNo, pageSize, jobGroup, jobId, beginTime, endTime, status, handlerName);
|
||||
int list_count = xxlJobLogDao.apiPageListCount(pageNo, pageSize, jobGroup, jobId, beginTime, endTime, status, handlerName);
|
||||
// package result
|
||||
PageResult<JobLogRespDTO> pageResult = new PageResult<>();
|
||||
pageResult.setTotal((long) list_count);
|
||||
pageResult.setList(list);
|
||||
return CommonResult.success(pageResult);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<JobLogRespDTO> get(Integer id) {
|
||||
XxlJobLog load = xxlJobLogDao.load(id);
|
||||
JobLogRespDTO jobLogRespDTO = new JobLogRespDTO();
|
||||
jobLogRespDTO.setId(id);
|
||||
jobLogRespDTO.setJobId(load.getJobId());
|
||||
if (load.getTriggerCode() == 200) {
|
||||
jobLogRespDTO.setDuration((int) (load.getHandleTime().getTime() - load.getTriggerTime().getTime()));
|
||||
}
|
||||
jobLogRespDTO.setBeginTime(load.getTriggerTime() == null ? null : DateUtil.formatDateTime(load.getTriggerTime()));
|
||||
jobLogRespDTO.setEndTime(load.getHandleTime() == null ? null : DateUtil.formatDateTime(load.getHandleTime()));
|
||||
jobLogRespDTO.setHandlerName(load.getExecutorHandler());
|
||||
jobLogRespDTO.setHandlerParam(load.getExecutorParam());
|
||||
jobLogRespDTO.setStatus(load.getHandleCode() == 200 ? 1 : 2);
|
||||
// 使用原系统的方法实现日志结果显示
|
||||
try {
|
||||
// valid
|
||||
XxlJobLog jobLog = xxlJobLogDao.load(id);
|
||||
if (jobLog == null) {
|
||||
jobLogRespDTO.setResult("joblog_logid_unvalid");
|
||||
}
|
||||
|
||||
// log cat
|
||||
ExecutorBiz executorBiz = XxlJobScheduler.getExecutorBiz(jobLog.getExecutorAddress());
|
||||
ReturnT<LogResult> logResult = executorBiz.log(new LogParam(jobLog.getTriggerTime().getTime(), id, 1));
|
||||
|
||||
// is end
|
||||
if (logResult.getContent() != null && logResult.getContent().getFromLineNum() > logResult.getContent().getToLineNum()) {
|
||||
if (jobLog.getHandleCode() > 0) {
|
||||
logResult.getContent().setEnd(true);
|
||||
}
|
||||
}
|
||||
|
||||
// fix xss
|
||||
if (logResult.getContent() != null && StringUtils.hasText(logResult.getContent().getLogContent())) {
|
||||
String newLogContent = logResult.getContent().getLogContent();
|
||||
newLogContent = HtmlUtils.htmlEscape(newLogContent, "UTF-8");
|
||||
logResult.getContent().setLogContent(newLogContent);
|
||||
}
|
||||
jobLogRespDTO.setResult(logResult.getContent().getLogContent());
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
jobLogRespDTO.setResult("joblog_logid_failed");
|
||||
}
|
||||
return CommonResult.success(jobLogRespDTO);
|
||||
}
|
||||
}
|
@ -1,157 +0,0 @@
|
||||
package com.xxl.job.admin.client;
|
||||
|
||||
import com.xxl.job.admin.client.dto.CommonResult;
|
||||
import com.xxl.job.admin.client.dto.oauth2.OAuth2AccessTokenRespDTO;
|
||||
import com.xxl.job.admin.client.dto.oauth2.OAuth2CheckTokenRespDTO;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.*;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.Base64Utils;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* OAuth 2.0 客户端
|
||||
*
|
||||
* 对应调用 OAuth2OpenController 接口
|
||||
*/
|
||||
@Component
|
||||
public class OAuth2Client {
|
||||
|
||||
private static final String BASE_URL = "http://121.36.203.133/admin-api/system/oauth2";
|
||||
|
||||
/**
|
||||
* 租户编号
|
||||
*
|
||||
* 默认使用 1;如果使用别的租户,可以调整
|
||||
*/
|
||||
public static final Long TENANT_ID = 1L;
|
||||
|
||||
private static final String CLIENT_ID = "ludu-job-admin";
|
||||
private static final String CLIENT_SECRET = "test";
|
||||
|
||||
|
||||
// @Resource // 可优化,注册一个 RestTemplate Bean,然后注入
|
||||
private final RestTemplate restTemplate = new RestTemplate();
|
||||
|
||||
/**
|
||||
* 使用 code 授权码,获得访问令牌
|
||||
*
|
||||
* @param code 授权码
|
||||
* @param redirectUri 重定向 URI
|
||||
* @return 访问令牌
|
||||
*/
|
||||
public CommonResult<OAuth2AccessTokenRespDTO> postAccessToken(String code, String redirectUri) {
|
||||
// 1.1 构建请求头
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
|
||||
headers.set("tenant-id", TENANT_ID.toString());
|
||||
addClientHeader(headers);
|
||||
// 1.2 构建请求参数
|
||||
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
|
||||
body.add("grant_type", "authorization_code");
|
||||
body.add("code", code);
|
||||
body.add("redirect_uri", redirectUri);
|
||||
// body.add("state", ""); // 选填;填了会校验
|
||||
|
||||
// 2. 执行请求
|
||||
ResponseEntity<CommonResult<OAuth2AccessTokenRespDTO>> exchange = restTemplate.exchange(
|
||||
BASE_URL + "/token",
|
||||
HttpMethod.POST,
|
||||
new HttpEntity<>(body, headers),
|
||||
new ParameterizedTypeReference<CommonResult<OAuth2AccessTokenRespDTO>>() {}); // 解决 CommonResult 的泛型丢失
|
||||
Assert.isTrue(exchange.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功");
|
||||
return exchange.getBody();
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验访问令牌,并返回它的基本信息
|
||||
*
|
||||
* @param token 访问令牌
|
||||
* @return 访问令牌的基本信息
|
||||
*/
|
||||
public CommonResult<OAuth2CheckTokenRespDTO> checkToken(String token) {
|
||||
// 1.1 构建请求头
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
|
||||
headers.set("tenant-id", TENANT_ID.toString());
|
||||
addClientHeader(headers);
|
||||
// 1.2 构建请求参数
|
||||
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
|
||||
body.add("token", token);
|
||||
|
||||
// 2. 执行请求
|
||||
ResponseEntity<CommonResult<OAuth2CheckTokenRespDTO>> exchange = restTemplate.exchange(
|
||||
BASE_URL + "/check-token",
|
||||
HttpMethod.POST,
|
||||
new HttpEntity<>(body, headers),
|
||||
new ParameterizedTypeReference<CommonResult<OAuth2CheckTokenRespDTO>>() {}); // 解决 CommonResult 的泛型丢失
|
||||
Assert.isTrue(exchange.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功");
|
||||
return exchange.getBody();
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用刷新令牌,获得(刷新)访问令牌
|
||||
*
|
||||
* @param refreshToken 刷新令牌
|
||||
* @return 访问令牌
|
||||
*/
|
||||
public CommonResult<OAuth2AccessTokenRespDTO> refreshToken(String refreshToken) {
|
||||
// 1.1 构建请求头
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
|
||||
headers.set("tenant-id", TENANT_ID.toString());
|
||||
addClientHeader(headers);
|
||||
// 1.2 构建请求参数
|
||||
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
|
||||
body.add("grant_type", "refresh_token");
|
||||
body.add("refresh_token", refreshToken);
|
||||
|
||||
// 2. 执行请求
|
||||
ResponseEntity<CommonResult<OAuth2AccessTokenRespDTO>> exchange = restTemplate.exchange(
|
||||
BASE_URL + "/token",
|
||||
HttpMethod.POST,
|
||||
new HttpEntity<>(body, headers),
|
||||
new ParameterizedTypeReference<CommonResult<OAuth2AccessTokenRespDTO>>() {}); // 解决 CommonResult 的泛型丢失
|
||||
Assert.isTrue(exchange.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功");
|
||||
return exchange.getBody();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除访问令牌
|
||||
*
|
||||
* @param token 访问令牌
|
||||
* @return 成功
|
||||
*/
|
||||
public CommonResult<Boolean> revokeToken(String token) {
|
||||
// 1.1 构建请求头
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
|
||||
headers.set("tenant-id", TENANT_ID.toString());
|
||||
addClientHeader(headers);
|
||||
// 1.2 构建请求参数
|
||||
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
|
||||
body.add("token", token);
|
||||
|
||||
// 2. 执行请求
|
||||
ResponseEntity<CommonResult<Boolean>> exchange = restTemplate.exchange(
|
||||
BASE_URL + "/token",
|
||||
HttpMethod.DELETE,
|
||||
new HttpEntity<>(body, headers),
|
||||
new ParameterizedTypeReference<CommonResult<Boolean>>() {}); // 解决 CommonResult 的泛型丢失
|
||||
Assert.isTrue(exchange.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功");
|
||||
return exchange.getBody();
|
||||
}
|
||||
|
||||
private static void addClientHeader(HttpHeaders headers) {
|
||||
// client 拼接,需要 BASE64 编码
|
||||
String client = CLIENT_ID + ":" + CLIENT_SECRET;
|
||||
client = Base64Utils.encodeToString(client.getBytes(StandardCharsets.UTF_8));
|
||||
headers.add("Authorization", "Basic " + client);
|
||||
}
|
||||
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
package com.xxl.job.admin.client;
|
||||
|
||||
import com.xxl.job.admin.client.dto.CommonResult;
|
||||
import com.xxl.job.admin.client.dto.user.UserInfoRespDTO;
|
||||
import com.xxl.job.admin.client.dto.user.UserUpdateReqDTO;
|
||||
import com.xxl.job.admin.framework.security.core.LoginUser;
|
||||
import com.xxl.job.admin.framework.security.core.util.SecurityUtils;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.*;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* 用户 User 信息的客户端
|
||||
*
|
||||
* 对应调用 OAuth2UserController 接口
|
||||
*/
|
||||
@Component
|
||||
public class UserClient {
|
||||
|
||||
private static final String BASE_URL = "http://121.36.203.133/admin-api/system/oauth2/user";
|
||||
|
||||
// @Resource // 可优化,注册一个 RestTemplate Bean,然后注入
|
||||
private final RestTemplate restTemplate = new RestTemplate();
|
||||
|
||||
public CommonResult<UserInfoRespDTO> getUser() {
|
||||
// 1.1 构建请求头
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
|
||||
headers.set("tenant-id", OAuth2Client.TENANT_ID.toString());
|
||||
addTokenHeader(headers);
|
||||
// 1.2 构建请求参数
|
||||
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
|
||||
|
||||
// 2. 执行请求
|
||||
ResponseEntity<CommonResult<UserInfoRespDTO>> exchange = restTemplate.exchange(
|
||||
BASE_URL + "/get",
|
||||
HttpMethod.GET,
|
||||
new HttpEntity<>(body, headers),
|
||||
new ParameterizedTypeReference<CommonResult<UserInfoRespDTO>>() {}); // 解决 CommonResult 的泛型丢失
|
||||
Assert.isTrue(exchange.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功");
|
||||
return exchange.getBody();
|
||||
}
|
||||
|
||||
public CommonResult<Boolean> updateUser(UserUpdateReqDTO updateReqDTO) {
|
||||
// 1.1 构建请求头
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
headers.set("tenant-id", OAuth2Client.TENANT_ID.toString());
|
||||
addTokenHeader(headers);
|
||||
// 1.2 构建请求参数
|
||||
// 使用 updateReqDTO 即可
|
||||
|
||||
// 2. 执行请求
|
||||
ResponseEntity<CommonResult<Boolean>> exchange = restTemplate.exchange(
|
||||
BASE_URL + "/update",
|
||||
HttpMethod.PUT,
|
||||
new HttpEntity<>(updateReqDTO, headers),
|
||||
new ParameterizedTypeReference<CommonResult<Boolean>>() {}); // 解决 CommonResult 的泛型丢失
|
||||
Assert.isTrue(exchange.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功");
|
||||
return exchange.getBody();
|
||||
}
|
||||
|
||||
|
||||
private static void addTokenHeader(HttpHeaders headers) {
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
Assert.notNull(loginUser, "登录用户不能为空");
|
||||
headers.add("Authorization", "Bearer " + loginUser.getAccessToken());
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
package com.xxl.job.admin.client.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 通用返回
|
||||
*
|
||||
* @param <T> 数据泛型
|
||||
*/
|
||||
@Data
|
||||
public class CommonResult<T> implements Serializable {
|
||||
|
||||
/**
|
||||
* 错误码
|
||||
*/
|
||||
private Integer code;
|
||||
/**
|
||||
* 返回数据
|
||||
*/
|
||||
private T data;
|
||||
/**
|
||||
* 错误提示,用户可阅读
|
||||
*/
|
||||
private String msg;
|
||||
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
package com.xxl.job.admin.client.dto.oauth2;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 访问令牌 Response DTO
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class OAuth2AccessTokenRespDTO {
|
||||
|
||||
/**
|
||||
* 访问令牌
|
||||
*/
|
||||
@JsonProperty("access_token")
|
||||
private String accessToken;
|
||||
|
||||
/**
|
||||
* 刷新令牌
|
||||
*/
|
||||
@JsonProperty("refresh_token")
|
||||
private String refreshToken;
|
||||
|
||||
/**
|
||||
* 令牌类型
|
||||
*/
|
||||
@JsonProperty("token_type")
|
||||
private String tokenType;
|
||||
|
||||
/**
|
||||
* 过期时间;单位:秒
|
||||
*/
|
||||
@JsonProperty("expires_in")
|
||||
private Long expiresIn;
|
||||
|
||||
/**
|
||||
* 授权范围;如果多个授权范围,使用空格分隔
|
||||
*/
|
||||
private String scope;
|
||||
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
package com.xxl.job.admin.client.dto.oauth2;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 校验令牌 Response DTO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class OAuth2CheckTokenRespDTO {
|
||||
|
||||
/**
|
||||
* 用户编号
|
||||
*/
|
||||
@JsonProperty("user_id")
|
||||
private Long userId;
|
||||
/**
|
||||
* 用户类型
|
||||
*/
|
||||
@JsonProperty("user_type")
|
||||
private Integer userType;
|
||||
/**
|
||||
* 租户编号
|
||||
*/
|
||||
@JsonProperty("tenant_id")
|
||||
private Long tenantId;
|
||||
|
||||
/**
|
||||
* 客户端编号
|
||||
*/
|
||||
@JsonProperty("client_id")
|
||||
private String clientId;
|
||||
/**
|
||||
* 授权范围
|
||||
*/
|
||||
private List<String> scopes;
|
||||
|
||||
/**
|
||||
* 访问令牌
|
||||
*/
|
||||
@JsonProperty("access_token")
|
||||
private String accessToken;
|
||||
|
||||
/**
|
||||
* 过期时间
|
||||
*
|
||||
* 时间戳 / 1000,即单位:秒
|
||||
*/
|
||||
private Long exp;
|
||||
|
||||
}
|
@ -1,97 +0,0 @@
|
||||
package com.xxl.job.admin.client.dto.user;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 获得用户基本信息 Response dto
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class UserInfoRespDTO {
|
||||
|
||||
/**
|
||||
* 用户编号
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 用户账号
|
||||
*/
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* 用户昵称
|
||||
*/
|
||||
private String nickname;
|
||||
|
||||
/**
|
||||
* 用户邮箱
|
||||
*/
|
||||
private String email;
|
||||
/**
|
||||
* 手机号码
|
||||
*/
|
||||
private String mobile;
|
||||
|
||||
/**
|
||||
* 用户性别
|
||||
*/
|
||||
private Integer sex;
|
||||
|
||||
/**
|
||||
* 用户头像
|
||||
*/
|
||||
private String avatar;
|
||||
|
||||
/**
|
||||
* 所在部门
|
||||
*/
|
||||
private Dept dept;
|
||||
|
||||
/**
|
||||
* 所属岗位数组
|
||||
*/
|
||||
private List<Post> posts;
|
||||
|
||||
/**
|
||||
* 部门
|
||||
*/
|
||||
@Data
|
||||
public static class Dept {
|
||||
|
||||
/**
|
||||
* 部门编号
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 部门名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 岗位
|
||||
*/
|
||||
@Data
|
||||
public static class Post {
|
||||
|
||||
/**
|
||||
* 岗位编号
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 岗位名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
package com.xxl.job.admin.client.dto.user;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 更新用户基本信息 Request DTO
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class UserUpdateReqDTO {
|
||||
|
||||
/**
|
||||
* 用户昵称
|
||||
*/
|
||||
private String nickname;
|
||||
|
||||
/**
|
||||
* 用户邮箱
|
||||
*/
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* 手机号码
|
||||
*/
|
||||
private String mobile;
|
||||
|
||||
/**
|
||||
* 用户性别
|
||||
*/
|
||||
private Integer sex;
|
||||
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
package com.xxl.job.admin.controller;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.xxl.job.admin.client.OAuth2Client;
|
||||
import com.xxl.job.admin.client.UserClient;
|
||||
import com.xxl.job.admin.client.dto.CommonResult;
|
||||
import com.xxl.job.admin.client.dto.oauth2.OAuth2AccessTokenRespDTO;
|
||||
import com.xxl.job.admin.client.dto.user.UserInfoRespDTO;
|
||||
import com.xxl.job.admin.framework.security.core.util.SecurityUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/auth")
|
||||
public class AuthController {
|
||||
@Resource
|
||||
private UserClient userClient;
|
||||
@Resource
|
||||
private OAuth2Client oauth2Client;
|
||||
|
||||
/**
|
||||
* 使用 code 访问令牌,获得访问令牌
|
||||
*
|
||||
* @param code 授权码
|
||||
* @param redirectUri 重定向 URI
|
||||
* @return 访问令牌;注意,实际项目中,最好创建对应的 ResponseVO 类,只返回必要的字段
|
||||
*/
|
||||
@PostMapping("/login-by-code")
|
||||
public CommonResult<OAuth2AccessTokenRespDTO> loginByCode(@RequestParam("code") String code,
|
||||
@RequestParam("redirectUri") String redirectUri) {
|
||||
return oauth2Client.postAccessToken(code, redirectUri);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用刷新令牌,获得(刷新)访问令牌
|
||||
*
|
||||
* @param refreshToken 刷新令牌
|
||||
* @return 访问令牌;注意,实际项目中,最好创建对应的 ResponseVO 类,只返回必要的字段
|
||||
*/
|
||||
@PostMapping("/refresh-token")
|
||||
public CommonResult<OAuth2AccessTokenRespDTO> refreshToken(@RequestParam("refreshToken") String refreshToken) {
|
||||
return oauth2Client.refreshToken(refreshToken);
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出登录
|
||||
*
|
||||
* @param request 请求
|
||||
* @return 成功
|
||||
*/
|
||||
@PostMapping("/logout")
|
||||
public CommonResult<Boolean> logout(HttpServletRequest request) {
|
||||
String token = SecurityUtils.obtainAuthorization(request, "Authorization");
|
||||
if (StrUtil.isNotBlank(token)) {
|
||||
return oauth2Client.revokeToken(token);
|
||||
}
|
||||
// 返回成功
|
||||
return new CommonResult<>();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获得当前登录用户的基本信息
|
||||
*
|
||||
* @return 用户信息;注意,实际项目中,最好创建对应的 ResponseVO 类,只返回必要的字段
|
||||
*/
|
||||
@GetMapping("/get")
|
||||
public CommonResult<UserInfoRespDTO> getUser() {
|
||||
return userClient.getUser();
|
||||
}
|
||||
}
|
@ -1,96 +0,0 @@
|
||||
package com.xxl.job.admin.controller;
|
||||
|
||||
import com.xxl.job.admin.controller.annotation.PermissionLimit;
|
||||
import com.xxl.job.admin.service.LoginService;
|
||||
import com.xxl.job.admin.service.XxlJobService;
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import org.springframework.beans.propertyeditors.CustomDateEditor;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
import org.springframework.web.bind.annotation.InitBinder;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.view.RedirectView;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* index controller
|
||||
* @author xuxueli 2015-12-19 16:13:16
|
||||
*/
|
||||
@Controller
|
||||
public class IndexController {
|
||||
|
||||
@Resource
|
||||
private XxlJobService xxlJobService;
|
||||
@Resource
|
||||
private LoginService loginService;
|
||||
|
||||
|
||||
@RequestMapping("/")
|
||||
public String index(Model model) {
|
||||
|
||||
Map<String, Object> dashboardMap = xxlJobService.dashboardInfo();
|
||||
model.addAllAttributes(dashboardMap);
|
||||
|
||||
return "index";
|
||||
}
|
||||
|
||||
@RequestMapping("/chartInfo")
|
||||
@ResponseBody
|
||||
public ReturnT<Map<String, Object>> chartInfo(Date startDate, Date endDate) {
|
||||
ReturnT<Map<String, Object>> chartInfo = xxlJobService.chartInfo(startDate, endDate);
|
||||
return chartInfo;
|
||||
}
|
||||
|
||||
@RequestMapping("/toLogin")
|
||||
@PermissionLimit(limit=false)
|
||||
public ModelAndView toLogin(HttpServletRequest request, HttpServletResponse response,ModelAndView modelAndView) {
|
||||
/*if (loginService.ifLogin(request, response) != null) {
|
||||
modelAndView.setView(new RedirectView("/",true,false));
|
||||
return modelAndView;
|
||||
}*/
|
||||
return new ModelAndView("login");
|
||||
}
|
||||
|
||||
@RequestMapping(value="login", method=RequestMethod.POST)
|
||||
@ResponseBody
|
||||
@PermissionLimit(limit=false)
|
||||
public ReturnT<String> loginDo(HttpServletRequest request, HttpServletResponse response, String userName, String password, String ifRemember){
|
||||
boolean ifRem = (ifRemember!=null && ifRemember.trim().length()>0 && "on".equals(ifRemember))?true:false;
|
||||
return loginService.login(request, response, userName, password, ifRem);
|
||||
}
|
||||
|
||||
@RequestMapping(value="logout", method=RequestMethod.POST)
|
||||
@ResponseBody
|
||||
@PermissionLimit(limit=false)
|
||||
public ReturnT<String> logout(HttpServletRequest request, HttpServletResponse response){
|
||||
return loginService.logout(request, response);
|
||||
}
|
||||
|
||||
@RequestMapping("/help")
|
||||
public String help() {
|
||||
|
||||
/*if (!PermissionInterceptor.ifLogin(request)) {
|
||||
return "redirect:/toLogin";
|
||||
}*/
|
||||
|
||||
return "help";
|
||||
}
|
||||
|
||||
@InitBinder
|
||||
public void initBinder(WebDataBinder binder) {
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
dateFormat.setLenient(false);
|
||||
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
|
||||
}
|
||||
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
package com.xxl.job.admin.controller;
|
||||
|
||||
import com.xxl.job.admin.controller.annotation.PermissionLimit;
|
||||
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
|
||||
import com.xxl.job.core.biz.AdminBiz;
|
||||
import com.xxl.job.core.biz.model.HandleCallbackParam;
|
||||
import com.xxl.job.core.biz.model.RegistryParam;
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import com.xxl.job.core.util.GsonTool;
|
||||
import com.xxl.job.core.util.XxlJobRemotingUtil;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by xuxueli on 17/5/10.
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/api")
|
||||
public class JobApiController {
|
||||
|
||||
@Resource
|
||||
private AdminBiz adminBiz;
|
||||
|
||||
/**
|
||||
* api
|
||||
*
|
||||
* @param uri
|
||||
* @param data
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping("/{uri}")
|
||||
@ResponseBody
|
||||
@PermissionLimit(limit=false)
|
||||
public ReturnT<String> api(HttpServletRequest request, @PathVariable("uri") String uri, @RequestBody(required = false) String data) {
|
||||
|
||||
// valid
|
||||
if (!"POST".equalsIgnoreCase(request.getMethod())) {
|
||||
return new ReturnT<String>(ReturnT.FAIL_CODE, "invalid request, HttpMethod not support.");
|
||||
}
|
||||
if (uri==null || uri.trim().length()==0) {
|
||||
return new ReturnT<String>(ReturnT.FAIL_CODE, "invalid request, uri-mapping empty.");
|
||||
}
|
||||
if (XxlJobAdminConfig.getAdminConfig().getAccessToken()!=null
|
||||
&& XxlJobAdminConfig.getAdminConfig().getAccessToken().trim().length()>0
|
||||
&& !XxlJobAdminConfig.getAdminConfig().getAccessToken().equals(request.getHeader(XxlJobRemotingUtil.XXL_JOB_ACCESS_TOKEN))) {
|
||||
return new ReturnT<String>(ReturnT.FAIL_CODE, "The access token is wrong.");
|
||||
}
|
||||
|
||||
// services mapping
|
||||
if ("callback".equals(uri)) {
|
||||
List<HandleCallbackParam> callbackParamList = GsonTool.fromJson(data, List.class, HandleCallbackParam.class);
|
||||
return adminBiz.callback(callbackParamList);
|
||||
} else if ("registry".equals(uri)) {
|
||||
RegistryParam registryParam = GsonTool.fromJson(data, RegistryParam.class);
|
||||
return adminBiz.registry(registryParam);
|
||||
} else if ("registryRemove".equals(uri)) {
|
||||
RegistryParam registryParam = GsonTool.fromJson(data, RegistryParam.class);
|
||||
return adminBiz.registryRemove(registryParam);
|
||||
} else {
|
||||
return new ReturnT<String>(ReturnT.FAIL_CODE, "invalid request, uri-mapping("+ uri +") not found.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,96 +0,0 @@
|
||||
package com.xxl.job.admin.controller;
|
||||
|
||||
import com.xxl.job.admin.core.model.XxlJobInfo;
|
||||
import com.xxl.job.admin.core.model.XxlJobLogGlue;
|
||||
import com.xxl.job.admin.core.util.I18nUtil;
|
||||
import com.xxl.job.admin.dao.XxlJobInfoDao;
|
||||
import com.xxl.job.admin.dao.XxlJobLogGlueDao;
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import com.xxl.job.core.glue.GlueTypeEnum;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* job code controller
|
||||
* @author xuxueli 2015-12-19 16:13:16
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/jobcode")
|
||||
public class JobCodeController {
|
||||
|
||||
@Resource
|
||||
private XxlJobInfoDao xxlJobInfoDao;
|
||||
@Resource
|
||||
private XxlJobLogGlueDao xxlJobLogGlueDao;
|
||||
|
||||
@RequestMapping
|
||||
public String index(HttpServletRequest request, Model model, int jobId) {
|
||||
XxlJobInfo jobInfo = xxlJobInfoDao.loadById(jobId);
|
||||
List<XxlJobLogGlue> jobLogGlues = xxlJobLogGlueDao.findByJobId(jobId);
|
||||
|
||||
if (jobInfo == null) {
|
||||
throw new RuntimeException(I18nUtil.getString("jobinfo_glue_jobid_unvalid"));
|
||||
}
|
||||
if (GlueTypeEnum.BEAN == GlueTypeEnum.match(jobInfo.getGlueType())) {
|
||||
throw new RuntimeException(I18nUtil.getString("jobinfo_glue_gluetype_unvalid"));
|
||||
}
|
||||
|
||||
// valid permission
|
||||
JobInfoController.validPermission(request, jobInfo.getJobGroup());
|
||||
|
||||
// Glue类型-字典
|
||||
model.addAttribute("GlueTypeEnum", GlueTypeEnum.values());
|
||||
|
||||
model.addAttribute("jobInfo", jobInfo);
|
||||
model.addAttribute("jobLogGlues", jobLogGlues);
|
||||
return "jobcode/jobcode.index";
|
||||
}
|
||||
|
||||
@RequestMapping("/save")
|
||||
@ResponseBody
|
||||
public ReturnT<String> save(Model model, int id, String glueSource, String glueRemark) {
|
||||
// valid
|
||||
if (glueRemark==null) {
|
||||
return new ReturnT<String>(500, (I18nUtil.getString("system_please_input") + I18nUtil.getString("jobinfo_glue_remark")) );
|
||||
}
|
||||
if (glueRemark.length()<4 || glueRemark.length()>100) {
|
||||
return new ReturnT<String>(500, I18nUtil.getString("jobinfo_glue_remark_limit"));
|
||||
}
|
||||
XxlJobInfo exists_jobInfo = xxlJobInfoDao.loadById(id);
|
||||
if (exists_jobInfo == null) {
|
||||
return new ReturnT<String>(500, I18nUtil.getString("jobinfo_glue_jobid_unvalid"));
|
||||
}
|
||||
|
||||
// update new code
|
||||
exists_jobInfo.setGlueSource(glueSource);
|
||||
exists_jobInfo.setGlueRemark(glueRemark);
|
||||
exists_jobInfo.setGlueUpdatetime(new Date());
|
||||
|
||||
exists_jobInfo.setUpdateTime(new Date());
|
||||
xxlJobInfoDao.update(exists_jobInfo);
|
||||
|
||||
// log old code
|
||||
XxlJobLogGlue xxlJobLogGlue = new XxlJobLogGlue();
|
||||
xxlJobLogGlue.setJobId(exists_jobInfo.getId());
|
||||
xxlJobLogGlue.setGlueType(exists_jobInfo.getGlueType());
|
||||
xxlJobLogGlue.setGlueSource(glueSource);
|
||||
xxlJobLogGlue.setGlueRemark(glueRemark);
|
||||
|
||||
xxlJobLogGlue.setAddTime(new Date());
|
||||
xxlJobLogGlue.setUpdateTime(new Date());
|
||||
xxlJobLogGlueDao.save(xxlJobLogGlue);
|
||||
|
||||
// remove code backup more than 30
|
||||
xxlJobLogGlueDao.removeOld(exists_jobInfo.getId(), 30);
|
||||
|
||||
return ReturnT.SUCCESS;
|
||||
}
|
||||
|
||||
}
|
@ -1,204 +0,0 @@
|
||||
package com.xxl.job.admin.controller;
|
||||
|
||||
import com.xxl.job.admin.controller.annotation.PermissionLimit;
|
||||
import com.xxl.job.admin.core.model.XxlJobGroup;
|
||||
import com.xxl.job.admin.core.model.XxlJobRegistry;
|
||||
import com.xxl.job.admin.core.util.I18nUtil;
|
||||
import com.xxl.job.admin.dao.XxlJobGroupDao;
|
||||
import com.xxl.job.admin.dao.XxlJobInfoDao;
|
||||
import com.xxl.job.admin.dao.XxlJobRegistryDao;
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import com.xxl.job.core.enums.RegistryConfig;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* job group controller
|
||||
* @author xuxueli 2016-10-02 20:52:56
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/jobgroup")
|
||||
public class JobGroupController {
|
||||
|
||||
@Resource
|
||||
public XxlJobInfoDao xxlJobInfoDao;
|
||||
@Resource
|
||||
public XxlJobGroupDao xxlJobGroupDao;
|
||||
@Resource
|
||||
private XxlJobRegistryDao xxlJobRegistryDao;
|
||||
|
||||
@RequestMapping
|
||||
@PermissionLimit(adminuser = true)
|
||||
public String index(Model model) {
|
||||
return "jobgroup/jobgroup.index";
|
||||
}
|
||||
|
||||
@RequestMapping("/pageList")
|
||||
@ResponseBody
|
||||
@PermissionLimit(adminuser = true)
|
||||
public Map<String, Object> pageList(HttpServletRequest request,
|
||||
@RequestParam(required = false, defaultValue = "0") int start,
|
||||
@RequestParam(required = false, defaultValue = "10") int length,
|
||||
String appname, String title) {
|
||||
|
||||
// page query
|
||||
List<XxlJobGroup> list = xxlJobGroupDao.pageList(start, length, appname, title);
|
||||
int list_count = xxlJobGroupDao.pageListCount(start, length, appname, title);
|
||||
|
||||
// package result
|
||||
Map<String, Object> maps = new HashMap<String, Object>();
|
||||
maps.put("recordsTotal", list_count); // 总记录数
|
||||
maps.put("recordsFiltered", list_count); // 过滤后的总记录数
|
||||
maps.put("data", list); // 分页列表
|
||||
return maps;
|
||||
}
|
||||
|
||||
@RequestMapping("/save")
|
||||
@ResponseBody
|
||||
@PermissionLimit(adminuser = true)
|
||||
public ReturnT<String> save(XxlJobGroup xxlJobGroup){
|
||||
|
||||
// valid
|
||||
if (xxlJobGroup.getAppname()==null || xxlJobGroup.getAppname().trim().length()==0) {
|
||||
return new ReturnT<String>(500, (I18nUtil.getString("system_please_input")+"AppName") );
|
||||
}
|
||||
if (xxlJobGroup.getAppname().length()<4 || xxlJobGroup.getAppname().length()>64) {
|
||||
return new ReturnT<String>(500, I18nUtil.getString("jobgroup_field_appname_length") );
|
||||
}
|
||||
if (xxlJobGroup.getAppname().contains(">") || xxlJobGroup.getAppname().contains("<")) {
|
||||
return new ReturnT<String>(500, "AppName"+I18nUtil.getString("system_unvalid") );
|
||||
}
|
||||
if (xxlJobGroup.getTitle()==null || xxlJobGroup.getTitle().trim().length()==0) {
|
||||
return new ReturnT<String>(500, (I18nUtil.getString("system_please_input") + I18nUtil.getString("jobgroup_field_title")) );
|
||||
}
|
||||
if (xxlJobGroup.getTitle().contains(">") || xxlJobGroup.getTitle().contains("<")) {
|
||||
return new ReturnT<String>(500, I18nUtil.getString("jobgroup_field_title")+I18nUtil.getString("system_unvalid") );
|
||||
}
|
||||
if (xxlJobGroup.getAddressType()!=0) {
|
||||
if (xxlJobGroup.getAddressList()==null || xxlJobGroup.getAddressList().trim().length()==0) {
|
||||
return new ReturnT<String>(500, I18nUtil.getString("jobgroup_field_addressType_limit") );
|
||||
}
|
||||
if (xxlJobGroup.getAddressList().contains(">") || xxlJobGroup.getAddressList().contains("<")) {
|
||||
return new ReturnT<String>(500, I18nUtil.getString("jobgroup_field_registryList")+I18nUtil.getString("system_unvalid") );
|
||||
}
|
||||
|
||||
String[] addresss = xxlJobGroup.getAddressList().split(",");
|
||||
for (String item: addresss) {
|
||||
if (item==null || item.trim().length()==0) {
|
||||
return new ReturnT<String>(500, I18nUtil.getString("jobgroup_field_registryList_unvalid") );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// process
|
||||
xxlJobGroup.setUpdateTime(new Date());
|
||||
|
||||
int ret = xxlJobGroupDao.save(xxlJobGroup);
|
||||
return (ret>0)?ReturnT.SUCCESS:ReturnT.FAIL;
|
||||
}
|
||||
|
||||
@RequestMapping("/update")
|
||||
@ResponseBody
|
||||
@PermissionLimit(adminuser = true)
|
||||
public ReturnT<String> update(XxlJobGroup xxlJobGroup){
|
||||
// valid
|
||||
if (xxlJobGroup.getAppname()==null || xxlJobGroup.getAppname().trim().length()==0) {
|
||||
return new ReturnT<String>(500, (I18nUtil.getString("system_please_input")+"AppName") );
|
||||
}
|
||||
if (xxlJobGroup.getAppname().length()<4 || xxlJobGroup.getAppname().length()>64) {
|
||||
return new ReturnT<String>(500, I18nUtil.getString("jobgroup_field_appname_length") );
|
||||
}
|
||||
if (xxlJobGroup.getTitle()==null || xxlJobGroup.getTitle().trim().length()==0) {
|
||||
return new ReturnT<String>(500, (I18nUtil.getString("system_please_input") + I18nUtil.getString("jobgroup_field_title")) );
|
||||
}
|
||||
if (xxlJobGroup.getAddressType() == 0) {
|
||||
// 0=自动注册
|
||||
List<String> registryList = findRegistryByAppName(xxlJobGroup.getAppname());
|
||||
String addressListStr = null;
|
||||
if (registryList!=null && !registryList.isEmpty()) {
|
||||
Collections.sort(registryList);
|
||||
addressListStr = "";
|
||||
for (String item:registryList) {
|
||||
addressListStr += item + ",";
|
||||
}
|
||||
addressListStr = addressListStr.substring(0, addressListStr.length()-1);
|
||||
}
|
||||
xxlJobGroup.setAddressList(addressListStr);
|
||||
} else {
|
||||
// 1=手动录入
|
||||
if (xxlJobGroup.getAddressList()==null || xxlJobGroup.getAddressList().trim().length()==0) {
|
||||
return new ReturnT<String>(500, I18nUtil.getString("jobgroup_field_addressType_limit") );
|
||||
}
|
||||
String[] addresss = xxlJobGroup.getAddressList().split(",");
|
||||
for (String item: addresss) {
|
||||
if (item==null || item.trim().length()==0) {
|
||||
return new ReturnT<String>(500, I18nUtil.getString("jobgroup_field_registryList_unvalid") );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// process
|
||||
xxlJobGroup.setUpdateTime(new Date());
|
||||
|
||||
int ret = xxlJobGroupDao.update(xxlJobGroup);
|
||||
return (ret>0)?ReturnT.SUCCESS:ReturnT.FAIL;
|
||||
}
|
||||
|
||||
private List<String> findRegistryByAppName(String appnameParam){
|
||||
HashMap<String, List<String>> appAddressMap = new HashMap<String, List<String>>();
|
||||
List<XxlJobRegistry> list = xxlJobRegistryDao.findAll(RegistryConfig.DEAD_TIMEOUT, new Date());
|
||||
if (list != null) {
|
||||
for (XxlJobRegistry item: list) {
|
||||
if (RegistryConfig.RegistType.EXECUTOR.name().equals(item.getRegistryGroup())) {
|
||||
String appname = item.getRegistryKey();
|
||||
List<String> registryList = appAddressMap.get(appname);
|
||||
if (registryList == null) {
|
||||
registryList = new ArrayList<String>();
|
||||
}
|
||||
|
||||
if (!registryList.contains(item.getRegistryValue())) {
|
||||
registryList.add(item.getRegistryValue());
|
||||
}
|
||||
appAddressMap.put(appname, registryList);
|
||||
}
|
||||
}
|
||||
}
|
||||
return appAddressMap.get(appnameParam);
|
||||
}
|
||||
|
||||
@RequestMapping("/remove")
|
||||
@ResponseBody
|
||||
@PermissionLimit(adminuser = true)
|
||||
public ReturnT<String> remove(int id){
|
||||
|
||||
// valid
|
||||
int count = xxlJobInfoDao.pageListCount(0, 10, id, -1, null, null, null);
|
||||
if (count > 0) {
|
||||
return new ReturnT<String>(500, I18nUtil.getString("jobgroup_del_limit_0") );
|
||||
}
|
||||
|
||||
List<XxlJobGroup> allList = xxlJobGroupDao.findAll();
|
||||
if (allList.size() == 1) {
|
||||
return new ReturnT<String>(500, I18nUtil.getString("jobgroup_del_limit_1") );
|
||||
}
|
||||
|
||||
int ret = xxlJobGroupDao.remove(id);
|
||||
return (ret>0)?ReturnT.SUCCESS:ReturnT.FAIL;
|
||||
}
|
||||
|
||||
@RequestMapping("/loadById")
|
||||
@ResponseBody
|
||||
@PermissionLimit(adminuser = true)
|
||||
public ReturnT<XxlJobGroup> loadById(int id){
|
||||
XxlJobGroup jobGroup = xxlJobGroupDao.load(id);
|
||||
return jobGroup!=null?new ReturnT<XxlJobGroup>(jobGroup):new ReturnT<XxlJobGroup>(ReturnT.FAIL_CODE, null);
|
||||
}
|
||||
|
||||
}
|
@ -1,172 +0,0 @@
|
||||
package com.xxl.job.admin.controller;
|
||||
|
||||
import com.xxl.job.admin.core.exception.XxlJobException;
|
||||
import com.xxl.job.admin.core.model.XxlJobGroup;
|
||||
import com.xxl.job.admin.core.model.XxlJobInfo;
|
||||
import com.xxl.job.admin.core.model.XxlJobUser;
|
||||
import com.xxl.job.admin.core.route.ExecutorRouteStrategyEnum;
|
||||
import com.xxl.job.admin.core.scheduler.MisfireStrategyEnum;
|
||||
import com.xxl.job.admin.core.scheduler.ScheduleTypeEnum;
|
||||
import com.xxl.job.admin.core.thread.JobScheduleHelper;
|
||||
import com.xxl.job.admin.core.util.I18nUtil;
|
||||
import com.xxl.job.admin.dao.XxlJobGroupDao;
|
||||
import com.xxl.job.admin.service.LoginService;
|
||||
import com.xxl.job.admin.service.XxlJobService;
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import com.xxl.job.core.enums.ExecutorBlockStrategyEnum;
|
||||
import com.xxl.job.core.glue.GlueTypeEnum;
|
||||
import com.xxl.job.core.util.DateUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* index controller
|
||||
* @author xuxueli 2015-12-19 16:13:16
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/jobinfo")
|
||||
public class JobInfoController {
|
||||
private static Logger logger = LoggerFactory.getLogger(JobInfoController.class);
|
||||
|
||||
@Resource
|
||||
private XxlJobGroupDao xxlJobGroupDao;
|
||||
@Resource
|
||||
private XxlJobService xxlJobService;
|
||||
|
||||
@RequestMapping
|
||||
public String index(HttpServletRequest request, Model model, @RequestParam(required = false, defaultValue = "-1") int jobGroup) {
|
||||
|
||||
// 枚举-字典
|
||||
model.addAttribute("ExecutorRouteStrategyEnum", ExecutorRouteStrategyEnum.values()); // 路由策略-列表
|
||||
model.addAttribute("GlueTypeEnum", GlueTypeEnum.values()); // Glue类型-字典
|
||||
model.addAttribute("ExecutorBlockStrategyEnum", ExecutorBlockStrategyEnum.values()); // 阻塞处理策略-字典
|
||||
model.addAttribute("ScheduleTypeEnum", ScheduleTypeEnum.values()); // 调度类型
|
||||
model.addAttribute("MisfireStrategyEnum", MisfireStrategyEnum.values()); // 调度过期策略
|
||||
|
||||
// 执行器列表
|
||||
List<XxlJobGroup> jobGroupList_all = xxlJobGroupDao.findAll();
|
||||
|
||||
// filter group
|
||||
List<XxlJobGroup> jobGroupList = filterJobGroupByRole(request, jobGroupList_all);
|
||||
if (jobGroupList==null || jobGroupList.size()==0) {
|
||||
throw new XxlJobException(I18nUtil.getString("jobgroup_empty"));
|
||||
}
|
||||
|
||||
model.addAttribute("JobGroupList", jobGroupList);
|
||||
model.addAttribute("jobGroup", jobGroup);
|
||||
|
||||
return "jobinfo/jobinfo.index";
|
||||
}
|
||||
|
||||
public static List<XxlJobGroup> filterJobGroupByRole(HttpServletRequest request, List<XxlJobGroup> jobGroupList_all){
|
||||
List<XxlJobGroup> jobGroupList = new ArrayList<>();
|
||||
if (jobGroupList_all!=null && jobGroupList_all.size()>0) {
|
||||
XxlJobUser loginUser = (XxlJobUser) request.getAttribute(LoginService.LOGIN_IDENTITY_KEY);
|
||||
if (loginUser.getRole() == 1) {
|
||||
jobGroupList = jobGroupList_all;
|
||||
} else {
|
||||
List<String> groupIdStrs = new ArrayList<>();
|
||||
if (loginUser.getPermission()!=null && loginUser.getPermission().trim().length()>0) {
|
||||
groupIdStrs = Arrays.asList(loginUser.getPermission().trim().split(","));
|
||||
}
|
||||
for (XxlJobGroup groupItem:jobGroupList_all) {
|
||||
if (groupIdStrs.contains(String.valueOf(groupItem.getId()))) {
|
||||
jobGroupList.add(groupItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return jobGroupList;
|
||||
}
|
||||
public static void validPermission(HttpServletRequest request, int jobGroup) {
|
||||
XxlJobUser loginUser = (XxlJobUser) request.getAttribute(LoginService.LOGIN_IDENTITY_KEY);
|
||||
if (!loginUser.validPermission(jobGroup)) {
|
||||
throw new RuntimeException(I18nUtil.getString("system_permission_limit") + "[username="+ loginUser.getUsername() +"]");
|
||||
}
|
||||
}
|
||||
|
||||
@RequestMapping("/pageList")
|
||||
@ResponseBody
|
||||
public Map<String, Object> pageList(@RequestParam(required = false, defaultValue = "0") int start,
|
||||
@RequestParam(required = false, defaultValue = "10") int length,
|
||||
int jobGroup, int triggerStatus, String jobDesc, String executorHandler, String author) {
|
||||
|
||||
return xxlJobService.pageList(start, length, jobGroup, triggerStatus, jobDesc, executorHandler, author);
|
||||
}
|
||||
|
||||
@RequestMapping("/add")
|
||||
@ResponseBody
|
||||
public ReturnT<String> add(XxlJobInfo jobInfo) {
|
||||
return xxlJobService.add(jobInfo);
|
||||
}
|
||||
|
||||
@RequestMapping("/update")
|
||||
@ResponseBody
|
||||
public ReturnT<String> update(XxlJobInfo jobInfo) {
|
||||
return xxlJobService.update(jobInfo);
|
||||
}
|
||||
|
||||
@RequestMapping("/remove")
|
||||
@ResponseBody
|
||||
public ReturnT<String> remove(int id) {
|
||||
return xxlJobService.remove(id);
|
||||
}
|
||||
|
||||
@RequestMapping("/stop")
|
||||
@ResponseBody
|
||||
public ReturnT<String> pause(int id) {
|
||||
return xxlJobService.stop(id);
|
||||
}
|
||||
|
||||
@RequestMapping("/start")
|
||||
@ResponseBody
|
||||
public ReturnT<String> start(int id) {
|
||||
return xxlJobService.start(id);
|
||||
}
|
||||
|
||||
@RequestMapping("/trigger")
|
||||
@ResponseBody
|
||||
public ReturnT<String> triggerJob(HttpServletRequest request, int id, String executorParam, String addressList) {
|
||||
// login user
|
||||
XxlJobUser loginUser = (XxlJobUser) request.getAttribute(LoginService.LOGIN_IDENTITY_KEY);
|
||||
// trigger
|
||||
return xxlJobService.trigger(loginUser, id, executorParam, addressList);
|
||||
}
|
||||
|
||||
@RequestMapping("/nextTriggerTime")
|
||||
@ResponseBody
|
||||
public ReturnT<List<String>> nextTriggerTime(String scheduleType, String scheduleConf) {
|
||||
|
||||
XxlJobInfo paramXxlJobInfo = new XxlJobInfo();
|
||||
paramXxlJobInfo.setScheduleType(scheduleType);
|
||||
paramXxlJobInfo.setScheduleConf(scheduleConf);
|
||||
|
||||
List<String> result = new ArrayList<>();
|
||||
try {
|
||||
Date lastTime = new Date();
|
||||
for (int i = 0; i < 5; i++) {
|
||||
lastTime = JobScheduleHelper.generateNextValidTime(paramXxlJobInfo, lastTime);
|
||||
if (lastTime != null) {
|
||||
result.add(DateUtil.formatDateTime(lastTime));
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
return new ReturnT<List<String>>(ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type")+I18nUtil.getString("system_unvalid")) + e.getMessage());
|
||||
}
|
||||
return new ReturnT<List<String>>(result);
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,246 +0,0 @@
|
||||
package com.xxl.job.admin.controller;
|
||||
|
||||
import com.xxl.job.admin.core.complete.XxlJobCompleter;
|
||||
import com.xxl.job.admin.core.exception.XxlJobException;
|
||||
import com.xxl.job.admin.core.model.XxlJobGroup;
|
||||
import com.xxl.job.admin.core.model.XxlJobInfo;
|
||||
import com.xxl.job.admin.core.model.XxlJobLog;
|
||||
import com.xxl.job.admin.core.scheduler.XxlJobScheduler;
|
||||
import com.xxl.job.admin.core.util.I18nUtil;
|
||||
import com.xxl.job.admin.dao.XxlJobGroupDao;
|
||||
import com.xxl.job.admin.dao.XxlJobInfoDao;
|
||||
import com.xxl.job.admin.dao.XxlJobLogDao;
|
||||
import com.xxl.job.core.biz.ExecutorBiz;
|
||||
import com.xxl.job.core.biz.model.KillParam;
|
||||
import com.xxl.job.core.biz.model.LogParam;
|
||||
import com.xxl.job.core.biz.model.LogResult;
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import com.xxl.job.core.util.DateUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.util.HtmlUtils;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* index controller
|
||||
* @author xuxueli 2015-12-19 16:13:16
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/joblog")
|
||||
public class JobLogController {
|
||||
private static Logger logger = LoggerFactory.getLogger(JobLogController.class);
|
||||
|
||||
@Resource
|
||||
private XxlJobGroupDao xxlJobGroupDao;
|
||||
@Resource
|
||||
public XxlJobInfoDao xxlJobInfoDao;
|
||||
@Resource
|
||||
public XxlJobLogDao xxlJobLogDao;
|
||||
|
||||
@RequestMapping
|
||||
public String index(HttpServletRequest request, Model model, @RequestParam(required = false, defaultValue = "0") Integer jobId) {
|
||||
|
||||
// 执行器列表
|
||||
List<XxlJobGroup> jobGroupList_all = xxlJobGroupDao.findAll();
|
||||
|
||||
// filter group
|
||||
List<XxlJobGroup> jobGroupList = JobInfoController.filterJobGroupByRole(request, jobGroupList_all);
|
||||
if (jobGroupList==null || jobGroupList.size()==0) {
|
||||
throw new XxlJobException(I18nUtil.getString("jobgroup_empty"));
|
||||
}
|
||||
|
||||
model.addAttribute("JobGroupList", jobGroupList);
|
||||
|
||||
// 任务
|
||||
if (jobId > 0) {
|
||||
XxlJobInfo jobInfo = xxlJobInfoDao.loadById(jobId);
|
||||
if (jobInfo == null) {
|
||||
throw new RuntimeException(I18nUtil.getString("jobinfo_field_id") + I18nUtil.getString("system_unvalid"));
|
||||
}
|
||||
|
||||
model.addAttribute("jobInfo", jobInfo);
|
||||
|
||||
// valid permission
|
||||
JobInfoController.validPermission(request, jobInfo.getJobGroup());
|
||||
}
|
||||
|
||||
return "joblog/joblog.index";
|
||||
}
|
||||
|
||||
@RequestMapping("/getJobsByGroup")
|
||||
@ResponseBody
|
||||
public ReturnT<List<XxlJobInfo>> getJobsByGroup(int jobGroup){
|
||||
List<XxlJobInfo> list = xxlJobInfoDao.getJobsByGroup(jobGroup);
|
||||
return new ReturnT<List<XxlJobInfo>>(list);
|
||||
}
|
||||
|
||||
@RequestMapping("/pageList")
|
||||
@ResponseBody
|
||||
public Map<String, Object> pageList(HttpServletRequest request,
|
||||
@RequestParam(required = false, defaultValue = "0") int start,
|
||||
@RequestParam(required = false, defaultValue = "10") int length,
|
||||
int jobGroup, int jobId, int logStatus, String filterTime) {
|
||||
|
||||
// valid permission
|
||||
JobInfoController.validPermission(request, jobGroup); // 仅管理员支持查询全部;普通用户仅支持查询有权限的 jobGroup
|
||||
|
||||
// parse param
|
||||
Date triggerTimeStart = null;
|
||||
Date triggerTimeEnd = null;
|
||||
if (filterTime!=null && filterTime.trim().length()>0) {
|
||||
String[] temp = filterTime.split(" - ");
|
||||
if (temp.length == 2) {
|
||||
triggerTimeStart = DateUtil.parseDateTime(temp[0]);
|
||||
triggerTimeEnd = DateUtil.parseDateTime(temp[1]);
|
||||
}
|
||||
}
|
||||
|
||||
// page query
|
||||
List<XxlJobLog> list = xxlJobLogDao.pageList(start, length, jobGroup, jobId, triggerTimeStart, triggerTimeEnd, logStatus);
|
||||
int list_count = xxlJobLogDao.pageListCount(start, length, jobGroup, jobId, triggerTimeStart, triggerTimeEnd, logStatus);
|
||||
|
||||
// package result
|
||||
Map<String, Object> maps = new HashMap<String, Object>();
|
||||
maps.put("recordsTotal", list_count); // 总记录数
|
||||
maps.put("recordsFiltered", list_count); // 过滤后的总记录数
|
||||
maps.put("data", list); // 分页列表
|
||||
return maps;
|
||||
}
|
||||
|
||||
@RequestMapping("/logDetailPage")
|
||||
public String logDetailPage(int id, Model model){
|
||||
|
||||
// base check
|
||||
ReturnT<String> logStatue = ReturnT.SUCCESS;
|
||||
XxlJobLog jobLog = xxlJobLogDao.load(id);
|
||||
if (jobLog == null) {
|
||||
throw new RuntimeException(I18nUtil.getString("joblog_logid_unvalid"));
|
||||
}
|
||||
|
||||
model.addAttribute("triggerCode", jobLog.getTriggerCode());
|
||||
model.addAttribute("handleCode", jobLog.getHandleCode());
|
||||
model.addAttribute("logId", jobLog.getId());
|
||||
return "joblog/joblog.detail";
|
||||
}
|
||||
|
||||
@RequestMapping("/logDetailCat")
|
||||
@ResponseBody
|
||||
public ReturnT<LogResult> logDetailCat(long logId, int fromLineNum){
|
||||
try {
|
||||
// valid
|
||||
XxlJobLog jobLog = xxlJobLogDao.load(logId); // todo, need to improve performance
|
||||
if (jobLog == null) {
|
||||
return new ReturnT<LogResult>(ReturnT.FAIL_CODE, I18nUtil.getString("joblog_logid_unvalid"));
|
||||
}
|
||||
|
||||
// log cat
|
||||
ExecutorBiz executorBiz = XxlJobScheduler.getExecutorBiz(jobLog.getExecutorAddress());
|
||||
ReturnT<LogResult> logResult = executorBiz.log(new LogParam(jobLog.getTriggerTime().getTime(), logId, fromLineNum));
|
||||
|
||||
// is end
|
||||
if (logResult.getContent()!=null && logResult.getContent().getFromLineNum() > logResult.getContent().getToLineNum()) {
|
||||
if (jobLog.getHandleCode() > 0) {
|
||||
logResult.getContent().setEnd(true);
|
||||
}
|
||||
}
|
||||
|
||||
// fix xss
|
||||
if (logResult.getContent()!=null && StringUtils.hasText(logResult.getContent().getLogContent())) {
|
||||
String newLogContent = logResult.getContent().getLogContent();
|
||||
newLogContent = HtmlUtils.htmlEscape(newLogContent, "UTF-8");
|
||||
logResult.getContent().setLogContent(newLogContent);
|
||||
}
|
||||
|
||||
return logResult;
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
return new ReturnT<LogResult>(ReturnT.FAIL_CODE, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@RequestMapping("/logKill")
|
||||
@ResponseBody
|
||||
public ReturnT<String> logKill(int id){
|
||||
// base check
|
||||
XxlJobLog log = xxlJobLogDao.load(id);
|
||||
XxlJobInfo jobInfo = xxlJobInfoDao.loadById(log.getJobId());
|
||||
if (jobInfo==null) {
|
||||
return new ReturnT<String>(500, I18nUtil.getString("jobinfo_glue_jobid_unvalid"));
|
||||
}
|
||||
if (ReturnT.SUCCESS_CODE != log.getTriggerCode()) {
|
||||
return new ReturnT<String>(500, I18nUtil.getString("joblog_kill_log_limit"));
|
||||
}
|
||||
|
||||
// request of kill
|
||||
ReturnT<String> runResult = null;
|
||||
try {
|
||||
ExecutorBiz executorBiz = XxlJobScheduler.getExecutorBiz(log.getExecutorAddress());
|
||||
runResult = executorBiz.kill(new KillParam(jobInfo.getId()));
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
runResult = new ReturnT<String>(500, e.getMessage());
|
||||
}
|
||||
|
||||
if (ReturnT.SUCCESS_CODE == runResult.getCode()) {
|
||||
log.setHandleCode(ReturnT.FAIL_CODE);
|
||||
log.setHandleMsg( I18nUtil.getString("joblog_kill_log_byman")+":" + (runResult.getMsg()!=null?runResult.getMsg():""));
|
||||
log.setHandleTime(new Date());
|
||||
XxlJobCompleter.updateHandleInfoAndFinish(log);
|
||||
return new ReturnT<String>(runResult.getMsg());
|
||||
} else {
|
||||
return new ReturnT<String>(500, runResult.getMsg());
|
||||
}
|
||||
}
|
||||
|
||||
@RequestMapping("/clearLog")
|
||||
@ResponseBody
|
||||
public ReturnT<String> clearLog(int jobGroup, int jobId, int type){
|
||||
|
||||
Date clearBeforeTime = null;
|
||||
int clearBeforeNum = 0;
|
||||
if (type == 1) {
|
||||
clearBeforeTime = DateUtil.addMonths(new Date(), -1); // 清理一个月之前日志数据
|
||||
} else if (type == 2) {
|
||||
clearBeforeTime = DateUtil.addMonths(new Date(), -3); // 清理三个月之前日志数据
|
||||
} else if (type == 3) {
|
||||
clearBeforeTime = DateUtil.addMonths(new Date(), -6); // 清理六个月之前日志数据
|
||||
} else if (type == 4) {
|
||||
clearBeforeTime = DateUtil.addYears(new Date(), -1); // 清理一年之前日志数据
|
||||
} else if (type == 5) {
|
||||
clearBeforeNum = 1000; // 清理一千条以前日志数据
|
||||
} else if (type == 6) {
|
||||
clearBeforeNum = 10000; // 清理一万条以前日志数据
|
||||
} else if (type == 7) {
|
||||
clearBeforeNum = 30000; // 清理三万条以前日志数据
|
||||
} else if (type == 8) {
|
||||
clearBeforeNum = 100000; // 清理十万条以前日志数据
|
||||
} else if (type == 9) {
|
||||
clearBeforeNum = 0; // 清理所有日志数据
|
||||
} else {
|
||||
return new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("joblog_clean_type_unvalid"));
|
||||
}
|
||||
|
||||
List<Long> logIds = null;
|
||||
do {
|
||||
logIds = xxlJobLogDao.findClearLogIds(jobGroup, jobId, clearBeforeTime, clearBeforeNum, 1000);
|
||||
if (logIds!=null && logIds.size()>0) {
|
||||
xxlJobLogDao.clearLog(logIds);
|
||||
}
|
||||
} while (logIds!=null && logIds.size()>0);
|
||||
|
||||
return ReturnT.SUCCESS;
|
||||
}
|
||||
|
||||
}
|
@ -1,179 +0,0 @@
|
||||
package com.xxl.job.admin.controller;
|
||||
|
||||
import com.xxl.job.admin.controller.annotation.PermissionLimit;
|
||||
import com.xxl.job.admin.core.model.XxlJobGroup;
|
||||
import com.xxl.job.admin.core.model.XxlJobUser;
|
||||
import com.xxl.job.admin.core.util.I18nUtil;
|
||||
import com.xxl.job.admin.dao.XxlJobGroupDao;
|
||||
import com.xxl.job.admin.dao.XxlJobUserDao;
|
||||
import com.xxl.job.admin.service.LoginService;
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.util.DigestUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author xuxueli 2019-05-04 16:39:50
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/user")
|
||||
public class UserController {
|
||||
|
||||
@Resource
|
||||
private XxlJobUserDao xxlJobUserDao;
|
||||
@Resource
|
||||
private XxlJobGroupDao xxlJobGroupDao;
|
||||
|
||||
@RequestMapping
|
||||
@PermissionLimit(adminuser = true)
|
||||
public String index(Model model) {
|
||||
|
||||
// 执行器列表
|
||||
List<XxlJobGroup> groupList = xxlJobGroupDao.findAll();
|
||||
model.addAttribute("groupList", groupList);
|
||||
|
||||
return "user/user.index";
|
||||
}
|
||||
|
||||
@RequestMapping("/pageList")
|
||||
@ResponseBody
|
||||
@PermissionLimit(adminuser = true)
|
||||
public Map<String, Object> pageList(@RequestParam(required = false, defaultValue = "0") int start,
|
||||
@RequestParam(required = false, defaultValue = "10") int length,
|
||||
String username, int role) {
|
||||
|
||||
// page list
|
||||
List<XxlJobUser> list = xxlJobUserDao.pageList(start, length, username, role);
|
||||
int list_count = xxlJobUserDao.pageListCount(start, length, username, role);
|
||||
|
||||
// filter
|
||||
if (list!=null && list.size()>0) {
|
||||
for (XxlJobUser item: list) {
|
||||
item.setPassword(null);
|
||||
}
|
||||
}
|
||||
|
||||
// package result
|
||||
Map<String, Object> maps = new HashMap<String, Object>();
|
||||
maps.put("recordsTotal", list_count); // 总记录数
|
||||
maps.put("recordsFiltered", list_count); // 过滤后的总记录数
|
||||
maps.put("data", list); // 分页列表
|
||||
return maps;
|
||||
}
|
||||
|
||||
@RequestMapping("/add")
|
||||
@ResponseBody
|
||||
@PermissionLimit(adminuser = true)
|
||||
public ReturnT<String> add(XxlJobUser xxlJobUser) {
|
||||
|
||||
// valid username
|
||||
if (!StringUtils.hasText(xxlJobUser.getUsername())) {
|
||||
return new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("system_please_input")+I18nUtil.getString("user_username") );
|
||||
}
|
||||
xxlJobUser.setUsername(xxlJobUser.getUsername().trim());
|
||||
if (!(xxlJobUser.getUsername().length()>=4 && xxlJobUser.getUsername().length()<=20)) {
|
||||
return new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("system_lengh_limit")+"[4-20]" );
|
||||
}
|
||||
// valid password
|
||||
if (!StringUtils.hasText(xxlJobUser.getPassword())) {
|
||||
return new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("system_please_input")+I18nUtil.getString("user_password") );
|
||||
}
|
||||
xxlJobUser.setPassword(xxlJobUser.getPassword().trim());
|
||||
if (!(xxlJobUser.getPassword().length()>=4 && xxlJobUser.getPassword().length()<=20)) {
|
||||
return new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("system_lengh_limit")+"[4-20]" );
|
||||
}
|
||||
// md5 password
|
||||
xxlJobUser.setPassword(DigestUtils.md5DigestAsHex(xxlJobUser.getPassword().getBytes()));
|
||||
|
||||
// check repeat
|
||||
XxlJobUser existUser = xxlJobUserDao.loadByUserName(xxlJobUser.getUsername());
|
||||
if (existUser != null) {
|
||||
return new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("user_username_repeat") );
|
||||
}
|
||||
|
||||
// write
|
||||
xxlJobUserDao.save(xxlJobUser);
|
||||
return ReturnT.SUCCESS;
|
||||
}
|
||||
|
||||
@RequestMapping("/update")
|
||||
@ResponseBody
|
||||
@PermissionLimit(adminuser = true)
|
||||
public ReturnT<String> update(HttpServletRequest request, XxlJobUser xxlJobUser) {
|
||||
|
||||
// avoid opt login seft
|
||||
XxlJobUser loginUser = (XxlJobUser) request.getAttribute(LoginService.LOGIN_IDENTITY_KEY);
|
||||
if (loginUser.getUsername().equals(xxlJobUser.getUsername())) {
|
||||
return new ReturnT<String>(ReturnT.FAIL.getCode(), I18nUtil.getString("user_update_loginuser_limit"));
|
||||
}
|
||||
|
||||
// valid password
|
||||
if (StringUtils.hasText(xxlJobUser.getPassword())) {
|
||||
xxlJobUser.setPassword(xxlJobUser.getPassword().trim());
|
||||
if (!(xxlJobUser.getPassword().length()>=4 && xxlJobUser.getPassword().length()<=20)) {
|
||||
return new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("system_lengh_limit")+"[4-20]" );
|
||||
}
|
||||
// md5 password
|
||||
xxlJobUser.setPassword(DigestUtils.md5DigestAsHex(xxlJobUser.getPassword().getBytes()));
|
||||
} else {
|
||||
xxlJobUser.setPassword(null);
|
||||
}
|
||||
|
||||
// write
|
||||
xxlJobUserDao.update(xxlJobUser);
|
||||
return ReturnT.SUCCESS;
|
||||
}
|
||||
|
||||
@RequestMapping("/remove")
|
||||
@ResponseBody
|
||||
@PermissionLimit(adminuser = true)
|
||||
public ReturnT<String> remove(HttpServletRequest request, int id) {
|
||||
|
||||
// avoid opt login seft
|
||||
XxlJobUser loginUser = (XxlJobUser) request.getAttribute(LoginService.LOGIN_IDENTITY_KEY);
|
||||
if (loginUser.getId() == id) {
|
||||
return new ReturnT<String>(ReturnT.FAIL.getCode(), I18nUtil.getString("user_update_loginuser_limit"));
|
||||
}
|
||||
|
||||
xxlJobUserDao.delete(id);
|
||||
return ReturnT.SUCCESS;
|
||||
}
|
||||
|
||||
@RequestMapping("/updatePwd")
|
||||
@ResponseBody
|
||||
public ReturnT<String> updatePwd(HttpServletRequest request, String password){
|
||||
|
||||
// valid password
|
||||
if (password==null || password.trim().length()==0){
|
||||
return new ReturnT<String>(ReturnT.FAIL.getCode(), "密码不可为空");
|
||||
}
|
||||
password = password.trim();
|
||||
if (!(password.length()>=4 && password.length()<=20)) {
|
||||
return new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("system_lengh_limit")+"[4-20]" );
|
||||
}
|
||||
|
||||
// md5 password
|
||||
String md5Password = DigestUtils.md5DigestAsHex(password.getBytes());
|
||||
|
||||
// update pwd
|
||||
XxlJobUser loginUser = (XxlJobUser) request.getAttribute(LoginService.LOGIN_IDENTITY_KEY);
|
||||
|
||||
// do write
|
||||
XxlJobUser existUser = xxlJobUserDao.loadByUserName(loginUser.getUsername());
|
||||
existUser.setPassword(md5Password);
|
||||
xxlJobUserDao.update(existUser);
|
||||
|
||||
return ReturnT.SUCCESS;
|
||||
}
|
||||
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
package com.xxl.job.admin.controller.annotation;
|
||||
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 权限限制
|
||||
* @author xuxueli 2015-12-12 18:29:02
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface PermissionLimit {
|
||||
|
||||
/**
|
||||
* 登录拦截 (默认拦截)
|
||||
*/
|
||||
boolean limit() default true;
|
||||
|
||||
/**
|
||||
* 要求管理员权限
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean adminuser() default false;
|
||||
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
package com.xxl.job.admin.controller.interceptor;
|
||||
|
||||
import com.xxl.job.admin.core.util.FtlUtil;
|
||||
import com.xxl.job.admin.core.util.I18nUtil;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.servlet.AsyncHandlerInterceptor;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* push cookies to model as cookieMap
|
||||
*
|
||||
* @author xuxueli 2015-12-12 18:09:04
|
||||
*/
|
||||
@Component
|
||||
public class CookieInterceptor implements AsyncHandlerInterceptor {
|
||||
|
||||
@Override
|
||||
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
|
||||
ModelAndView modelAndView) throws Exception {
|
||||
|
||||
// cookie
|
||||
if (modelAndView!=null && request.getCookies()!=null && request.getCookies().length>0) {
|
||||
HashMap<String, Cookie> cookieMap = new HashMap<String, Cookie>();
|
||||
for (Cookie ck : request.getCookies()) {
|
||||
cookieMap.put(ck.getName(), ck);
|
||||
}
|
||||
modelAndView.addObject("cookieMap", cookieMap);
|
||||
}
|
||||
|
||||
// static method
|
||||
if (modelAndView != null) {
|
||||
modelAndView.addObject("I18nUtil", FtlUtil.generateStaticModel(I18nUtil.class.getName()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
package com.xxl.job.admin.controller.interceptor;
|
||||
|
||||
import com.xxl.job.admin.controller.annotation.PermissionLimit;
|
||||
import com.xxl.job.admin.core.model.XxlJobUser;
|
||||
import com.xxl.job.admin.core.util.I18nUtil;
|
||||
import com.xxl.job.admin.service.LoginService;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.AsyncHandlerInterceptor;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* 权限拦截
|
||||
*
|
||||
* @author xuxueli 2015-12-12 18:09:04
|
||||
*/
|
||||
@Component
|
||||
public class PermissionInterceptor implements AsyncHandlerInterceptor {
|
||||
|
||||
@Resource
|
||||
private LoginService loginService;
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
|
||||
if (!(handler instanceof HandlerMethod)) {
|
||||
return true; // proceed with the next interceptor
|
||||
}
|
||||
|
||||
// if need login
|
||||
boolean needLogin = true;
|
||||
boolean needAdminuser = false;
|
||||
HandlerMethod method = (HandlerMethod)handler;
|
||||
PermissionLimit permission = method.getMethodAnnotation(PermissionLimit.class);
|
||||
if (permission!=null) {
|
||||
needLogin = permission.limit();
|
||||
needAdminuser = permission.adminuser();
|
||||
}
|
||||
|
||||
if (needLogin) {
|
||||
XxlJobUser loginUser = loginService.ifLogin(request, response);
|
||||
Boolean authorState = loginService.ifAuthorizedLogin(request, response);
|
||||
if (loginUser == null || !authorState) {
|
||||
response.setStatus(302);
|
||||
response.setHeader("location", request.getContextPath()+"/toLogin");
|
||||
return false;
|
||||
}
|
||||
if (needAdminuser && loginUser.getRole()!=1) {
|
||||
throw new RuntimeException(I18nUtil.getString("system_permission_limit"));
|
||||
}
|
||||
request.setAttribute(LoginService.LOGIN_IDENTITY_KEY, loginUser);
|
||||
}
|
||||
|
||||
return true; // proceed with the next interceptor
|
||||
}
|
||||
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
package com.xxl.job.admin.controller.interceptor;
|
||||
|
||||
import com.xxl.job.admin.enums.ApiConstants;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* web mvc config
|
||||
*
|
||||
* @author xuxueli 2018-04-02 20:48:20
|
||||
*/
|
||||
@Configuration
|
||||
public class WebMvcConfig implements WebMvcConfigurer {
|
||||
|
||||
@Resource
|
||||
private PermissionInterceptor permissionInterceptor;
|
||||
@Resource
|
||||
private CookieInterceptor cookieInterceptor;
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(permissionInterceptor).addPathPatterns("/**").excludePathPatterns("/auth/login-by-code", "/auth/refresh-token", "/auth/logout", ApiConstants.PREFIX + "/**");
|
||||
registry.addInterceptor(cookieInterceptor).addPathPatterns("/**").excludePathPatterns("/auth/login-by-code", "/auth/refresh-token", "/auth/logout", ApiConstants.PREFIX + "/**");
|
||||
}
|
||||
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
package com.xxl.job.admin.controller.resolver;
|
||||
|
||||
import com.xxl.job.admin.core.exception.XxlJobException;
|
||||
import com.xxl.job.admin.core.util.JacksonUtil;
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.HandlerExceptionResolver;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* common exception resolver
|
||||
*
|
||||
* @author xuxueli 2016-1-6 19:22:18
|
||||
*/
|
||||
@Component
|
||||
public class WebExceptionResolver implements HandlerExceptionResolver {
|
||||
private static transient Logger logger = LoggerFactory.getLogger(WebExceptionResolver.class);
|
||||
|
||||
@Override
|
||||
public ModelAndView resolveException(HttpServletRequest request,
|
||||
HttpServletResponse response, Object handler, Exception ex) {
|
||||
|
||||
if (!(ex instanceof XxlJobException)) {
|
||||
logger.error("WebExceptionResolver:{}", ex);
|
||||
}
|
||||
|
||||
// if json
|
||||
boolean isJson = false;
|
||||
if (handler instanceof HandlerMethod) {
|
||||
HandlerMethod method = (HandlerMethod)handler;
|
||||
ResponseBody responseBody = method.getMethodAnnotation(ResponseBody.class);
|
||||
if (responseBody != null) {
|
||||
isJson = true;
|
||||
}
|
||||
}
|
||||
|
||||
// error result
|
||||
ReturnT<String> errorResult = new ReturnT<String>(ReturnT.FAIL_CODE, ex.toString().replaceAll("\n", "<br/>"));
|
||||
|
||||
// response
|
||||
ModelAndView mv = new ModelAndView();
|
||||
if (isJson) {
|
||||
try {
|
||||
response.setContentType("application/json;charset=utf-8");
|
||||
response.getWriter().print(JacksonUtil.writeValueAsString(errorResult));
|
||||
} catch (IOException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
return mv;
|
||||
} else {
|
||||
|
||||
mv.addObject("exceptionMsg", errorResult.getMsg());
|
||||
mv.setViewName("/common/common.exception");
|
||||
return mv;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
package com.xxl.job.admin.core.alarm;
|
||||
|
||||
import com.xxl.job.admin.core.model.XxlJobInfo;
|
||||
import com.xxl.job.admin.core.model.XxlJobLog;
|
||||
|
||||
/**
|
||||
* @author xuxueli 2020-01-19
|
||||
*/
|
||||
public interface JobAlarm {
|
||||
|
||||
/**
|
||||
* job alarm
|
||||
*
|
||||
* @param info
|
||||
* @param jobLog
|
||||
* @return
|
||||
*/
|
||||
public boolean doAlarm(XxlJobInfo info, XxlJobLog jobLog);
|
||||
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
package com.xxl.job.admin.core.alarm;
|
||||
|
||||
import com.xxl.job.admin.core.model.XxlJobInfo;
|
||||
import com.xxl.job.admin.core.model.XxlJobLog;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class JobAlarmer implements ApplicationContextAware, InitializingBean {
|
||||
private static Logger logger = LoggerFactory.getLogger(JobAlarmer.class);
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
private List<JobAlarm> jobAlarmList;
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Map<String, JobAlarm> serviceBeanMap = applicationContext.getBeansOfType(JobAlarm.class);
|
||||
if (serviceBeanMap != null && serviceBeanMap.size() > 0) {
|
||||
jobAlarmList = new ArrayList<JobAlarm>(serviceBeanMap.values());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* job alarm
|
||||
*
|
||||
* @param info
|
||||
* @param jobLog
|
||||
* @return
|
||||
*/
|
||||
public boolean alarm(XxlJobInfo info, XxlJobLog jobLog) {
|
||||
|
||||
boolean result = false;
|
||||
if (jobAlarmList!=null && jobAlarmList.size()>0) {
|
||||
result = true; // success means all-success
|
||||
for (JobAlarm alarm: jobAlarmList) {
|
||||
boolean resultItem = false;
|
||||
try {
|
||||
resultItem = alarm.doAlarm(info, jobLog);
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
if (!resultItem) {
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@ -1,118 +0,0 @@
|
||||
package com.xxl.job.admin.core.alarm.impl;
|
||||
|
||||
import com.xxl.job.admin.core.alarm.JobAlarm;
|
||||
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
|
||||
import com.xxl.job.admin.core.model.XxlJobGroup;
|
||||
import com.xxl.job.admin.core.model.XxlJobInfo;
|
||||
import com.xxl.job.admin.core.model.XxlJobLog;
|
||||
import com.xxl.job.admin.core.util.I18nUtil;
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.mail.javamail.MimeMessageHelper;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.mail.internet.MimeMessage;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* job alarm by email
|
||||
*
|
||||
* @author xuxueli 2020-01-19
|
||||
*/
|
||||
@Component
|
||||
public class EmailJobAlarm implements JobAlarm {
|
||||
private static Logger logger = LoggerFactory.getLogger(EmailJobAlarm.class);
|
||||
|
||||
/**
|
||||
* fail alarm
|
||||
*
|
||||
* @param jobLog
|
||||
*/
|
||||
@Override
|
||||
public boolean doAlarm(XxlJobInfo info, XxlJobLog jobLog){
|
||||
boolean alarmResult = true;
|
||||
|
||||
// send monitor email
|
||||
if (info!=null && info.getAlarmEmail()!=null && info.getAlarmEmail().trim().length()>0) {
|
||||
|
||||
// alarmContent
|
||||
String alarmContent = "Alarm Job LogId=" + jobLog.getId();
|
||||
if (jobLog.getTriggerCode() != ReturnT.SUCCESS_CODE) {
|
||||
alarmContent += "<br>TriggerMsg=<br>" + jobLog.getTriggerMsg();
|
||||
}
|
||||
if (jobLog.getHandleCode()>0 && jobLog.getHandleCode() != ReturnT.SUCCESS_CODE) {
|
||||
alarmContent += "<br>HandleCode=" + jobLog.getHandleMsg();
|
||||
}
|
||||
|
||||
// email info
|
||||
XxlJobGroup group = XxlJobAdminConfig.getAdminConfig().getXxlJobGroupDao().load(Integer.valueOf(info.getJobGroup()));
|
||||
String personal = I18nUtil.getString("admin_name_full");
|
||||
String title = I18nUtil.getString("jobconf_monitor");
|
||||
String content = MessageFormat.format(loadEmailJobAlarmTemplate(),
|
||||
group!=null?group.getTitle():"null",
|
||||
info.getId(),
|
||||
info.getJobDesc(),
|
||||
alarmContent);
|
||||
|
||||
Set<String> emailSet = new HashSet<String>(Arrays.asList(info.getAlarmEmail().split(",")));
|
||||
for (String email: emailSet) {
|
||||
|
||||
// make mail
|
||||
try {
|
||||
MimeMessage mimeMessage = XxlJobAdminConfig.getAdminConfig().getMailSender().createMimeMessage();
|
||||
|
||||
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
|
||||
helper.setFrom(XxlJobAdminConfig.getAdminConfig().getEmailFrom(), personal);
|
||||
helper.setTo(email);
|
||||
helper.setSubject(title);
|
||||
helper.setText(content, true);
|
||||
|
||||
XxlJobAdminConfig.getAdminConfig().getMailSender().send(mimeMessage);
|
||||
} catch (Exception e) {
|
||||
logger.error(">>>>>>>>>>> xxl-job, job fail alarm email send error, JobLogId:{}", jobLog.getId(), e);
|
||||
|
||||
alarmResult = false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return alarmResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* load email job alarm template
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private static final String loadEmailJobAlarmTemplate(){
|
||||
String mailBodyTemplate = "<h5>" + I18nUtil.getString("jobconf_monitor_detail") + ":</span>" +
|
||||
"<table border=\"1\" cellpadding=\"3\" style=\"border-collapse:collapse; width:80%;\" >\n" +
|
||||
" <thead style=\"font-weight: bold;color: #ffffff;background-color: #ff8c00;\" >" +
|
||||
" <tr>\n" +
|
||||
" <td width=\"20%\" >"+ I18nUtil.getString("jobinfo_field_jobgroup") +"</td>\n" +
|
||||
" <td width=\"10%\" >"+ I18nUtil.getString("jobinfo_field_id") +"</td>\n" +
|
||||
" <td width=\"20%\" >"+ I18nUtil.getString("jobinfo_field_jobdesc") +"</td>\n" +
|
||||
" <td width=\"10%\" >"+ I18nUtil.getString("jobconf_monitor_alarm_title") +"</td>\n" +
|
||||
" <td width=\"40%\" >"+ I18nUtil.getString("jobconf_monitor_alarm_content") +"</td>\n" +
|
||||
" </tr>\n" +
|
||||
" </thead>\n" +
|
||||
" <tbody>\n" +
|
||||
" <tr>\n" +
|
||||
" <td>{0}</td>\n" +
|
||||
" <td>{1}</td>\n" +
|
||||
" <td>{2}</td>\n" +
|
||||
" <td>"+ I18nUtil.getString("jobconf_monitor_alarm_type") +"</td>\n" +
|
||||
" <td>{3}</td>\n" +
|
||||
" </tr>\n" +
|
||||
" </tbody>\n" +
|
||||
"</table>";
|
||||
|
||||
return mailBodyTemplate;
|
||||
}
|
||||
|
||||
}
|
@ -1,99 +0,0 @@
|
||||
package com.xxl.job.admin.core.complete;
|
||||
|
||||
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
|
||||
import com.xxl.job.admin.core.model.XxlJobInfo;
|
||||
import com.xxl.job.admin.core.model.XxlJobLog;
|
||||
import com.xxl.job.admin.core.thread.JobTriggerPoolHelper;
|
||||
import com.xxl.job.admin.core.trigger.TriggerTypeEnum;
|
||||
import com.xxl.job.admin.core.util.I18nUtil;
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import com.xxl.job.core.context.XxlJobContext;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
|
||||
/**
|
||||
* @author xuxueli 2020-10-30 20:43:10
|
||||
*/
|
||||
public class XxlJobCompleter {
|
||||
private static Logger logger = LoggerFactory.getLogger(XxlJobCompleter.class);
|
||||
|
||||
/**
|
||||
* common fresh handle entrance (limit only once)
|
||||
*
|
||||
* @param xxlJobLog
|
||||
* @return
|
||||
*/
|
||||
public static int updateHandleInfoAndFinish(XxlJobLog xxlJobLog) {
|
||||
|
||||
// finish
|
||||
finishJob(xxlJobLog);
|
||||
|
||||
// text最大64kb 避免长度过长
|
||||
if (xxlJobLog.getHandleMsg().length() > 15000) {
|
||||
xxlJobLog.setHandleMsg( xxlJobLog.getHandleMsg().substring(0, 15000) );
|
||||
}
|
||||
|
||||
// fresh handle
|
||||
return XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().updateHandleInfo(xxlJobLog);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* do somethind to finish job
|
||||
*/
|
||||
private static void finishJob(XxlJobLog xxlJobLog){
|
||||
|
||||
// 1、handle success, to trigger child job
|
||||
String triggerChildMsg = null;
|
||||
if (XxlJobContext.HANDLE_CODE_SUCCESS == xxlJobLog.getHandleCode()) {
|
||||
XxlJobInfo xxlJobInfo = XxlJobAdminConfig.getAdminConfig().getXxlJobInfoDao().loadById(xxlJobLog.getJobId());
|
||||
if (xxlJobInfo!=null && xxlJobInfo.getChildJobId()!=null && xxlJobInfo.getChildJobId().trim().length()>0) {
|
||||
triggerChildMsg = "<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>"+ I18nUtil.getString("jobconf_trigger_child_run") +"<<<<<<<<<<< </span><br>";
|
||||
|
||||
String[] childJobIds = xxlJobInfo.getChildJobId().split(",");
|
||||
for (int i = 0; i < childJobIds.length; i++) {
|
||||
int childJobId = (childJobIds[i]!=null && childJobIds[i].trim().length()>0 && isNumeric(childJobIds[i]))?Integer.valueOf(childJobIds[i]):-1;
|
||||
if (childJobId > 0) {
|
||||
|
||||
JobTriggerPoolHelper.trigger(childJobId, TriggerTypeEnum.PARENT, -1, null, null, null);
|
||||
ReturnT<String> triggerChildResult = ReturnT.SUCCESS;
|
||||
|
||||
// add msg
|
||||
triggerChildMsg += MessageFormat.format(I18nUtil.getString("jobconf_callback_child_msg1"),
|
||||
(i+1),
|
||||
childJobIds.length,
|
||||
childJobIds[i],
|
||||
(triggerChildResult.getCode()==ReturnT.SUCCESS_CODE?I18nUtil.getString("system_success"):I18nUtil.getString("system_fail")),
|
||||
triggerChildResult.getMsg());
|
||||
} else {
|
||||
triggerChildMsg += MessageFormat.format(I18nUtil.getString("jobconf_callback_child_msg2"),
|
||||
(i+1),
|
||||
childJobIds.length,
|
||||
childJobIds[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (triggerChildMsg != null) {
|
||||
xxlJobLog.setHandleMsg( xxlJobLog.getHandleMsg() + triggerChildMsg );
|
||||
}
|
||||
|
||||
// 2、fix_delay trigger next
|
||||
// on the way
|
||||
|
||||
}
|
||||
|
||||
private static boolean isNumeric(String str){
|
||||
try {
|
||||
int result = Integer.valueOf(str);
|
||||
return true;
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,158 +0,0 @@
|
||||
package com.xxl.job.admin.core.conf;
|
||||
|
||||
import com.xxl.job.admin.core.alarm.JobAlarmer;
|
||||
import com.xxl.job.admin.core.scheduler.XxlJobScheduler;
|
||||
import com.xxl.job.admin.dao.*;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.mail.javamail.JavaMailSender;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.sql.DataSource;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* xxl-job config
|
||||
*
|
||||
* @author xuxueli 2017-04-28
|
||||
*/
|
||||
|
||||
@Component
|
||||
public class XxlJobAdminConfig implements InitializingBean, DisposableBean {
|
||||
|
||||
private static XxlJobAdminConfig adminConfig = null;
|
||||
public static XxlJobAdminConfig getAdminConfig() {
|
||||
return adminConfig;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------- XxlJobScheduler ----------------------
|
||||
|
||||
private XxlJobScheduler xxlJobScheduler;
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
adminConfig = this;
|
||||
|
||||
xxlJobScheduler = new XxlJobScheduler();
|
||||
xxlJobScheduler.init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
xxlJobScheduler.destroy();
|
||||
}
|
||||
|
||||
|
||||
// ---------------------- XxlJobScheduler ----------------------
|
||||
|
||||
// conf
|
||||
@Value("${xxl.job.i18n}")
|
||||
private String i18n;
|
||||
|
||||
@Value("${xxl.job.accessToken}")
|
||||
private String accessToken;
|
||||
|
||||
@Value("${spring.mail.from}")
|
||||
private String emailFrom;
|
||||
|
||||
@Value("${xxl.job.triggerpool.fast.max}")
|
||||
private int triggerPoolFastMax;
|
||||
|
||||
@Value("${xxl.job.triggerpool.slow.max}")
|
||||
private int triggerPoolSlowMax;
|
||||
|
||||
@Value("${xxl.job.logretentiondays}")
|
||||
private int logretentiondays;
|
||||
|
||||
// dao, service
|
||||
|
||||
@Resource
|
||||
private XxlJobLogDao xxlJobLogDao;
|
||||
@Resource
|
||||
private XxlJobInfoDao xxlJobInfoDao;
|
||||
@Resource
|
||||
private XxlJobRegistryDao xxlJobRegistryDao;
|
||||
@Resource
|
||||
private XxlJobGroupDao xxlJobGroupDao;
|
||||
@Resource
|
||||
private XxlJobLogReportDao xxlJobLogReportDao;
|
||||
@Resource
|
||||
private JavaMailSender mailSender;
|
||||
@Resource
|
||||
private DataSource dataSource;
|
||||
@Resource
|
||||
private JobAlarmer jobAlarmer;
|
||||
|
||||
|
||||
public String getI18n() {
|
||||
if (!Arrays.asList("zh_CN", "zh_TC", "en").contains(i18n)) {
|
||||
return "zh_CN";
|
||||
}
|
||||
return i18n;
|
||||
}
|
||||
|
||||
public String getAccessToken() {
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
public String getEmailFrom() {
|
||||
return emailFrom;
|
||||
}
|
||||
|
||||
public int getTriggerPoolFastMax() {
|
||||
if (triggerPoolFastMax < 200) {
|
||||
return 200;
|
||||
}
|
||||
return triggerPoolFastMax;
|
||||
}
|
||||
|
||||
public int getTriggerPoolSlowMax() {
|
||||
if (triggerPoolSlowMax < 100) {
|
||||
return 100;
|
||||
}
|
||||
return triggerPoolSlowMax;
|
||||
}
|
||||
|
||||
public int getLogretentiondays() {
|
||||
if (logretentiondays < 7) {
|
||||
return -1; // Limit greater than or equal to 7, otherwise close
|
||||
}
|
||||
return logretentiondays;
|
||||
}
|
||||
|
||||
public XxlJobLogDao getXxlJobLogDao() {
|
||||
return xxlJobLogDao;
|
||||
}
|
||||
|
||||
public XxlJobInfoDao getXxlJobInfoDao() {
|
||||
return xxlJobInfoDao;
|
||||
}
|
||||
|
||||
public XxlJobRegistryDao getXxlJobRegistryDao() {
|
||||
return xxlJobRegistryDao;
|
||||
}
|
||||
|
||||
public XxlJobGroupDao getXxlJobGroupDao() {
|
||||
return xxlJobGroupDao;
|
||||
}
|
||||
|
||||
public XxlJobLogReportDao getXxlJobLogReportDao() {
|
||||
return xxlJobLogReportDao;
|
||||
}
|
||||
|
||||
public JavaMailSender getMailSender() {
|
||||
return mailSender;
|
||||
}
|
||||
|
||||
public DataSource getDataSource() {
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
public JobAlarmer getJobAlarmer() {
|
||||
return jobAlarmer;
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,14 +0,0 @@
|
||||
package com.xxl.job.admin.core.exception;
|
||||
|
||||
/**
|
||||
* @author xuxueli 2019-05-04 23:19:29
|
||||
*/
|
||||
public class XxlJobException extends RuntimeException {
|
||||
|
||||
public XxlJobException() {
|
||||
}
|
||||
public XxlJobException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
package com.xxl.job.admin.core.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by xuxueli on 16/9/30.
|
||||
*/
|
||||
public class XxlJobGroup {
|
||||
|
||||
private int id;
|
||||
private String appname;
|
||||
private String title;
|
||||
private int addressType; // 执行器地址类型:0=自动注册、1=手动录入
|
||||
private String addressList; // 执行器地址列表,多地址逗号分隔(手动录入)
|
||||
private Date updateTime;
|
||||
|
||||
// registry list
|
||||
private List<String> registryList; // 执行器地址列表(系统注册)
|
||||
public List<String> getRegistryList() {
|
||||
if (addressList!=null && addressList.trim().length()>0) {
|
||||
registryList = new ArrayList<String>(Arrays.asList(addressList.split(",")));
|
||||
}
|
||||
return registryList;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getAppname() {
|
||||
return appname;
|
||||
}
|
||||
|
||||
public void setAppname(String appname) {
|
||||
this.appname = appname;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public int getAddressType() {
|
||||
return addressType;
|
||||
}
|
||||
|
||||
public void setAddressType(int addressType) {
|
||||
this.addressType = addressType;
|
||||
}
|
||||
|
||||
public String getAddressList() {
|
||||
return addressList;
|
||||
}
|
||||
|
||||
public Date getUpdateTime() {
|
||||
return updateTime;
|
||||
}
|
||||
|
||||
public void setUpdateTime(Date updateTime) {
|
||||
this.updateTime = updateTime;
|
||||
}
|
||||
|
||||
public void setAddressList(String addressList) {
|
||||
this.addressList = addressList;
|
||||
}
|
||||
|
||||
}
|
@ -1,237 +0,0 @@
|
||||
package com.xxl.job.admin.core.model;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* xxl-job info
|
||||
*
|
||||
* @author xuxueli 2016-1-12 18:25:49
|
||||
*/
|
||||
public class XxlJobInfo {
|
||||
|
||||
private int id; // 主键ID
|
||||
|
||||
private int jobGroup; // 执行器主键ID
|
||||
private String jobDesc;
|
||||
|
||||
private Date addTime;
|
||||
private Date updateTime;
|
||||
|
||||
private String author; // 负责人
|
||||
private String alarmEmail; // 报警邮件
|
||||
|
||||
private String scheduleType; // 调度类型
|
||||
private String scheduleConf; // 调度配置,值含义取决于调度类型
|
||||
private String misfireStrategy; // 调度过期策略
|
||||
|
||||
private String executorRouteStrategy; // 执行器路由策略
|
||||
private String executorHandler; // 执行器,任务Handler名称
|
||||
private String executorParam; // 执行器,任务参数
|
||||
private String executorBlockStrategy; // 阻塞处理策略
|
||||
private int executorTimeout; // 任务执行超时时间,单位秒
|
||||
private int executorFailRetryCount; // 失败重试次数
|
||||
|
||||
private String glueType; // GLUE类型 #com.xxl.job.core.glue.GlueTypeEnum
|
||||
private String glueSource; // GLUE源代码
|
||||
private String glueRemark; // GLUE备注
|
||||
private Date glueUpdatetime; // GLUE更新时间
|
||||
|
||||
private String childJobId; // 子任务ID,多个逗号分隔
|
||||
|
||||
private int triggerStatus; // 调度状态:0-停止,1-运行
|
||||
private long triggerLastTime; // 上次调度时间
|
||||
private long triggerNextTime; // 下次调度时间
|
||||
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int getJobGroup() {
|
||||
return jobGroup;
|
||||
}
|
||||
|
||||
public void setJobGroup(int jobGroup) {
|
||||
this.jobGroup = jobGroup;
|
||||
}
|
||||
|
||||
public String getJobDesc() {
|
||||
return jobDesc;
|
||||
}
|
||||
|
||||
public void setJobDesc(String jobDesc) {
|
||||
this.jobDesc = jobDesc;
|
||||
}
|
||||
|
||||
public Date getAddTime() {
|
||||
return addTime;
|
||||
}
|
||||
|
||||
public void setAddTime(Date addTime) {
|
||||
this.addTime = addTime;
|
||||
}
|
||||
|
||||
public Date getUpdateTime() {
|
||||
return updateTime;
|
||||
}
|
||||
|
||||
public void setUpdateTime(Date updateTime) {
|
||||
this.updateTime = updateTime;
|
||||
}
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(String author) {
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
public String getAlarmEmail() {
|
||||
return alarmEmail;
|
||||
}
|
||||
|
||||
public void setAlarmEmail(String alarmEmail) {
|
||||
this.alarmEmail = alarmEmail;
|
||||
}
|
||||
|
||||
public String getScheduleType() {
|
||||
return scheduleType;
|
||||
}
|
||||
|
||||
public void setScheduleType(String scheduleType) {
|
||||
this.scheduleType = scheduleType;
|
||||
}
|
||||
|
||||
public String getScheduleConf() {
|
||||
return scheduleConf;
|
||||
}
|
||||
|
||||
public void setScheduleConf(String scheduleConf) {
|
||||
this.scheduleConf = scheduleConf;
|
||||
}
|
||||
|
||||
public String getMisfireStrategy() {
|
||||
return misfireStrategy;
|
||||
}
|
||||
|
||||
public void setMisfireStrategy(String misfireStrategy) {
|
||||
this.misfireStrategy = misfireStrategy;
|
||||
}
|
||||
|
||||
public String getExecutorRouteStrategy() {
|
||||
return executorRouteStrategy;
|
||||
}
|
||||
|
||||
public void setExecutorRouteStrategy(String executorRouteStrategy) {
|
||||
this.executorRouteStrategy = executorRouteStrategy;
|
||||
}
|
||||
|
||||
public String getExecutorHandler() {
|
||||
return executorHandler;
|
||||
}
|
||||
|
||||
public void setExecutorHandler(String executorHandler) {
|
||||
this.executorHandler = executorHandler;
|
||||
}
|
||||
|
||||
public String getExecutorParam() {
|
||||
return executorParam;
|
||||
}
|
||||
|
||||
public void setExecutorParam(String executorParam) {
|
||||
this.executorParam = executorParam;
|
||||
}
|
||||
|
||||
public String getExecutorBlockStrategy() {
|
||||
return executorBlockStrategy;
|
||||
}
|
||||
|
||||
public void setExecutorBlockStrategy(String executorBlockStrategy) {
|
||||
this.executorBlockStrategy = executorBlockStrategy;
|
||||
}
|
||||
|
||||
public int getExecutorTimeout() {
|
||||
return executorTimeout;
|
||||
}
|
||||
|
||||
public void setExecutorTimeout(int executorTimeout) {
|
||||
this.executorTimeout = executorTimeout;
|
||||
}
|
||||
|
||||
public int getExecutorFailRetryCount() {
|
||||
return executorFailRetryCount;
|
||||
}
|
||||
|
||||
public void setExecutorFailRetryCount(int executorFailRetryCount) {
|
||||
this.executorFailRetryCount = executorFailRetryCount;
|
||||
}
|
||||
|
||||
public String getGlueType() {
|
||||
return glueType;
|
||||
}
|
||||
|
||||
public void setGlueType(String glueType) {
|
||||
this.glueType = glueType;
|
||||
}
|
||||
|
||||
public String getGlueSource() {
|
||||
return glueSource;
|
||||
}
|
||||
|
||||
public void setGlueSource(String glueSource) {
|
||||
this.glueSource = glueSource;
|
||||
}
|
||||
|
||||
public String getGlueRemark() {
|
||||
return glueRemark;
|
||||
}
|
||||
|
||||
public void setGlueRemark(String glueRemark) {
|
||||
this.glueRemark = glueRemark;
|
||||
}
|
||||
|
||||
public Date getGlueUpdatetime() {
|
||||
return glueUpdatetime;
|
||||
}
|
||||
|
||||
public void setGlueUpdatetime(Date glueUpdatetime) {
|
||||
this.glueUpdatetime = glueUpdatetime;
|
||||
}
|
||||
|
||||
public String getChildJobId() {
|
||||
return childJobId;
|
||||
}
|
||||
|
||||
public void setChildJobId(String childJobId) {
|
||||
this.childJobId = childJobId;
|
||||
}
|
||||
|
||||
public int getTriggerStatus() {
|
||||
return triggerStatus;
|
||||
}
|
||||
|
||||
public void setTriggerStatus(int triggerStatus) {
|
||||
this.triggerStatus = triggerStatus;
|
||||
}
|
||||
|
||||
public long getTriggerLastTime() {
|
||||
return triggerLastTime;
|
||||
}
|
||||
|
||||
public void setTriggerLastTime(long triggerLastTime) {
|
||||
this.triggerLastTime = triggerLastTime;
|
||||
}
|
||||
|
||||
public long getTriggerNextTime() {
|
||||
return triggerNextTime;
|
||||
}
|
||||
|
||||
public void setTriggerNextTime(long triggerNextTime) {
|
||||
this.triggerNextTime = triggerNextTime;
|
||||
}
|
||||
}
|
@ -1,157 +0,0 @@
|
||||
package com.xxl.job.admin.core.model;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* xxl-job log, used to track trigger process
|
||||
* @author xuxueli 2015-12-19 23:19:09
|
||||
*/
|
||||
public class XxlJobLog {
|
||||
|
||||
private long id;
|
||||
|
||||
// job info
|
||||
private int jobGroup;
|
||||
private int jobId;
|
||||
|
||||
// execute info
|
||||
private String executorAddress;
|
||||
private String executorHandler;
|
||||
private String executorParam;
|
||||
private String executorShardingParam;
|
||||
private int executorFailRetryCount;
|
||||
|
||||
// trigger info
|
||||
private Date triggerTime;
|
||||
private int triggerCode;
|
||||
private String triggerMsg;
|
||||
|
||||
// handle info
|
||||
private Date handleTime;
|
||||
private int handleCode;
|
||||
private String handleMsg;
|
||||
|
||||
// alarm info
|
||||
private int alarmStatus;
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int getJobGroup() {
|
||||
return jobGroup;
|
||||
}
|
||||
|
||||
public void setJobGroup(int jobGroup) {
|
||||
this.jobGroup = jobGroup;
|
||||
}
|
||||
|
||||
public int getJobId() {
|
||||
return jobId;
|
||||
}
|
||||
|
||||
public void setJobId(int jobId) {
|
||||
this.jobId = jobId;
|
||||
}
|
||||
|
||||
public String getExecutorAddress() {
|
||||
return executorAddress;
|
||||
}
|
||||
|
||||
public void setExecutorAddress(String executorAddress) {
|
||||
this.executorAddress = executorAddress;
|
||||
}
|
||||
|
||||
public String getExecutorHandler() {
|
||||
return executorHandler;
|
||||
}
|
||||
|
||||
public void setExecutorHandler(String executorHandler) {
|
||||
this.executorHandler = executorHandler;
|
||||
}
|
||||
|
||||
public String getExecutorParam() {
|
||||
return executorParam;
|
||||
}
|
||||
|
||||
public void setExecutorParam(String executorParam) {
|
||||
this.executorParam = executorParam;
|
||||
}
|
||||
|
||||
public String getExecutorShardingParam() {
|
||||
return executorShardingParam;
|
||||
}
|
||||
|
||||
public void setExecutorShardingParam(String executorShardingParam) {
|
||||
this.executorShardingParam = executorShardingParam;
|
||||
}
|
||||
|
||||
public int getExecutorFailRetryCount() {
|
||||
return executorFailRetryCount;
|
||||
}
|
||||
|
||||
public void setExecutorFailRetryCount(int executorFailRetryCount) {
|
||||
this.executorFailRetryCount = executorFailRetryCount;
|
||||
}
|
||||
|
||||
public Date getTriggerTime() {
|
||||
return triggerTime;
|
||||
}
|
||||
|
||||
public void setTriggerTime(Date triggerTime) {
|
||||
this.triggerTime = triggerTime;
|
||||
}
|
||||
|
||||
public int getTriggerCode() {
|
||||
return triggerCode;
|
||||
}
|
||||
|
||||
public void setTriggerCode(int triggerCode) {
|
||||
this.triggerCode = triggerCode;
|
||||
}
|
||||
|
||||
public String getTriggerMsg() {
|
||||
return triggerMsg;
|
||||
}
|
||||
|
||||
public void setTriggerMsg(String triggerMsg) {
|
||||
this.triggerMsg = triggerMsg;
|
||||
}
|
||||
|
||||
public Date getHandleTime() {
|
||||
return handleTime;
|
||||
}
|
||||
|
||||
public void setHandleTime(Date handleTime) {
|
||||
this.handleTime = handleTime;
|
||||
}
|
||||
|
||||
public int getHandleCode() {
|
||||
return handleCode;
|
||||
}
|
||||
|
||||
public void setHandleCode(int handleCode) {
|
||||
this.handleCode = handleCode;
|
||||
}
|
||||
|
||||
public String getHandleMsg() {
|
||||
return handleMsg;
|
||||
}
|
||||
|
||||
public void setHandleMsg(String handleMsg) {
|
||||
this.handleMsg = handleMsg;
|
||||
}
|
||||
|
||||
public int getAlarmStatus() {
|
||||
return alarmStatus;
|
||||
}
|
||||
|
||||
public void setAlarmStatus(int alarmStatus) {
|
||||
this.alarmStatus = alarmStatus;
|
||||
}
|
||||
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
package com.xxl.job.admin.core.model;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* xxl-job log for glue, used to track job code process
|
||||
* @author xuxueli 2016-5-19 17:57:46
|
||||
*/
|
||||
public class XxlJobLogGlue {
|
||||
|
||||
private int id;
|
||||
private int jobId; // 任务主键ID
|
||||
private String glueType; // GLUE类型 #com.xxl.job.core.glue.GlueTypeEnum
|
||||
private String glueSource;
|
||||
private String glueRemark;
|
||||
private Date addTime;
|
||||
private Date updateTime;
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int getJobId() {
|
||||
return jobId;
|
||||
}
|
||||
|
||||
public void setJobId(int jobId) {
|
||||
this.jobId = jobId;
|
||||
}
|
||||
|
||||
public String getGlueType() {
|
||||
return glueType;
|
||||
}
|
||||
|
||||
public void setGlueType(String glueType) {
|
||||
this.glueType = glueType;
|
||||
}
|
||||
|
||||
public String getGlueSource() {
|
||||
return glueSource;
|
||||
}
|
||||
|
||||
public void setGlueSource(String glueSource) {
|
||||
this.glueSource = glueSource;
|
||||
}
|
||||
|
||||
public String getGlueRemark() {
|
||||
return glueRemark;
|
||||
}
|
||||
|
||||
public void setGlueRemark(String glueRemark) {
|
||||
this.glueRemark = glueRemark;
|
||||
}
|
||||
|
||||
public Date getAddTime() {
|
||||
return addTime;
|
||||
}
|
||||
|
||||
public void setAddTime(Date addTime) {
|
||||
this.addTime = addTime;
|
||||
}
|
||||
|
||||
public Date getUpdateTime() {
|
||||
return updateTime;
|
||||
}
|
||||
|
||||
public void setUpdateTime(Date updateTime) {
|
||||
this.updateTime = updateTime;
|
||||
}
|
||||
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
package com.xxl.job.admin.core.model;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class XxlJobLogReport {
|
||||
|
||||
private int id;
|
||||
|
||||
private Date triggerDay;
|
||||
|
||||
private int runningCount;
|
||||
private int sucCount;
|
||||
private int failCount;
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Date getTriggerDay() {
|
||||
return triggerDay;
|
||||
}
|
||||
|
||||
public void setTriggerDay(Date triggerDay) {
|
||||
this.triggerDay = triggerDay;
|
||||
}
|
||||
|
||||
public int getRunningCount() {
|
||||
return runningCount;
|
||||
}
|
||||
|
||||
public void setRunningCount(int runningCount) {
|
||||
this.runningCount = runningCount;
|
||||
}
|
||||
|
||||
public int getSucCount() {
|
||||
return sucCount;
|
||||
}
|
||||
|
||||
public void setSucCount(int sucCount) {
|
||||
this.sucCount = sucCount;
|
||||
}
|
||||
|
||||
public int getFailCount() {
|
||||
return failCount;
|
||||
}
|
||||
|
||||
public void setFailCount(int failCount) {
|
||||
this.failCount = failCount;
|
||||
}
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
package com.xxl.job.admin.core.model;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Created by xuxueli on 16/9/30.
|
||||
*/
|
||||
public class XxlJobRegistry {
|
||||
|
||||
private int id;
|
||||
private String registryGroup;
|
||||
private String registryKey;
|
||||
private String registryValue;
|
||||
private Date updateTime;
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getRegistryGroup() {
|
||||
return registryGroup;
|
||||
}
|
||||
|
||||
public void setRegistryGroup(String registryGroup) {
|
||||
this.registryGroup = registryGroup;
|
||||
}
|
||||
|
||||
public String getRegistryKey() {
|
||||
return registryKey;
|
||||
}
|
||||
|
||||
public void setRegistryKey(String registryKey) {
|
||||
this.registryKey = registryKey;
|
||||
}
|
||||
|
||||
public String getRegistryValue() {
|
||||
return registryValue;
|
||||
}
|
||||
|
||||
public void setRegistryValue(String registryValue) {
|
||||
this.registryValue = registryValue;
|
||||
}
|
||||
|
||||
public Date getUpdateTime() {
|
||||
return updateTime;
|
||||
}
|
||||
|
||||
public void setUpdateTime(Date updateTime) {
|
||||
this.updateTime = updateTime;
|
||||
}
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
package com.xxl.job.admin.core.model;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* @author xuxueli 2019-05-04 16:43:12
|
||||
*/
|
||||
public class XxlJobUser {
|
||||
|
||||
private int id;
|
||||
private String username; // 账号
|
||||
private String password; // 密码
|
||||
private int role; // 角色:0-普通用户、1-管理员
|
||||
private String permission; // 权限:执行器ID列表,多个逗号分割
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public int getRole() {
|
||||
return role;
|
||||
}
|
||||
|
||||
public void setRole(int role) {
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
public String getPermission() {
|
||||
return permission;
|
||||
}
|
||||
|
||||
public void setPermission(String permission) {
|
||||
this.permission = permission;
|
||||
}
|
||||
|
||||
// plugin
|
||||
public boolean validPermission(int jobGroup){
|
||||
if (this.role == 1) {
|
||||
return true;
|
||||
} else {
|
||||
if (StringUtils.hasText(this.permission)) {
|
||||
for (String permissionItem : this.permission.split(",")) {
|
||||
if (String.valueOf(jobGroup).equals(permissionItem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
package com.xxl.job.admin.core.old;//package com.xxl.job.admin.core.jobbean;
|
||||
//
|
||||
//import com.xxl.job.admin.core.thread.JobTriggerPoolHelper;
|
||||
//import com.xxl.job.admin.core.trigger.TriggerTypeEnum;
|
||||
//import org.quartz.JobExecutionContext;
|
||||
//import org.quartz.JobExecutionException;
|
||||
//import org.quartz.JobKey;
|
||||
//import org.slf4j.Logger;
|
||||
//import org.slf4j.LoggerFactory;
|
||||
//import org.springframework.scheduling.quartz.QuartzJobBean;
|
||||
//
|
||||
///**
|
||||
// * http job bean
|
||||
// * “@DisallowConcurrentExecution” disable concurrent, thread size can not be only one, better given more
|
||||
// * @author xuxueli 2015-12-17 18:20:34
|
||||
// */
|
||||
////@DisallowConcurrentExecution
|
||||
//public class RemoteHttpJobBean extends QuartzJobBean {
|
||||
// private static Logger logger = LoggerFactory.getLogger(RemoteHttpJobBean.class);
|
||||
//
|
||||
// @Override
|
||||
// protected void executeInternal(JobExecutionContext context)
|
||||
// throws JobExecutionException {
|
||||
//
|
||||
// // load jobId
|
||||
// JobKey jobKey = context.getTrigger().getJobKey();
|
||||
// Integer jobId = Integer.valueOf(jobKey.getName());
|
||||
//
|
||||
//
|
||||
// }
|
||||
//
|
||||
//}
|
@ -1,413 +0,0 @@
|
||||
package com.xxl.job.admin.core.old;//package com.xxl.job.admin.core.schedule;
|
||||
//
|
||||
//import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
|
||||
//import com.xxl.job.admin.core.jobbean.RemoteHttpJobBean;
|
||||
//import com.xxl.job.admin.core.model.XxlJobInfo;
|
||||
//import com.xxl.job.admin.core.thread.JobFailMonitorHelper;
|
||||
//import com.xxl.job.admin.core.thread.JobRegistryMonitorHelper;
|
||||
//import com.xxl.job.admin.core.thread.JobTriggerPoolHelper;
|
||||
//import com.xxl.job.admin.core.util.I18nUtil;
|
||||
//import com.xxl.job.core.biz.AdminBiz;
|
||||
//import com.xxl.job.core.biz.ExecutorBiz;
|
||||
//import com.xxl.job.core.enums.ExecutorBlockStrategyEnum;
|
||||
//import com.xxl.rpc.remoting.invoker.XxlRpcInvokerFactory;
|
||||
//import com.xxl.rpc.remoting.invoker.call.CallType;
|
||||
//import com.xxl.rpc.remoting.invoker.reference.XxlRpcReferenceBean;
|
||||
//import com.xxl.rpc.remoting.invoker.route.LoadBalance;
|
||||
//import com.xxl.rpc.remoting.net.NetEnum;
|
||||
//import com.xxl.rpc.remoting.net.impl.servlet.server.ServletServerHandler;
|
||||
//import com.xxl.rpc.remoting.provider.XxlRpcProviderFactory;
|
||||
//import com.xxl.rpc.serialize.Serializer;
|
||||
//import org.quartz.*;
|
||||
//import org.quartz.Trigger.TriggerState;
|
||||
//import org.quartz.impl.triggers.CronTriggerImpl;
|
||||
//import org.slf4j.Logger;
|
||||
//import org.slf4j.LoggerFactory;
|
||||
//import org.springframework.util.Assert;
|
||||
//
|
||||
//import javax.servlet.ServletException;
|
||||
//import javax.servlet.http.HttpServletRequest;
|
||||
//import javax.servlet.http.HttpServletResponse;
|
||||
//import java.io.IOException;
|
||||
//import java.util.Date;
|
||||
//import java.util.concurrent.ConcurrentHashMap;
|
||||
//
|
||||
///**
|
||||
// * base quartz scheduler util
|
||||
// * @author xuxueli 2015-12-19 16:13:53
|
||||
// */
|
||||
//public final class XxlJobDynamicScheduler {
|
||||
// private static final Logger logger = LoggerFactory.getLogger(XxlJobDynamicScheduler_old.class);
|
||||
//
|
||||
// // ---------------------- param ----------------------
|
||||
//
|
||||
// // scheduler
|
||||
// private static Scheduler scheduler;
|
||||
// public void setScheduler(Scheduler scheduler) {
|
||||
// XxlJobDynamicScheduler_old.scheduler = scheduler;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// // ---------------------- init + destroy ----------------------
|
||||
// public void start() throws Exception {
|
||||
// // valid
|
||||
// Assert.notNull(scheduler, "quartz scheduler is null");
|
||||
//
|
||||
// // init i18n
|
||||
// initI18n();
|
||||
//
|
||||
// // admin registry monitor run
|
||||
// JobRegistryMonitorHelper.getInstance().start();
|
||||
//
|
||||
// // admin monitor run
|
||||
// JobFailMonitorHelper.getInstance().start();
|
||||
//
|
||||
// // admin-server
|
||||
// initRpcProvider();
|
||||
//
|
||||
// logger.info(">>>>>>>>> init xxl-job admin success.");
|
||||
// }
|
||||
//
|
||||
//
|
||||
// public void destroy() throws Exception {
|
||||
// // admin trigger pool stop
|
||||
// JobTriggerPoolHelper.toStop();
|
||||
//
|
||||
// // admin registry stop
|
||||
// JobRegistryMonitorHelper.getInstance().toStop();
|
||||
//
|
||||
// // admin monitor stop
|
||||
// JobFailMonitorHelper.getInstance().toStop();
|
||||
//
|
||||
// // admin-server
|
||||
// stopRpcProvider();
|
||||
// }
|
||||
//
|
||||
//
|
||||
// // ---------------------- I18n ----------------------
|
||||
//
|
||||
// private void initI18n(){
|
||||
// for (ExecutorBlockStrategyEnum item:ExecutorBlockStrategyEnum.values()) {
|
||||
// item.setTitle(I18nUtil.getString("jobconf_block_".concat(item.name())));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// // ---------------------- admin rpc provider (no server version) ----------------------
|
||||
// private static ServletServerHandler servletServerHandler;
|
||||
// private void initRpcProvider(){
|
||||
// // init
|
||||
// XxlRpcProviderFactory xxlRpcProviderFactory = new XxlRpcProviderFactory();
|
||||
// xxlRpcProviderFactory.initConfig(
|
||||
// NetEnum.NETTY_HTTP,
|
||||
// Serializer.SerializeEnum.HESSIAN.getSerializer(),
|
||||
// null,
|
||||
// 0,
|
||||
// XxlJobAdminConfig.getAdminConfig().getAccessToken(),
|
||||
// null,
|
||||
// null);
|
||||
//
|
||||
// // add services
|
||||
// xxlRpcProviderFactory.addService(AdminBiz.class.getName(), null, XxlJobAdminConfig.getAdminConfig().getAdminBiz());
|
||||
//
|
||||
// // servlet handler
|
||||
// servletServerHandler = new ServletServerHandler(xxlRpcProviderFactory);
|
||||
// }
|
||||
// private void stopRpcProvider() throws Exception {
|
||||
// XxlRpcInvokerFactory.getInstance().stop();
|
||||
// }
|
||||
// public static void invokeAdminService(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
|
||||
// servletServerHandler.handle(null, request, response);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// // ---------------------- executor-client ----------------------
|
||||
// private static ConcurrentHashMap<String, ExecutorBiz> executorBizRepository = new ConcurrentHashMap<String, ExecutorBiz>();
|
||||
// public static ExecutorBiz getExecutorBiz(String address) throws Exception {
|
||||
// // valid
|
||||
// if (address==null || address.trim().length()==0) {
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// // load-cache
|
||||
// address = address.trim();
|
||||
// ExecutorBiz executorBiz = executorBizRepository.get(address);
|
||||
// if (executorBiz != null) {
|
||||
// return executorBiz;
|
||||
// }
|
||||
//
|
||||
// // set-cache
|
||||
// executorBiz = (ExecutorBiz) new XxlRpcReferenceBean(
|
||||
// NetEnum.NETTY_HTTP,
|
||||
// Serializer.SerializeEnum.HESSIAN.getSerializer(),
|
||||
// CallType.SYNC,
|
||||
// LoadBalance.ROUND,
|
||||
// ExecutorBiz.class,
|
||||
// null,
|
||||
// 5000,
|
||||
// address,
|
||||
// XxlJobAdminConfig.getAdminConfig().getAccessToken(),
|
||||
// null,
|
||||
// null).getObject();
|
||||
//
|
||||
// executorBizRepository.put(address, executorBiz);
|
||||
// return executorBiz;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// // ---------------------- schedule util ----------------------
|
||||
//
|
||||
// /**
|
||||
// * fill job info
|
||||
// *
|
||||
// * @param jobInfo
|
||||
// */
|
||||
// public static void fillJobInfo(XxlJobInfo jobInfo) {
|
||||
//
|
||||
// String name = String.valueOf(jobInfo.getId());
|
||||
//
|
||||
// // trigger key
|
||||
// TriggerKey triggerKey = TriggerKey.triggerKey(name);
|
||||
// try {
|
||||
//
|
||||
// // trigger cron
|
||||
// Trigger trigger = scheduler.getTrigger(triggerKey);
|
||||
// if (trigger!=null && trigger instanceof CronTriggerImpl) {
|
||||
// String cronExpression = ((CronTriggerImpl) trigger).getCronExpression();
|
||||
// jobInfo.setJobCron(cronExpression);
|
||||
// }
|
||||
//
|
||||
// // trigger state
|
||||
// TriggerState triggerState = scheduler.getTriggerState(triggerKey);
|
||||
// if (triggerState!=null) {
|
||||
// jobInfo.setJobStatus(triggerState.name());
|
||||
// }
|
||||
//
|
||||
// //JobKey jobKey = new JobKey(jobInfo.getJobName(), String.valueOf(jobInfo.getJobGroup()));
|
||||
// //JobDetail jobDetail = scheduler.getJobDetail(jobKey);
|
||||
// //String jobClass = jobDetail.getJobClass().getName();
|
||||
//
|
||||
// } catch (SchedulerException e) {
|
||||
// logger.error(e.getMessage(), e);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * add trigger + job
|
||||
// *
|
||||
// * @param jobName
|
||||
// * @param cronExpression
|
||||
// * @return
|
||||
// * @throws SchedulerException
|
||||
// */
|
||||
// public static boolean addJob(String jobName, String cronExpression) throws SchedulerException {
|
||||
// // 1、job key
|
||||
// TriggerKey triggerKey = TriggerKey.triggerKey(jobName);
|
||||
// JobKey jobKey = new JobKey(jobName);
|
||||
//
|
||||
// // 2、valid
|
||||
// if (scheduler.checkExists(triggerKey)) {
|
||||
// return true; // PASS
|
||||
// }
|
||||
//
|
||||
// // 3、corn trigger
|
||||
// CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression).withMisfireHandlingInstructionDoNothing(); // withMisfireHandlingInstructionDoNothing 忽略掉调度终止过程中忽略的调度
|
||||
// CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(cronScheduleBuilder).build();
|
||||
//
|
||||
// // 4、job detail
|
||||
// Class<? extends Job> jobClass_ = RemoteHttpJobBean.class; // Class.forName(jobInfo.getJobClass());
|
||||
// JobDetail jobDetail = JobBuilder.newJob(jobClass_).withIdentity(jobKey).build();
|
||||
//
|
||||
// /*if (jobInfo.getJobData()!=null) {
|
||||
// JobDataMap jobDataMap = jobDetail.getJobDataMap();
|
||||
// jobDataMap.putAll(JacksonUtil.readValue(jobInfo.getJobData(), Map.class));
|
||||
// // JobExecutionContext context.getMergedJobDataMap().get("mailGuid");
|
||||
// }*/
|
||||
//
|
||||
// // 5、schedule job
|
||||
// Date date = scheduler.scheduleJob(jobDetail, cronTrigger);
|
||||
//
|
||||
// logger.info(">>>>>>>>>>> addJob success(quartz), jobDetail:{}, cronTrigger:{}, date:{}", jobDetail, cronTrigger, date);
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * remove trigger + job
|
||||
// *
|
||||
// * @param jobName
|
||||
// * @return
|
||||
// * @throws SchedulerException
|
||||
// */
|
||||
// public static boolean removeJob(String jobName) throws SchedulerException {
|
||||
//
|
||||
// JobKey jobKey = new JobKey(jobName);
|
||||
// scheduler.deleteJob(jobKey);
|
||||
//
|
||||
// /*TriggerKey triggerKey = TriggerKey.triggerKey(jobName);
|
||||
// if (scheduler.checkExists(triggerKey)) {
|
||||
// scheduler.unscheduleJob(triggerKey); // trigger + job
|
||||
// }*/
|
||||
//
|
||||
// logger.info(">>>>>>>>>>> removeJob success(quartz), jobKey:{}", jobKey);
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * updateJobCron
|
||||
// *
|
||||
// * @param jobName
|
||||
// * @param cronExpression
|
||||
// * @return
|
||||
// * @throws SchedulerException
|
||||
// */
|
||||
// public static boolean updateJobCron(String jobName, String cronExpression) throws SchedulerException {
|
||||
//
|
||||
// // 1、job key
|
||||
// TriggerKey triggerKey = TriggerKey.triggerKey(jobName);
|
||||
//
|
||||
// // 2、valid
|
||||
// if (!scheduler.checkExists(triggerKey)) {
|
||||
// return true; // PASS
|
||||
// }
|
||||
//
|
||||
// CronTrigger oldTrigger = (CronTrigger) scheduler.getTrigger(triggerKey);
|
||||
//
|
||||
// // 3、avoid repeat cron
|
||||
// String oldCron = oldTrigger.getCronExpression();
|
||||
// if (oldCron.equals(cronExpression)){
|
||||
// return true; // PASS
|
||||
// }
|
||||
//
|
||||
// // 4、new cron trigger
|
||||
// CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression).withMisfireHandlingInstructionDoNothing();
|
||||
// oldTrigger = oldTrigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(cronScheduleBuilder).build();
|
||||
//
|
||||
// // 5、rescheduleJob
|
||||
// scheduler.rescheduleJob(triggerKey, oldTrigger);
|
||||
//
|
||||
// /*
|
||||
// JobKey jobKey = new JobKey(jobName);
|
||||
//
|
||||
// // old job detail
|
||||
// JobDetail jobDetail = scheduler.getJobDetail(jobKey);
|
||||
//
|
||||
// // new trigger
|
||||
// HashSet<Trigger> triggerSet = new HashSet<Trigger>();
|
||||
// triggerSet.add(cronTrigger);
|
||||
// // cover trigger of job detail
|
||||
// scheduler.scheduleJob(jobDetail, triggerSet, true);*/
|
||||
//
|
||||
// logger.info(">>>>>>>>>>> resumeJob success, JobName:{}", jobName);
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * pause
|
||||
// *
|
||||
// * @param jobName
|
||||
// * @return
|
||||
// * @throws SchedulerException
|
||||
// */
|
||||
// /*public static boolean pauseJob(String jobName) throws SchedulerException {
|
||||
//
|
||||
// TriggerKey triggerKey = TriggerKey.triggerKey(jobName);
|
||||
//
|
||||
// boolean result = false;
|
||||
// if (scheduler.checkExists(triggerKey)) {
|
||||
// scheduler.pauseTrigger(triggerKey);
|
||||
// result = true;
|
||||
// }
|
||||
//
|
||||
// logger.info(">>>>>>>>>>> pauseJob {}, triggerKey:{}", (result?"success":"fail"),triggerKey);
|
||||
// return result;
|
||||
// }*/
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * resume
|
||||
// *
|
||||
// * @param jobName
|
||||
// * @return
|
||||
// * @throws SchedulerException
|
||||
// */
|
||||
// /*public static boolean resumeJob(String jobName) throws SchedulerException {
|
||||
//
|
||||
// TriggerKey triggerKey = TriggerKey.triggerKey(jobName);
|
||||
//
|
||||
// boolean result = false;
|
||||
// if (scheduler.checkExists(triggerKey)) {
|
||||
// scheduler.resumeTrigger(triggerKey);
|
||||
// result = true;
|
||||
// }
|
||||
//
|
||||
// logger.info(">>>>>>>>>>> resumeJob {}, triggerKey:{}", (result?"success":"fail"), triggerKey);
|
||||
// return result;
|
||||
// }*/
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * run
|
||||
// *
|
||||
// * @param jobName
|
||||
// * @return
|
||||
// * @throws SchedulerException
|
||||
// */
|
||||
// /*public static boolean triggerJob(String jobName) throws SchedulerException {
|
||||
// // TriggerKey : name + group
|
||||
// JobKey jobKey = new JobKey(jobName);
|
||||
// TriggerKey triggerKey = TriggerKey.triggerKey(jobName);
|
||||
//
|
||||
// boolean result = false;
|
||||
// if (scheduler.checkExists(triggerKey)) {
|
||||
// scheduler.triggerJob(jobKey);
|
||||
// result = true;
|
||||
// logger.info(">>>>>>>>>>> runJob success, jobKey:{}", jobKey);
|
||||
// } else {
|
||||
// logger.info(">>>>>>>>>>> runJob fail, jobKey:{}", jobKey);
|
||||
// }
|
||||
// return result;
|
||||
// }*/
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * finaAllJobList
|
||||
// *
|
||||
// * @return
|
||||
// *//*
|
||||
// @Deprecated
|
||||
// public static List<Map<String, Object>> finaAllJobList(){
|
||||
// List<Map<String, Object>> jobList = new ArrayList<Map<String,Object>>();
|
||||
//
|
||||
// try {
|
||||
// if (scheduler.getJobGroupNames()==null || scheduler.getJobGroupNames().size()==0) {
|
||||
// return null;
|
||||
// }
|
||||
// String groupName = scheduler.getJobGroupNames().get(0);
|
||||
// Set<JobKey> jobKeys = scheduler.getJobKeys(GroupMatcher.jobGroupEquals(groupName));
|
||||
// if (jobKeys!=null && jobKeys.size()>0) {
|
||||
// for (JobKey jobKey : jobKeys) {
|
||||
// TriggerKey triggerKey = TriggerKey.triggerKey(jobKey.getName(), Scheduler.DEFAULT_GROUP);
|
||||
// Trigger trigger = scheduler.getTrigger(triggerKey);
|
||||
// JobDetail jobDetail = scheduler.getJobDetail(jobKey);
|
||||
// TriggerState triggerState = scheduler.getTriggerState(triggerKey);
|
||||
// Map<String, Object> jobMap = new HashMap<String, Object>();
|
||||
// jobMap.put("TriggerKey", triggerKey);
|
||||
// jobMap.put("Trigger", trigger);
|
||||
// jobMap.put("JobDetail", jobDetail);
|
||||
// jobMap.put("TriggerState", triggerState);
|
||||
// jobList.add(jobMap);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// } catch (SchedulerException e) {
|
||||
// logger.error(e.getMessage(), e);
|
||||
// return null;
|
||||
// }
|
||||
// return jobList;
|
||||
// }*/
|
||||
//
|
||||
//}
|
@ -1,58 +0,0 @@
|
||||
package com.xxl.job.admin.core.old;//package com.xxl.job.admin.core.quartz;
|
||||
//
|
||||
//import org.quartz.SchedulerConfigException;
|
||||
//import org.quartz.spi.ThreadPool;
|
||||
//
|
||||
///**
|
||||
// * single thread pool, for async trigger
|
||||
// *
|
||||
// * @author xuxueli 2019-03-06
|
||||
// */
|
||||
//public class XxlJobThreadPool implements ThreadPool {
|
||||
//
|
||||
// @Override
|
||||
// public boolean runInThread(Runnable runnable) {
|
||||
//
|
||||
// // async run
|
||||
// runnable.run();
|
||||
// return true;
|
||||
//
|
||||
// //return false;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public int blockForAvailableThreads() {
|
||||
// return 1;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void initialize() throws SchedulerConfigException {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void shutdown(boolean waitForJobsToComplete) {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public int getPoolSize() {
|
||||
// return 1;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void setInstanceId(String schedInstId) {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void setInstanceName(String schedName) {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// // support
|
||||
// public void setThreadCount(int count) {
|
||||
// //
|
||||
// }
|
||||
//
|
||||
//}
|
@ -1,48 +0,0 @@
|
||||
package com.xxl.job.admin.core.route;
|
||||
|
||||
import com.xxl.job.admin.core.route.strategy.*;
|
||||
import com.xxl.job.admin.core.util.I18nUtil;
|
||||
|
||||
/**
|
||||
* Created by xuxueli on 17/3/10.
|
||||
*/
|
||||
public enum ExecutorRouteStrategyEnum {
|
||||
|
||||
FIRST(I18nUtil.getString("jobconf_route_first"), new ExecutorRouteFirst()),
|
||||
LAST(I18nUtil.getString("jobconf_route_last"), new ExecutorRouteLast()),
|
||||
ROUND(I18nUtil.getString("jobconf_route_round"), new ExecutorRouteRound()),
|
||||
RANDOM(I18nUtil.getString("jobconf_route_random"), new ExecutorRouteRandom()),
|
||||
CONSISTENT_HASH(I18nUtil.getString("jobconf_route_consistenthash"), new ExecutorRouteConsistentHash()),
|
||||
LEAST_FREQUENTLY_USED(I18nUtil.getString("jobconf_route_lfu"), new ExecutorRouteLFU()),
|
||||
LEAST_RECENTLY_USED(I18nUtil.getString("jobconf_route_lru"), new ExecutorRouteLRU()),
|
||||
FAILOVER(I18nUtil.getString("jobconf_route_failover"), new ExecutorRouteFailover()),
|
||||
BUSYOVER(I18nUtil.getString("jobconf_route_busyover"), new ExecutorRouteBusyover()),
|
||||
SHARDING_BROADCAST(I18nUtil.getString("jobconf_route_shard"), null);
|
||||
|
||||
ExecutorRouteStrategyEnum(String title, ExecutorRouter router) {
|
||||
this.title = title;
|
||||
this.router = router;
|
||||
}
|
||||
|
||||
private String title;
|
||||
private ExecutorRouter router;
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
public ExecutorRouter getRouter() {
|
||||
return router;
|
||||
}
|
||||
|
||||
public static ExecutorRouteStrategyEnum match(String name, ExecutorRouteStrategyEnum defaultItem){
|
||||
if (name != null) {
|
||||
for (ExecutorRouteStrategyEnum item: ExecutorRouteStrategyEnum.values()) {
|
||||
if (item.name().equals(name)) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
return defaultItem;
|
||||
}
|
||||
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
package com.xxl.job.admin.core.route;
|
||||
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import com.xxl.job.core.biz.model.TriggerParam;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by xuxueli on 17/3/10.
|
||||
*/
|
||||
public abstract class ExecutorRouter {
|
||||
protected static Logger logger = LoggerFactory.getLogger(ExecutorRouter.class);
|
||||
|
||||
/**
|
||||
* route address
|
||||
*
|
||||
* @param addressList
|
||||
* @return ReturnT.content=address
|
||||
*/
|
||||
public abstract ReturnT<String> route(TriggerParam triggerParam, List<String> addressList);
|
||||
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
package com.xxl.job.admin.core.route.strategy;
|
||||
|
||||
import com.xxl.job.admin.core.route.ExecutorRouter;
|
||||
import com.xxl.job.admin.core.scheduler.XxlJobScheduler;
|
||||
import com.xxl.job.admin.core.util.I18nUtil;
|
||||
import com.xxl.job.core.biz.ExecutorBiz;
|
||||
import com.xxl.job.core.biz.model.IdleBeatParam;
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import com.xxl.job.core.biz.model.TriggerParam;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by xuxueli on 17/3/10.
|
||||
*/
|
||||
public class ExecutorRouteBusyover extends ExecutorRouter {
|
||||
|
||||
@Override
|
||||
public ReturnT<String> route(TriggerParam triggerParam, List<String> addressList) {
|
||||
StringBuffer idleBeatResultSB = new StringBuffer();
|
||||
for (String address : addressList) {
|
||||
// beat
|
||||
ReturnT<String> idleBeatResult = null;
|
||||
try {
|
||||
ExecutorBiz executorBiz = XxlJobScheduler.getExecutorBiz(address);
|
||||
idleBeatResult = executorBiz.idleBeat(new IdleBeatParam(triggerParam.getJobId()));
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
idleBeatResult = new ReturnT<String>(ReturnT.FAIL_CODE, ""+e );
|
||||
}
|
||||
idleBeatResultSB.append( (idleBeatResultSB.length()>0)?"<br><br>":"")
|
||||
.append(I18nUtil.getString("jobconf_idleBeat") + ":")
|
||||
.append("<br>address:").append(address)
|
||||
.append("<br>code:").append(idleBeatResult.getCode())
|
||||
.append("<br>msg:").append(idleBeatResult.getMsg());
|
||||
|
||||
// beat success
|
||||
if (idleBeatResult.getCode() == ReturnT.SUCCESS_CODE) {
|
||||
idleBeatResult.setMsg(idleBeatResultSB.toString());
|
||||
idleBeatResult.setContent(address);
|
||||
return idleBeatResult;
|
||||
}
|
||||
}
|
||||
|
||||
return new ReturnT<String>(ReturnT.FAIL_CODE, idleBeatResultSB.toString());
|
||||
}
|
||||
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
package com.xxl.job.admin.core.route.strategy;
|
||||
|
||||
import com.xxl.job.admin.core.route.ExecutorRouter;
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import com.xxl.job.core.biz.model.TriggerParam;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.List;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* 分组下机器地址相同,不同JOB均匀散列在不同机器上,保证分组下机器分配JOB平均;且每个JOB固定调度其中一台机器;
|
||||
* a、virtual node:解决不均衡问题
|
||||
* b、hash method replace hashCode:String的hashCode可能重复,需要进一步扩大hashCode的取值范围
|
||||
* Created by xuxueli on 17/3/10.
|
||||
*/
|
||||
public class ExecutorRouteConsistentHash extends ExecutorRouter {
|
||||
|
||||
private static int VIRTUAL_NODE_NUM = 100;
|
||||
|
||||
/**
|
||||
* get hash code on 2^32 ring (md5散列的方式计算hash值)
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
private static long hash(String key) {
|
||||
|
||||
// md5 byte
|
||||
MessageDigest md5;
|
||||
try {
|
||||
md5 = MessageDigest.getInstance("MD5");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException("MD5 not supported", e);
|
||||
}
|
||||
md5.reset();
|
||||
byte[] keyBytes = null;
|
||||
try {
|
||||
keyBytes = key.getBytes("UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException("Unknown string :" + key, e);
|
||||
}
|
||||
|
||||
md5.update(keyBytes);
|
||||
byte[] digest = md5.digest();
|
||||
|
||||
// hash code, Truncate to 32-bits
|
||||
long hashCode = ((long) (digest[3] & 0xFF) << 24)
|
||||
| ((long) (digest[2] & 0xFF) << 16)
|
||||
| ((long) (digest[1] & 0xFF) << 8)
|
||||
| (digest[0] & 0xFF);
|
||||
|
||||
long truncateHashCode = hashCode & 0xffffffffL;
|
||||
return truncateHashCode;
|
||||
}
|
||||
|
||||
public String hashJob(int jobId, List<String> addressList) {
|
||||
|
||||
// ------A1------A2-------A3------
|
||||
// -----------J1------------------
|
||||
TreeMap<Long, String> addressRing = new TreeMap<Long, String>();
|
||||
for (String address: addressList) {
|
||||
for (int i = 0; i < VIRTUAL_NODE_NUM; i++) {
|
||||
long addressHash = hash("SHARD-" + address + "-NODE-" + i);
|
||||
addressRing.put(addressHash, address);
|
||||
}
|
||||
}
|
||||
|
||||
long jobHash = hash(String.valueOf(jobId));
|
||||
SortedMap<Long, String> lastRing = addressRing.tailMap(jobHash);
|
||||
if (!lastRing.isEmpty()) {
|
||||
return lastRing.get(lastRing.firstKey());
|
||||
}
|
||||
return addressRing.firstEntry().getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnT<String> route(TriggerParam triggerParam, List<String> addressList) {
|
||||
String address = hashJob(triggerParam.getJobId(), addressList);
|
||||
return new ReturnT<String>(address);
|
||||
}
|
||||
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
package com.xxl.job.admin.core.route.strategy;
|
||||
|
||||
import com.xxl.job.admin.core.route.ExecutorRouter;
|
||||
import com.xxl.job.admin.core.scheduler.XxlJobScheduler;
|
||||
import com.xxl.job.admin.core.util.I18nUtil;
|
||||
import com.xxl.job.core.biz.ExecutorBiz;
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import com.xxl.job.core.biz.model.TriggerParam;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by xuxueli on 17/3/10.
|
||||
*/
|
||||
public class ExecutorRouteFailover extends ExecutorRouter {
|
||||
|
||||
@Override
|
||||
public ReturnT<String> route(TriggerParam triggerParam, List<String> addressList) {
|
||||
|
||||
StringBuffer beatResultSB = new StringBuffer();
|
||||
for (String address : addressList) {
|
||||
// beat
|
||||
ReturnT<String> beatResult = null;
|
||||
try {
|
||||
ExecutorBiz executorBiz = XxlJobScheduler.getExecutorBiz(address);
|
||||
beatResult = executorBiz.beat();
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
beatResult = new ReturnT<String>(ReturnT.FAIL_CODE, ""+e );
|
||||
}
|
||||
beatResultSB.append( (beatResultSB.length()>0)?"<br><br>":"")
|
||||
.append(I18nUtil.getString("jobconf_beat") + ":")
|
||||
.append("<br>address:").append(address)
|
||||
.append("<br>code:").append(beatResult.getCode())
|
||||
.append("<br>msg:").append(beatResult.getMsg());
|
||||
|
||||
// beat success
|
||||
if (beatResult.getCode() == ReturnT.SUCCESS_CODE) {
|
||||
|
||||
beatResult.setMsg(beatResultSB.toString());
|
||||
beatResult.setContent(address);
|
||||
return beatResult;
|
||||
}
|
||||
}
|
||||
return new ReturnT<String>(ReturnT.FAIL_CODE, beatResultSB.toString());
|
||||
|
||||
}
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
package com.xxl.job.admin.core.route.strategy;
|
||||
|
||||
import com.xxl.job.admin.core.route.ExecutorRouter;
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import com.xxl.job.core.biz.model.TriggerParam;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by xuxueli on 17/3/10.
|
||||
*/
|
||||
public class ExecutorRouteFirst extends ExecutorRouter {
|
||||
|
||||
@Override
|
||||
public ReturnT<String> route(TriggerParam triggerParam, List<String> addressList){
|
||||
return new ReturnT<String>(addressList.get(0));
|
||||
}
|
||||
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
package com.xxl.job.admin.core.route.strategy;
|
||||
|
||||
import com.xxl.job.admin.core.route.ExecutorRouter;
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import com.xxl.job.core.biz.model.TriggerParam;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* 单个JOB对应的每个执行器,使用频率最低的优先被选举
|
||||
* a(*)、LFU(Least Frequently Used):最不经常使用,频率/次数
|
||||
* b、LRU(Least Recently Used):最近最久未使用,时间
|
||||
*
|
||||
* Created by xuxueli on 17/3/10.
|
||||
*/
|
||||
public class ExecutorRouteLFU extends ExecutorRouter {
|
||||
|
||||
private static ConcurrentMap<Integer, HashMap<String, Integer>> jobLfuMap = new ConcurrentHashMap<Integer, HashMap<String, Integer>>();
|
||||
private static long CACHE_VALID_TIME = 0;
|
||||
|
||||
public String route(int jobId, List<String> addressList) {
|
||||
|
||||
// cache clear
|
||||
if (System.currentTimeMillis() > CACHE_VALID_TIME) {
|
||||
jobLfuMap.clear();
|
||||
CACHE_VALID_TIME = System.currentTimeMillis() + 1000*60*60*24;
|
||||
}
|
||||
|
||||
// lfu item init
|
||||
HashMap<String, Integer> lfuItemMap = jobLfuMap.get(jobId); // Key排序可以用TreeMap+构造入参Compare;Value排序暂时只能通过ArrayList;
|
||||
if (lfuItemMap == null) {
|
||||
lfuItemMap = new HashMap<String, Integer>();
|
||||
jobLfuMap.putIfAbsent(jobId, lfuItemMap); // 避免重复覆盖
|
||||
}
|
||||
|
||||
// put new
|
||||
for (String address: addressList) {
|
||||
if (!lfuItemMap.containsKey(address) || lfuItemMap.get(address) >1000000 ) {
|
||||
lfuItemMap.put(address, new Random().nextInt(addressList.size())); // 初始化时主动Random一次,缓解首次压力
|
||||
}
|
||||
}
|
||||
// remove old
|
||||
List<String> delKeys = new ArrayList<>();
|
||||
for (String existKey: lfuItemMap.keySet()) {
|
||||
if (!addressList.contains(existKey)) {
|
||||
delKeys.add(existKey);
|
||||
}
|
||||
}
|
||||
if (delKeys.size() > 0) {
|
||||
for (String delKey: delKeys) {
|
||||
lfuItemMap.remove(delKey);
|
||||
}
|
||||
}
|
||||
|
||||
// load least userd count address
|
||||
List<Map.Entry<String, Integer>> lfuItemList = new ArrayList<Map.Entry<String, Integer>>(lfuItemMap.entrySet());
|
||||
Collections.sort(lfuItemList, new Comparator<Map.Entry<String, Integer>>() {
|
||||
@Override
|
||||
public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
|
||||
return o1.getValue().compareTo(o2.getValue());
|
||||
}
|
||||
});
|
||||
|
||||
Map.Entry<String, Integer> addressItem = lfuItemList.get(0);
|
||||
String minAddress = addressItem.getKey();
|
||||
addressItem.setValue(addressItem.getValue() + 1);
|
||||
|
||||
return addressItem.getKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnT<String> route(TriggerParam triggerParam, List<String> addressList) {
|
||||
String address = route(triggerParam.getJobId(), addressList);
|
||||
return new ReturnT<String>(address);
|
||||
}
|
||||
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
package com.xxl.job.admin.core.route.strategy;
|
||||
|
||||
import com.xxl.job.admin.core.route.ExecutorRouter;
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import com.xxl.job.core.biz.model.TriggerParam;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* 单个JOB对应的每个执行器,最久为使用的优先被选举
|
||||
* a、LFU(Least Frequently Used):最不经常使用,频率/次数
|
||||
* b(*)、LRU(Least Recently Used):最近最久未使用,时间
|
||||
*
|
||||
* Created by xuxueli on 17/3/10.
|
||||
*/
|
||||
public class ExecutorRouteLRU extends ExecutorRouter {
|
||||
|
||||
private static ConcurrentMap<Integer, LinkedHashMap<String, String>> jobLRUMap = new ConcurrentHashMap<Integer, LinkedHashMap<String, String>>();
|
||||
private static long CACHE_VALID_TIME = 0;
|
||||
|
||||
public String route(int jobId, List<String> addressList) {
|
||||
|
||||
// cache clear
|
||||
if (System.currentTimeMillis() > CACHE_VALID_TIME) {
|
||||
jobLRUMap.clear();
|
||||
CACHE_VALID_TIME = System.currentTimeMillis() + 1000*60*60*24;
|
||||
}
|
||||
|
||||
// init lru
|
||||
LinkedHashMap<String, String> lruItem = jobLRUMap.get(jobId);
|
||||
if (lruItem == null) {
|
||||
/**
|
||||
* LinkedHashMap
|
||||
* a、accessOrder:true=访问顺序排序(get/put时排序);false=插入顺序排期;
|
||||
* b、removeEldestEntry:新增元素时将会调用,返回true时会删除最老元素;可封装LinkedHashMap并重写该方法,比如定义最大容量,超出是返回true即可实现固定长度的LRU算法;
|
||||
*/
|
||||
lruItem = new LinkedHashMap<String, String>(16, 0.75f, true);
|
||||
jobLRUMap.putIfAbsent(jobId, lruItem);
|
||||
}
|
||||
|
||||
// put new
|
||||
for (String address: addressList) {
|
||||
if (!lruItem.containsKey(address)) {
|
||||
lruItem.put(address, address);
|
||||
}
|
||||
}
|
||||
// remove old
|
||||
List<String> delKeys = new ArrayList<>();
|
||||
for (String existKey: lruItem.keySet()) {
|
||||
if (!addressList.contains(existKey)) {
|
||||
delKeys.add(existKey);
|
||||
}
|
||||
}
|
||||
if (delKeys.size() > 0) {
|
||||
for (String delKey: delKeys) {
|
||||
lruItem.remove(delKey);
|
||||
}
|
||||
}
|
||||
|
||||
// load
|
||||
String eldestKey = lruItem.entrySet().iterator().next().getKey();
|
||||
String eldestValue = lruItem.get(eldestKey);
|
||||
return eldestValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnT<String> route(TriggerParam triggerParam, List<String> addressList) {
|
||||
String address = route(triggerParam.getJobId(), addressList);
|
||||
return new ReturnT<String>(address);
|
||||
}
|
||||
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
package com.xxl.job.admin.core.route.strategy;
|
||||
|
||||
import com.xxl.job.admin.core.route.ExecutorRouter;
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import com.xxl.job.core.biz.model.TriggerParam;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by xuxueli on 17/3/10.
|
||||
*/
|
||||
public class ExecutorRouteLast extends ExecutorRouter {
|
||||
|
||||
@Override
|
||||
public ReturnT<String> route(TriggerParam triggerParam, List<String> addressList) {
|
||||
return new ReturnT<String>(addressList.get(addressList.size()-1));
|
||||
}
|
||||
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
package com.xxl.job.admin.core.route.strategy;
|
||||
|
||||
import com.xxl.job.admin.core.route.ExecutorRouter;
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import com.xxl.job.core.biz.model.TriggerParam;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Created by xuxueli on 17/3/10.
|
||||
*/
|
||||
public class ExecutorRouteRandom extends ExecutorRouter {
|
||||
|
||||
private static Random localRandom = new Random();
|
||||
|
||||
@Override
|
||||
public ReturnT<String> route(TriggerParam triggerParam, List<String> addressList) {
|
||||
String address = addressList.get(localRandom.nextInt(addressList.size()));
|
||||
return new ReturnT<String>(address);
|
||||
}
|
||||
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
package com.xxl.job.admin.core.route.strategy;
|
||||
|
||||
import com.xxl.job.admin.core.route.ExecutorRouter;
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import com.xxl.job.core.biz.model.TriggerParam;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* Created by xuxueli on 17/3/10.
|
||||
*/
|
||||
public class ExecutorRouteRound extends ExecutorRouter {
|
||||
|
||||
private static ConcurrentMap<Integer, AtomicInteger> routeCountEachJob = new ConcurrentHashMap<>();
|
||||
private static long CACHE_VALID_TIME = 0;
|
||||
|
||||
private static int count(int jobId) {
|
||||
// cache clear
|
||||
if (System.currentTimeMillis() > CACHE_VALID_TIME) {
|
||||
routeCountEachJob.clear();
|
||||
CACHE_VALID_TIME = System.currentTimeMillis() + 1000*60*60*24;
|
||||
}
|
||||
|
||||
AtomicInteger count = routeCountEachJob.get(jobId);
|
||||
if (count == null || count.get() > 1000000) {
|
||||
// 初始化时主动Random一次,缓解首次压力
|
||||
count = new AtomicInteger(new Random().nextInt(100));
|
||||
} else {
|
||||
// count++
|
||||
count.addAndGet(1);
|
||||
}
|
||||
routeCountEachJob.put(jobId, count);
|
||||
return count.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnT<String> route(TriggerParam triggerParam, List<String> addressList) {
|
||||
String address = addressList.get(count(triggerParam.getJobId())%addressList.size());
|
||||
return new ReturnT<String>(address);
|
||||
}
|
||||
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
package com.xxl.job.admin.core.scheduler;
|
||||
|
||||
import com.xxl.job.admin.core.util.I18nUtil;
|
||||
|
||||
/**
|
||||
* @author xuxueli 2020-10-29 21:11:23
|
||||
*/
|
||||
public enum MisfireStrategyEnum {
|
||||
|
||||
/**
|
||||
* do nothing
|
||||
*/
|
||||
DO_NOTHING(I18nUtil.getString("misfire_strategy_do_nothing")),
|
||||
|
||||
/**
|
||||
* fire once now
|
||||
*/
|
||||
FIRE_ONCE_NOW(I18nUtil.getString("misfire_strategy_fire_once_now"));
|
||||
|
||||
private String title;
|
||||
|
||||
MisfireStrategyEnum(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public static MisfireStrategyEnum match(String name, MisfireStrategyEnum defaultItem){
|
||||
for (MisfireStrategyEnum item: MisfireStrategyEnum.values()) {
|
||||
if (item.name().equals(name)) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return defaultItem;
|
||||
}
|
||||
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
package com.xxl.job.admin.core.scheduler;
|
||||
|
||||
import com.xxl.job.admin.core.util.I18nUtil;
|
||||
|
||||
/**
|
||||
* @author xuxueli 2020-10-29 21:11:23
|
||||
*/
|
||||
public enum ScheduleTypeEnum {
|
||||
|
||||
NONE(I18nUtil.getString("schedule_type_none")),
|
||||
|
||||
/**
|
||||
* schedule by cron
|
||||
*/
|
||||
CRON(I18nUtil.getString("schedule_type_cron")),
|
||||
|
||||
/**
|
||||
* schedule by fixed rate (in seconds)
|
||||
*/
|
||||
FIX_RATE(I18nUtil.getString("schedule_type_fix_rate")),
|
||||
|
||||
/**
|
||||
* schedule by fix delay (in seconds), after the last time
|
||||
*/
|
||||
/*FIX_DELAY(I18nUtil.getString("schedule_type_fix_delay"))*/;
|
||||
|
||||
private String title;
|
||||
|
||||
ScheduleTypeEnum(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public static ScheduleTypeEnum match(String name, ScheduleTypeEnum defaultItem){
|
||||
for (ScheduleTypeEnum item: ScheduleTypeEnum.values()) {
|
||||
if (item.name().equals(name)) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return defaultItem;
|
||||
}
|
||||
|
||||
}
|
@ -1,101 +0,0 @@
|
||||
package com.xxl.job.admin.core.scheduler;
|
||||
|
||||
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
|
||||
import com.xxl.job.admin.core.thread.*;
|
||||
import com.xxl.job.admin.core.util.I18nUtil;
|
||||
import com.xxl.job.core.biz.ExecutorBiz;
|
||||
import com.xxl.job.core.biz.client.ExecutorBizClient;
|
||||
import com.xxl.job.core.enums.ExecutorBlockStrategyEnum;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* @author xuxueli 2018-10-28 00:18:17
|
||||
*/
|
||||
|
||||
public class XxlJobScheduler {
|
||||
private static final Logger logger = LoggerFactory.getLogger(XxlJobScheduler.class);
|
||||
|
||||
|
||||
public void init() throws Exception {
|
||||
// init i18n
|
||||
initI18n();
|
||||
|
||||
// admin trigger pool start
|
||||
JobTriggerPoolHelper.toStart();
|
||||
|
||||
// admin registry monitor run
|
||||
JobRegistryHelper.getInstance().start();
|
||||
|
||||
// admin fail-monitor run
|
||||
JobFailMonitorHelper.getInstance().start();
|
||||
|
||||
// admin lose-monitor run ( depend on JobTriggerPoolHelper )
|
||||
JobCompleteHelper.getInstance().start();
|
||||
|
||||
// admin log report start
|
||||
JobLogReportHelper.getInstance().start();
|
||||
|
||||
// start-schedule ( depend on JobTriggerPoolHelper )
|
||||
JobScheduleHelper.getInstance().start();
|
||||
|
||||
logger.info(">>>>>>>>> init xxl-job admin success.");
|
||||
}
|
||||
|
||||
|
||||
public void destroy() throws Exception {
|
||||
|
||||
// stop-schedule
|
||||
JobScheduleHelper.getInstance().toStop();
|
||||
|
||||
// admin log report stop
|
||||
JobLogReportHelper.getInstance().toStop();
|
||||
|
||||
// admin lose-monitor stop
|
||||
JobCompleteHelper.getInstance().toStop();
|
||||
|
||||
// admin fail-monitor stop
|
||||
JobFailMonitorHelper.getInstance().toStop();
|
||||
|
||||
// admin registry stop
|
||||
JobRegistryHelper.getInstance().toStop();
|
||||
|
||||
// admin trigger pool stop
|
||||
JobTriggerPoolHelper.toStop();
|
||||
|
||||
}
|
||||
|
||||
// ---------------------- I18n ----------------------
|
||||
|
||||
private void initI18n(){
|
||||
for (ExecutorBlockStrategyEnum item:ExecutorBlockStrategyEnum.values()) {
|
||||
item.setTitle(I18nUtil.getString("jobconf_block_".concat(item.name())));
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------- executor-client ----------------------
|
||||
private static ConcurrentMap<String, ExecutorBiz> executorBizRepository = new ConcurrentHashMap<String, ExecutorBiz>();
|
||||
public static ExecutorBiz getExecutorBiz(String address) throws Exception {
|
||||
// valid
|
||||
if (address==null || address.trim().length()==0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// load-cache
|
||||
address = address.trim();
|
||||
ExecutorBiz executorBiz = executorBizRepository.get(address);
|
||||
if (executorBiz != null) {
|
||||
return executorBiz;
|
||||
}
|
||||
|
||||
// set-cache
|
||||
executorBiz = new ExecutorBizClient(address, XxlJobAdminConfig.getAdminConfig().getAccessToken());
|
||||
|
||||
executorBizRepository.put(address, executorBiz);
|
||||
return executorBiz;
|
||||
}
|
||||
|
||||
}
|
@ -1,184 +0,0 @@
|
||||
package com.xxl.job.admin.core.thread;
|
||||
|
||||
import com.xxl.job.admin.core.complete.XxlJobCompleter;
|
||||
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
|
||||
import com.xxl.job.admin.core.model.XxlJobLog;
|
||||
import com.xxl.job.admin.core.util.I18nUtil;
|
||||
import com.xxl.job.core.biz.model.HandleCallbackParam;
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import com.xxl.job.core.util.DateUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
/**
|
||||
* job lose-monitor instance
|
||||
*
|
||||
* @author xuxueli 2015-9-1 18:05:56
|
||||
*/
|
||||
public class JobCompleteHelper {
|
||||
private static Logger logger = LoggerFactory.getLogger(JobCompleteHelper.class);
|
||||
|
||||
private static JobCompleteHelper instance = new JobCompleteHelper();
|
||||
public static JobCompleteHelper getInstance(){
|
||||
return instance;
|
||||
}
|
||||
|
||||
// ---------------------- monitor ----------------------
|
||||
|
||||
private ThreadPoolExecutor callbackThreadPool = null;
|
||||
private Thread monitorThread;
|
||||
private volatile boolean toStop = false;
|
||||
public void start(){
|
||||
|
||||
// for callback
|
||||
callbackThreadPool = new ThreadPoolExecutor(
|
||||
2,
|
||||
20,
|
||||
30L,
|
||||
TimeUnit.SECONDS,
|
||||
new LinkedBlockingQueue<Runnable>(3000),
|
||||
new ThreadFactory() {
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
return new Thread(r, "xxl-job, admin JobLosedMonitorHelper-callbackThreadPool-" + r.hashCode());
|
||||
}
|
||||
},
|
||||
new RejectedExecutionHandler() {
|
||||
@Override
|
||||
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
|
||||
r.run();
|
||||
logger.warn(">>>>>>>>>>> xxl-job, callback too fast, match threadpool rejected handler(run now).");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// for monitor
|
||||
monitorThread = new Thread(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
// wait for JobTriggerPoolHelper-init
|
||||
try {
|
||||
TimeUnit.MILLISECONDS.sleep(50);
|
||||
} catch (InterruptedException e) {
|
||||
if (!toStop) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
// monitor
|
||||
while (!toStop) {
|
||||
try {
|
||||
// 任务结果丢失处理:调度记录停留在 "运行中" 状态超过10min,且对应执行器心跳注册失败不在线,则将本地调度主动标记失败;
|
||||
Date losedTime = DateUtil.addMinutes(new Date(), -10);
|
||||
List<Long> losedJobIds = XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().findLostJobIds(losedTime);
|
||||
|
||||
if (losedJobIds!=null && losedJobIds.size()>0) {
|
||||
for (Long logId: losedJobIds) {
|
||||
|
||||
XxlJobLog jobLog = new XxlJobLog();
|
||||
jobLog.setId(logId);
|
||||
|
||||
jobLog.setHandleTime(new Date());
|
||||
jobLog.setHandleCode(ReturnT.FAIL_CODE);
|
||||
jobLog.setHandleMsg( I18nUtil.getString("joblog_lost_fail") );
|
||||
|
||||
XxlJobCompleter.updateHandleInfoAndFinish(jobLog);
|
||||
}
|
||||
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (!toStop) {
|
||||
logger.error(">>>>>>>>>>> xxl-job, job fail monitor thread error:{}", e);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
TimeUnit.SECONDS.sleep(60);
|
||||
} catch (Exception e) {
|
||||
if (!toStop) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
logger.info(">>>>>>>>>>> xxl-job, JobLosedMonitorHelper stop");
|
||||
|
||||
}
|
||||
});
|
||||
monitorThread.setDaemon(true);
|
||||
monitorThread.setName("xxl-job, admin JobLosedMonitorHelper");
|
||||
monitorThread.start();
|
||||
}
|
||||
|
||||
public void toStop(){
|
||||
toStop = true;
|
||||
|
||||
// stop registryOrRemoveThreadPool
|
||||
callbackThreadPool.shutdownNow();
|
||||
|
||||
// stop monitorThread (interrupt and wait)
|
||||
monitorThread.interrupt();
|
||||
try {
|
||||
monitorThread.join();
|
||||
} catch (InterruptedException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---------------------- helper ----------------------
|
||||
|
||||
public ReturnT<String> callback(List<HandleCallbackParam> callbackParamList) {
|
||||
|
||||
callbackThreadPool.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (HandleCallbackParam handleCallbackParam: callbackParamList) {
|
||||
ReturnT<String> callbackResult = callback(handleCallbackParam);
|
||||
logger.debug(">>>>>>>>> JobApiController.callback {}, handleCallbackParam={}, callbackResult={}",
|
||||
(callbackResult.getCode()== ReturnT.SUCCESS_CODE?"success":"fail"), handleCallbackParam, callbackResult);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return ReturnT.SUCCESS;
|
||||
}
|
||||
|
||||
private ReturnT<String> callback(HandleCallbackParam handleCallbackParam) {
|
||||
// valid log item
|
||||
XxlJobLog log = XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().load(handleCallbackParam.getLogId());
|
||||
if (log == null) {
|
||||
return new ReturnT<String>(ReturnT.FAIL_CODE, "log item not found.");
|
||||
}
|
||||
if (log.getHandleCode() > 0) {
|
||||
return new ReturnT<String>(ReturnT.FAIL_CODE, "log repeate callback."); // avoid repeat callback, trigger child job etc
|
||||
}
|
||||
|
||||
// handle msg
|
||||
StringBuffer handleMsg = new StringBuffer();
|
||||
if (log.getHandleMsg()!=null) {
|
||||
handleMsg.append(log.getHandleMsg()).append("<br>");
|
||||
}
|
||||
if (handleCallbackParam.getHandleMsg() != null) {
|
||||
handleMsg.append(handleCallbackParam.getHandleMsg());
|
||||
}
|
||||
|
||||
// success, save log
|
||||
log.setHandleTime(new Date());
|
||||
log.setHandleCode(handleCallbackParam.getHandleCode());
|
||||
log.setHandleMsg(handleMsg.toString());
|
||||
XxlJobCompleter.updateHandleInfoAndFinish(log);
|
||||
|
||||
return ReturnT.SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -1,110 +0,0 @@
|
||||
package com.xxl.job.admin.core.thread;
|
||||
|
||||
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
|
||||
import com.xxl.job.admin.core.model.XxlJobInfo;
|
||||
import com.xxl.job.admin.core.model.XxlJobLog;
|
||||
import com.xxl.job.admin.core.trigger.TriggerTypeEnum;
|
||||
import com.xxl.job.admin.core.util.I18nUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* job monitor instance
|
||||
*
|
||||
* @author xuxueli 2015-9-1 18:05:56
|
||||
*/
|
||||
public class JobFailMonitorHelper {
|
||||
private static Logger logger = LoggerFactory.getLogger(JobFailMonitorHelper.class);
|
||||
|
||||
private static JobFailMonitorHelper instance = new JobFailMonitorHelper();
|
||||
public static JobFailMonitorHelper getInstance(){
|
||||
return instance;
|
||||
}
|
||||
|
||||
// ---------------------- monitor ----------------------
|
||||
|
||||
private Thread monitorThread;
|
||||
private volatile boolean toStop = false;
|
||||
public void start(){
|
||||
monitorThread = new Thread(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
// monitor
|
||||
while (!toStop) {
|
||||
try {
|
||||
|
||||
List<Long> failLogIds = XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().findFailJobLogIds(1000);
|
||||
if (failLogIds!=null && !failLogIds.isEmpty()) {
|
||||
for (long failLogId: failLogIds) {
|
||||
|
||||
// lock log
|
||||
int lockRet = XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().updateAlarmStatus(failLogId, 0, -1);
|
||||
if (lockRet < 1) {
|
||||
continue;
|
||||
}
|
||||
XxlJobLog log = XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().load(failLogId);
|
||||
XxlJobInfo info = XxlJobAdminConfig.getAdminConfig().getXxlJobInfoDao().loadById(log.getJobId());
|
||||
|
||||
// 1、fail retry monitor
|
||||
if (log.getExecutorFailRetryCount() > 0) {
|
||||
JobTriggerPoolHelper.trigger(log.getJobId(), TriggerTypeEnum.RETRY, (log.getExecutorFailRetryCount()-1), log.getExecutorShardingParam(), log.getExecutorParam(), null);
|
||||
String retryMsg = "<br><br><span style=\"color:#F39C12;\" > >>>>>>>>>>>"+ I18nUtil.getString("jobconf_trigger_type_retry") +"<<<<<<<<<<< </span><br>";
|
||||
log.setTriggerMsg(log.getTriggerMsg() + retryMsg);
|
||||
XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().updateTriggerInfo(log);
|
||||
}
|
||||
|
||||
// 2、fail alarm monitor
|
||||
int newAlarmStatus = 0; // 告警状态:0-默认、-1=锁定状态、1-无需告警、2-告警成功、3-告警失败
|
||||
if (info != null) {
|
||||
boolean alarmResult = XxlJobAdminConfig.getAdminConfig().getJobAlarmer().alarm(info, log);
|
||||
newAlarmStatus = alarmResult?2:3;
|
||||
} else {
|
||||
newAlarmStatus = 1;
|
||||
}
|
||||
|
||||
XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().updateAlarmStatus(failLogId, -1, newAlarmStatus);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
if (!toStop) {
|
||||
logger.error(">>>>>>>>>>> xxl-job, job fail monitor thread error:{}", e);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
TimeUnit.SECONDS.sleep(10);
|
||||
} catch (Exception e) {
|
||||
if (!toStop) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
logger.info(">>>>>>>>>>> xxl-job, job fail monitor thread stop");
|
||||
|
||||
}
|
||||
});
|
||||
monitorThread.setDaemon(true);
|
||||
monitorThread.setName("xxl-job, admin JobFailMonitorHelper");
|
||||
monitorThread.start();
|
||||
}
|
||||
|
||||
public void toStop(){
|
||||
toStop = true;
|
||||
// interrupt and wait
|
||||
monitorThread.interrupt();
|
||||
try {
|
||||
monitorThread.join();
|
||||
} catch (InterruptedException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,152 +0,0 @@
|
||||
package com.xxl.job.admin.core.thread;
|
||||
|
||||
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
|
||||
import com.xxl.job.admin.core.model.XxlJobLogReport;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* job log report helper
|
||||
*
|
||||
* @author xuxueli 2019-11-22
|
||||
*/
|
||||
public class JobLogReportHelper {
|
||||
private static Logger logger = LoggerFactory.getLogger(JobLogReportHelper.class);
|
||||
|
||||
private static JobLogReportHelper instance = new JobLogReportHelper();
|
||||
public static JobLogReportHelper getInstance(){
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
private Thread logrThread;
|
||||
private volatile boolean toStop = false;
|
||||
public void start(){
|
||||
logrThread = new Thread(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
// last clean log time
|
||||
long lastCleanLogTime = 0;
|
||||
|
||||
|
||||
while (!toStop) {
|
||||
|
||||
// 1、log-report refresh: refresh log report in 3 days
|
||||
try {
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
|
||||
// today
|
||||
Calendar itemDay = Calendar.getInstance();
|
||||
itemDay.add(Calendar.DAY_OF_MONTH, -i);
|
||||
itemDay.set(Calendar.HOUR_OF_DAY, 0);
|
||||
itemDay.set(Calendar.MINUTE, 0);
|
||||
itemDay.set(Calendar.SECOND, 0);
|
||||
itemDay.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
Date todayFrom = itemDay.getTime();
|
||||
|
||||
itemDay.set(Calendar.HOUR_OF_DAY, 23);
|
||||
itemDay.set(Calendar.MINUTE, 59);
|
||||
itemDay.set(Calendar.SECOND, 59);
|
||||
itemDay.set(Calendar.MILLISECOND, 999);
|
||||
|
||||
Date todayTo = itemDay.getTime();
|
||||
|
||||
// refresh log-report every minute
|
||||
XxlJobLogReport xxlJobLogReport = new XxlJobLogReport();
|
||||
xxlJobLogReport.setTriggerDay(todayFrom);
|
||||
xxlJobLogReport.setRunningCount(0);
|
||||
xxlJobLogReport.setSucCount(0);
|
||||
xxlJobLogReport.setFailCount(0);
|
||||
|
||||
Map<String, Object> triggerCountMap = XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().findLogReport(todayFrom, todayTo);
|
||||
if (triggerCountMap!=null && triggerCountMap.size()>0) {
|
||||
int triggerDayCount = triggerCountMap.containsKey("triggerDayCount")?Integer.valueOf(String.valueOf(triggerCountMap.get("triggerDayCount"))):0;
|
||||
int triggerDayCountRunning = triggerCountMap.containsKey("triggerDayCountRunning")?Integer.valueOf(String.valueOf(triggerCountMap.get("triggerDayCountRunning"))):0;
|
||||
int triggerDayCountSuc = triggerCountMap.containsKey("triggerDayCountSuc")?Integer.valueOf(String.valueOf(triggerCountMap.get("triggerDayCountSuc"))):0;
|
||||
int triggerDayCountFail = triggerDayCount - triggerDayCountRunning - triggerDayCountSuc;
|
||||
|
||||
xxlJobLogReport.setRunningCount(triggerDayCountRunning);
|
||||
xxlJobLogReport.setSucCount(triggerDayCountSuc);
|
||||
xxlJobLogReport.setFailCount(triggerDayCountFail);
|
||||
}
|
||||
|
||||
// do refresh
|
||||
int ret = XxlJobAdminConfig.getAdminConfig().getXxlJobLogReportDao().update(xxlJobLogReport);
|
||||
if (ret < 1) {
|
||||
XxlJobAdminConfig.getAdminConfig().getXxlJobLogReportDao().save(xxlJobLogReport);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
if (!toStop) {
|
||||
logger.error(">>>>>>>>>>> xxl-job, job log report thread error:{}", e);
|
||||
}
|
||||
}
|
||||
|
||||
// 2、log-clean: switch open & once each day
|
||||
if (XxlJobAdminConfig.getAdminConfig().getLogretentiondays()>0
|
||||
&& System.currentTimeMillis() - lastCleanLogTime > 24*60*60*1000) {
|
||||
|
||||
// expire-time
|
||||
Calendar expiredDay = Calendar.getInstance();
|
||||
expiredDay.add(Calendar.DAY_OF_MONTH, -1 * XxlJobAdminConfig.getAdminConfig().getLogretentiondays());
|
||||
expiredDay.set(Calendar.HOUR_OF_DAY, 0);
|
||||
expiredDay.set(Calendar.MINUTE, 0);
|
||||
expiredDay.set(Calendar.SECOND, 0);
|
||||
expiredDay.set(Calendar.MILLISECOND, 0);
|
||||
Date clearBeforeTime = expiredDay.getTime();
|
||||
|
||||
// clean expired log
|
||||
List<Long> logIds = null;
|
||||
do {
|
||||
logIds = XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().findClearLogIds(0, 0, clearBeforeTime, 0, 1000);
|
||||
if (logIds!=null && logIds.size()>0) {
|
||||
XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().clearLog(logIds);
|
||||
}
|
||||
} while (logIds!=null && logIds.size()>0);
|
||||
|
||||
// update clean time
|
||||
lastCleanLogTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
try {
|
||||
TimeUnit.MINUTES.sleep(1);
|
||||
} catch (Exception e) {
|
||||
if (!toStop) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
logger.info(">>>>>>>>>>> xxl-job, job log report thread stop");
|
||||
|
||||
}
|
||||
});
|
||||
logrThread.setDaemon(true);
|
||||
logrThread.setName("xxl-job, admin JobLogReportHelper");
|
||||
logrThread.start();
|
||||
}
|
||||
|
||||
public void toStop(){
|
||||
toStop = true;
|
||||
// interrupt and wait
|
||||
logrThread.interrupt();
|
||||
try {
|
||||
logrThread.join();
|
||||
} catch (InterruptedException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,204 +0,0 @@
|
||||
package com.xxl.job.admin.core.thread;
|
||||
|
||||
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
|
||||
import com.xxl.job.admin.core.model.XxlJobGroup;
|
||||
import com.xxl.job.admin.core.model.XxlJobRegistry;
|
||||
import com.xxl.job.core.biz.model.RegistryParam;
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import com.xxl.job.core.enums.RegistryConfig;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
/**
|
||||
* job registry instance
|
||||
* @author xuxueli 2016-10-02 19:10:24
|
||||
*/
|
||||
public class JobRegistryHelper {
|
||||
private static Logger logger = LoggerFactory.getLogger(JobRegistryHelper.class);
|
||||
|
||||
private static JobRegistryHelper instance = new JobRegistryHelper();
|
||||
public static JobRegistryHelper getInstance(){
|
||||
return instance;
|
||||
}
|
||||
|
||||
private ThreadPoolExecutor registryOrRemoveThreadPool = null;
|
||||
private Thread registryMonitorThread;
|
||||
private volatile boolean toStop = false;
|
||||
|
||||
public void start(){
|
||||
|
||||
// for registry or remove
|
||||
registryOrRemoveThreadPool = new ThreadPoolExecutor(
|
||||
2,
|
||||
10,
|
||||
30L,
|
||||
TimeUnit.SECONDS,
|
||||
new LinkedBlockingQueue<Runnable>(2000),
|
||||
new ThreadFactory() {
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
return new Thread(r, "xxl-job, admin JobRegistryMonitorHelper-registryOrRemoveThreadPool-" + r.hashCode());
|
||||
}
|
||||
},
|
||||
new RejectedExecutionHandler() {
|
||||
@Override
|
||||
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
|
||||
r.run();
|
||||
logger.warn(">>>>>>>>>>> xxl-job, registry or remove too fast, match threadpool rejected handler(run now).");
|
||||
}
|
||||
});
|
||||
|
||||
// for monitor
|
||||
registryMonitorThread = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
while (!toStop) {
|
||||
try {
|
||||
// auto registry group
|
||||
List<XxlJobGroup> groupList = XxlJobAdminConfig.getAdminConfig().getXxlJobGroupDao().findByAddressType(0);
|
||||
if (groupList!=null && !groupList.isEmpty()) {
|
||||
|
||||
// remove dead address (admin/executor)
|
||||
List<Integer> ids = XxlJobAdminConfig.getAdminConfig().getXxlJobRegistryDao().findDead(RegistryConfig.DEAD_TIMEOUT, new Date());
|
||||
if (ids!=null && ids.size()>0) {
|
||||
XxlJobAdminConfig.getAdminConfig().getXxlJobRegistryDao().removeDead(ids);
|
||||
}
|
||||
|
||||
// fresh online address (admin/executor)
|
||||
HashMap<String, List<String>> appAddressMap = new HashMap<String, List<String>>();
|
||||
List<XxlJobRegistry> list = XxlJobAdminConfig.getAdminConfig().getXxlJobRegistryDao().findAll(RegistryConfig.DEAD_TIMEOUT, new Date());
|
||||
if (list != null) {
|
||||
for (XxlJobRegistry item: list) {
|
||||
if (RegistryConfig.RegistType.EXECUTOR.name().equals(item.getRegistryGroup())) {
|
||||
String appname = item.getRegistryKey();
|
||||
List<String> registryList = appAddressMap.get(appname);
|
||||
if (registryList == null) {
|
||||
registryList = new ArrayList<String>();
|
||||
}
|
||||
|
||||
if (!registryList.contains(item.getRegistryValue())) {
|
||||
registryList.add(item.getRegistryValue());
|
||||
}
|
||||
appAddressMap.put(appname, registryList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fresh group address
|
||||
for (XxlJobGroup group: groupList) {
|
||||
List<String> registryList = appAddressMap.get(group.getAppname());
|
||||
String addressListStr = null;
|
||||
if (registryList!=null && !registryList.isEmpty()) {
|
||||
Collections.sort(registryList);
|
||||
StringBuilder addressListSB = new StringBuilder();
|
||||
for (String item:registryList) {
|
||||
addressListSB.append(item).append(",");
|
||||
}
|
||||
addressListStr = addressListSB.toString();
|
||||
addressListStr = addressListStr.substring(0, addressListStr.length()-1);
|
||||
}
|
||||
group.setAddressList(addressListStr);
|
||||
group.setUpdateTime(new Date());
|
||||
|
||||
XxlJobAdminConfig.getAdminConfig().getXxlJobGroupDao().update(group);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (!toStop) {
|
||||
logger.error(">>>>>>>>>>> xxl-job, job registry monitor thread error:{}", e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
TimeUnit.SECONDS.sleep(RegistryConfig.BEAT_TIMEOUT);
|
||||
} catch (InterruptedException e) {
|
||||
if (!toStop) {
|
||||
logger.error(">>>>>>>>>>> xxl-job, job registry monitor thread error:{}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
logger.info(">>>>>>>>>>> xxl-job, job registry monitor thread stop");
|
||||
}
|
||||
});
|
||||
registryMonitorThread.setDaemon(true);
|
||||
registryMonitorThread.setName("xxl-job, admin JobRegistryMonitorHelper-registryMonitorThread");
|
||||
registryMonitorThread.start();
|
||||
}
|
||||
|
||||
public void toStop(){
|
||||
toStop = true;
|
||||
|
||||
// stop registryOrRemoveThreadPool
|
||||
registryOrRemoveThreadPool.shutdownNow();
|
||||
|
||||
// stop monitir (interrupt and wait)
|
||||
registryMonitorThread.interrupt();
|
||||
try {
|
||||
registryMonitorThread.join();
|
||||
} catch (InterruptedException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---------------------- helper ----------------------
|
||||
|
||||
public ReturnT<String> registry(RegistryParam registryParam) {
|
||||
|
||||
// valid
|
||||
if (!StringUtils.hasText(registryParam.getRegistryGroup())
|
||||
|| !StringUtils.hasText(registryParam.getRegistryKey())
|
||||
|| !StringUtils.hasText(registryParam.getRegistryValue())) {
|
||||
return new ReturnT<String>(ReturnT.FAIL_CODE, "Illegal Argument.");
|
||||
}
|
||||
|
||||
// async execute
|
||||
registryOrRemoveThreadPool.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int ret = XxlJobAdminConfig.getAdminConfig().getXxlJobRegistryDao().registryUpdate(registryParam.getRegistryGroup(), registryParam.getRegistryKey(), registryParam.getRegistryValue(), new Date());
|
||||
if (ret < 1) {
|
||||
XxlJobAdminConfig.getAdminConfig().getXxlJobRegistryDao().registrySave(registryParam.getRegistryGroup(), registryParam.getRegistryKey(), registryParam.getRegistryValue(), new Date());
|
||||
|
||||
// fresh
|
||||
freshGroupRegistryInfo(registryParam);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return ReturnT.SUCCESS;
|
||||
}
|
||||
|
||||
public ReturnT<String> registryRemove(RegistryParam registryParam) {
|
||||
|
||||
// valid
|
||||
if (!StringUtils.hasText(registryParam.getRegistryGroup())
|
||||
|| !StringUtils.hasText(registryParam.getRegistryKey())
|
||||
|| !StringUtils.hasText(registryParam.getRegistryValue())) {
|
||||
return new ReturnT<String>(ReturnT.FAIL_CODE, "Illegal Argument.");
|
||||
}
|
||||
|
||||
// async execute
|
||||
registryOrRemoveThreadPool.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int ret = XxlJobAdminConfig.getAdminConfig().getXxlJobRegistryDao().registryDelete(registryParam.getRegistryGroup(), registryParam.getRegistryKey(), registryParam.getRegistryValue());
|
||||
if (ret > 0) {
|
||||
// fresh
|
||||
freshGroupRegistryInfo(registryParam);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return ReturnT.SUCCESS;
|
||||
}
|
||||
|
||||
private void freshGroupRegistryInfo(RegistryParam registryParam){
|
||||
// Under consideration, prevent affecting core tables
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,369 +0,0 @@
|
||||
package com.xxl.job.admin.core.thread;
|
||||
|
||||
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
|
||||
import com.xxl.job.admin.core.cron.CronExpression;
|
||||
import com.xxl.job.admin.core.model.XxlJobInfo;
|
||||
import com.xxl.job.admin.core.scheduler.MisfireStrategyEnum;
|
||||
import com.xxl.job.admin.core.scheduler.ScheduleTypeEnum;
|
||||
import com.xxl.job.admin.core.trigger.TriggerTypeEnum;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author xuxueli 2019-05-21
|
||||
*/
|
||||
public class JobScheduleHelper {
|
||||
private static Logger logger = LoggerFactory.getLogger(JobScheduleHelper.class);
|
||||
|
||||
private static JobScheduleHelper instance = new JobScheduleHelper();
|
||||
public static JobScheduleHelper getInstance(){
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static final long PRE_READ_MS = 5000; // pre read
|
||||
|
||||
private Thread scheduleThread;
|
||||
private Thread ringThread;
|
||||
private volatile boolean scheduleThreadToStop = false;
|
||||
private volatile boolean ringThreadToStop = false;
|
||||
private volatile static Map<Integer, List<Integer>> ringData = new ConcurrentHashMap<>();
|
||||
|
||||
public void start(){
|
||||
|
||||
// schedule thread
|
||||
scheduleThread = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
try {
|
||||
TimeUnit.MILLISECONDS.sleep(5000 - System.currentTimeMillis()%1000 );
|
||||
} catch (InterruptedException e) {
|
||||
if (!scheduleThreadToStop) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
logger.info(">>>>>>>>> init xxl-job admin scheduler success.");
|
||||
|
||||
// pre-read count: treadpool-size * trigger-qps (each trigger cost 50ms, qps = 1000/50 = 20)
|
||||
int preReadCount = (XxlJobAdminConfig.getAdminConfig().getTriggerPoolFastMax() + XxlJobAdminConfig.getAdminConfig().getTriggerPoolSlowMax()) * 20;
|
||||
|
||||
while (!scheduleThreadToStop) {
|
||||
|
||||
// Scan Job
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
Connection conn = null;
|
||||
Boolean connAutoCommit = null;
|
||||
PreparedStatement preparedStatement = null;
|
||||
|
||||
boolean preReadSuc = true;
|
||||
try {
|
||||
|
||||
conn = XxlJobAdminConfig.getAdminConfig().getDataSource().getConnection();
|
||||
connAutoCommit = conn.getAutoCommit();
|
||||
conn.setAutoCommit(false);
|
||||
|
||||
preparedStatement = conn.prepareStatement( "select * from xxl_job_lock where lock_name = 'schedule_lock' for update" );
|
||||
preparedStatement.execute();
|
||||
|
||||
// tx start
|
||||
|
||||
// 1、pre read
|
||||
long nowTime = System.currentTimeMillis();
|
||||
List<XxlJobInfo> scheduleList = XxlJobAdminConfig.getAdminConfig().getXxlJobInfoDao().scheduleJobQuery(nowTime + PRE_READ_MS, preReadCount);
|
||||
if (scheduleList!=null && scheduleList.size()>0) {
|
||||
// 2、push time-ring
|
||||
for (XxlJobInfo jobInfo: scheduleList) {
|
||||
|
||||
// time-ring jump
|
||||
if (nowTime > jobInfo.getTriggerNextTime() + PRE_READ_MS) {
|
||||
// 2.1、trigger-expire > 5s:pass && make next-trigger-time
|
||||
logger.warn(">>>>>>>>>>> xxl-job, schedule misfire, jobId = " + jobInfo.getId());
|
||||
|
||||
// 1、misfire match
|
||||
MisfireStrategyEnum misfireStrategyEnum = MisfireStrategyEnum.match(jobInfo.getMisfireStrategy(), MisfireStrategyEnum.DO_NOTHING);
|
||||
if (MisfireStrategyEnum.FIRE_ONCE_NOW == misfireStrategyEnum) {
|
||||
// FIRE_ONCE_NOW 》 trigger
|
||||
JobTriggerPoolHelper.trigger(jobInfo.getId(), TriggerTypeEnum.MISFIRE, -1, null, null, null);
|
||||
logger.debug(">>>>>>>>>>> xxl-job, schedule push trigger : jobId = " + jobInfo.getId() );
|
||||
}
|
||||
|
||||
// 2、fresh next
|
||||
refreshNextValidTime(jobInfo, new Date());
|
||||
|
||||
} else if (nowTime > jobInfo.getTriggerNextTime()) {
|
||||
// 2.2、trigger-expire < 5s:direct-trigger && make next-trigger-time
|
||||
|
||||
// 1、trigger
|
||||
JobTriggerPoolHelper.trigger(jobInfo.getId(), TriggerTypeEnum.CRON, -1, null, null, null);
|
||||
logger.debug(">>>>>>>>>>> xxl-job, schedule push trigger : jobId = " + jobInfo.getId() );
|
||||
|
||||
// 2、fresh next
|
||||
refreshNextValidTime(jobInfo, new Date());
|
||||
|
||||
// next-trigger-time in 5s, pre-read again
|
||||
if (jobInfo.getTriggerStatus()==1 && nowTime + PRE_READ_MS > jobInfo.getTriggerNextTime()) {
|
||||
|
||||
// 1、make ring second
|
||||
int ringSecond = (int)((jobInfo.getTriggerNextTime()/1000)%60);
|
||||
|
||||
// 2、push time ring
|
||||
pushTimeRing(ringSecond, jobInfo.getId());
|
||||
|
||||
// 3、fresh next
|
||||
refreshNextValidTime(jobInfo, new Date(jobInfo.getTriggerNextTime()));
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
// 2.3、trigger-pre-read:time-ring trigger && make next-trigger-time
|
||||
|
||||
// 1、make ring second
|
||||
int ringSecond = (int)((jobInfo.getTriggerNextTime()/1000)%60);
|
||||
|
||||
// 2、push time ring
|
||||
pushTimeRing(ringSecond, jobInfo.getId());
|
||||
|
||||
// 3、fresh next
|
||||
refreshNextValidTime(jobInfo, new Date(jobInfo.getTriggerNextTime()));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 3、update trigger info
|
||||
for (XxlJobInfo jobInfo: scheduleList) {
|
||||
XxlJobAdminConfig.getAdminConfig().getXxlJobInfoDao().scheduleUpdate(jobInfo);
|
||||
}
|
||||
|
||||
} else {
|
||||
preReadSuc = false;
|
||||
}
|
||||
|
||||
// tx stop
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
if (!scheduleThreadToStop) {
|
||||
logger.error(">>>>>>>>>>> xxl-job, JobScheduleHelper#scheduleThread error:{}", e);
|
||||
}
|
||||
} finally {
|
||||
|
||||
// commit
|
||||
if (conn != null) {
|
||||
try {
|
||||
conn.commit();
|
||||
} catch (SQLException e) {
|
||||
if (!scheduleThreadToStop) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
conn.setAutoCommit(connAutoCommit);
|
||||
} catch (SQLException e) {
|
||||
if (!scheduleThreadToStop) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
conn.close();
|
||||
} catch (SQLException e) {
|
||||
if (!scheduleThreadToStop) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// close PreparedStatement
|
||||
if (null != preparedStatement) {
|
||||
try {
|
||||
preparedStatement.close();
|
||||
} catch (SQLException e) {
|
||||
if (!scheduleThreadToStop) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
long cost = System.currentTimeMillis()-start;
|
||||
|
||||
|
||||
// Wait seconds, align second
|
||||
if (cost < 1000) { // scan-overtime, not wait
|
||||
try {
|
||||
// pre-read period: success > scan each second; fail > skip this period;
|
||||
TimeUnit.MILLISECONDS.sleep((preReadSuc?1000:PRE_READ_MS) - System.currentTimeMillis()%1000);
|
||||
} catch (InterruptedException e) {
|
||||
if (!scheduleThreadToStop) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
logger.info(">>>>>>>>>>> xxl-job, JobScheduleHelper#scheduleThread stop");
|
||||
}
|
||||
});
|
||||
scheduleThread.setDaemon(true);
|
||||
scheduleThread.setName("xxl-job, admin JobScheduleHelper#scheduleThread");
|
||||
scheduleThread.start();
|
||||
|
||||
|
||||
// ring thread
|
||||
ringThread = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
while (!ringThreadToStop) {
|
||||
|
||||
// align second
|
||||
try {
|
||||
TimeUnit.MILLISECONDS.sleep(1000 - System.currentTimeMillis() % 1000);
|
||||
} catch (InterruptedException e) {
|
||||
if (!ringThreadToStop) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// second data
|
||||
List<Integer> ringItemData = new ArrayList<>();
|
||||
int nowSecond = Calendar.getInstance().get(Calendar.SECOND); // 避免处理耗时太长,跨过刻度,向前校验一个刻度;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
List<Integer> tmpData = ringData.remove( (nowSecond+60-i)%60 );
|
||||
if (tmpData != null) {
|
||||
ringItemData.addAll(tmpData);
|
||||
}
|
||||
}
|
||||
|
||||
// ring trigger
|
||||
logger.debug(">>>>>>>>>>> xxl-job, time-ring beat : " + nowSecond + " = " + Arrays.asList(ringItemData) );
|
||||
if (ringItemData.size() > 0) {
|
||||
// do trigger
|
||||
for (int jobId: ringItemData) {
|
||||
// do trigger
|
||||
JobTriggerPoolHelper.trigger(jobId, TriggerTypeEnum.CRON, -1, null, null, null);
|
||||
}
|
||||
// clear
|
||||
ringItemData.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (!ringThreadToStop) {
|
||||
logger.error(">>>>>>>>>>> xxl-job, JobScheduleHelper#ringThread error:{}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
logger.info(">>>>>>>>>>> xxl-job, JobScheduleHelper#ringThread stop");
|
||||
}
|
||||
});
|
||||
ringThread.setDaemon(true);
|
||||
ringThread.setName("xxl-job, admin JobScheduleHelper#ringThread");
|
||||
ringThread.start();
|
||||
}
|
||||
|
||||
private void refreshNextValidTime(XxlJobInfo jobInfo, Date fromTime) throws Exception {
|
||||
Date nextValidTime = generateNextValidTime(jobInfo, fromTime);
|
||||
if (nextValidTime != null) {
|
||||
jobInfo.setTriggerLastTime(jobInfo.getTriggerNextTime());
|
||||
jobInfo.setTriggerNextTime(nextValidTime.getTime());
|
||||
} else {
|
||||
jobInfo.setTriggerStatus(0);
|
||||
jobInfo.setTriggerLastTime(0);
|
||||
jobInfo.setTriggerNextTime(0);
|
||||
logger.warn(">>>>>>>>>>> xxl-job, refreshNextValidTime fail for job: jobId={}, scheduleType={}, scheduleConf={}",
|
||||
jobInfo.getId(), jobInfo.getScheduleType(), jobInfo.getScheduleConf());
|
||||
}
|
||||
}
|
||||
|
||||
private void pushTimeRing(int ringSecond, int jobId){
|
||||
// push async ring
|
||||
List<Integer> ringItemData = ringData.get(ringSecond);
|
||||
if (ringItemData == null) {
|
||||
ringItemData = new ArrayList<Integer>();
|
||||
ringData.put(ringSecond, ringItemData);
|
||||
}
|
||||
ringItemData.add(jobId);
|
||||
|
||||
logger.debug(">>>>>>>>>>> xxl-job, schedule push time-ring : " + ringSecond + " = " + Arrays.asList(ringItemData) );
|
||||
}
|
||||
|
||||
public void toStop(){
|
||||
|
||||
// 1、stop schedule
|
||||
scheduleThreadToStop = true;
|
||||
try {
|
||||
TimeUnit.SECONDS.sleep(1); // wait
|
||||
} catch (InterruptedException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
if (scheduleThread.getState() != Thread.State.TERMINATED){
|
||||
// interrupt and wait
|
||||
scheduleThread.interrupt();
|
||||
try {
|
||||
scheduleThread.join();
|
||||
} catch (InterruptedException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
// if has ring data
|
||||
boolean hasRingData = false;
|
||||
if (!ringData.isEmpty()) {
|
||||
for (int second : ringData.keySet()) {
|
||||
List<Integer> tmpData = ringData.get(second);
|
||||
if (tmpData!=null && tmpData.size()>0) {
|
||||
hasRingData = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hasRingData) {
|
||||
try {
|
||||
TimeUnit.SECONDS.sleep(8);
|
||||
} catch (InterruptedException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
// stop ring (wait job-in-memory stop)
|
||||
ringThreadToStop = true;
|
||||
try {
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
} catch (InterruptedException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
if (ringThread.getState() != Thread.State.TERMINATED){
|
||||
// interrupt and wait
|
||||
ringThread.interrupt();
|
||||
try {
|
||||
ringThread.join();
|
||||
} catch (InterruptedException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
logger.info(">>>>>>>>>>> xxl-job, JobScheduleHelper stop");
|
||||
}
|
||||
|
||||
|
||||
// ---------------------- tools ----------------------
|
||||
public static Date generateNextValidTime(XxlJobInfo jobInfo, Date fromTime) throws Exception {
|
||||
ScheduleTypeEnum scheduleTypeEnum = ScheduleTypeEnum.match(jobInfo.getScheduleType(), null);
|
||||
if (ScheduleTypeEnum.CRON == scheduleTypeEnum) {
|
||||
Date nextValidTime = new CronExpression(jobInfo.getScheduleConf()).getNextValidTimeAfter(fromTime);
|
||||
return nextValidTime;
|
||||
} else if (ScheduleTypeEnum.FIX_RATE == scheduleTypeEnum /*|| ScheduleTypeEnum.FIX_DELAY == scheduleTypeEnum*/) {
|
||||
return new Date(fromTime.getTime() + Integer.valueOf(jobInfo.getScheduleConf())*1000 );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -1,150 +0,0 @@
|
||||
package com.xxl.job.admin.core.thread;
|
||||
|
||||
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
|
||||
import com.xxl.job.admin.core.trigger.TriggerTypeEnum;
|
||||
import com.xxl.job.admin.core.trigger.XxlJobTrigger;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* job trigger thread pool helper
|
||||
*
|
||||
* @author xuxueli 2018-07-03 21:08:07
|
||||
*/
|
||||
public class JobTriggerPoolHelper {
|
||||
private static Logger logger = LoggerFactory.getLogger(JobTriggerPoolHelper.class);
|
||||
|
||||
|
||||
// ---------------------- trigger pool ----------------------
|
||||
|
||||
// fast/slow thread pool
|
||||
private ThreadPoolExecutor fastTriggerPool = null;
|
||||
private ThreadPoolExecutor slowTriggerPool = null;
|
||||
|
||||
public void start(){
|
||||
fastTriggerPool = new ThreadPoolExecutor(
|
||||
10,
|
||||
XxlJobAdminConfig.getAdminConfig().getTriggerPoolFastMax(),
|
||||
60L,
|
||||
TimeUnit.SECONDS,
|
||||
new LinkedBlockingQueue<Runnable>(1000),
|
||||
new ThreadFactory() {
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
return new Thread(r, "xxl-job, admin JobTriggerPoolHelper-fastTriggerPool-" + r.hashCode());
|
||||
}
|
||||
});
|
||||
|
||||
slowTriggerPool = new ThreadPoolExecutor(
|
||||
10,
|
||||
XxlJobAdminConfig.getAdminConfig().getTriggerPoolSlowMax(),
|
||||
60L,
|
||||
TimeUnit.SECONDS,
|
||||
new LinkedBlockingQueue<Runnable>(2000),
|
||||
new ThreadFactory() {
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
return new Thread(r, "xxl-job, admin JobTriggerPoolHelper-slowTriggerPool-" + r.hashCode());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void stop() {
|
||||
//triggerPool.shutdown();
|
||||
fastTriggerPool.shutdownNow();
|
||||
slowTriggerPool.shutdownNow();
|
||||
logger.info(">>>>>>>>> xxl-job trigger thread pool shutdown success.");
|
||||
}
|
||||
|
||||
|
||||
// job timeout count
|
||||
private volatile long minTim = System.currentTimeMillis()/60000; // ms > min
|
||||
private volatile ConcurrentMap<Integer, AtomicInteger> jobTimeoutCountMap = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
/**
|
||||
* add trigger
|
||||
*/
|
||||
public void addTrigger(final int jobId,
|
||||
final TriggerTypeEnum triggerType,
|
||||
final int failRetryCount,
|
||||
final String executorShardingParam,
|
||||
final String executorParam,
|
||||
final String addressList) {
|
||||
|
||||
// choose thread pool
|
||||
ThreadPoolExecutor triggerPool_ = fastTriggerPool;
|
||||
AtomicInteger jobTimeoutCount = jobTimeoutCountMap.get(jobId);
|
||||
if (jobTimeoutCount!=null && jobTimeoutCount.get() > 10) { // job-timeout 10 times in 1 min
|
||||
triggerPool_ = slowTriggerPool;
|
||||
}
|
||||
|
||||
// trigger
|
||||
triggerPool_.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
try {
|
||||
// do trigger
|
||||
XxlJobTrigger.trigger(jobId, triggerType, failRetryCount, executorShardingParam, executorParam, addressList);
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
} finally {
|
||||
|
||||
// check timeout-count-map
|
||||
long minTim_now = System.currentTimeMillis()/60000;
|
||||
if (minTim != minTim_now) {
|
||||
minTim = minTim_now;
|
||||
jobTimeoutCountMap.clear();
|
||||
}
|
||||
|
||||
// incr timeout-count-map
|
||||
long cost = System.currentTimeMillis()-start;
|
||||
if (cost > 500) { // ob-timeout threshold 500ms
|
||||
AtomicInteger timeoutCount = jobTimeoutCountMap.putIfAbsent(jobId, new AtomicInteger(1));
|
||||
if (timeoutCount != null) {
|
||||
timeoutCount.incrementAndGet();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ---------------------- helper ----------------------
|
||||
|
||||
private static JobTriggerPoolHelper helper = new JobTriggerPoolHelper();
|
||||
|
||||
public static void toStart() {
|
||||
helper.start();
|
||||
}
|
||||
public static void toStop() {
|
||||
helper.stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param jobId
|
||||
* @param triggerType
|
||||
* @param failRetryCount
|
||||
* >=0: use this param
|
||||
* <0: use param from job info config
|
||||
* @param executorShardingParam
|
||||
* @param executorParam
|
||||
* null: use job param
|
||||
* not null: cover job param
|
||||
*/
|
||||
public static void trigger(int jobId, TriggerTypeEnum triggerType, int failRetryCount, String executorShardingParam, String executorParam, String addressList) {
|
||||
helper.addTrigger(jobId, triggerType, failRetryCount, executorShardingParam, executorParam, addressList);
|
||||
}
|
||||
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
package com.xxl.job.admin.core.trigger;
|
||||
|
||||
import com.xxl.job.admin.core.util.I18nUtil;
|
||||
|
||||
/**
|
||||
* trigger type enum
|
||||
*
|
||||
* @author xuxueli 2018-09-16 04:56:41
|
||||
*/
|
||||
public enum TriggerTypeEnum {
|
||||
|
||||
MANUAL(I18nUtil.getString("jobconf_trigger_type_manual")),
|
||||
CRON(I18nUtil.getString("jobconf_trigger_type_cron")),
|
||||
RETRY(I18nUtil.getString("jobconf_trigger_type_retry")),
|
||||
PARENT(I18nUtil.getString("jobconf_trigger_type_parent")),
|
||||
API(I18nUtil.getString("jobconf_trigger_type_api")),
|
||||
MISFIRE(I18nUtil.getString("jobconf_trigger_type_misfire"));
|
||||
|
||||
private TriggerTypeEnum(String title){
|
||||
this.title = title;
|
||||
}
|
||||
private String title;
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
}
|
@ -1,226 +0,0 @@
|
||||
package com.xxl.job.admin.core.trigger;
|
||||
|
||||
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
|
||||
import com.xxl.job.admin.core.model.XxlJobGroup;
|
||||
import com.xxl.job.admin.core.model.XxlJobInfo;
|
||||
import com.xxl.job.admin.core.model.XxlJobLog;
|
||||
import com.xxl.job.admin.core.route.ExecutorRouteStrategyEnum;
|
||||
import com.xxl.job.admin.core.scheduler.XxlJobScheduler;
|
||||
import com.xxl.job.admin.core.util.I18nUtil;
|
||||
import com.xxl.job.core.biz.ExecutorBiz;
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import com.xxl.job.core.biz.model.TriggerParam;
|
||||
import com.xxl.job.core.enums.ExecutorBlockStrategyEnum;
|
||||
import com.xxl.job.core.util.IpUtil;
|
||||
import com.xxl.job.core.util.ThrowableUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* xxl-job trigger
|
||||
* Created by xuxueli on 17/7/13.
|
||||
*/
|
||||
public class XxlJobTrigger {
|
||||
private static Logger logger = LoggerFactory.getLogger(XxlJobTrigger.class);
|
||||
|
||||
/**
|
||||
* trigger job
|
||||
*
|
||||
* @param jobId
|
||||
* @param triggerType
|
||||
* @param failRetryCount
|
||||
* >=0: use this param
|
||||
* <0: use param from job info config
|
||||
* @param executorShardingParam
|
||||
* @param executorParam
|
||||
* null: use job param
|
||||
* not null: cover job param
|
||||
* @param addressList
|
||||
* null: use executor addressList
|
||||
* not null: cover
|
||||
*/
|
||||
public static void trigger(int jobId,
|
||||
TriggerTypeEnum triggerType,
|
||||
int failRetryCount,
|
||||
String executorShardingParam,
|
||||
String executorParam,
|
||||
String addressList) {
|
||||
|
||||
// load data
|
||||
XxlJobInfo jobInfo = XxlJobAdminConfig.getAdminConfig().getXxlJobInfoDao().loadById(jobId);
|
||||
if (jobInfo == null) {
|
||||
logger.warn(">>>>>>>>>>>> trigger fail, jobId invalid,jobId={}", jobId);
|
||||
return;
|
||||
}
|
||||
if (executorParam != null) {
|
||||
jobInfo.setExecutorParam(executorParam);
|
||||
}
|
||||
int finalFailRetryCount = failRetryCount>=0?failRetryCount:jobInfo.getExecutorFailRetryCount();
|
||||
XxlJobGroup group = XxlJobAdminConfig.getAdminConfig().getXxlJobGroupDao().load(jobInfo.getJobGroup());
|
||||
|
||||
// cover addressList
|
||||
if (addressList!=null && addressList.trim().length()>0) {
|
||||
group.setAddressType(1);
|
||||
group.setAddressList(addressList.trim());
|
||||
}
|
||||
|
||||
// sharding param
|
||||
int[] shardingParam = null;
|
||||
if (executorShardingParam!=null){
|
||||
String[] shardingArr = executorShardingParam.split("/");
|
||||
if (shardingArr.length==2 && isNumeric(shardingArr[0]) && isNumeric(shardingArr[1])) {
|
||||
shardingParam = new int[2];
|
||||
shardingParam[0] = Integer.valueOf(shardingArr[0]);
|
||||
shardingParam[1] = Integer.valueOf(shardingArr[1]);
|
||||
}
|
||||
}
|
||||
if (ExecutorRouteStrategyEnum.SHARDING_BROADCAST==ExecutorRouteStrategyEnum.match(jobInfo.getExecutorRouteStrategy(), null)
|
||||
&& group.getRegistryList()!=null && !group.getRegistryList().isEmpty()
|
||||
&& shardingParam==null) {
|
||||
for (int i = 0; i < group.getRegistryList().size(); i++) {
|
||||
processTrigger(group, jobInfo, finalFailRetryCount, triggerType, i, group.getRegistryList().size());
|
||||
}
|
||||
} else {
|
||||
if (shardingParam == null) {
|
||||
shardingParam = new int[]{0, 1};
|
||||
}
|
||||
processTrigger(group, jobInfo, finalFailRetryCount, triggerType, shardingParam[0], shardingParam[1]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static boolean isNumeric(String str){
|
||||
try {
|
||||
int result = Integer.valueOf(str);
|
||||
return true;
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param group job group, registry list may be empty
|
||||
* @param jobInfo
|
||||
* @param finalFailRetryCount
|
||||
* @param triggerType
|
||||
* @param index sharding index
|
||||
* @param total sharding index
|
||||
*/
|
||||
private static void processTrigger(XxlJobGroup group, XxlJobInfo jobInfo, int finalFailRetryCount, TriggerTypeEnum triggerType, int index, int total){
|
||||
|
||||
// param
|
||||
ExecutorBlockStrategyEnum blockStrategy = ExecutorBlockStrategyEnum.match(jobInfo.getExecutorBlockStrategy(), ExecutorBlockStrategyEnum.SERIAL_EXECUTION); // block strategy
|
||||
ExecutorRouteStrategyEnum executorRouteStrategyEnum = ExecutorRouteStrategyEnum.match(jobInfo.getExecutorRouteStrategy(), null); // route strategy
|
||||
String shardingParam = (ExecutorRouteStrategyEnum.SHARDING_BROADCAST==executorRouteStrategyEnum)?String.valueOf(index).concat("/").concat(String.valueOf(total)):null;
|
||||
|
||||
// 1、save log-id
|
||||
XxlJobLog jobLog = new XxlJobLog();
|
||||
jobLog.setJobGroup(jobInfo.getJobGroup());
|
||||
jobLog.setJobId(jobInfo.getId());
|
||||
jobLog.setTriggerTime(new Date());
|
||||
XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().save(jobLog);
|
||||
logger.debug(">>>>>>>>>>> xxl-job trigger start, jobId:{}", jobLog.getId());
|
||||
|
||||
// 2、init trigger-param
|
||||
TriggerParam triggerParam = new TriggerParam();
|
||||
triggerParam.setJobId(jobInfo.getId());
|
||||
triggerParam.setExecutorHandler(jobInfo.getExecutorHandler());
|
||||
triggerParam.setExecutorParams(jobInfo.getExecutorParam());
|
||||
triggerParam.setExecutorBlockStrategy(jobInfo.getExecutorBlockStrategy());
|
||||
triggerParam.setExecutorTimeout(jobInfo.getExecutorTimeout());
|
||||
triggerParam.setLogId(jobLog.getId());
|
||||
triggerParam.setLogDateTime(jobLog.getTriggerTime().getTime());
|
||||
triggerParam.setGlueType(jobInfo.getGlueType());
|
||||
triggerParam.setGlueSource(jobInfo.getGlueSource());
|
||||
triggerParam.setGlueUpdatetime(jobInfo.getGlueUpdatetime().getTime());
|
||||
triggerParam.setBroadcastIndex(index);
|
||||
triggerParam.setBroadcastTotal(total);
|
||||
|
||||
// 3、init address
|
||||
String address = null;
|
||||
ReturnT<String> routeAddressResult = null;
|
||||
if (group.getRegistryList()!=null && !group.getRegistryList().isEmpty()) {
|
||||
if (ExecutorRouteStrategyEnum.SHARDING_BROADCAST == executorRouteStrategyEnum) {
|
||||
if (index < group.getRegistryList().size()) {
|
||||
address = group.getRegistryList().get(index);
|
||||
} else {
|
||||
address = group.getRegistryList().get(0);
|
||||
}
|
||||
} else {
|
||||
routeAddressResult = executorRouteStrategyEnum.getRouter().route(triggerParam, group.getRegistryList());
|
||||
if (routeAddressResult.getCode() == ReturnT.SUCCESS_CODE) {
|
||||
address = routeAddressResult.getContent();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
routeAddressResult = new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("jobconf_trigger_address_empty"));
|
||||
}
|
||||
|
||||
// 4、trigger remote executor
|
||||
ReturnT<String> triggerResult = null;
|
||||
if (address != null) {
|
||||
triggerResult = runExecutor(triggerParam, address);
|
||||
} else {
|
||||
triggerResult = new ReturnT<String>(ReturnT.FAIL_CODE, null);
|
||||
}
|
||||
|
||||
// 5、collection trigger info
|
||||
StringBuffer triggerMsgSb = new StringBuffer();
|
||||
triggerMsgSb.append(I18nUtil.getString("jobconf_trigger_type")).append(":").append(triggerType.getTitle());
|
||||
triggerMsgSb.append("<br>").append(I18nUtil.getString("jobconf_trigger_admin_adress")).append(":").append(IpUtil.getIp());
|
||||
triggerMsgSb.append("<br>").append(I18nUtil.getString("jobconf_trigger_exe_regtype")).append(":")
|
||||
.append( (group.getAddressType() == 0)?I18nUtil.getString("jobgroup_field_addressType_0"):I18nUtil.getString("jobgroup_field_addressType_1") );
|
||||
triggerMsgSb.append("<br>").append(I18nUtil.getString("jobconf_trigger_exe_regaddress")).append(":").append(group.getRegistryList());
|
||||
triggerMsgSb.append("<br>").append(I18nUtil.getString("jobinfo_field_executorRouteStrategy")).append(":").append(executorRouteStrategyEnum.getTitle());
|
||||
if (shardingParam != null) {
|
||||
triggerMsgSb.append("("+shardingParam+")");
|
||||
}
|
||||
triggerMsgSb.append("<br>").append(I18nUtil.getString("jobinfo_field_executorBlockStrategy")).append(":").append(blockStrategy.getTitle());
|
||||
triggerMsgSb.append("<br>").append(I18nUtil.getString("jobinfo_field_timeout")).append(":").append(jobInfo.getExecutorTimeout());
|
||||
triggerMsgSb.append("<br>").append(I18nUtil.getString("jobinfo_field_executorFailRetryCount")).append(":").append(finalFailRetryCount);
|
||||
|
||||
triggerMsgSb.append("<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>"+ I18nUtil.getString("jobconf_trigger_run") +"<<<<<<<<<<< </span><br>")
|
||||
.append((routeAddressResult!=null&&routeAddressResult.getMsg()!=null)?routeAddressResult.getMsg()+"<br><br>":"").append(triggerResult.getMsg()!=null?triggerResult.getMsg():"");
|
||||
|
||||
// 6、save log trigger-info
|
||||
jobLog.setExecutorAddress(address);
|
||||
jobLog.setExecutorHandler(jobInfo.getExecutorHandler());
|
||||
jobLog.setExecutorParam(jobInfo.getExecutorParam());
|
||||
jobLog.setExecutorShardingParam(shardingParam);
|
||||
jobLog.setExecutorFailRetryCount(finalFailRetryCount);
|
||||
//jobLog.setTriggerTime();
|
||||
jobLog.setTriggerCode(triggerResult.getCode());
|
||||
jobLog.setTriggerMsg(triggerMsgSb.toString());
|
||||
XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().updateTriggerInfo(jobLog);
|
||||
|
||||
logger.debug(">>>>>>>>>>> xxl-job trigger end, jobId:{}", jobLog.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* run executor
|
||||
* @param triggerParam
|
||||
* @param address
|
||||
* @return
|
||||
*/
|
||||
public static ReturnT<String> runExecutor(TriggerParam triggerParam, String address){
|
||||
ReturnT<String> runResult = null;
|
||||
try {
|
||||
ExecutorBiz executorBiz = XxlJobScheduler.getExecutorBiz(address);
|
||||
runResult = executorBiz.run(triggerParam);
|
||||
} catch (Exception e) {
|
||||
logger.error(">>>>>>>>>>> xxl-job trigger error, please check if the executor[{}] is running.", address, e);
|
||||
runResult = new ReturnT<String>(ReturnT.FAIL_CODE, ThrowableUtil.toString(e));
|
||||
}
|
||||
|
||||
StringBuffer runResultSB = new StringBuffer(I18nUtil.getString("jobconf_trigger_run") + ":");
|
||||
runResultSB.append("<br>address:").append(address);
|
||||
runResultSB.append("<br>code:").append(runResult.getCode());
|
||||
runResultSB.append("<br>msg:").append(runResult.getMsg());
|
||||
|
||||
runResult.setMsg(runResultSB.toString());
|
||||
return runResult;
|
||||
}
|
||||
|
||||
}
|
@ -1,108 +0,0 @@
|
||||
package com.xxl.job.admin.core.util;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* Cookie.Util
|
||||
*
|
||||
* @author xuxueli 2015-12-12 18:01:06
|
||||
*/
|
||||
public class CookieUtil {
|
||||
|
||||
// 默认缓存时间,单位/秒, 2H
|
||||
private static final int COOKIE_MAX_AGE = Integer.MAX_VALUE;
|
||||
// 保存路径,根路径
|
||||
private static final String COOKIE_PATH = "/";
|
||||
|
||||
/**
|
||||
* 保存
|
||||
*
|
||||
* @param response
|
||||
* @param key
|
||||
* @param value
|
||||
* @param ifRemember
|
||||
*/
|
||||
public static void set(HttpServletResponse response, String key, String value, boolean ifRemember) {
|
||||
int age = ifRemember?COOKIE_MAX_AGE:-1;
|
||||
set(response, key, value, null, COOKIE_PATH, age, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存
|
||||
*
|
||||
* @param response
|
||||
* @param key
|
||||
* @param value
|
||||
* @param maxAge
|
||||
*/
|
||||
public static void set(HttpServletResponse response, String key, String value, String domain, String path, int maxAge, boolean isHttpOnly) {
|
||||
Cookie cookie = new Cookie(key, value);
|
||||
if (domain != null) {
|
||||
cookie.setDomain(domain);
|
||||
}
|
||||
cookie.setPath(path);
|
||||
cookie.setMaxAge(maxAge);
|
||||
cookie.setHttpOnly(isHttpOnly);
|
||||
response.addCookie(cookie);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询value
|
||||
*
|
||||
* @param request
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public static String getValue(HttpServletRequest request, String key) {
|
||||
Cookie cookie = get(request, key);
|
||||
if (cookie != null) {
|
||||
return cookie.getValue();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询Cookie
|
||||
*
|
||||
* @param request
|
||||
* @param key
|
||||
*/
|
||||
private static Cookie get(HttpServletRequest request, String key) {
|
||||
Cookie[] arr_cookie = request.getCookies();
|
||||
if (arr_cookie != null && arr_cookie.length > 0) {
|
||||
for (Cookie cookie : arr_cookie) {
|
||||
if (cookie.getName().equals(key)) {
|
||||
return cookie;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除Cookie
|
||||
*
|
||||
* @param request
|
||||
* @param response
|
||||
* @param key
|
||||
*/
|
||||
public static void remove(HttpServletRequest request, HttpServletResponse response, String key) {
|
||||
remove(request, response, key, COOKIE_PATH);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除Cookie(自定义作用范围路径)
|
||||
*
|
||||
* @param request
|
||||
* @param response
|
||||
* @param key
|
||||
*/
|
||||
public static void remove(HttpServletRequest request, HttpServletResponse response, String key, String path) {
|
||||
Cookie cookie = get(request, key);
|
||||
if (cookie != null) {
|
||||
set(response, key, "", null, path, 0, true);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
package com.xxl.job.admin.core.util;
|
||||
|
||||
import freemarker.ext.beans.BeansWrapper;
|
||||
import freemarker.ext.beans.BeansWrapperBuilder;
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.TemplateHashModel;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* ftl util
|
||||
*
|
||||
* @author xuxueli 2018-01-17 20:37:48
|
||||
*/
|
||||
public class FtlUtil {
|
||||
private static Logger logger = LoggerFactory.getLogger(FtlUtil.class);
|
||||
|
||||
private static BeansWrapper wrapper = new BeansWrapperBuilder(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS).build(); //BeansWrapper.getDefaultInstance();
|
||||
|
||||
public static TemplateHashModel generateStaticModel(String packageName) {
|
||||
try {
|
||||
TemplateHashModel staticModels = wrapper.getStaticModels();
|
||||
TemplateHashModel fileStatics = (TemplateHashModel) staticModels.get(packageName);
|
||||
return fileStatics;
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
package com.xxl.job.admin.core.util;
|
||||
|
||||
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.EncodedResource;
|
||||
import org.springframework.core.io.support.PropertiesLoaderUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* i18n util
|
||||
*
|
||||
* @author xuxueli 2018-01-17 20:39:06
|
||||
*/
|
||||
public class I18nUtil {
|
||||
private static Logger logger = LoggerFactory.getLogger(I18nUtil.class);
|
||||
|
||||
private static Properties prop = null;
|
||||
public static Properties loadI18nProp(){
|
||||
if (prop != null) {
|
||||
return prop;
|
||||
}
|
||||
try {
|
||||
// build i18n prop
|
||||
String i18n = XxlJobAdminConfig.getAdminConfig().getI18n();
|
||||
String i18nFile = MessageFormat.format("i18n/message_{0}.properties", i18n);
|
||||
|
||||
// load prop
|
||||
Resource resource = new ClassPathResource(i18nFile);
|
||||
EncodedResource encodedResource = new EncodedResource(resource,"UTF-8");
|
||||
prop = PropertiesLoaderUtils.loadProperties(encodedResource);
|
||||
} catch (IOException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
return prop;
|
||||
}
|
||||
|
||||
/**
|
||||
* get val of i18n key
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public static String getString(String key) {
|
||||
return loadI18nProp().getProperty(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* get mult val of i18n mult key, as json
|
||||
*
|
||||
* @param keys
|
||||
* @return
|
||||
*/
|
||||
public static String getMultString(String... keys) {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
|
||||
Properties prop = loadI18nProp();
|
||||
if (keys!=null && keys.length>0) {
|
||||
for (String key: keys) {
|
||||
map.put(key, prop.getProperty(key));
|
||||
}
|
||||
} else {
|
||||
for (String key: prop.stringPropertyNames()) {
|
||||
map.put(key, prop.getProperty(key));
|
||||
}
|
||||
}
|
||||
|
||||
String json = JacksonUtil.writeValueAsString(map);
|
||||
return json;
|
||||
}
|
||||
|
||||
}
|
@ -1,92 +0,0 @@
|
||||
package com.xxl.job.admin.core.util;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerationException;
|
||||
import com.fasterxml.jackson.core.JsonParseException;
|
||||
import com.fasterxml.jackson.databind.JavaType;
|
||||
import com.fasterxml.jackson.databind.JsonMappingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Jackson util
|
||||
*
|
||||
* 1、obj need private and set/get;
|
||||
* 2、do not support inner class;
|
||||
*
|
||||
* @author xuxueli 2015-9-25 18:02:56
|
||||
*/
|
||||
public class JacksonUtil {
|
||||
private static Logger logger = LoggerFactory.getLogger(JacksonUtil.class);
|
||||
|
||||
private final static ObjectMapper objectMapper = new ObjectMapper();
|
||||
public static ObjectMapper getInstance() {
|
||||
return objectMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* bean、array、List、Map --> json
|
||||
*
|
||||
* @param obj
|
||||
* @return json string
|
||||
* @throws Exception
|
||||
*/
|
||||
public static String writeValueAsString(Object obj) {
|
||||
try {
|
||||
return getInstance().writeValueAsString(obj);
|
||||
} catch (JsonGenerationException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
} catch (JsonMappingException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
} catch (IOException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* string --> bean、Map、List(array)
|
||||
*
|
||||
* @param jsonStr
|
||||
* @param clazz
|
||||
* @return obj
|
||||
* @throws Exception
|
||||
*/
|
||||
public static <T> T readValue(String jsonStr, Class<T> clazz) {
|
||||
try {
|
||||
return getInstance().readValue(jsonStr, clazz);
|
||||
} catch (JsonParseException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
} catch (JsonMappingException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
} catch (IOException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* string --> List<Bean>...
|
||||
*
|
||||
* @param jsonStr
|
||||
* @param parametrized
|
||||
* @param parameterClasses
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public static <T> T readValue(String jsonStr, Class<?> parametrized, Class<?>... parameterClasses) {
|
||||
try {
|
||||
JavaType javaType = getInstance().getTypeFactory().constructParametricType(parametrized, parameterClasses);
|
||||
return getInstance().readValue(jsonStr, javaType);
|
||||
} catch (JsonParseException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
} catch (JsonMappingException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
} catch (IOException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,133 +0,0 @@
|
||||
package com.xxl.job.admin.core.util;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* local cache tool
|
||||
*
|
||||
* @author xuxueli 2018-01-22 21:37:34
|
||||
*/
|
||||
public class LocalCacheUtil {
|
||||
|
||||
private static ConcurrentMap<String, LocalCacheData> cacheRepository = new ConcurrentHashMap<String, LocalCacheData>(); // 类型建议用抽象父类,兼容性更好;
|
||||
private static class LocalCacheData{
|
||||
private String key;
|
||||
private Object val;
|
||||
private long timeoutTime;
|
||||
|
||||
public LocalCacheData() {
|
||||
}
|
||||
|
||||
public LocalCacheData(String key, Object val, long timeoutTime) {
|
||||
this.key = key;
|
||||
this.val = val;
|
||||
this.timeoutTime = timeoutTime;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public void setKey(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public Object getVal() {
|
||||
return val;
|
||||
}
|
||||
|
||||
public void setVal(Object val) {
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
public long getTimeoutTime() {
|
||||
return timeoutTime;
|
||||
}
|
||||
|
||||
public void setTimeoutTime(long timeoutTime) {
|
||||
this.timeoutTime = timeoutTime;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* set cache
|
||||
*
|
||||
* @param key
|
||||
* @param val
|
||||
* @param cacheTime
|
||||
* @return
|
||||
*/
|
||||
public static boolean set(String key, Object val, long cacheTime){
|
||||
|
||||
// clean timeout cache, before set new cache (avoid cache too much)
|
||||
cleanTimeoutCache();
|
||||
|
||||
// set new cache
|
||||
if (key==null || key.trim().length()==0) {
|
||||
return false;
|
||||
}
|
||||
if (val == null) {
|
||||
remove(key);
|
||||
}
|
||||
if (cacheTime <= 0) {
|
||||
remove(key);
|
||||
}
|
||||
long timeoutTime = System.currentTimeMillis() + cacheTime;
|
||||
LocalCacheData localCacheData = new LocalCacheData(key, val, timeoutTime);
|
||||
cacheRepository.put(localCacheData.getKey(), localCacheData);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* remove cache
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public static boolean remove(String key){
|
||||
if (key==null || key.trim().length()==0) {
|
||||
return false;
|
||||
}
|
||||
cacheRepository.remove(key);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* get cache
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public static Object get(String key){
|
||||
if (key==null || key.trim().length()==0) {
|
||||
return null;
|
||||
}
|
||||
LocalCacheData localCacheData = cacheRepository.get(key);
|
||||
if (localCacheData!=null && System.currentTimeMillis()<localCacheData.getTimeoutTime()) {
|
||||
return localCacheData.getVal();
|
||||
} else {
|
||||
remove(key);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* clean timeout cache
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static boolean cleanTimeoutCache(){
|
||||
if (!cacheRepository.keySet().isEmpty()) {
|
||||
for (String key: cacheRepository.keySet()) {
|
||||
LocalCacheData localCacheData = cacheRepository.get(key);
|
||||
if (localCacheData!=null && System.currentTimeMillis()>=localCacheData.getTimeoutTime()) {
|
||||
cacheRepository.remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
package com.xxl.job.admin.dao;
|
||||
|
||||
import com.xxl.job.admin.core.model.XxlJobGroup;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by xuxueli on 16/9/30.
|
||||
*/
|
||||
@Mapper
|
||||
public interface XxlJobGroupDao {
|
||||
|
||||
public List<XxlJobGroup> findAll();
|
||||
|
||||
public List<XxlJobGroup> findByAddressType(@Param("addressType") int addressType);
|
||||
|
||||
public int save(XxlJobGroup xxlJobGroup);
|
||||
|
||||
public int update(XxlJobGroup xxlJobGroup);
|
||||
|
||||
public int remove(@Param("id") int id);
|
||||
|
||||
public XxlJobGroup load(@Param("id") int id);
|
||||
|
||||
public List<XxlJobGroup> pageList(@Param("offset") int offset,
|
||||
@Param("pagesize") int pagesize,
|
||||
@Param("appname") String appname,
|
||||
@Param("title") String title);
|
||||
|
||||
public int pageListCount(@Param("offset") int offset,
|
||||
@Param("pagesize") int pagesize,
|
||||
@Param("appname") String appname,
|
||||
@Param("title") String title);
|
||||
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
package com.xxl.job.admin.dao;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import com.xxl.job.admin.api.info.dto.JobInfoDetailRespDTO;
|
||||
import com.xxl.job.admin.api.info.dto.JobInfoRespDTO;
|
||||
import com.xxl.job.admin.api.info.dto.JobInfoSaveReqDTO;
|
||||
import com.xxl.job.admin.core.model.XxlJobInfo;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* job info
|
||||
* @author xuxueli 2016-1-12 18:03:45
|
||||
*/
|
||||
@Mapper
|
||||
public interface XxlJobInfoDao extends BaseMapperX<XxlJobInfo> {
|
||||
|
||||
public List<XxlJobInfo> pageList(@Param("offset") int offset,
|
||||
@Param("pagesize") int pagesize,
|
||||
@Param("jobGroup") int jobGroup,
|
||||
@Param("triggerStatus") int triggerStatus,
|
||||
@Param("jobDesc") String jobDesc,
|
||||
@Param("executorHandler") String executorHandler,
|
||||
@Param("author") String author);
|
||||
public int pageListCount(@Param("offset") int offset,
|
||||
@Param("pagesize") int pagesize,
|
||||
@Param("jobGroup") int jobGroup,
|
||||
@Param("triggerStatus") int triggerStatus,
|
||||
@Param("jobDesc") String jobDesc,
|
||||
@Param("executorHandler") String executorHandler,
|
||||
@Param("author") String author);
|
||||
|
||||
public int save(XxlJobInfo info);
|
||||
|
||||
public XxlJobInfo loadById(@Param("id") int id);
|
||||
|
||||
public int update(XxlJobInfo xxlJobInfo);
|
||||
|
||||
public int delete(@Param("id") long id);
|
||||
|
||||
public List<XxlJobInfo> getJobsByGroup(@Param("jobGroup") int jobGroup);
|
||||
|
||||
public int findAllCount();
|
||||
|
||||
public List<XxlJobInfo> scheduleJobQuery(@Param("maxNextTime") long maxNextTime, @Param("pagesize") int pagesize );
|
||||
|
||||
public int scheduleUpdate(XxlJobInfo xxlJobInfo);
|
||||
|
||||
|
||||
List<JobInfoRespDTO> apiPage(@Param("pageNo") Integer pageNo, @Param("pageSize") Integer pageSize, @Param("name") String name, @Param("status") Integer status, @Param("handlerName") String handlerName);
|
||||
|
||||
Long apiPageCount(@Param("name") String name, @Param("status") Integer status, @Param("handlerName") String handlerName);
|
||||
|
||||
JobInfoDetailRespDTO apiGet(@Param("id") Integer id);
|
||||
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
package com.xxl.job.admin.dao;
|
||||
|
||||
import com.xxl.job.admin.api.log.dto.JobLogRespDTO;
|
||||
import com.xxl.job.admin.core.model.XxlJobLog;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* job log
|
||||
* @author xuxueli 2016-1-12 18:03:06
|
||||
*/
|
||||
@Mapper
|
||||
public interface XxlJobLogDao {
|
||||
|
||||
// exist jobId not use jobGroup, not exist use jobGroup
|
||||
public List<XxlJobLog> pageList(@Param("offset") int offset,
|
||||
@Param("pagesize") int pagesize,
|
||||
@Param("jobGroup") int jobGroup,
|
||||
@Param("jobId") int jobId,
|
||||
@Param("triggerTimeStart") Date triggerTimeStart,
|
||||
@Param("triggerTimeEnd") Date triggerTimeEnd,
|
||||
@Param("logStatus") int logStatus);
|
||||
public List<JobLogRespDTO> apiPageList(@Param("offset") int offset,
|
||||
@Param("pagesize") int pagesize,
|
||||
@Param("jobGroup") int jobGroup,
|
||||
@Param("jobId") int jobId,
|
||||
@Param("triggerTimeStart") String triggerTimeStart,
|
||||
@Param("triggerTimeEnd") String triggerTimeEnd,
|
||||
@Param("logStatus") Integer logStatus,
|
||||
@Param("handlerName") String handlerName);
|
||||
public int pageListCount(@Param("offset") int offset,
|
||||
@Param("pagesize") int pagesize,
|
||||
@Param("jobGroup") int jobGroup,
|
||||
@Param("jobId") int jobId,
|
||||
@Param("triggerTimeStart") Date triggerTimeStart,
|
||||
@Param("triggerTimeEnd") Date triggerTimeEnd,
|
||||
@Param("logStatus") int logStatus);
|
||||
|
||||
public XxlJobLog load(@Param("id") long id);
|
||||
|
||||
public long save(XxlJobLog xxlJobLog);
|
||||
|
||||
public int updateTriggerInfo(XxlJobLog xxlJobLog);
|
||||
|
||||
public int updateHandleInfo(XxlJobLog xxlJobLog);
|
||||
|
||||
public int delete(@Param("jobId") int jobId);
|
||||
|
||||
public Map<String, Object> findLogReport(@Param("from") Date from,
|
||||
@Param("to") Date to);
|
||||
|
||||
public List<Long> findClearLogIds(@Param("jobGroup") int jobGroup,
|
||||
@Param("jobId") int jobId,
|
||||
@Param("clearBeforeTime") Date clearBeforeTime,
|
||||
@Param("clearBeforeNum") int clearBeforeNum,
|
||||
@Param("pagesize") int pagesize);
|
||||
public int clearLog(@Param("logIds") List<Long> logIds);
|
||||
|
||||
public List<Long> findFailJobLogIds(@Param("pagesize") int pagesize);
|
||||
|
||||
public int updateAlarmStatus(@Param("logId") long logId,
|
||||
@Param("oldAlarmStatus") int oldAlarmStatus,
|
||||
@Param("newAlarmStatus") int newAlarmStatus);
|
||||
|
||||
public List<Long> findLostJobIds(@Param("losedTime") Date losedTime);
|
||||
|
||||
int apiPageListCount(@Param("offset") int offset,
|
||||
@Param("pagesize") int pagesize,
|
||||
@Param("jobGroup") int jobGroup,
|
||||
@Param("jobId") int jobId,
|
||||
@Param("triggerTimeStart") String triggerTimeStart,
|
||||
@Param("triggerTimeEnd") String triggerTimeEnd,
|
||||
@Param("logStatus") Integer logStatus,
|
||||
@Param("handlerName") String handlerName);
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
package com.xxl.job.admin.dao;
|
||||
|
||||
import com.xxl.job.admin.core.model.XxlJobLogGlue;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* job log for glue
|
||||
* @author xuxueli 2016-5-19 18:04:56
|
||||
*/
|
||||
@Mapper
|
||||
public interface XxlJobLogGlueDao {
|
||||
|
||||
public int save(XxlJobLogGlue xxlJobLogGlue);
|
||||
|
||||
public List<XxlJobLogGlue> findByJobId(@Param("jobId") int jobId);
|
||||
|
||||
public int removeOld(@Param("jobId") int jobId, @Param("limit") int limit);
|
||||
|
||||
public int deleteByJobId(@Param("jobId") int jobId);
|
||||
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
package com.xxl.job.admin.dao;
|
||||
|
||||
import com.xxl.job.admin.core.model.XxlJobLogReport;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* job log
|
||||
* @author xuxueli 2019-11-22
|
||||
*/
|
||||
@Mapper
|
||||
public interface XxlJobLogReportDao {
|
||||
|
||||
public int save(XxlJobLogReport xxlJobLogReport);
|
||||
|
||||
public int update(XxlJobLogReport xxlJobLogReport);
|
||||
|
||||
public List<XxlJobLogReport> queryLogReport(@Param("triggerDayFrom") Date triggerDayFrom,
|
||||
@Param("triggerDayTo") Date triggerDayTo);
|
||||
|
||||
public XxlJobLogReport queryLogReportTotal();
|
||||
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
package com.xxl.job.admin.dao;
|
||||
|
||||
import com.xxl.job.admin.core.model.XxlJobRegistry;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by xuxueli on 16/9/30.
|
||||
*/
|
||||
@Mapper
|
||||
public interface XxlJobRegistryDao {
|
||||
|
||||
public List<Integer> findDead(@Param("timeout") int timeout,
|
||||
@Param("nowTime") Date nowTime);
|
||||
|
||||
public int removeDead(@Param("ids") List<Integer> ids);
|
||||
|
||||
public List<XxlJobRegistry> findAll(@Param("timeout") int timeout,
|
||||
@Param("nowTime") Date nowTime);
|
||||
|
||||
public int registryUpdate(@Param("registryGroup") String registryGroup,
|
||||
@Param("registryKey") String registryKey,
|
||||
@Param("registryValue") String registryValue,
|
||||
@Param("updateTime") Date updateTime);
|
||||
|
||||
public int registrySave(@Param("registryGroup") String registryGroup,
|
||||
@Param("registryKey") String registryKey,
|
||||
@Param("registryValue") String registryValue,
|
||||
@Param("updateTime") Date updateTime);
|
||||
|
||||
public int registryDelete(@Param("registryGroup") String registryGroup,
|
||||
@Param("registryKey") String registryKey,
|
||||
@Param("registryValue") String registryValue);
|
||||
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
package com.xxl.job.admin.dao;
|
||||
|
||||
import com.xxl.job.admin.core.model.XxlJobUser;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author xuxueli 2019-05-04 16:44:59
|
||||
*/
|
||||
@Mapper
|
||||
public interface XxlJobUserDao {
|
||||
|
||||
public List<XxlJobUser> pageList(@Param("offset") int offset,
|
||||
@Param("pagesize") int pagesize,
|
||||
@Param("username") String username,
|
||||
@Param("role") int role);
|
||||
public int pageListCount(@Param("offset") int offset,
|
||||
@Param("pagesize") int pagesize,
|
||||
@Param("username") String username,
|
||||
@Param("role") int role);
|
||||
|
||||
public XxlJobUser loadByUserName(@Param("username") String username);
|
||||
|
||||
public int save(XxlJobUser xxlJobUser);
|
||||
|
||||
public int update(XxlJobUser xxlJobUser);
|
||||
|
||||
public int delete(@Param("id") int id);
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user