commit
eebb40d4b9
2629 changed files with 698329 additions and 0 deletions
@ -0,0 +1,2 @@ |
|||||
|
= 6.0.0(2022-04-29) |
||||
|
. 初始版本发布 |
@ -0,0 +1,19 @@ |
|||||
|
/** |
||||
|
* 设置打包文件的运行时目标环境(target) |
||||
|
* 设置方式: 通过命令行 -D 传入目标环境参数 |
||||
|
* 打包命令如下: |
||||
|
* 1. gradle bootwar # 默认, target=tomcat |
||||
|
* 2. gradle bootwar -Dtarget=undertow # undertow, target=undertow |
||||
|
* 3. gradle bootwar -Dtarget=jetty # jetty, target=jetty |
||||
|
*/ |
||||
|
def target =System.getProperty("target") ?: "tomcat"; |
||||
|
System.setProperty('target',target); |
||||
|
|
||||
|
// 根据 targetRuntime 变量的值执行实际的 build.gradle |
||||
|
apply from: "build-${target}.gradle" |
||||
|
|
||||
|
// 应用启动项目无需发布到仓库中 |
||||
|
publishPublicationPublicationToMavenRepository.enabled=false |
||||
|
|
||||
|
// 开启 docker 镜像生成任务 |
||||
|
jibBuildTar.enabled =true |
@ -0,0 +1,15 @@ |
|||||
|
println "[Jetty] 环境 ......" |
||||
|
|
||||
|
configurations { |
||||
|
all*.exclude group: "org.springframework.boot", module: "spring-boot-starter-tomcat" |
||||
|
all*.exclude group: "org.apache.tomcat.embed", module: "tomcat-embed-core" |
||||
|
all*.exclude group: "org.apache.tomcat.embed", module: "tomcat-embed-websocket" |
||||
|
} |
||||
|
|
||||
|
dependencies { |
||||
|
implementation("org.springframework.boot:spring-boot-starter-jetty") |
||||
|
|
||||
|
providedRuntime( |
||||
|
"org.springframework.boot:spring-boot-starter-jetty", |
||||
|
) |
||||
|
} |
@ -0,0 +1,7 @@ |
|||||
|
println "[Tomcat] 环境 ......" |
||||
|
|
||||
|
dependencies { |
||||
|
providedRuntime( |
||||
|
"org.springframework.boot:spring-boot-starter-tomcat", |
||||
|
) |
||||
|
} |
@ -0,0 +1,15 @@ |
|||||
|
println "[Undertow] 环境 ......" |
||||
|
|
||||
|
configurations { |
||||
|
all*.exclude group: "org.springframework.boot", module: "spring-boot-starter-tomcat" |
||||
|
all*.exclude group: "org.apache.tomcat.embed", module: "tomcat-embed-core" |
||||
|
all*.exclude group: "org.apache.tomcat.embed", module: "tomcat-embed-websocket" |
||||
|
} |
||||
|
|
||||
|
dependencies { |
||||
|
implementation("org.springframework.boot:spring-boot-starter-undertow") |
||||
|
|
||||
|
providedRuntime( |
||||
|
"org.springframework.boot:spring-boot-starter-undertow", |
||||
|
) |
||||
|
} |
@ -0,0 +1,100 @@ |
|||||
|
apply plugin: 'war' |
||||
|
apply plugin: 'com.google.cloud.tools.jib' |
||||
|
|
||||
|
apply from: "build-common.gradle" |
||||
|
|
||||
|
dependencies { |
||||
|
implementation("org.springframework.boot:spring-boot-starter-web"){ |
||||
|
exclude group: "org.springframework.boot", module: "spring-boot-starter-tomcat" |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
dependencies { |
||||
|
implementation ( |
||||
|
project(":io.sc.platform.app"), |
||||
|
project(":io.sc.platform.developer"), |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* replace [application.version] in i18n message file |
||||
|
*/ |
||||
|
processResources { |
||||
|
filesMatching('**/messages*.properties') { |
||||
|
println 'replace ${version} in [' + it + ']' |
||||
|
filteringCharset = 'iso8859-1' |
||||
|
filter(org.apache.tools.ant.filters.ReplaceTokens, beginToken: '$version', endToken: '',tokens: [version: '' + project.version]) |
||||
|
} |
||||
|
|
||||
|
doLast{ |
||||
|
// 为了能够兼容 eclipse 和 idea 两种开发环境,调整如下: |
||||
|
// 1. 将 environment.properties 文件放在了 src/main/resources 目录中 |
||||
|
// 2. 在打包时,将该文件删除 |
||||
|
delete "$buildDir/resources/main/running-mode.properties" |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
bootWar{ |
||||
|
mainClass = "${project.name}.Application" |
||||
|
//launchScript() |
||||
|
manifest { |
||||
|
attributes 'Implementation-Version': archiveVersion, |
||||
|
'Implementation-Title': project.name |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
bootJar{ |
||||
|
mainClass = "${project.name}.Application" |
||||
|
//launchScript() |
||||
|
manifest { |
||||
|
attributes 'Implementation-Version': archiveVersion, |
||||
|
'Implementation-Title': project.name |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
jib { |
||||
|
outputPaths { |
||||
|
tar = "build/libs/${project.name}-${project.version}-image.tar" |
||||
|
} |
||||
|
from { |
||||
|
image = "openjdk:8u342-slim" |
||||
|
//image = "eclipse-temurin:8u382-b05-jdk-focal" |
||||
|
platforms { |
||||
|
platform { |
||||
|
architecture ="arm64" |
||||
|
os ="linux" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
to { |
||||
|
image = "${project.name}:${project.version}" |
||||
|
} |
||||
|
extraDirectories { |
||||
|
paths { |
||||
|
path { |
||||
|
from = "build/libs/" |
||||
|
into = "/opt/${project.name}/" |
||||
|
includes = ["${project.name}-${project.version}.war"] |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
container { |
||||
|
/** |
||||
|
* 设置jvm的启动参数 |
||||
|
* user.timezone - 解决Java程序的时区问题 |
||||
|
*/ |
||||
|
jvmFlags = ["-Duser.timezone=Asia/Shanghai"] |
||||
|
creationTime = "USE_CURRENT_TIMESTAMP" |
||||
|
ports = ["8080"] |
||||
|
entrypoint = [ |
||||
|
"java", |
||||
|
"-jar", |
||||
|
"/opt/" + project.name + "/" + project.name + "-" + project.version + ".war", |
||||
|
"--" + project.name + ".home.dir=" + "/opt/" + project.name |
||||
|
] |
||||
|
//entrypoint = "java -version" |
||||
|
//appRoot = "/usr/local/tomcat/webapps/ROOT" |
||||
|
} |
||||
|
} |
@ -0,0 +1,16 @@ |
|||||
|
package app.platform; |
||||
|
|
||||
|
import io.sc.platform.core.ApplicationLauncher; |
||||
|
import io.sc.platform.core.PlatformSpringBootServletInitializer; |
||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication; |
||||
|
import org.springframework.web.WebApplicationInitializer; |
||||
|
|
||||
|
/** |
||||
|
* 应用程序入口 |
||||
|
*/ |
||||
|
@SpringBootApplication(proxyBeanMethods = false) |
||||
|
public class Application extends PlatformSpringBootServletInitializer implements WebApplicationInitializer { |
||||
|
public static void main(String[] args) throws Exception { |
||||
|
ApplicationLauncher.run(Application.class,args); |
||||
|
} |
||||
|
} |
@ -0,0 +1,5 @@ |
|||||
|
{ |
||||
|
"includes":[ |
||||
|
"app/platform/i18n/messages" |
||||
|
] |
||||
|
} |
@ -0,0 +1,3 @@ |
|||||
|
application.title=Application Platform |
||||
|
application.version=$version |
||||
|
application.copyright=Copyright \u00A9 2019\u20132022 |
@ -0,0 +1,3 @@ |
|||||
|
application.title=\u61C9\u7528\u958B\u767C\u5E73\u53F0 |
||||
|
application.version=$version |
||||
|
application.copyright=Copyright \u00A9 2019\u20132022 |
@ -0,0 +1,3 @@ |
|||||
|
application.title=\u5E94\u7528\u5F00\u53D1\u5E73\u53F0 |
||||
|
application.version=$version |
||||
|
application.copyright=Copyright \u00A9 2019\u20132022 |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 923 KiB |
After Width: | Height: | Size: 1.2 KiB |
@ -0,0 +1 @@ |
|||||
|
development=true |
@ -0,0 +1,201 @@ |
|||||
|
/*********************************************************************** |
||||
|
* 覆盖 springboot 默认包版本 |
||||
|
**********************************************************************/ |
||||
|
subprojects { |
||||
|
// ext['activemq.version'] = |
||||
|
// ext['antlr2.version'] = |
||||
|
// ext['appengine-sdk.version'] = |
||||
|
// ext['artemis.version'] = |
||||
|
// ext['aspectj.version'] = |
||||
|
// ext['assertj.version'] = |
||||
|
// ext['atomikos.version'] = |
||||
|
// ext['awaitility.version'] = |
||||
|
// ext['bitronix.version'] = |
||||
|
// ext['build-helper-maven-plugin.version'] = |
||||
|
// ext['byte-buddy.version'] = |
||||
|
// ext['caffeine.version'] = |
||||
|
// ext['cassandra-driver.version'] = |
||||
|
// ext['classmate.version'] = |
||||
|
// ext['commons-codec.version'] = |
||||
|
// ext['commons-dbcp2.version'] = |
||||
|
// ext['commons-lang3.version'] = |
||||
|
// ext['commons-pool.version'] = |
||||
|
// ext['commons-pool2.version'] = |
||||
|
// ext['couchbase-client.version'] = |
||||
|
// ext['db2-jdbc.version'] = |
||||
|
// ext['dependency-management-plugin.version'] = |
||||
|
// ext['derby.version'] = |
||||
|
// ext['dropwizard-metrics.version'] = |
||||
|
// ext['ehcache.version'] = |
||||
|
// ext['ehcache3.version'] = |
||||
|
// ext['elasticsearch.version'] = |
||||
|
// ext['embedded-mongo.version'] = |
||||
|
// ext['flyway.version'] = |
||||
|
// ext['freemarker.version'] = |
||||
|
// ext['git-commit-id-plugin.version'] = |
||||
|
// ext['glassfish-el.version'] = |
||||
|
// ext['glassfish-jaxb.version'] = |
||||
|
// ext['groovy.version'] = |
||||
|
// ext['gson.version'] = |
||||
|
// ext['h2.version'] = |
||||
|
// ext['hamcrest.version'] = |
||||
|
// ext['hazelcast.version'] = |
||||
|
// ext['hazelcast-hibernate5.version'] = |
||||
|
// ext['hibernate.version'] = |
||||
|
// ext['hibernate-validator.version'] = |
||||
|
// ext['hikaricp.version'] = |
||||
|
// ext['hsqldb.version'] = |
||||
|
// ext['htmlunit.version'] = |
||||
|
// ext['httpasyncclient.version'] = |
||||
|
// ext['httpclient.version'] = |
||||
|
// ext['httpcore.version'] = |
||||
|
// ext['infinispan.version'] = |
||||
|
// ext['influxdb-java.version'] = |
||||
|
// ext['jackson-bom.version'] = |
||||
|
// ext['jakarta-activation.version'] = |
||||
|
// ext['jakarta-annotation.version'] = |
||||
|
// ext['jakarta-jms.version'] = |
||||
|
// ext['jakarta-json.version'] = |
||||
|
// ext['jakarta-json-bind.version'] = |
||||
|
// ext['jakarta-mail.version'] = |
||||
|
// ext['jakarta-persistence.version'] = |
||||
|
// ext['jakarta-servlet.version'] = |
||||
|
// ext['jakarta-servlet-jsp-jstl.version'] = |
||||
|
// ext['jakarta-transaction.version'] = |
||||
|
// ext['jakarta-validation.version'] = |
||||
|
// ext['jakarta-websocket.version'] = |
||||
|
// ext['jakarta-ws-rs.version'] = |
||||
|
// ext['jakarta-xml-bind.version'] = |
||||
|
// ext['jakarta-xml-soap.version'] = |
||||
|
// ext['jakarta-xml-ws.version'] = |
||||
|
// ext['janino.version'] = |
||||
|
// ext['javax-activation.version'] = |
||||
|
// ext['javax-annotation.version'] = |
||||
|
// ext['javax-cache.version'] = |
||||
|
// ext['javax-jaxb.version'] = |
||||
|
// ext['javax-jaxws.version'] = |
||||
|
// ext['javax-jms.version'] = |
||||
|
// ext['javax-json.version'] = |
||||
|
// ext['javax-jsonb.version'] = |
||||
|
// ext['javax-mail.version'] = |
||||
|
// ext['javax-money.version'] = |
||||
|
// ext['javax-persistence.version'] = |
||||
|
// ext['javax-transaction.version'] = |
||||
|
// ext['javax-validation.version'] = |
||||
|
// ext['javax-websocket.version'] = |
||||
|
// ext['jaxen.version'] = |
||||
|
// ext['jaybird.version'] = |
||||
|
// ext['jboss-logging.version'] = |
||||
|
// ext['jboss-transaction-spi.version'] = |
||||
|
// ext['jdom2.version'] = |
||||
|
// ext['jedis.version'] = |
||||
|
// ext['jersey.version'] = |
||||
|
// ext['jetty.version'] = |
||||
|
// ext['jetty-el.version'] = |
||||
|
// ext['jetty-jsp.version'] = |
||||
|
// ext['jetty-reactive-httpclient.version'] = |
||||
|
// ext['jmustache.version'] = |
||||
|
// ext['johnzon.version'] = |
||||
|
// ext['jolokia.version'] = |
||||
|
// ext['jooq.version'] = |
||||
|
// ext['json-path.version'] = |
||||
|
// ext['json-smart.version'] = |
||||
|
// ext['jsonassert.version'] = |
||||
|
// ext['jstl.version'] = |
||||
|
// ext['jtds.version'] = |
||||
|
// ext['junit.version'] = |
||||
|
// ext['junit-jupiter.version'] = |
||||
|
// ext['kafka.version'] = |
||||
|
// ext['kotlin.version'] = |
||||
|
// ext['kotlin-coroutines.version'] = |
||||
|
// ext['lettuce.version'] = |
||||
|
// ext['liquibase.version'] = |
||||
|
// ext['log4j2.version'] = |
||||
|
// ext['logback.version'] = |
||||
|
// ext['lombok.version'] = |
||||
|
// ext['mariadb.version'] = |
||||
|
// ext['maven-antrun-plugin.version'] = |
||||
|
// ext['maven-assembly-plugin.version'] = |
||||
|
// ext['maven-clean-plugin.version'] = |
||||
|
// ext['maven-compiler-plugin.version'] = |
||||
|
// ext['maven-dependency-plugin.version'] = |
||||
|
// ext['maven-deploy-plugin.version'] = |
||||
|
// ext['maven-enforcer-plugin.version'] = |
||||
|
// ext['maven-failsafe-plugin.version'] = |
||||
|
// ext['maven-help-plugin.version'] = |
||||
|
// ext['maven-install-plugin.version'] = |
||||
|
// ext['maven-invoker-plugin.version'] = |
||||
|
// ext['maven-jar-plugin.version'] = |
||||
|
// ext['maven-javadoc-plugin.version'] = |
||||
|
// ext['maven-resources-plugin.version'] = |
||||
|
// ext['maven-shade-plugin.version'] = |
||||
|
// ext['maven-source-plugin.version'] = |
||||
|
// ext['maven-surefire-plugin.version'] = |
||||
|
// ext['maven-war-plugin.version'] = |
||||
|
// ext['micrometer.version'] = |
||||
|
// ext['mimepull.version'] = |
||||
|
// ext['mockito.version'] = |
||||
|
// ext['mongodb.version'] = |
||||
|
// ext['mssql-jdbc.version'] = |
||||
|
// ext['mysql.version'] = |
||||
|
// ext['nekohtml.version'] = |
||||
|
// ext['neo4j-java-driver.version'] = |
||||
|
// ext['netty.version'] = |
||||
|
// ext['netty-tcnative.version'] = |
||||
|
// ext['nimbus-jose-jwt.version'] = |
||||
|
// ext['oauth2-oidc-sdk.version'] = |
||||
|
// ext['ojdbc.version'] = |
||||
|
// ext['okhttp3.version'] = |
||||
|
// ext['oracle-database.version'] = |
||||
|
// ext['pooled-jms.version'] = |
||||
|
// ext['postgresql.version'] = |
||||
|
// ext['prometheus-pushgateway.version'] = |
||||
|
// ext['quartz.version'] = |
||||
|
// ext['querydsl.version'] = |
||||
|
// ext['r2dbc-bom.version'] = |
||||
|
// ext['rabbit-amqp-client.version'] = |
||||
|
// ext['reactive-streams.version'] = |
||||
|
// ext['reactor-bom.version'] = |
||||
|
// ext['rest-assured.version'] = |
||||
|
// ext['rsocket.version'] = |
||||
|
// ext['rxjava.version'] = |
||||
|
// ext['rxjava-adapter.version'] = |
||||
|
// ext['rxjava2.version'] = |
||||
|
// ext['saaj-impl.version'] = |
||||
|
// ext['selenium.version'] = |
||||
|
// ext['selenium-htmlunit.version'] = |
||||
|
// ext['sendgrid.version'] = |
||||
|
// ext['servlet-api.version'] = |
||||
|
// ext['slf4j.version'] = |
||||
|
// ext['snakeyaml.version'] = |
||||
|
// ext['solr.version'] = |
||||
|
// ext['spring-amqp.version'] = |
||||
|
// ext['spring-batch.version'] = |
||||
|
// ext['spring-data-bom.version'] = |
||||
|
// ext['spring-framework.version'] = |
||||
|
// ext['spring-hateoas.version'] = |
||||
|
// ext['spring-integration.version'] = |
||||
|
// ext['spring-kafka.version'] = |
||||
|
// ext['spring-ldap.version'] = |
||||
|
// ext['spring-restdocs.version'] = |
||||
|
// ext['spring-retry.version'] = |
||||
|
// ext['spring-security.version'] = |
||||
|
// ext['spring-session-bom.version'] = |
||||
|
// ext['spring-ws.version'] = |
||||
|
// ext['sqlite-jdbc.version'] = |
||||
|
// ext['sun-mail.version'] = |
||||
|
// ext['thymeleaf.version'] = |
||||
|
// ext['thymeleaf-extras-data-attribute.version'] = |
||||
|
// ext['thymeleaf-extras-java8time.version'] = |
||||
|
// ext['thymeleaf-extras-springsecurity.version'] = |
||||
|
// ext['thymeleaf-layout-dialect.version'] = |
||||
|
// ext['tomcat.version'] = |
||||
|
// ext['unboundid-ldapsdk.version'] = |
||||
|
// ext['undertow.version'] = |
||||
|
// ext['versions-maven-plugin.version'] = |
||||
|
// ext['webjars-hal-browser.version'] = |
||||
|
// ext['webjars-locator-core.version'] = |
||||
|
// ext['wsdl4j.version'] = |
||||
|
// ext['xml-maven-plugin.version'] = |
||||
|
// ext['xmlunit2.version'] = |
||||
|
} |
@ -0,0 +1,775 @@ |
|||||
|
apply from: "build-version.gradle" |
||||
|
|
||||
|
def isFrontendProject(currentDir){ |
||||
|
return file(currentDir.getAbsolutePath() + '/package.json').exists() && !file(currentDir.getAbsolutePath() + '/webpack.env.lib.cjs').exists(); |
||||
|
} |
||||
|
|
||||
|
/*********************************************************************** |
||||
|
* gradle 插件 |
||||
|
**********************************************************************/ |
||||
|
buildscript { |
||||
|
repositories { |
||||
|
maven { |
||||
|
allowInsecureProtocol = true |
||||
|
url "${repository_url}" |
||||
|
} |
||||
|
} |
||||
|
dependencies { |
||||
|
classpath "org.springframework.boot:org.springframework.boot.gradle.plugin:${spring_boot_version}" |
||||
|
classpath "io.sc:io.sc.platform.gradle:${platform_plugin_version}" |
||||
|
classpath "org.asciidoctor:asciidoctor-gradle-jvm:${asciidoctor_version}" |
||||
|
classpath "com.google.cloud.tools:jib-gradle-plugin:${jib_version}" |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/*********************************************************************** |
||||
|
* 所有项目(根项目及其子项目)都应用的插件 |
||||
|
**********************************************************************/ |
||||
|
allprojects { |
||||
|
apply plugin: 'idea' |
||||
|
apply plugin: 'io.sc.platform.gradle' |
||||
|
} |
||||
|
|
||||
|
/*********************************************************************** |
||||
|
* 所有子项目应用的插件 |
||||
|
**********************************************************************/ |
||||
|
subprojects { |
||||
|
apply plugin: 'java' |
||||
|
apply plugin: 'java-library' |
||||
|
apply plugin: 'eclipse' |
||||
|
apply plugin: 'maven-publish' |
||||
|
apply plugin: 'org.springframework.boot' |
||||
|
apply plugin: 'io.spring.dependency-management' |
||||
|
apply plugin: "org.asciidoctor.jvm.convert" |
||||
|
|
||||
|
configurations.all { |
||||
|
//设置 gradle 拉取依赖包的缓存策略为不进行缓存,可保证每次拉取最新的依赖包 |
||||
|
//resolutionStrategy.cacheDynamicVersionsFor 0, 'seconds' //动态版本: 1.1.+ |
||||
|
//resolutionStrategy.cacheChangingModulesFor 0, 'seconds' //静态版本: 1.1.2 |
||||
|
|
||||
|
//排除不需要的外部依赖 |
||||
|
exclude group: "org.apache.logging.log4j", module: "log4j-api" |
||||
|
exclude group: "org.apache.logging.log4j", module: "log4j-to-slf4j" |
||||
|
exclude group: "org.slf4j", module: "slf4j-jdk14" |
||||
|
exclude group: "org.slf4j", module: "slf4j-nop" |
||||
|
} |
||||
|
|
||||
|
dependencyManagement { |
||||
|
resolutionStrategy { |
||||
|
//设置 gradle 拉取依赖包的缓存策略为不进行缓存,可保证每次拉取最新的依赖包 |
||||
|
//cacheDynamicVersionsFor 0, 'seconds' //动态版本: 1.1.+ |
||||
|
//cacheChangingModulesFor 0, 'seconds' //静态版本: 1.1.2 |
||||
|
} |
||||
|
imports { |
||||
|
//mavenBom "org.springframework.cloud:spring-cloud-dependencies:${spring_cloud_version}" |
||||
|
mavenBom "com.alibaba.cloud:spring-cloud-alibaba-dependencies:${spring_cloud_alibaba_version}" |
||||
|
mavenBom "org.springframework.statemachine:spring-statemachine-bom:${spring_statemachine_version}" |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/*----------------------------------------------------------------- |
||||
|
* 配置构建时所需依赖的仓库 url |
||||
|
* 将仓库 url 都定位到 ${repository_url} 指定的本地私有仓库地址 |
||||
|
*----------------------------------------------------------------*/ |
||||
|
repositories { |
||||
|
all { ArtifactRepository repo -> |
||||
|
if(repo instanceof MavenArtifactRepository){ |
||||
|
def url = repo.url.toString() |
||||
|
if ( |
||||
|
url.startsWith('https://repo1.maven.org/maven2') |
||||
|
|| url.startsWith('https://jcenter.bintray.com/') |
||||
|
|| url.startsWith('https://maven.aliyun.com') |
||||
|
) { |
||||
|
remove repo |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
maven { |
||||
|
allowInsecureProtocol = true |
||||
|
url "${repository_url}" |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/*----------------------------------------------------------------- |
||||
|
* java 编译时选项 |
||||
|
*----------------------------------------------------------------*/ |
||||
|
sourceCompatibility ="${java_version}" |
||||
|
targetCompatibility ="${java_version}" |
||||
|
compileJava.options.encoding ="${java_encoding}" |
||||
|
compileTestJava.options.encoding ="${java_encoding}" |
||||
|
|
||||
|
tasks.withType(JavaCompile) { |
||||
|
//options.compilerArgs += ["-Xdoclint:none", "-Xlint:none", "-nowarn"] |
||||
|
options.compilerArgs += ["-Xlint:deprecation","-Xlint:unchecked"] |
||||
|
} |
||||
|
|
||||
|
/*----------------------------------------------------------------- |
||||
|
* 配置项目基本信息 |
||||
|
*----------------------------------------------------------------*/ |
||||
|
group ="${platform_group}" |
||||
|
version ="${platform_version}" |
||||
|
|
||||
|
if(file('package.json').exists()){ |
||||
|
mkdir 'java-src/main/java'; |
||||
|
mkdir 'java-src/main/resources'; |
||||
|
mkdir 'dist'; |
||||
|
sourceSets.main.java.srcDir 'java-src/main/java' |
||||
|
sourceSets.main.resources.srcDir 'java-src/main/resources' |
||||
|
sourceSets.main.resources.srcDir 'dist' |
||||
|
} |
||||
|
|
||||
|
/*----------------------------------------------------------------- |
||||
|
* 源代码打包配置 |
||||
|
*----------------------------------------------------------------*/ |
||||
|
task sourcesJar (type : Jar) { |
||||
|
from sourceSets.main.allJava |
||||
|
archiveClassifier = 'sources' |
||||
|
} |
||||
|
|
||||
|
/*----------------------------------------------------------------- |
||||
|
* Java 文档打包配置 |
||||
|
*----------------------------------------------------------------*/ |
||||
|
javadoc { |
||||
|
options.encoding = 'UTF-8' |
||||
|
// 为了能够尽量规范 java doc 文档编写, 指定如果 java doc 中有错误,会报错,并且无法发布到仓库中 |
||||
|
failOnError=false |
||||
|
} |
||||
|
|
||||
|
task javadocJar (type: Jar) { |
||||
|
from javadoc |
||||
|
archiveClassifier = 'javadoc' |
||||
|
} |
||||
|
|
||||
|
clean { |
||||
|
delete 'dist' //删除前端自动生成的资源目录 |
||||
|
delete 'bin' //删除 eclipse 编译的 bin 目录 |
||||
|
delete 'build' //删除 gradle 构建目录 |
||||
|
} |
||||
|
|
||||
|
/*----------------------------------------------------------------- |
||||
|
* 配置 eclipse 插件 |
||||
|
*----------------------------------------------------------------*/ |
||||
|
eclipse{ |
||||
|
jdt{ |
||||
|
sourceCompatibility ="${java_version}" |
||||
|
targetCompatibility ="${java_version}" |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/*----------------------------------------------------------------- |
||||
|
* springboot 插件配置 |
||||
|
*----------------------------------------------------------------*/ |
||||
|
jar { |
||||
|
//可以生成普通的 jar |
||||
|
enabled = true |
||||
|
archiveClassifier.set("") |
||||
|
manifest { |
||||
|
attributes 'Manifest-Version' : '1.0', |
||||
|
'Implementation-Title' : name, |
||||
|
'Implementation-Vendor' : group, |
||||
|
'Implementation-Version': archiveVersion |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/*----------------------------------------------------------------- |
||||
|
* asciidoctor 插件配置,用于生成 asciidoc 文档,用于打包到 jar 中 |
||||
|
*----------------------------------------------------------------*/ |
||||
|
asciidoctor { |
||||
|
baseDirFollowsSourceDir() |
||||
|
outputs.upToDateWhen { true } |
||||
|
|
||||
|
logDocuments = true |
||||
|
sourceDir = file('asciidoc') |
||||
|
sources { |
||||
|
include '*.adoc' |
||||
|
} |
||||
|
//outputDir = file("$buildDir/resources/main/help/" + project.name) |
||||
|
outputDir = file("dist/help/" + project.name) |
||||
|
resources { |
||||
|
from(sourceDir) { |
||||
|
include 'resources/**' |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
asciidoctorj { |
||||
|
modules { |
||||
|
diagram.use() |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/*----------------------------------------------------------------- |
||||
|
* 自定义任务,用于生成 asciidoc 文档到 web 服务器,以便实时查看效果 |
||||
|
*----------------------------------------------------------------*/ |
||||
|
task doc(type: org.asciidoctor.gradle.jvm.AsciidoctorTask){ |
||||
|
baseDirFollowsSourceDir() |
||||
|
outputs.upToDateWhen { true } |
||||
|
|
||||
|
logDocuments = true |
||||
|
sourceDir = file('asciidoc') |
||||
|
sources { |
||||
|
include '*.adoc' |
||||
|
} |
||||
|
outputDir = file("$asciidoc_deploy_dir" + project.name) |
||||
|
|
||||
|
// 拷贝 asciidoc 自定义资源 |
||||
|
// 设置方式: 通过命令行 -D 传入目标环境参数 |
||||
|
// gradle doc -DdocResource=true # 需要拷贝自定义资源 |
||||
|
// gradle doc -DdocResource=false # 不需要拷贝自定义资源 |
||||
|
def docResource =System.getProperty("docResource")?:"true"; |
||||
|
if(docResource=="true"){ |
||||
|
resources { |
||||
|
from(sourceDir) { |
||||
|
include 'resources/**' |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/*----------------------------------------------------------------- |
||||
|
* 资源处理前执行 asciidoctor |
||||
|
*----------------------------------------------------------------*/ |
||||
|
processResources { |
||||
|
dependsOn asciidoctor |
||||
|
doLast{ |
||||
|
//打包时移除 jrebel 相关的文件 |
||||
|
delete "$buildDir/resources/main/rebel.xml" |
||||
|
// |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/*----------------------------------------------------------------- |
||||
|
* 用于自动生成 jrebel.xml 文件的自定义任务(eclipse) |
||||
|
*----------------------------------------------------------------*/ |
||||
|
task jrebelEclipse() {} |
||||
|
tasks.jrebelEclipse.doLast { |
||||
|
File resourcesFile =file('src/main/resources') |
||||
|
if(resourcesFile!=null && resourcesFile.exists()){ |
||||
|
File rebelFile = file('src/main/resources/rebel.xml') |
||||
|
rebelFile.withWriter('UTF-8') { writer -> |
||||
|
writer.write('<?xml version="1.0" encoding="UTF-8"?>\n'); |
||||
|
writer.write('<application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.zeroturnaround.com" xsi:schemaLocation="http://www.zeroturnaround.com http://update.zeroturnaround.com/jrebel/rebel-2_1.xsd">\n'); |
||||
|
writer.write('\t<classpath>\n'); |
||||
|
if(file(project.name + '/src/main').exists()){ |
||||
|
writer.write('\t\t<dir name="' + project.projectDir + '/bin/main"/>\n'); |
||||
|
} |
||||
|
if(file(project.name + '/src/generated').exists()){ |
||||
|
writer.write('\t\t<dir name="' + project.projectDir + '/bin/generated"/>\n'); |
||||
|
} |
||||
|
writer.write('\t</classpath>\n'); |
||||
|
writer.write('</application>'); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/*----------------------------------------------------------------- |
||||
|
* 用于自动生成 jrebel.xml 文件的自定义任务(idea) |
||||
|
*----------------------------------------------------------------*/ |
||||
|
task jrebelIdea() {} |
||||
|
tasks.jrebelIdea.doLast { |
||||
|
File resourcesFile =file('src/main/resources') |
||||
|
if(resourcesFile!=null && resourcesFile.exists()){ |
||||
|
File rebelFile = file('src/main/resources/rebel.xml') |
||||
|
rebelFile.withWriter('UTF-8') { writer -> |
||||
|
writer.write('<?xml version="1.0" encoding="UTF-8"?>\n'); |
||||
|
writer.write('<application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.zeroturnaround.com" xsi:schemaLocation="http://www.zeroturnaround.com http://update.zeroturnaround.com/jrebel/rebel-2_1.xsd">\n'); |
||||
|
writer.write('\t<classpath>\n'); |
||||
|
if(file(project.name + '/src/main').exists()){ |
||||
|
writer.write('\t\t<dir name="' + project.rootProject.projectDir + '/out/production/' + project.name + '"/>\n'); |
||||
|
} |
||||
|
writer.write('\t</classpath>\n'); |
||||
|
writer.write('</application>'); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/*----------------------------------------------------------------- |
||||
|
* maven publish 插件配置 |
||||
|
*----------------------------------------------------------------*/ |
||||
|
publishing { |
||||
|
repositories { |
||||
|
maven { |
||||
|
allowInsecureProtocol = true //允许采用 http 协议发布 |
||||
|
url = version.contains('SNAPSHOT') ? "${repository_snapshot_url}" : "${repository_release_url}" |
||||
|
credentials { |
||||
|
username = (version.contains('SNAPSHOT') ? "${repository_snapshot_username}" : "${repository_release_username}") |
||||
|
password = (version.contains('SNAPSHOT') ? "${repository_snapshot_password}" : "${repository_release_password}") |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
publications{ |
||||
|
publication(MavenPublication){ |
||||
|
from components.java |
||||
|
artifact sourcesJar |
||||
|
//artifact javadocJar |
||||
|
versionMapping { |
||||
|
usage('java-api') { |
||||
|
fromResolutionOf('runtimeClasspath') |
||||
|
} |
||||
|
usage('java-runtime') { |
||||
|
fromResolutionResult() |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/*----------------------------------------------------------------- |
||||
|
* 更新前端模块的 package.json 文件,同步其中的 name 和 version |
||||
|
*----------------------------------------------------------------*/ |
||||
|
task frontendUpdatePackageJson(){} |
||||
|
tasks.frontendUpdatePackageJson.doFirst { |
||||
|
if(isFrontendProject(file('.'))) { |
||||
|
println '开始执行 frontendUpdatePackageJson ......' |
||||
|
} |
||||
|
} |
||||
|
tasks.frontendUpdatePackageJson.doLast { |
||||
|
if(isFrontendProject(file('.'))){ |
||||
|
String content =file('package.json').text; |
||||
|
def packageJson = new groovy.json.JsonSlurper().parseText(content); |
||||
|
if(packageJson!=null){ |
||||
|
println packageJson.dependencies; |
||||
|
packageJson.name =project.name; |
||||
|
packageJson.version =project.version; |
||||
|
packageJson.dependencies['platform-core']=platform_core_frontend_version; |
||||
|
def json = groovy.json.JsonOutput.toJson(packageJson); |
||||
|
file('package.json').withWriter('UTF-8') { writer -> |
||||
|
writer.write(groovy.json.JsonOutput.prettyPrint(json)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/*----------------------------------------------------------------- |
||||
|
* pnpm install |
||||
|
*----------------------------------------------------------------*/ |
||||
|
task frontendNpmInstall(type:Exec){ |
||||
|
if(isFrontendProject(file('.'))){ |
||||
|
workingDir '.' |
||||
|
if(org.gradle.internal.os.OperatingSystem.current().isWindows()){ |
||||
|
commandLine 'cmd', '/c', 'pnpm', 'install' |
||||
|
}else{ |
||||
|
commandLine 'pnpm', 'install' |
||||
|
} |
||||
|
}else{ |
||||
|
if(org.gradle.internal.os.OperatingSystem.current().isWindows()){ |
||||
|
commandLine 'cmd', '/c', 'cd', '.' |
||||
|
}else{ |
||||
|
commandLine 'cd', '.' |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
tasks.frontendNpmInstall.doFirst { |
||||
|
if(isFrontendProject(file('.'))) { |
||||
|
println '开始执行 pnpm install ......'; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/*----------------------------------------------------------------- |
||||
|
* pnpm run build |
||||
|
*----------------------------------------------------------------*/ |
||||
|
task frontendNpmBuild(type:Exec) { |
||||
|
if(isFrontendProject(file('.'))){ |
||||
|
workingDir '.' |
||||
|
if(org.gradle.internal.os.OperatingSystem.current().isWindows()){ |
||||
|
commandLine 'cmd', '/c', 'pnpm', 'run', 'build' |
||||
|
}else{ |
||||
|
commandLine 'pnpm', 'run', 'build' |
||||
|
} |
||||
|
}else{ |
||||
|
if(org.gradle.internal.os.OperatingSystem.current().isWindows()){ |
||||
|
commandLine 'cmd', '/c', 'cd', '.' |
||||
|
}else{ |
||||
|
commandLine 'cd', '.' |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
tasks.frontendNpmBuild.doFirst { |
||||
|
if (isFrontendProject(file('.'))) { |
||||
|
println '开始执行 pnpm run build ......' |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/*----------------------------------------------------------------- |
||||
|
* pnpm run prod |
||||
|
*----------------------------------------------------------------*/ |
||||
|
task frontendNpmProd(type:Exec) { |
||||
|
if(isFrontendProject(file('.'))){ |
||||
|
workingDir '.' |
||||
|
if(org.gradle.internal.os.OperatingSystem.current().isWindows()){ |
||||
|
commandLine 'cmd', '/c', 'pnpm', 'run', 'prod' |
||||
|
}else{ |
||||
|
commandLine 'pnpm', 'run', 'prod' |
||||
|
} |
||||
|
}else{ |
||||
|
if(org.gradle.internal.os.OperatingSystem.current().isWindows()){ |
||||
|
commandLine 'cmd', '/c', 'cd', '.' |
||||
|
}else{ |
||||
|
commandLine 'cd', '.' |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
tasks.frontendNpmProd.doFirst { |
||||
|
if(isFrontendProject(file('.'))){ |
||||
|
println '开始执行 pnpm run prod ......' |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/*----------------------------------------------------------------- |
||||
|
* 将入口前端 dist/public/模块名 目录下 index.html 文件复制到 classpath:/templates/模块名.html |
||||
|
* 提供给 thymeleaf 作为视图模板使用 |
||||
|
*----------------------------------------------------------------*/ |
||||
|
task frontendGenerateThymeleafTemplate {} |
||||
|
tasks.frontendGenerateThymeleafTemplate.doFirst { |
||||
|
if(isFrontendProject(file('.'))) { |
||||
|
println '开始执行 frontendGenerateThymeleafTemplate ......' |
||||
|
delete "java-src/main/resources/templates" |
||||
|
mkdir "java-src/main/resources/templates" |
||||
|
} |
||||
|
} |
||||
|
tasks.frontendGenerateThymeleafTemplate.doLast { |
||||
|
if(isFrontendProject(file('.'))) { |
||||
|
def content = file("dist/public/${project.name}/index.html").text; |
||||
|
content = content.replace('<script defer src="javascript/main', """<script defer src="${project.name}/javascript/main"""); |
||||
|
def output = file("java-src/main/resources/templates/${project.name}.html"); |
||||
|
output.withWriter('utf-8') { writer -> |
||||
|
writer.write content; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/*----------------------------------------------------------------- |
||||
|
* 根据前端定义的多语言 json 文件生成后端 properties 文件 |
||||
|
*----------------------------------------------------------------*/ |
||||
|
task frontendGenerateI18n {} |
||||
|
tasks.frontendGenerateI18n.doFirst { |
||||
|
if(isFrontendProject(file('.'))){ |
||||
|
println '开始执行 frontendGenerateI18n ......' |
||||
|
delete 'java-src/main/resources/' + project.name.replace('.', '/') + '/i18n'; |
||||
|
delete 'java-src/main/resources/META-INF/platform/plugins/messages.json'; |
||||
|
|
||||
|
mkdir 'java-src/main/resources/' + project.name.replace('.', '/') + '/i18n'; |
||||
|
mkdir 'java-src/main/resources/META-INF/platform/plugins'; |
||||
|
} |
||||
|
} |
||||
|
tasks.frontendGenerateI18n.doLast { |
||||
|
if(isFrontendProject(file('.'))){ |
||||
|
def messagesDir ='java-src/main/resources/' + project.name.replace('.', '/') + '/i18n'; |
||||
|
def pluginDir ='java-src/main/resources/META-INF/platform/plugins'; |
||||
|
def jsonDir ='src/i18n'; |
||||
|
|
||||
|
// 获取所有的多语言消息文件 |
||||
|
def tree = fileTree(jsonDir) { include '**/*.json' } |
||||
|
def i18nMessageFileList =new ArrayList<String>(); |
||||
|
tree.each { File jsonFile -> i18nMessageFileList.add(jsonFile.getName()) } |
||||
|
|
||||
|
if(i18nMessageFileList.size()>0){ |
||||
|
// 生成 java-src/main/resources/META-INF/platform/plugins/messages.json 文件 |
||||
|
def content =''; |
||||
|
content +='{\n'; |
||||
|
content +=' includes:[\n'; |
||||
|
content +=' "' + project.name.replace('.','/') + '/i18n/messages"' + '\n'; |
||||
|
content +=' ]\n'; |
||||
|
content +='}\n'; |
||||
|
def output =file(pluginDir + '/messages.json'); |
||||
|
output.withWriter('utf-8') { writer -> |
||||
|
writer.write content; |
||||
|
} |
||||
|
// 生成 java-src/main/resources/{project.name}/messages_{locale}.properties |
||||
|
for(String fileName : i18nMessageFileList){ |
||||
|
def json = new groovy.json.JsonSlurper().parseText(file(jsonDir + '/' + fileName).text); |
||||
|
def sb =new StringBuilder(); |
||||
|
json.keySet().each { String key -> |
||||
|
sb.append(key).append("=").append(groovy.json.StringEscapeUtils.escapeJava(json.get(key))).append("\n"); |
||||
|
}; |
||||
|
def outputFilePath =messagesDir + '/' + fileName.replace('.json','.properties'); |
||||
|
file(outputFilePath).withWriter('utf-8') { writer -> |
||||
|
writer.write sb.toString(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/*----------------------------------------------------------------- |
||||
|
* 根据前端定义的菜单 json 文件生成后端插件 json 文件 |
||||
|
*----------------------------------------------------------------*/ |
||||
|
task frontendGenerateMenus {} |
||||
|
tasks.frontendGenerateMenus.doFirst { |
||||
|
if(isFrontendProject(file('.'))){ |
||||
|
println '开始执行 frontendGenerateMenus ......' |
||||
|
delete 'java-src/main/resources/META-INF/platform/plugins/menus.json'; |
||||
|
} |
||||
|
} |
||||
|
tasks.frontendGenerateMenus.doLast { |
||||
|
if(isFrontendProject(file('.'))) { |
||||
|
java.nio.file.Files.copy(file('src/menus/menus.json').toPath(), file('java-src/main/resources/META-INF/platform/plugins/menus.json').toPath()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/*----------------------------------------------------------------- |
||||
|
* 根据前端定义的路由 json 文件生成后端插件 json 文件 |
||||
|
*----------------------------------------------------------------*/ |
||||
|
task frontendGenerateRoutes {} |
||||
|
tasks.frontendGenerateRoutes.doFirst { |
||||
|
if(isFrontendProject(file('.'))){ |
||||
|
println '开始执行 frontendGenerateRoutes ......' |
||||
|
delete 'java-src/main/resources/META-INF/platform/plugins/frontend-routes.json'; |
||||
|
} |
||||
|
} |
||||
|
tasks.frontendGenerateRoutes.doLast { |
||||
|
if(isFrontendProject(file('.'))) { |
||||
|
def routes = new groovy.json.JsonSlurper().parseText(file("src/routes/routes.json").text); |
||||
|
for(def route : routes){ |
||||
|
route.module=project.name; |
||||
|
} |
||||
|
def json = groovy.json.JsonOutput.toJson(routes); |
||||
|
def outputFile =file("java-src/main/resources/META-INF/platform/plugins/frontend-routes.json"); |
||||
|
outputFile.withWriter('UTF-8') { writer -> |
||||
|
writer.write(groovy.json.JsonOutput.prettyPrint(json)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/*----------------------------------------------------------------- |
||||
|
* 为后端生成前端资源清单,以便可通过一键导出成独立的前端系统 |
||||
|
*----------------------------------------------------------------*/ |
||||
|
task frontendModule {} |
||||
|
tasks.frontendModule.doFirst { |
||||
|
if(isFrontendProject(file('.'))) { |
||||
|
println '开始执行 frontendModule ......' |
||||
|
delete 'java-src/main/resources/META-INF/platform/plugins/frontend-module.json' |
||||
|
} |
||||
|
} |
||||
|
tasks.frontendModule.doLast { |
||||
|
if(isFrontendProject(file('.'))) { |
||||
|
//components--------------------------------------- |
||||
|
List<String> components =new ArrayList<String>(); |
||||
|
def routes = new groovy.json.JsonSlurper().parseText(file("java-src/main/resources/META-INF/platform/plugins/frontend-routes.json").text); |
||||
|
for(def route : routes){ |
||||
|
components.add(route.component); |
||||
|
} |
||||
|
|
||||
|
//resources---------------------------------------- |
||||
|
List<String> resources = new ArrayList<String>(); |
||||
|
def dirPath = file('dist').absolutePath; |
||||
|
def tree = fileTree('dist') { |
||||
|
include '**/*.*' |
||||
|
} |
||||
|
tree.each { File file -> |
||||
|
resources.add(file.absolutePath.substring(dirPath.length())); |
||||
|
} |
||||
|
|
||||
|
//all-in-one------------------------------------ |
||||
|
Map<String,Object> allInOne =new LinkedHashMap<>(); |
||||
|
allInOne.put("name",project.name); |
||||
|
allInOne.put("components",components); |
||||
|
allInOne.put("resources",resources); |
||||
|
|
||||
|
def json = groovy.json.JsonOutput.toJson(allInOne); |
||||
|
def outputFile =file('java-src/main/resources/META-INF/platform/plugins/frontend-module.json'); |
||||
|
outputFile.withWriter('UTF-8') { writer -> |
||||
|
writer.write(groovy.json.JsonOutput.prettyPrint(json)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/*----------------------------------------------------------------- |
||||
|
* 打包 jar 之前处理前端资源 |
||||
|
*----------------------------------------------------------------*/ |
||||
|
task frontend() {} |
||||
|
tasks.frontend.doFirst { |
||||
|
if(isFrontendProject(file('.'))){ |
||||
|
println '开始执行 frontend ......' |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 定义前端构建任务的依赖及执行顺序 |
||||
|
frontendNpmInstall.dependsOn(frontendUpdatePackageJson) |
||||
|
frontendNpmBuild.dependsOn(frontendNpmInstall) |
||||
|
frontendNpmProd.dependsOn(frontendNpmInstall) |
||||
|
|
||||
|
// 资源处理前进行前端模块的构建 |
||||
|
// 设置方式: 通过命令行 -D 传入目标环境参数 |
||||
|
// gradle bootwar -Dfrontend=dev # 采用 pnpm build 构建前端 |
||||
|
// gradle bootwar -Dfrontend=prod # 采用 pnpm prod 构建前端 |
||||
|
// gradle bootwar -Dfrontend # 不构建前端, 仅生成后端需要的文件 |
||||
|
def isFrontend =System.getProperty("frontend")?:"dev"; |
||||
|
if(isFrontend=="dev"){ |
||||
|
frontendGenerateThymeleafTemplate.dependsOn(frontendNpmBuild); |
||||
|
}else if(isFrontend=="prod"){ |
||||
|
frontendGenerateThymeleafTemplate.dependsOn(frontendNpmProd); |
||||
|
} |
||||
|
frontendGenerateI18n.dependsOn(frontendGenerateThymeleafTemplate); |
||||
|
frontendGenerateMenus.dependsOn(frontendGenerateI18n); |
||||
|
frontendGenerateRoutes.dependsOn(frontendGenerateMenus); |
||||
|
frontendModule.dependsOn(frontendGenerateRoutes); |
||||
|
frontend.dependsOn(frontendModule); |
||||
|
|
||||
|
//tasks.preBuild.dependsOn(frontend); |
||||
|
processResources.dependsOn(frontend) |
||||
|
|
||||
|
processResources { |
||||
|
if(isFrontendProject(file('.'))) { |
||||
|
exclude("**/${project.name}/*.*") |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/*********************************************************************** |
||||
|
* 根(Root)项目配置, 该部分仅用于根项目 |
||||
|
**********************************************************************/ |
||||
|
/*----------------------------------------------------------------- |
||||
|
* idea 配置 |
||||
|
*----------------------------------------------------------------*/ |
||||
|
tasks.ideaProject.enabled=true //在根工程中执行 ideaProject 任务,用于生成 ipr 文件 |
||||
|
tasks.ideaModule.enabled=false //在根工程中不执行 ideaModule 任务 |
||||
|
tasks.ideaWorkspace.enabled=true //在根工程中执行 ideaWorkspace 任务,用于修改 iws 文件 |
||||
|
|
||||
|
tasks.ideaProject.doFirst { |
||||
|
delete project.name + '.ipr' |
||||
|
} |
||||
|
|
||||
|
/*----------------------------------------------------------------- |
||||
|
* 定制生成的 idea xml 文件内容 |
||||
|
*----------------------------------------------------------------*/ |
||||
|
idea { |
||||
|
workspace { |
||||
|
iws { |
||||
|
// 自动化配置生成的 iws 文件内容,减少手工操作 |
||||
|
// 1. 设置 Automatically show first error in editor 属性为 false,避免在编辑代码时,总是打开其他有错误的文件,导致混乱 |
||||
|
withXml { |
||||
|
// 1. 设置 Automatically show first error in editor 属性为 false,避免在编辑代码时,总是打开其他有错误的文件,导致混乱 |
||||
|
def node = it.asNode(); |
||||
|
def compilerWorkspaceConfigurationNode =node.find{it.@name=='CompilerWorkspaceConfiguration'} |
||||
|
if(compilerWorkspaceConfigurationNode==null){ |
||||
|
compilerWorkspaceConfigurationNode =node.appendNode("component",[name:"CompilerWorkspaceConfiguration"]); |
||||
|
} |
||||
|
def autoShowErrorsInEditorNode =compilerWorkspaceConfigurationNode.find{it.@name=='AUTO_SHOW_ERRORS_IN_EDITOR'} |
||||
|
if(autoShowErrorsInEditorNode==null){ |
||||
|
autoShowErrorsInEditorNode =compilerWorkspaceConfigurationNode.appendNode("option",[name:"AUTO_SHOW_ERRORS_IN_EDITOR"]); |
||||
|
} |
||||
|
autoShowErrorsInEditorNode.@value ="false"; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
project { |
||||
|
vcs = 'Git' |
||||
|
ipr { |
||||
|
// 自动化配置生成的 ipr 文件内容,减少手工操作 |
||||
|
// 1. 移除根项目模块 |
||||
|
// <component name="ProjectModuleManager"> |
||||
|
// <modules> |
||||
|
// <module fileurl="file://$PROJECT_DIR$/projectName.iml" filepath="$PROJECT_DIR$/projectName.iml"/> #移除 |
||||
|
// ...... |
||||
|
// </modules> |
||||
|
// </component> |
||||
|
// 2. 设置打开 .properties 文件时的转码功能(可显示中文) |
||||
|
// 将 |
||||
|
// <component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false"/> |
||||
|
// 替换为: |
||||
|
// <component name="Encoding" native2AsciiForPropertiesFiles="true" /> |
||||
|
// 3. 使 idea 编译器支持注解(enable annotation processing) |
||||
|
// 将 |
||||
|
// <annotationProcessing enabled="false" useClasspath="true"/> |
||||
|
// 替换为: |
||||
|
// <annotationProcessing> |
||||
|
// <profile default="true" name="" enabled="true" /> |
||||
|
// </annotationProcessing> |
||||
|
withXml { |
||||
|
// 1. 移除根项目模块 |
||||
|
def node = it.asNode() |
||||
|
def projectModuleManagerNode =node.find{it.@name=='ProjectModuleManager'} |
||||
|
def rootImlNode =projectModuleManagerNode.modules.module.find{it.@fileurl=='file://$PROJECT_DIR$/' + project.name + '.iml'} |
||||
|
def rootImlParentNode =rootImlNode.parent() |
||||
|
rootImlParentNode.remove(rootImlNode) |
||||
|
|
||||
|
// 2. 替换 Encoding |
||||
|
def encodingNode =node.find{it.@name=='Encoding'} |
||||
|
encodingNode.@native2AsciiForPropertiesFiles="true" |
||||
|
|
||||
|
// 3. 使 idea 编译器支持注解(enable annotation processing) |
||||
|
def compilerConfigurationNode =node.find{it.@name=='CompilerConfiguration'} |
||||
|
def annotationProcessingNode =compilerConfigurationNode.annotationProcessing[0] |
||||
|
def annotationProcessingParentNode =annotationProcessingNode.parent() |
||||
|
annotationProcessingParentNode.remove(annotationProcessingNode) |
||||
|
annotationProcessingNode =annotationProcessingParentNode.appendNode("annotationProcessing") |
||||
|
annotationProcessingNode.appendNode("profile",[default:true,enabled:true]) |
||||
|
|
||||
|
// 4. 激活 SaveActions 插件, 修改文件后自动编译并发布, 在 .ipr 文件中生成以下 xml 片段 |
||||
|
// <component name="SaveActionSettings"> |
||||
|
// <option name="actions"> |
||||
|
// <set> |
||||
|
// <option value="activate" /> |
||||
|
// <option value="reload" /> |
||||
|
// </set> |
||||
|
// </option> |
||||
|
// <option name="configurationPath" value="" /> |
||||
|
// </component> |
||||
|
|
||||
|
// <component name="SaveActionSettings"> |
||||
|
def saveActionSettingsNode =node.find{it.@name=='SaveActionSettings'} |
||||
|
if(saveActionSettingsNode==null){ |
||||
|
saveActionSettingsNode =node.appendNode("component",[name:"SaveActionSettings"]) |
||||
|
} |
||||
|
|
||||
|
// <option name="actions"> |
||||
|
def actionsNode =saveActionSettingsNode.find{it.@name=='actions'} |
||||
|
if(actionsNode==null){ |
||||
|
actionsNode =saveActionSettingsNode.appendNode("option",[name:"actions"]) |
||||
|
} |
||||
|
|
||||
|
// <set> |
||||
|
def setNode =actionsNode.set[0] |
||||
|
|
||||
|
if(setNode==null){ |
||||
|
setNode =actionsNode.appendNode("set") |
||||
|
} |
||||
|
|
||||
|
// <option value="activate" /> |
||||
|
// <option value="reload" /> |
||||
|
def options =setNode.option |
||||
|
if(options!=null && options.size()>0){ |
||||
|
// 先移除 |
||||
|
for(int i=0;i<options.size();i++){ |
||||
|
setNode.remove(options.get(i)); |
||||
|
} |
||||
|
} |
||||
|
// 再添加 |
||||
|
setNode.appendNode("option",[value:"activate"]) |
||||
|
setNode.appendNode("option",[value:"reload"]) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/*----------------------------------------------------------------- |
||||
|
* 覆盖根项目的 clean 任务 |
||||
|
* 删除 idea 编译的 out 目录,实际上 out 目录并不在每个子模块中,而在根工程目录中 |
||||
|
* 但是 gradle 对根项目并没有提供 clean 任务, 在此单独为根项目提供 clean 任务 |
||||
|
*----------------------------------------------------------------*/ |
||||
|
task clean { |
||||
|
doFirst{ |
||||
|
delete 'out' |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/*----------------------------------------------------------------- |
||||
|
* 覆盖根工程的 cleanIdea 任务,由于默认 cleanIdea 任务只执行: |
||||
|
* cleanIdeaProject, cleanIdeaModule 两个任务, |
||||
|
* gradle 也单独提供了一个 cleanIdeaWorkspace 任务,用于删除 .iws 文件。 |
||||
|
* 为了方便, 我们将 cleanIdea 任务的默认行为改为同时执行 3 两个任务 |
||||
|
* cleanIdeaProject, cleanIdeaModule, cleanIdeaWorkspace |
||||
|
*----------------------------------------------------------------*/ |
||||
|
cleanIdea { |
||||
|
dependsOn cleanIdeaWorkspace |
||||
|
} |
||||
|
|
||||
|
task github { |
||||
|
println '' |
||||
|
} |
||||
|
|
||||
|
tasks.named('wrapper') { |
||||
|
distributionUrl = "http://nexus.sc.io:8000/repository/maven-releases/gradle/gradle/${gradleVersion}/gradle-${gradleVersion}.zip" |
||||
|
} |
@ -0,0 +1,8 @@ |
|||||
|
dependencies { |
||||
|
api( |
||||
|
project(":com.xuxueli.xxl-job-core"), |
||||
|
"org.springframework.boot:spring-boot-starter-mail", |
||||
|
"org.freemarker:freemarker", |
||||
|
"org.mybatis.spring.boot:mybatis-spring-boot-starter:2.3.0", |
||||
|
) |
||||
|
} |
@ -0,0 +1,16 @@ |
|||||
|
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); |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,96 @@ |
|||||
|
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)); |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,72 @@ |
|||||
|
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."); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,96 @@ |
|||||
|
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; |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,204 @@ |
|||||
|
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); |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,180 @@ |
|||||
|
package com.xxl.job.admin.controller; |
||||
|
|
||||
|
import com.xxl.job.admin.core.cron.CronExpression; |
||||
|
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.thread.JobTriggerPoolHelper; |
||||
|
import com.xxl.job.admin.core.trigger.TriggerTypeEnum; |
||||
|
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.text.ParseException; |
||||
|
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 |
||||
|
//@PermissionLimit(limit = false)
|
||||
|
public ReturnT<String> triggerJob(int id, String executorParam, String addressList) { |
||||
|
// force cover job param
|
||||
|
if (executorParam == null) { |
||||
|
executorParam = ""; |
||||
|
} |
||||
|
|
||||
|
JobTriggerPoolHelper.trigger(id, TriggerTypeEnum.MANUAL, -1, null, executorParam, addressList); |
||||
|
return ReturnT.SUCCESS; |
||||
|
} |
||||
|
|
||||
|
@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); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,237 @@ |
|||||
|
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.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.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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
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; |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,179 @@ |
|||||
|
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; |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,29 @@ |
|||||
|
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; |
||||
|
|
||||
|
} |
@ -0,0 +1,42 @@ |
|||||
|
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())); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,59 @@ |
|||||
|
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); |
||||
|
if (loginUser == null) { |
||||
|
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
|
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,28 @@ |
|||||
|
package com.xxl.job.admin.controller.interceptor; |
||||
|
|
||||
|
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("/**"); |
||||
|
registry.addInterceptor(cookieInterceptor).addPathPatterns("/**"); |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,66 @@ |
|||||
|
package com.xxl.job.admin.controller.resolver; |
||||
|
|
||||
|
import com.xxl.job.admin.core.exception.XxlJobException; |
||||
|
import com.xxl.job.core.biz.model.ReturnT; |
||||
|
import com.xxl.job.admin.core.util.JacksonUtil; |
||||
|
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; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,20 @@ |
|||||
|
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); |
||||
|
|
||||
|
} |
@ -0,0 +1,65 @@ |
|||||
|
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; |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,118 @@ |
|||||
|
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; |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,99 @@ |
|||||
|
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; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,158 @@ |
|||||
|
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
@ -0,0 +1,14 @@ |
|||||
|
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); |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,77 @@ |
|||||
|
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; |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,237 @@ |
|||||
|
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; |
||||
|
} |
||||
|
} |
@ -0,0 +1,157 @@ |
|||||
|
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; |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,75 @@ |
|||||
|
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; |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,54 @@ |
|||||
|
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; |
||||
|
} |
||||
|
} |
@ -0,0 +1,55 @@ |
|||||
|
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; |
||||
|
} |
||||
|
} |
@ -0,0 +1,73 @@ |
|||||
|
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; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,32 @@ |
|||||
|
//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());
|
||||
|
//
|
||||
|
//
|
||||
|
// }
|
||||
|
//
|
||||
|
//}
|
@ -0,0 +1,413 @@ |
|||||
|
//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;
|
||||
|
// }*/
|
||||
|
//
|
||||
|
//}
|
@ -0,0 +1,58 @@ |
|||||
|
//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) {
|
||||
|
// //
|
||||
|
// }
|
||||
|
//
|
||||
|
//}
|
@ -0,0 +1,48 @@ |
|||||
|
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; |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,24 @@ |
|||||
|
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); |
||||
|
|
||||
|
} |
@ -0,0 +1,48 @@ |
|||||
|
package com.xxl.job.admin.core.route.strategy; |
||||
|
|
||||
|
import com.xxl.job.admin.core.scheduler.XxlJobScheduler; |
||||
|
import com.xxl.job.admin.core.route.ExecutorRouter; |
||||
|
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()); |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,85 @@ |
|||||
|
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); |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,48 @@ |
|||||
|
package com.xxl.job.admin.core.route.strategy; |
||||
|
|
||||
|
import com.xxl.job.admin.core.scheduler.XxlJobScheduler; |
||||
|
import com.xxl.job.admin.core.route.ExecutorRouter; |
||||
|
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()); |
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,19 @@ |
|||||
|
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)); |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,79 @@ |
|||||
|
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); |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,76 @@ |
|||||
|
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); |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,19 @@ |
|||||
|
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)); |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,23 @@ |
|||||
|
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); |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,46 @@ |
|||||
|
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); |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,39 @@ |
|||||
|
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; |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,46 @@ |
|||||
|
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; |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,101 @@ |
|||||
|
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; |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,184 @@ |
|||||
|
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; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
} |
@ -0,0 +1,110 @@ |
|||||
|
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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,152 @@ |
|||||
|
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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,204 @@ |
|||||
|
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
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
@ -0,0 +1,369 @@ |
|||||
|
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; |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,150 @@ |
|||||
|
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); |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,27 @@ |
|||||
|
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; |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,226 @@ |
|||||
|
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; |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,98 @@ |
|||||
|
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 |
||||
|
*/ |
||||
|
private 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) { |
||||
|
Cookie cookie = get(request, key); |
||||
|
if (cookie != null) { |
||||
|
set(response, key, "", null, COOKIE_PATH, 0, true); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,31 @@ |
|||||
|
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; |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,79 @@ |
|||||
|
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; |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,92 @@ |
|||||
|
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; |
||||
|
} |
||||
|
} |
@ -0,0 +1,133 @@ |
|||||
|
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; |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,37 @@ |
|||||
|
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); |
||||
|
|
||||
|
} |
@ -0,0 +1,49 @@ |
|||||
|
package com.xxl.job.admin.dao; |
||||
|
|
||||
|
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 { |
||||
|
|
||||
|
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); |
||||
|
|
||||
|
|
||||
|
} |
@ -0,0 +1,62 @@ |
|||||
|
package com.xxl.job.admin.dao; |
||||
|
|
||||
|
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 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); |
||||
|
|
||||
|
} |
@ -0,0 +1,24 @@ |
|||||
|
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); |
||||
|
|
||||
|
} |
@ -0,0 +1,26 @@ |
|||||
|
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(); |
||||
|
|
||||
|
} |
@ -0,0 +1,38 @@ |
|||||
|
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); |
||||
|
|
||||
|
} |
@ -0,0 +1,31 @@ |
|||||
|
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); |
||||
|
|
||||
|
} |
@ -0,0 +1,107 @@ |
|||||
|
package com.xxl.job.admin.service; |
||||
|
|
||||
|
import com.xxl.job.admin.core.model.XxlJobUser; |
||||
|
import com.xxl.job.admin.core.util.CookieUtil; |
||||
|
import com.xxl.job.admin.core.util.I18nUtil; |
||||
|
import com.xxl.job.admin.core.util.JacksonUtil; |
||||
|
import com.xxl.job.admin.dao.XxlJobUserDao; |
||||
|
import com.xxl.job.core.biz.model.ReturnT; |
||||
|
import org.springframework.context.annotation.Configuration; |
||||
|
import org.springframework.util.DigestUtils; |
||||
|
|
||||
|
import javax.annotation.Resource; |
||||
|
import javax.servlet.http.HttpServletRequest; |
||||
|
import javax.servlet.http.HttpServletResponse; |
||||
|
import java.math.BigInteger; |
||||
|
|
||||
|
/** |
||||
|
* @author xuxueli 2019-05-04 22:13:264 |
||||
|
*/ |
||||
|
@Configuration |
||||
|
public class LoginService { |
||||
|
|
||||
|
public static final String LOGIN_IDENTITY_KEY = "XXL_JOB_LOGIN_IDENTITY"; |
||||
|
|
||||
|
@Resource |
||||
|
private XxlJobUserDao xxlJobUserDao; |
||||
|
|
||||
|
|
||||
|
private String makeToken(XxlJobUser xxlJobUser){ |
||||
|
String tokenJson = JacksonUtil.writeValueAsString(xxlJobUser); |
||||
|
String tokenHex = new BigInteger(tokenJson.getBytes()).toString(16); |
||||
|
return tokenHex; |
||||
|
} |
||||
|
private XxlJobUser parseToken(String tokenHex){ |
||||
|
XxlJobUser xxlJobUser = null; |
||||
|
if (tokenHex != null) { |
||||
|
String tokenJson = new String(new BigInteger(tokenHex, 16).toByteArray()); // username_password(md5)
|
||||
|
xxlJobUser = JacksonUtil.readValue(tokenJson, XxlJobUser.class); |
||||
|
} |
||||
|
return xxlJobUser; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
public ReturnT<String> login(HttpServletRequest request, HttpServletResponse response, String username, String password, boolean ifRemember){ |
||||
|
|
||||
|
// param
|
||||
|
if (username==null || username.trim().length()==0 || password==null || password.trim().length()==0){ |
||||
|
return new ReturnT<String>(500, I18nUtil.getString("login_param_empty")); |
||||
|
} |
||||
|
|
||||
|
// valid passowrd
|
||||
|
XxlJobUser xxlJobUser = xxlJobUserDao.loadByUserName(username); |
||||
|
if (xxlJobUser == null) { |
||||
|
return new ReturnT<String>(500, I18nUtil.getString("login_param_unvalid")); |
||||
|
} |
||||
|
String passwordMd5 = DigestUtils.md5DigestAsHex(password.getBytes()); |
||||
|
if (!passwordMd5.equals(xxlJobUser.getPassword())) { |
||||
|
return new ReturnT<String>(500, I18nUtil.getString("login_param_unvalid")); |
||||
|
} |
||||
|
|
||||
|
String loginToken = makeToken(xxlJobUser); |
||||
|
|
||||
|
// do login
|
||||
|
CookieUtil.set(response, LOGIN_IDENTITY_KEY, loginToken, ifRemember); |
||||
|
return ReturnT.SUCCESS; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* logout |
||||
|
* |
||||
|
* @param request |
||||
|
* @param response |
||||
|
*/ |
||||
|
public ReturnT<String> logout(HttpServletRequest request, HttpServletResponse response){ |
||||
|
CookieUtil.remove(request, response, LOGIN_IDENTITY_KEY); |
||||
|
return ReturnT.SUCCESS; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* logout |
||||
|
* |
||||
|
* @param request |
||||
|
* @return |
||||
|
*/ |
||||
|
public XxlJobUser ifLogin(HttpServletRequest request, HttpServletResponse response){ |
||||
|
String cookieToken = CookieUtil.getValue(request, LOGIN_IDENTITY_KEY); |
||||
|
if (cookieToken != null) { |
||||
|
XxlJobUser cookieUser = null; |
||||
|
try { |
||||
|
cookieUser = parseToken(cookieToken); |
||||
|
} catch (Exception e) { |
||||
|
logout(request, response); |
||||
|
} |
||||
|
if (cookieUser != null) { |
||||
|
XxlJobUser dbUser = xxlJobUserDao.loadByUserName(cookieUser.getUsername()); |
||||
|
if (dbUser != null) { |
||||
|
if (cookieUser.getPassword().equals(dbUser.getPassword())) { |
||||
|
return dbUser; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
@ -0,0 +1,86 @@ |
|||||
|
package com.xxl.job.admin.service; |
||||
|
|
||||
|
|
||||
|
import com.xxl.job.admin.core.model.XxlJobInfo; |
||||
|
import com.xxl.job.core.biz.model.ReturnT; |
||||
|
|
||||
|
import java.util.Date; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
/** |
||||
|
* core job action for xxl-job |
||||
|
* |
||||
|
* @author xuxueli 2016-5-28 15:30:33 |
||||
|
*/ |
||||
|
public interface XxlJobService { |
||||
|
|
||||
|
/** |
||||
|
* page list |
||||
|
* |
||||
|
* @param start |
||||
|
* @param length |
||||
|
* @param jobGroup |
||||
|
* @param jobDesc |
||||
|
* @param executorHandler |
||||
|
* @param author |
||||
|
* @return |
||||
|
*/ |
||||
|
public Map<String, Object> pageList(int start, int length, int jobGroup, int triggerStatus, String jobDesc, String executorHandler, String author); |
||||
|
|
||||
|
/** |
||||
|
* add job |
||||
|
* |
||||
|
* @param jobInfo |
||||
|
* @return |
||||
|
*/ |
||||
|
public ReturnT<String> add(XxlJobInfo jobInfo); |
||||
|
|
||||
|
/** |
||||
|
* update job |
||||
|
* |
||||
|
* @param jobInfo |
||||
|
* @return |
||||
|
*/ |
||||
|
public ReturnT<String> update(XxlJobInfo jobInfo); |
||||
|
|
||||
|
/** |
||||
|
* remove job |
||||
|
* * |
||||
|
* @param id |
||||
|
* @return |
||||
|
*/ |
||||
|
public ReturnT<String> remove(int id); |
||||
|
|
||||
|
/** |
||||
|
* start job |
||||
|
* |
||||
|
* @param id |
||||
|
* @return |
||||
|
*/ |
||||
|
public ReturnT<String> start(int id); |
||||
|
|
||||
|
/** |
||||
|
* stop job |
||||
|
* |
||||
|
* @param id |
||||
|
* @return |
||||
|
*/ |
||||
|
public ReturnT<String> stop(int id); |
||||
|
|
||||
|
/** |
||||
|
* dashboard info |
||||
|
* |
||||
|
* @return |
||||
|
*/ |
||||
|
public Map<String,Object> dashboardInfo(); |
||||
|
|
||||
|
/** |
||||
|
* chart info |
||||
|
* |
||||
|
* @param startDate |
||||
|
* @param endDate |
||||
|
* @return |
||||
|
*/ |
||||
|
public ReturnT<Map<String,Object>> chartInfo(Date startDate, Date endDate); |
||||
|
|
||||
|
} |
@ -0,0 +1,35 @@ |
|||||
|
package com.xxl.job.admin.service.impl; |
||||
|
|
||||
|
import com.xxl.job.admin.core.thread.JobCompleteHelper; |
||||
|
import com.xxl.job.admin.core.thread.JobRegistryHelper; |
||||
|
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 org.springframework.stereotype.Service; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
/** |
||||
|
* @author xuxueli 2017-07-27 21:54:20 |
||||
|
*/ |
||||
|
@Service |
||||
|
public class AdminBizImpl implements AdminBiz { |
||||
|
|
||||
|
|
||||
|
@Override |
||||
|
public ReturnT<String> callback(List<HandleCallbackParam> callbackParamList) { |
||||
|
return JobCompleteHelper.getInstance().callback(callbackParamList); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public ReturnT<String> registry(RegistryParam registryParam) { |
||||
|
return JobRegistryHelper.getInstance().registry(registryParam); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public ReturnT<String> registryRemove(RegistryParam registryParam) { |
||||
|
return JobRegistryHelper.getInstance().registryRemove(registryParam); |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,434 @@ |
|||||
|
package com.xxl.job.admin.service.impl; |
||||
|
|
||||
|
import com.xxl.job.admin.core.cron.CronExpression; |
||||
|
import com.xxl.job.admin.core.model.XxlJobGroup; |
||||
|
import com.xxl.job.admin.core.model.XxlJobInfo; |
||||
|
import com.xxl.job.admin.core.model.XxlJobLogReport; |
||||
|
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.*; |
||||
|
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.Service; |
||||
|
|
||||
|
import javax.annotation.Resource; |
||||
|
import java.text.MessageFormat; |
||||
|
import java.util.*; |
||||
|
|
||||
|
/** |
||||
|
* core job action for xxl-job |
||||
|
* @author xuxueli 2016-5-28 15:30:33 |
||||
|
*/ |
||||
|
@Service |
||||
|
public class XxlJobServiceImpl implements XxlJobService { |
||||
|
private static Logger logger = LoggerFactory.getLogger(XxlJobServiceImpl.class); |
||||
|
|
||||
|
@Resource |
||||
|
private XxlJobGroupDao xxlJobGroupDao; |
||||
|
@Resource |
||||
|
private XxlJobInfoDao xxlJobInfoDao; |
||||
|
@Resource |
||||
|
public XxlJobLogDao xxlJobLogDao; |
||||
|
@Resource |
||||
|
private XxlJobLogGlueDao xxlJobLogGlueDao; |
||||
|
@Resource |
||||
|
private XxlJobLogReportDao xxlJobLogReportDao; |
||||
|
|
||||
|
@Override |
||||
|
public Map<String, Object> pageList(int start, int length, int jobGroup, int triggerStatus, String jobDesc, String executorHandler, String author) { |
||||
|
|
||||
|
// page list
|
||||
|
List<XxlJobInfo> list = xxlJobInfoDao.pageList(start, length, jobGroup, triggerStatus, jobDesc, executorHandler, author); |
||||
|
int list_count = xxlJobInfoDao.pageListCount(start, length, jobGroup, triggerStatus, jobDesc, executorHandler, author); |
||||
|
|
||||
|
// 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; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public ReturnT<String> add(XxlJobInfo jobInfo) { |
||||
|
|
||||
|
// valid base
|
||||
|
XxlJobGroup group = xxlJobGroupDao.load(jobInfo.getJobGroup()); |
||||
|
if (group == null) { |
||||
|
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("system_please_choose")+I18nUtil.getString("jobinfo_field_jobgroup")) ); |
||||
|
} |
||||
|
if (jobInfo.getJobDesc()==null || jobInfo.getJobDesc().trim().length()==0) { |
||||
|
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("system_please_input")+I18nUtil.getString("jobinfo_field_jobdesc")) ); |
||||
|
} |
||||
|
if (jobInfo.getAuthor()==null || jobInfo.getAuthor().trim().length()==0) { |
||||
|
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("system_please_input")+I18nUtil.getString("jobinfo_field_author")) ); |
||||
|
} |
||||
|
|
||||
|
// valid trigger
|
||||
|
ScheduleTypeEnum scheduleTypeEnum = ScheduleTypeEnum.match(jobInfo.getScheduleType(), null); |
||||
|
if (scheduleTypeEnum == null) { |
||||
|
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type")+I18nUtil.getString("system_unvalid")) ); |
||||
|
} |
||||
|
if (scheduleTypeEnum == ScheduleTypeEnum.CRON) { |
||||
|
if (jobInfo.getScheduleConf()==null || !CronExpression.isValidExpression(jobInfo.getScheduleConf())) { |
||||
|
return new ReturnT<String>(ReturnT.FAIL_CODE, "Cron"+I18nUtil.getString("system_unvalid")); |
||||
|
} |
||||
|
} else if (scheduleTypeEnum == ScheduleTypeEnum.FIX_RATE/* || scheduleTypeEnum == ScheduleTypeEnum.FIX_DELAY*/) { |
||||
|
if (jobInfo.getScheduleConf() == null) { |
||||
|
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type")) ); |
||||
|
} |
||||
|
try { |
||||
|
int fixSecond = Integer.valueOf(jobInfo.getScheduleConf()); |
||||
|
if (fixSecond < 1) { |
||||
|
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type")+I18nUtil.getString("system_unvalid")) ); |
||||
|
} |
||||
|
} catch (Exception e) { |
||||
|
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type")+I18nUtil.getString("system_unvalid")) ); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// valid job
|
||||
|
if (GlueTypeEnum.match(jobInfo.getGlueType()) == null) { |
||||
|
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_gluetype")+I18nUtil.getString("system_unvalid")) ); |
||||
|
} |
||||
|
if (GlueTypeEnum.BEAN==GlueTypeEnum.match(jobInfo.getGlueType()) && (jobInfo.getExecutorHandler()==null || jobInfo.getExecutorHandler().trim().length()==0) ) { |
||||
|
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("system_please_input")+"JobHandler") ); |
||||
|
} |
||||
|
// 》fix "\r" in shell
|
||||
|
if (GlueTypeEnum.GLUE_SHELL==GlueTypeEnum.match(jobInfo.getGlueType()) && jobInfo.getGlueSource()!=null) { |
||||
|
jobInfo.setGlueSource(jobInfo.getGlueSource().replaceAll("\r", "")); |
||||
|
} |
||||
|
|
||||
|
// valid advanced
|
||||
|
if (ExecutorRouteStrategyEnum.match(jobInfo.getExecutorRouteStrategy(), null) == null) { |
||||
|
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_executorRouteStrategy")+I18nUtil.getString("system_unvalid")) ); |
||||
|
} |
||||
|
if (MisfireStrategyEnum.match(jobInfo.getMisfireStrategy(), null) == null) { |
||||
|
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("misfire_strategy")+I18nUtil.getString("system_unvalid")) ); |
||||
|
} |
||||
|
if (ExecutorBlockStrategyEnum.match(jobInfo.getExecutorBlockStrategy(), null) == null) { |
||||
|
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_executorBlockStrategy")+I18nUtil.getString("system_unvalid")) ); |
||||
|
} |
||||
|
|
||||
|
// 》ChildJobId valid
|
||||
|
if (jobInfo.getChildJobId()!=null && jobInfo.getChildJobId().trim().length()>0) { |
||||
|
String[] childJobIds = jobInfo.getChildJobId().split(","); |
||||
|
for (String childJobIdItem: childJobIds) { |
||||
|
if (childJobIdItem!=null && childJobIdItem.trim().length()>0 && isNumeric(childJobIdItem)) { |
||||
|
XxlJobInfo childJobInfo = xxlJobInfoDao.loadById(Integer.parseInt(childJobIdItem)); |
||||
|
if (childJobInfo==null) { |
||||
|
return new ReturnT<String>(ReturnT.FAIL_CODE, |
||||
|
MessageFormat.format((I18nUtil.getString("jobinfo_field_childJobId")+"({0})"+I18nUtil.getString("system_not_found")), childJobIdItem)); |
||||
|
} |
||||
|
} else { |
||||
|
return new ReturnT<String>(ReturnT.FAIL_CODE, |
||||
|
MessageFormat.format((I18nUtil.getString("jobinfo_field_childJobId")+"({0})"+I18nUtil.getString("system_unvalid")), childJobIdItem)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// join , avoid "xxx,,"
|
||||
|
String temp = ""; |
||||
|
for (String item:childJobIds) { |
||||
|
temp += item + ","; |
||||
|
} |
||||
|
temp = temp.substring(0, temp.length()-1); |
||||
|
|
||||
|
jobInfo.setChildJobId(temp); |
||||
|
} |
||||
|
|
||||
|
// add in db
|
||||
|
jobInfo.setAddTime(new Date()); |
||||
|
jobInfo.setUpdateTime(new Date()); |
||||
|
jobInfo.setGlueUpdatetime(new Date()); |
||||
|
xxlJobInfoDao.save(jobInfo); |
||||
|
if (jobInfo.getId() < 1) { |
||||
|
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_add")+I18nUtil.getString("system_fail")) ); |
||||
|
} |
||||
|
|
||||
|
return new ReturnT<String>(String.valueOf(jobInfo.getId())); |
||||
|
} |
||||
|
|
||||
|
private boolean isNumeric(String str){ |
||||
|
try { |
||||
|
int result = Integer.valueOf(str); |
||||
|
return true; |
||||
|
} catch (NumberFormatException e) { |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public ReturnT<String> update(XxlJobInfo jobInfo) { |
||||
|
|
||||
|
// valid base
|
||||
|
if (jobInfo.getJobDesc()==null || jobInfo.getJobDesc().trim().length()==0) { |
||||
|
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("system_please_input")+I18nUtil.getString("jobinfo_field_jobdesc")) ); |
||||
|
} |
||||
|
if (jobInfo.getAuthor()==null || jobInfo.getAuthor().trim().length()==0) { |
||||
|
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("system_please_input")+I18nUtil.getString("jobinfo_field_author")) ); |
||||
|
} |
||||
|
|
||||
|
// valid trigger
|
||||
|
ScheduleTypeEnum scheduleTypeEnum = ScheduleTypeEnum.match(jobInfo.getScheduleType(), null); |
||||
|
if (scheduleTypeEnum == null) { |
||||
|
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type")+I18nUtil.getString("system_unvalid")) ); |
||||
|
} |
||||
|
if (scheduleTypeEnum == ScheduleTypeEnum.CRON) { |
||||
|
if (jobInfo.getScheduleConf()==null || !CronExpression.isValidExpression(jobInfo.getScheduleConf())) { |
||||
|
return new ReturnT<String>(ReturnT.FAIL_CODE, "Cron"+I18nUtil.getString("system_unvalid") ); |
||||
|
} |
||||
|
} else if (scheduleTypeEnum == ScheduleTypeEnum.FIX_RATE /*|| scheduleTypeEnum == ScheduleTypeEnum.FIX_DELAY*/) { |
||||
|
if (jobInfo.getScheduleConf() == null) { |
||||
|
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type")+I18nUtil.getString("system_unvalid")) ); |
||||
|
} |
||||
|
try { |
||||
|
int fixSecond = Integer.valueOf(jobInfo.getScheduleConf()); |
||||
|
if (fixSecond < 1) { |
||||
|
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type")+I18nUtil.getString("system_unvalid")) ); |
||||
|
} |
||||
|
} catch (Exception e) { |
||||
|
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type")+I18nUtil.getString("system_unvalid")) ); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// valid advanced
|
||||
|
if (ExecutorRouteStrategyEnum.match(jobInfo.getExecutorRouteStrategy(), null) == null) { |
||||
|
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_executorRouteStrategy")+I18nUtil.getString("system_unvalid")) ); |
||||
|
} |
||||
|
if (MisfireStrategyEnum.match(jobInfo.getMisfireStrategy(), null) == null) { |
||||
|
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("misfire_strategy")+I18nUtil.getString("system_unvalid")) ); |
||||
|
} |
||||
|
if (ExecutorBlockStrategyEnum.match(jobInfo.getExecutorBlockStrategy(), null) == null) { |
||||
|
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_executorBlockStrategy")+I18nUtil.getString("system_unvalid")) ); |
||||
|
} |
||||
|
|
||||
|
// 》ChildJobId valid
|
||||
|
if (jobInfo.getChildJobId()!=null && jobInfo.getChildJobId().trim().length()>0) { |
||||
|
String[] childJobIds = jobInfo.getChildJobId().split(","); |
||||
|
for (String childJobIdItem: childJobIds) { |
||||
|
if (childJobIdItem!=null && childJobIdItem.trim().length()>0 && isNumeric(childJobIdItem)) { |
||||
|
XxlJobInfo childJobInfo = xxlJobInfoDao.loadById(Integer.parseInt(childJobIdItem)); |
||||
|
if (childJobInfo==null) { |
||||
|
return new ReturnT<String>(ReturnT.FAIL_CODE, |
||||
|
MessageFormat.format((I18nUtil.getString("jobinfo_field_childJobId")+"({0})"+I18nUtil.getString("system_not_found")), childJobIdItem)); |
||||
|
} |
||||
|
} else { |
||||
|
return new ReturnT<String>(ReturnT.FAIL_CODE, |
||||
|
MessageFormat.format((I18nUtil.getString("jobinfo_field_childJobId")+"({0})"+I18nUtil.getString("system_unvalid")), childJobIdItem)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// join , avoid "xxx,,"
|
||||
|
String temp = ""; |
||||
|
for (String item:childJobIds) { |
||||
|
temp += item + ","; |
||||
|
} |
||||
|
temp = temp.substring(0, temp.length()-1); |
||||
|
|
||||
|
jobInfo.setChildJobId(temp); |
||||
|
} |
||||
|
|
||||
|
// group valid
|
||||
|
XxlJobGroup jobGroup = xxlJobGroupDao.load(jobInfo.getJobGroup()); |
||||
|
if (jobGroup == null) { |
||||
|
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_jobgroup")+I18nUtil.getString("system_unvalid")) ); |
||||
|
} |
||||
|
|
||||
|
// stage job info
|
||||
|
XxlJobInfo exists_jobInfo = xxlJobInfoDao.loadById(jobInfo.getId()); |
||||
|
if (exists_jobInfo == null) { |
||||
|
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_id")+I18nUtil.getString("system_not_found")) ); |
||||
|
} |
||||
|
|
||||
|
// next trigger time (5s后生效,避开预读周期)
|
||||
|
long nextTriggerTime = exists_jobInfo.getTriggerNextTime(); |
||||
|
boolean scheduleDataNotChanged = jobInfo.getScheduleType().equals(exists_jobInfo.getScheduleType()) && jobInfo.getScheduleConf().equals(exists_jobInfo.getScheduleConf()); |
||||
|
if (exists_jobInfo.getTriggerStatus() == 1 && !scheduleDataNotChanged) { |
||||
|
try { |
||||
|
Date nextValidTime = JobScheduleHelper.generateNextValidTime(jobInfo, new Date(System.currentTimeMillis() + JobScheduleHelper.PRE_READ_MS)); |
||||
|
if (nextValidTime == null) { |
||||
|
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type")+I18nUtil.getString("system_unvalid")) ); |
||||
|
} |
||||
|
nextTriggerTime = nextValidTime.getTime(); |
||||
|
} catch (Exception e) { |
||||
|
logger.error(e.getMessage(), e); |
||||
|
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type")+I18nUtil.getString("system_unvalid")) ); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
exists_jobInfo.setJobGroup(jobInfo.getJobGroup()); |
||||
|
exists_jobInfo.setJobDesc(jobInfo.getJobDesc()); |
||||
|
exists_jobInfo.setAuthor(jobInfo.getAuthor()); |
||||
|
exists_jobInfo.setAlarmEmail(jobInfo.getAlarmEmail()); |
||||
|
exists_jobInfo.setScheduleType(jobInfo.getScheduleType()); |
||||
|
exists_jobInfo.setScheduleConf(jobInfo.getScheduleConf()); |
||||
|
exists_jobInfo.setMisfireStrategy(jobInfo.getMisfireStrategy()); |
||||
|
exists_jobInfo.setExecutorRouteStrategy(jobInfo.getExecutorRouteStrategy()); |
||||
|
exists_jobInfo.setExecutorHandler(jobInfo.getExecutorHandler()); |
||||
|
exists_jobInfo.setExecutorParam(jobInfo.getExecutorParam()); |
||||
|
exists_jobInfo.setExecutorBlockStrategy(jobInfo.getExecutorBlockStrategy()); |
||||
|
exists_jobInfo.setExecutorTimeout(jobInfo.getExecutorTimeout()); |
||||
|
exists_jobInfo.setExecutorFailRetryCount(jobInfo.getExecutorFailRetryCount()); |
||||
|
exists_jobInfo.setChildJobId(jobInfo.getChildJobId()); |
||||
|
exists_jobInfo.setTriggerNextTime(nextTriggerTime); |
||||
|
|
||||
|
exists_jobInfo.setUpdateTime(new Date()); |
||||
|
xxlJobInfoDao.update(exists_jobInfo); |
||||
|
|
||||
|
|
||||
|
return ReturnT.SUCCESS; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public ReturnT<String> remove(int id) { |
||||
|
XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(id); |
||||
|
if (xxlJobInfo == null) { |
||||
|
return ReturnT.SUCCESS; |
||||
|
} |
||||
|
|
||||
|
xxlJobInfoDao.delete(id); |
||||
|
xxlJobLogDao.delete(id); |
||||
|
xxlJobLogGlueDao.deleteByJobId(id); |
||||
|
return ReturnT.SUCCESS; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public ReturnT<String> start(int id) { |
||||
|
XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(id); |
||||
|
|
||||
|
// valid
|
||||
|
ScheduleTypeEnum scheduleTypeEnum = ScheduleTypeEnum.match(xxlJobInfo.getScheduleType(), ScheduleTypeEnum.NONE); |
||||
|
if (ScheduleTypeEnum.NONE == scheduleTypeEnum) { |
||||
|
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type_none_limit_start")) ); |
||||
|
} |
||||
|
|
||||
|
// next trigger time (5s后生效,避开预读周期)
|
||||
|
long nextTriggerTime = 0; |
||||
|
try { |
||||
|
Date nextValidTime = JobScheduleHelper.generateNextValidTime(xxlJobInfo, new Date(System.currentTimeMillis() + JobScheduleHelper.PRE_READ_MS)); |
||||
|
if (nextValidTime == null) { |
||||
|
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type")+I18nUtil.getString("system_unvalid")) ); |
||||
|
} |
||||
|
nextTriggerTime = nextValidTime.getTime(); |
||||
|
} catch (Exception e) { |
||||
|
logger.error(e.getMessage(), e); |
||||
|
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type")+I18nUtil.getString("system_unvalid")) ); |
||||
|
} |
||||
|
|
||||
|
xxlJobInfo.setTriggerStatus(1); |
||||
|
xxlJobInfo.setTriggerLastTime(0); |
||||
|
xxlJobInfo.setTriggerNextTime(nextTriggerTime); |
||||
|
|
||||
|
xxlJobInfo.setUpdateTime(new Date()); |
||||
|
xxlJobInfoDao.update(xxlJobInfo); |
||||
|
return ReturnT.SUCCESS; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public ReturnT<String> stop(int id) { |
||||
|
XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(id); |
||||
|
|
||||
|
xxlJobInfo.setTriggerStatus(0); |
||||
|
xxlJobInfo.setTriggerLastTime(0); |
||||
|
xxlJobInfo.setTriggerNextTime(0); |
||||
|
|
||||
|
xxlJobInfo.setUpdateTime(new Date()); |
||||
|
xxlJobInfoDao.update(xxlJobInfo); |
||||
|
return ReturnT.SUCCESS; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public Map<String, Object> dashboardInfo() { |
||||
|
|
||||
|
int jobInfoCount = xxlJobInfoDao.findAllCount(); |
||||
|
int jobLogCount = 0; |
||||
|
int jobLogSuccessCount = 0; |
||||
|
XxlJobLogReport xxlJobLogReport = xxlJobLogReportDao.queryLogReportTotal(); |
||||
|
if (xxlJobLogReport != null) { |
||||
|
jobLogCount = xxlJobLogReport.getRunningCount() + xxlJobLogReport.getSucCount() + xxlJobLogReport.getFailCount(); |
||||
|
jobLogSuccessCount = xxlJobLogReport.getSucCount(); |
||||
|
} |
||||
|
|
||||
|
// executor count
|
||||
|
Set<String> executorAddressSet = new HashSet<String>(); |
||||
|
List<XxlJobGroup> groupList = xxlJobGroupDao.findAll(); |
||||
|
|
||||
|
if (groupList!=null && !groupList.isEmpty()) { |
||||
|
for (XxlJobGroup group: groupList) { |
||||
|
if (group.getRegistryList()!=null && !group.getRegistryList().isEmpty()) { |
||||
|
executorAddressSet.addAll(group.getRegistryList()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
int executorCount = executorAddressSet.size(); |
||||
|
|
||||
|
Map<String, Object> dashboardMap = new HashMap<String, Object>(); |
||||
|
dashboardMap.put("jobInfoCount", jobInfoCount); |
||||
|
dashboardMap.put("jobLogCount", jobLogCount); |
||||
|
dashboardMap.put("jobLogSuccessCount", jobLogSuccessCount); |
||||
|
dashboardMap.put("executorCount", executorCount); |
||||
|
return dashboardMap; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public ReturnT<Map<String, Object>> chartInfo(Date startDate, Date endDate) { |
||||
|
|
||||
|
// process
|
||||
|
List<String> triggerDayList = new ArrayList<String>(); |
||||
|
List<Integer> triggerDayCountRunningList = new ArrayList<Integer>(); |
||||
|
List<Integer> triggerDayCountSucList = new ArrayList<Integer>(); |
||||
|
List<Integer> triggerDayCountFailList = new ArrayList<Integer>(); |
||||
|
int triggerCountRunningTotal = 0; |
||||
|
int triggerCountSucTotal = 0; |
||||
|
int triggerCountFailTotal = 0; |
||||
|
|
||||
|
List<XxlJobLogReport> logReportList = xxlJobLogReportDao.queryLogReport(startDate, endDate); |
||||
|
|
||||
|
if (logReportList!=null && logReportList.size()>0) { |
||||
|
for (XxlJobLogReport item: logReportList) { |
||||
|
String day = DateUtil.formatDate(item.getTriggerDay()); |
||||
|
int triggerDayCountRunning = item.getRunningCount(); |
||||
|
int triggerDayCountSuc = item.getSucCount(); |
||||
|
int triggerDayCountFail = item.getFailCount(); |
||||
|
|
||||
|
triggerDayList.add(day); |
||||
|
triggerDayCountRunningList.add(triggerDayCountRunning); |
||||
|
triggerDayCountSucList.add(triggerDayCountSuc); |
||||
|
triggerDayCountFailList.add(triggerDayCountFail); |
||||
|
|
||||
|
triggerCountRunningTotal += triggerDayCountRunning; |
||||
|
triggerCountSucTotal += triggerDayCountSuc; |
||||
|
triggerCountFailTotal += triggerDayCountFail; |
||||
|
} |
||||
|
} else { |
||||
|
for (int i = -6; i <= 0; i++) { |
||||
|
triggerDayList.add(DateUtil.formatDate(DateUtil.addDays(new Date(), i))); |
||||
|
triggerDayCountRunningList.add(0); |
||||
|
triggerDayCountSucList.add(0); |
||||
|
triggerDayCountFailList.add(0); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
Map<String, Object> result = new HashMap<String, Object>(); |
||||
|
result.put("triggerDayList", triggerDayList); |
||||
|
result.put("triggerDayCountRunningList", triggerDayCountRunningList); |
||||
|
result.put("triggerDayCountSucList", triggerDayCountSucList); |
||||
|
result.put("triggerDayCountFailList", triggerDayCountFailList); |
||||
|
|
||||
|
result.put("triggerCountRunningTotal", triggerCountRunningTotal); |
||||
|
result.put("triggerCountSucTotal", triggerCountSucTotal); |
||||
|
result.put("triggerCountFailTotal", triggerCountFailTotal); |
||||
|
|
||||
|
return new ReturnT<Map<String, Object>>(result); |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,65 @@ |
|||||
|
### web |
||||
|
server.port=8080 |
||||
|
server.servlet.context-path=/xxl-job-admin |
||||
|
|
||||
|
### actuator |
||||
|
management.server.servlet.context-path=/actuator |
||||
|
management.health.mail.enabled=false |
||||
|
|
||||
|
### resources |
||||
|
spring.mvc.servlet.load-on-startup=0 |
||||
|
spring.mvc.static-path-pattern=/static/** |
||||
|
spring.resources.static-locations=classpath:/static/ |
||||
|
|
||||
|
### freemarker |
||||
|
spring.freemarker.templateLoaderPath=classpath:/templates/ |
||||
|
spring.freemarker.suffix=.ftl |
||||
|
spring.freemarker.charset=UTF-8 |
||||
|
spring.freemarker.request-context-attribute=request |
||||
|
spring.freemarker.settings.number_format=0.########## |
||||
|
|
||||
|
### mybatis |
||||
|
mybatis.mapper-locations=classpath:/mybatis-mapper/*Mapper.xml |
||||
|
#mybatis.type-aliases-package=com.xxl.job.admin.core.model |
||||
|
|
||||
|
### xxl-job, datasource |
||||
|
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/xxl_job?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai |
||||
|
spring.datasource.username=root |
||||
|
spring.datasource.password=root_pwd |
||||
|
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver |
||||
|
|
||||
|
### datasource-pool |
||||
|
spring.datasource.type=com.zaxxer.hikari.HikariDataSource |
||||
|
spring.datasource.hikari.minimum-idle=10 |
||||
|
spring.datasource.hikari.maximum-pool-size=30 |
||||
|
spring.datasource.hikari.auto-commit=true |
||||
|
spring.datasource.hikari.idle-timeout=30000 |
||||
|
spring.datasource.hikari.pool-name=HikariCP |
||||
|
spring.datasource.hikari.max-lifetime=900000 |
||||
|
spring.datasource.hikari.connection-timeout=10000 |
||||
|
spring.datasource.hikari.connection-test-query=SELECT 1 |
||||
|
spring.datasource.hikari.validation-timeout=1000 |
||||
|
|
||||
|
### xxl-job, email |
||||
|
spring.mail.host=smtp.qq.com |
||||
|
spring.mail.port=25 |
||||
|
spring.mail.username=xxx@qq.com |
||||
|
spring.mail.from=xxx@qq.com |
||||
|
spring.mail.password=xxx |
||||
|
spring.mail.properties.mail.smtp.auth=true |
||||
|
spring.mail.properties.mail.smtp.starttls.enable=true |
||||
|
spring.mail.properties.mail.smtp.starttls.required=true |
||||
|
spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory |
||||
|
|
||||
|
### xxl-job, access token |
||||
|
xxl.job.accessToken=default_token |
||||
|
|
||||
|
### xxl-job, i18n (default is zh_CN, and you can choose "zh_CN", "zh_TC" and "en") |
||||
|
xxl.job.i18n=zh_CN |
||||
|
|
||||
|
## xxl-job, triggerpool max size |
||||
|
xxl.job.triggerpool.fast.max=200 |
||||
|
xxl.job.triggerpool.slow.max=100 |
||||
|
|
||||
|
### xxl-job, log retention days |
||||
|
xxl.job.logretentiondays=30 |
@ -0,0 +1,276 @@ |
|||||
|
admin_name=Scheduling Center |
||||
|
admin_name_full=Distributed Task Scheduling Platform XXL-JOB |
||||
|
admin_version=2.4.1-SNAPSHOT |
||||
|
admin_i18n=en |
||||
|
|
||||
|
## system |
||||
|
system_tips=System message |
||||
|
system_ok=Confirm |
||||
|
system_close=Close |
||||
|
system_save=Save |
||||
|
system_cancel=Cancel |
||||
|
system_search=Search |
||||
|
system_status=Status |
||||
|
system_opt=Operate |
||||
|
system_please_input=please input |
||||
|
system_please_choose=please choose |
||||
|
system_success=success |
||||
|
system_fail=fail |
||||
|
system_add_suc=add success |
||||
|
system_add_fail=add fail |
||||
|
system_update_suc=update success |
||||
|
system_update_fail=update fail |
||||
|
system_all=All |
||||
|
system_api_error=net error |
||||
|
system_show=Show |
||||
|
system_empty=Empty |
||||
|
system_opt_suc=operate success |
||||
|
system_opt_fail=operate fail |
||||
|
system_opt_edit=Edit |
||||
|
system_opt_del=Delete |
||||
|
system_opt_copy=Copy |
||||
|
system_unvalid=illegal |
||||
|
system_not_found=not exist |
||||
|
system_nav=Navigation |
||||
|
system_digits=digits |
||||
|
system_lengh_limit=Length limit |
||||
|
system_permission_limit=Permission limit |
||||
|
system_welcome=Welcome |
||||
|
|
||||
|
## daterangepicker |
||||
|
daterangepicker_ranges_recent_hour=recent one hour |
||||
|
daterangepicker_ranges_today=today |
||||
|
daterangepicker_ranges_yesterday=yesterday |
||||
|
daterangepicker_ranges_this_month=this month |
||||
|
daterangepicker_ranges_last_month=last month |
||||
|
daterangepicker_ranges_recent_week=recent one week |
||||
|
daterangepicker_ranges_recent_month=recent one month |
||||
|
daterangepicker_custom_name=custom |
||||
|
daterangepicker_custom_starttime=start time |
||||
|
daterangepicker_custom_endtime=end time |
||||
|
daterangepicker_custom_daysofweek=Sun,Mon,Tue,Wed,Thu,Fri,Sat |
||||
|
daterangepicker_custom_monthnames=Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec |
||||
|
|
||||
|
## dataTable |
||||
|
dataTable_sProcessing=processing... |
||||
|
dataTable_sLengthMenu= _MENU_ records per page |
||||
|
dataTable_sZeroRecords=No matching results |
||||
|
dataTable_sInfo=page _PAGE_ ( Total _PAGES_ pages,_TOTAL_ records ) |
||||
|
dataTable_sInfoEmpty=No Record |
||||
|
dataTable_sInfoFiltered=(Filtered by _MAX_ results) |
||||
|
dataTable_sSearch=Search |
||||
|
dataTable_sEmptyTable=Table data is empty |
||||
|
dataTable_sLoadingRecords=Loading... |
||||
|
dataTable_sFirst=FIRST PAGE |
||||
|
dataTable_sPrevious=Previous Page |
||||
|
dataTable_sNext=Next Page |
||||
|
dataTable_sLast=LAST PAGE |
||||
|
dataTable_sSortAscending=: Rank this column in ascending order |
||||
|
dataTable_sSortDescending=: Rank this column in descending order |
||||
|
|
||||
|
## login |
||||
|
login_btn=Login |
||||
|
login_remember_me=Remember Me |
||||
|
login_username_placeholder=Please enter username |
||||
|
login_password_placeholder=Please enter password |
||||
|
login_username_empty=Please enter username |
||||
|
login_username_lt_4=Username length should not be less than 4 |
||||
|
login_password_empty=Please enter password |
||||
|
login_password_lt_4=Password length should not be less than 4 |
||||
|
login_success=Login success |
||||
|
login_fail=Login fail |
||||
|
login_param_empty=Username or password is empty |
||||
|
login_param_unvalid=Username or password error |
||||
|
|
||||
|
## logout |
||||
|
logout_btn=Logout |
||||
|
logout_confirm=Confirm logout? |
||||
|
logout_success=Logout success |
||||
|
logout_fail=Logout fail |
||||
|
|
||||
|
## change pwd |
||||
|
change_pwd=Change password |
||||
|
change_pwd_suc_to_logout=Change password successful, about to log out login |
||||
|
change_pwd_field_newpwd=new password |
||||
|
|
||||
|
## dashboard |
||||
|
job_dashboard_name=Run report |
||||
|
job_dashboard_job_num=Job number |
||||
|
job_dashboard_job_num_tip=The number of tasks running in the scheduling center |
||||
|
job_dashboard_trigger_num=trigger number |
||||
|
job_dashboard_trigger_num_tip=The number of trigger record scheduled by the scheduling center |
||||
|
job_dashboard_jobgroup_num=Executor number |
||||
|
job_dashboard_jobgroup_num_tip=The number of online executor machines perceived by the scheduling center |
||||
|
job_dashboard_report=Scheduling report |
||||
|
job_dashboard_report_loaddata_fail=Scheduling report load data error |
||||
|
job_dashboard_date_report=Date distribution |
||||
|
job_dashboard_rate_report=Percentage distribution |
||||
|
|
||||
|
## job info |
||||
|
jobinfo_name=Job Manage |
||||
|
jobinfo_job=Job |
||||
|
jobinfo_field_add=Add Job |
||||
|
jobinfo_field_update=Edit Job |
||||
|
jobinfo_field_id=Job ID |
||||
|
jobinfo_field_jobgroup=Executor |
||||
|
jobinfo_field_jobdesc=Job description |
||||
|
jobinfo_field_timeout=Job timeout period |
||||
|
jobinfo_field_gluetype=GLUE Type |
||||
|
jobinfo_field_executorparam=Param |
||||
|
jobinfo_field_author=Author |
||||
|
jobinfo_field_alarmemail=Alarm email |
||||
|
jobinfo_field_alarmemail_placeholder=Please enter alarm mail, if there are more than one comma separated |
||||
|
jobinfo_field_executorRouteStrategy=Route Strategy |
||||
|
jobinfo_field_childJobId=Child Job ID |
||||
|
jobinfo_field_childJobId_placeholder=Please enter the Child job ID, if there are more than one comma separated |
||||
|
jobinfo_field_executorBlockStrategy=Block Strategy |
||||
|
jobinfo_field_executorFailRetryCount=Fail Retry Count |
||||
|
jobinfo_field_executorFailRetryCount_placeholder=Fail Retry Count. effect if greater than zero |
||||
|
jobinfo_script_location=Script location |
||||
|
jobinfo_shard_index=Shard index |
||||
|
jobinfo_shard_total=Shard total |
||||
|
jobinfo_opt_stop=Stop |
||||
|
jobinfo_opt_start=Start |
||||
|
jobinfo_opt_log=Query Log |
||||
|
jobinfo_opt_run=Run Once |
||||
|
jobinfo_opt_run_tips=Please input the address for this trigger. Null will be obtained from the executor |
||||
|
jobinfo_opt_registryinfo=Registry Info |
||||
|
jobinfo_opt_next_time=Next trigger time |
||||
|
jobinfo_glue_remark=Resource Remark |
||||
|
jobinfo_glue_remark_limit=Resource Remark length is limited to 4~100 |
||||
|
jobinfo_glue_rollback=Version Backtrack |
||||
|
jobinfo_glue_jobid_unvalid=Job ID is illegal |
||||
|
jobinfo_glue_gluetype_unvalid=The job is not GLUE Type |
||||
|
jobinfo_field_executorTimeout_placeholder=Job Timeout period,in seconds. effect if greater than zero |
||||
|
schedule_type=Schedule Type |
||||
|
schedule_type_none=None |
||||
|
schedule_type_cron=Cron |
||||
|
schedule_type_fix_rate=Fix rate |
||||
|
schedule_type_fix_delay=Fix delay |
||||
|
schedule_type_none_limit_start=The current schedule type disables startup |
||||
|
misfire_strategy=Misfire strategy |
||||
|
misfire_strategy_do_nothing=Do nothing |
||||
|
misfire_strategy_fire_once_now=Fire once now |
||||
|
jobinfo_conf_base=Base configuration |
||||
|
jobinfo_conf_schedule=Schedule configuration |
||||
|
jobinfo_conf_job=Job configuration |
||||
|
jobinfo_conf_advanced=Advanced configuration |
||||
|
|
||||
|
## job log |
||||
|
joblog_name=Trigger Log |
||||
|
joblog_status=Status |
||||
|
joblog_status_all=All |
||||
|
joblog_status_suc=Success |
||||
|
joblog_status_fail=Fail |
||||
|
joblog_status_running=Running |
||||
|
joblog_field_triggerTime=Trigger Time |
||||
|
joblog_field_triggerCode=Trigger Result |
||||
|
joblog_field_triggerMsg=Trigger Msg |
||||
|
joblog_field_handleTime=Handle Time |
||||
|
joblog_field_handleCode=Handle Result |
||||
|
joblog_field_handleMsg=Trigger Msg |
||||
|
joblog_field_executorAddress=Executor Address |
||||
|
joblog_clean=Clean |
||||
|
joblog_clean_log=Clean Log |
||||
|
joblog_clean_type=Clean Type |
||||
|
joblog_clean_type_1=Clean up log data a month ago |
||||
|
joblog_clean_type_2=Clean up log data three month ago |
||||
|
joblog_clean_type_3=Clean up log data six month ago |
||||
|
joblog_clean_type_4=Clean up log data a year ago |
||||
|
joblog_clean_type_5=Clean up log data a thousand record ago |
||||
|
joblog_clean_type_6=Clean up log data ten thousand record ago |
||||
|
joblog_clean_type_7=Clean up log data thirty thousand record ago |
||||
|
joblog_clean_type_8=Clean up log data hundred thousand record ago |
||||
|
joblog_clean_type_9=Clean up all log data |
||||
|
joblog_clean_type_unvalid=Clean type is illegal |
||||
|
joblog_handleCode_200=Success |
||||
|
joblog_handleCode_500=Fail |
||||
|
joblog_handleCode_502=Timeout |
||||
|
joblog_kill_log=Kill Job |
||||
|
joblog_kill_log_limit=Trigger Fail, can not kill job |
||||
|
joblog_kill_log_byman=Manual operation, kill job |
||||
|
joblog_lost_fail=Job result lost, marked as failure |
||||
|
joblog_rolling_log=Rolling log |
||||
|
joblog_rolling_log_refresh=Refresh |
||||
|
joblog_rolling_log_triggerfail=The job trigger fail, can not view the rolling log |
||||
|
joblog_rolling_log_failoften=The request for the Rolling log is terminated, the number of failed requests exceeds the limit, Reload the log on the refresh page |
||||
|
joblog_logid_unvalid=Log ID is illegal |
||||
|
|
||||
|
## job group |
||||
|
jobgroup_name=Executor Manage |
||||
|
jobgroup_list=Executor List |
||||
|
jobgroup_add=Add Executor |
||||
|
jobgroup_edit=Edit Executor |
||||
|
jobgroup_del=Delete Executor |
||||
|
jobgroup_field_title=Title |
||||
|
jobgroup_field_addressType=Registry Type |
||||
|
jobgroup_field_addressType_0=Automatic registration |
||||
|
jobgroup_field_addressType_1=Manual registration |
||||
|
jobgroup_field_addressType_limit=Manually registration type, the machine address must not be empty |
||||
|
jobgroup_field_registryList=machine address |
||||
|
jobgroup_field_registryList_unvalid=registry machine address is illegal |
||||
|
jobgroup_field_registryList_placeholder=Please enter the machine address, if there are more than one comma separated |
||||
|
jobgroup_field_appname_limit=Limit the beginning of a lowercase letter, consists of lowercase letters、number and hyphen. |
||||
|
jobgroup_field_appname_length=AppName length is limited to 4~64 |
||||
|
jobgroup_field_title_length=Title length is limited to 4~12 |
||||
|
jobgroup_field_order_digits=Please enter a positive integer |
||||
|
jobgroup_field_orderrange=Order is limited to 1~1000 |
||||
|
jobgroup_del_limit_0=Refuse to delete, the executor is being used |
||||
|
jobgroup_del_limit_1=Refuses to delete, the system retains at least one executor |
||||
|
jobgroup_empty=There is no valid executor. Please contact the administrator |
||||
|
|
||||
|
## job conf |
||||
|
jobconf_block_SERIAL_EXECUTION=Serial execution |
||||
|
jobconf_block_DISCARD_LATER=Discard Later |
||||
|
jobconf_block_COVER_EARLY=Cover Early |
||||
|
jobconf_route_first=First |
||||
|
jobconf_route_last=Last |
||||
|
jobconf_route_round=Round |
||||
|
jobconf_route_random=Random |
||||
|
jobconf_route_consistenthash=Consistent Hash |
||||
|
jobconf_route_lfu=Least Frequently Used |
||||
|
jobconf_route_lru=Least Recently Used |
||||
|
jobconf_route_failover=Failover |
||||
|
jobconf_route_busyover=Busyover |
||||
|
jobconf_route_shard=Sharding Broadcast |
||||
|
jobconf_idleBeat=Idle check |
||||
|
jobconf_beat=Heartbeats |
||||
|
jobconf_monitor=Task Scheduling Center monitor alarm |
||||
|
jobconf_monitor_detail=monitor alarm details |
||||
|
jobconf_monitor_alarm_title=Alarm Type |
||||
|
jobconf_monitor_alarm_type=Trigger Fail |
||||
|
jobconf_monitor_alarm_content=Alarm Content |
||||
|
jobconf_trigger_admin_adress=Trigger machine address |
||||
|
jobconf_trigger_exe_regtype=Execotor-Registry Type |
||||
|
jobconf_trigger_exe_regaddress=Execotor-Registry Address |
||||
|
jobconf_trigger_address_empty=Trigger Fail:registry address is empty |
||||
|
jobconf_trigger_run=Trigger Job |
||||
|
jobconf_trigger_child_run=Trigger child job |
||||
|
jobconf_callback_child_msg1={0}/{1} [Job ID={2}], Trigger {3}, Trigger msg: {4} <br> |
||||
|
jobconf_callback_child_msg2={0}/{1} [Job ID={2}], Trigger Fail, Trigger msg: Job ID is illegal <br> |
||||
|
jobconf_trigger_type=Job trigger type |
||||
|
jobconf_trigger_type_cron=Cron trigger |
||||
|
jobconf_trigger_type_manual=Manual trigger |
||||
|
jobconf_trigger_type_parent=Parent job trigger |
||||
|
jobconf_trigger_type_api=Api trigger |
||||
|
jobconf_trigger_type_retry=Fail retry trigger |
||||
|
jobconf_trigger_type_misfire=Misfire compensation trigger |
||||
|
|
||||
|
## user |
||||
|
user_manage=User Manage |
||||
|
user_username=Username |
||||
|
user_password=Password |
||||
|
user_role=Role |
||||
|
user_role_admin=Admin User |
||||
|
user_role_normal=Normal User |
||||
|
user_permission=Permission |
||||
|
user_add=Add User |
||||
|
user_update=Edit User |
||||
|
user_username_repeat=Username Repeat |
||||
|
user_username_valid=Restrictions start with a lowercase letter and consist of lowercase letters and Numbers |
||||
|
user_password_update_placeholder=Please input password, empty means not update |
||||
|
user_update_loginuser_limit=Operation of current login account is not allowed |
||||
|
|
||||
|
## help |
||||
|
job_help=Tutorial |
||||
|
job_help_document=Official Document |
@ -0,0 +1,276 @@ |
|||||
|
admin_name=任务调度中心 |
||||
|
admin_name_full=分布式任务调度平台XXL-JOB |
||||
|
admin_version=2.4.1-SNAPSHOT |
||||
|
admin_i18n= |
||||
|
|
||||
|
## system |
||||
|
system_tips=系统提示 |
||||
|
system_ok=确定 |
||||
|
system_close=关闭 |
||||
|
system_save=保存 |
||||
|
system_cancel=取消 |
||||
|
system_search=搜索 |
||||
|
system_status=状态 |
||||
|
system_opt=操作 |
||||
|
system_please_input=请输入 |
||||
|
system_please_choose=请选择 |
||||
|
system_success=成功 |
||||
|
system_fail=失败 |
||||
|
system_add_suc=新增成功 |
||||
|
system_add_fail=新增失败 |
||||
|
system_update_suc=更新成功 |
||||
|
system_update_fail=更新失败 |
||||
|
system_all=全部 |
||||
|
system_api_error=接口异常 |
||||
|
system_show=查看 |
||||
|
system_empty=无 |
||||
|
system_opt_suc=操作成功 |
||||
|
system_opt_fail=操作失败 |
||||
|
system_opt_edit=编辑 |
||||
|
system_opt_del=删除 |
||||
|
system_opt_copy=复制 |
||||
|
system_unvalid=非法 |
||||
|
system_not_found=不存在 |
||||
|
system_nav=导航 |
||||
|
system_digits=整数 |
||||
|
system_lengh_limit=长度限制 |
||||
|
system_permission_limit=权限拦截 |
||||
|
system_welcome=欢迎 |
||||
|
|
||||
|
## daterangepicker |
||||
|
daterangepicker_ranges_recent_hour=最近一小时 |
||||
|
daterangepicker_ranges_today=今日 |
||||
|
daterangepicker_ranges_yesterday=昨日 |
||||
|
daterangepicker_ranges_this_month=本月 |
||||
|
daterangepicker_ranges_last_month=上个月 |
||||
|
daterangepicker_ranges_recent_week=最近一周 |
||||
|
daterangepicker_ranges_recent_month=最近一月 |
||||
|
daterangepicker_custom_name=自定义 |
||||
|
daterangepicker_custom_starttime=起始时间 |
||||
|
daterangepicker_custom_endtime=结束时间 |
||||
|
daterangepicker_custom_daysofweek=日,一,二,三,四,五,六 |
||||
|
daterangepicker_custom_monthnames=一月,二月,三月,四月,五月,六月,七月,八月,九月,十月,十一月,十二月 |
||||
|
|
||||
|
## dataTable |
||||
|
dataTable_sProcessing=处理中... |
||||
|
dataTable_sLengthMenu=每页 _MENU_ 条记录 |
||||
|
dataTable_sZeroRecords=没有匹配结果 |
||||
|
dataTable_sInfo=第 _PAGE_ 页 ( 总共 _PAGES_ 页,_TOTAL_ 条记录 ) |
||||
|
dataTable_sInfoEmpty=无记录 |
||||
|
dataTable_sInfoFiltered=(由 _MAX_ 项结果过滤) |
||||
|
dataTable_sSearch=搜索 |
||||
|
dataTable_sEmptyTable=表中数据为空 |
||||
|
dataTable_sLoadingRecords=载入中... |
||||
|
dataTable_sFirst=首页 |
||||
|
dataTable_sPrevious=上页 |
||||
|
dataTable_sNext=下页 |
||||
|
dataTable_sLast=末页 |
||||
|
dataTable_sSortAscending=: 以升序排列此列 |
||||
|
dataTable_sSortDescending=: 以降序排列此列 |
||||
|
|
||||
|
## login |
||||
|
login_btn=登录 |
||||
|
login_remember_me=记住密码 |
||||
|
login_username_placeholder=请输入登录账号 |
||||
|
login_password_placeholder=请输入登录密码 |
||||
|
login_username_empty=请输入登录账号 |
||||
|
login_username_lt_4=登录账号不应低于4位 |
||||
|
login_password_empty=请输入登录密码 |
||||
|
login_password_lt_4=登录密码不应低于4位 |
||||
|
login_success=登录成功 |
||||
|
login_fail=登录失败 |
||||
|
login_param_empty=账号或密码为空 |
||||
|
login_param_unvalid=账号或密码错误 |
||||
|
|
||||
|
## logout |
||||
|
logout_btn=注销 |
||||
|
logout_confirm=确认注销登录? |
||||
|
logout_success=注销成功 |
||||
|
logout_fail=注销失败 |
||||
|
|
||||
|
## change pwd |
||||
|
change_pwd=修改密码 |
||||
|
change_pwd_suc_to_logout=修改密码成功,即将注销登陆 |
||||
|
change_pwd_field_newpwd=新密码 |
||||
|
|
||||
|
## dashboard |
||||
|
job_dashboard_name=运行报表 |
||||
|
job_dashboard_job_num=任务数量 |
||||
|
job_dashboard_job_num_tip=调度中心运行的任务数量 |
||||
|
job_dashboard_trigger_num=调度次数 |
||||
|
job_dashboard_trigger_num_tip=调度中心触发的调度次数 |
||||
|
job_dashboard_jobgroup_num=执行器数量 |
||||
|
job_dashboard_jobgroup_num_tip=调度中心在线的执行器机器数量 |
||||
|
job_dashboard_report=调度报表 |
||||
|
job_dashboard_report_loaddata_fail=调度报表数据加载异常 |
||||
|
job_dashboard_date_report=日期分布图 |
||||
|
job_dashboard_rate_report=成功比例图 |
||||
|
|
||||
|
## job info |
||||
|
jobinfo_name=任务管理 |
||||
|
jobinfo_job=任务 |
||||
|
jobinfo_field_add=新增 |
||||
|
jobinfo_field_update=更新任务 |
||||
|
jobinfo_field_id=任务ID |
||||
|
jobinfo_field_jobgroup=执行器 |
||||
|
jobinfo_field_jobdesc=任务描述 |
||||
|
jobinfo_field_gluetype=运行模式 |
||||
|
jobinfo_field_executorparam=任务参数 |
||||
|
jobinfo_field_author=负责人 |
||||
|
jobinfo_field_timeout=任务超时时间 |
||||
|
jobinfo_field_alarmemail=报警邮件 |
||||
|
jobinfo_field_alarmemail_placeholder=请输入报警邮件,多个邮件地址则逗号分隔 |
||||
|
jobinfo_field_executorRouteStrategy=路由策略 |
||||
|
jobinfo_field_childJobId=子任务ID |
||||
|
jobinfo_field_childJobId_placeholder=请输入子任务的任务ID,如存在多个则逗号分隔 |
||||
|
jobinfo_field_executorBlockStrategy=阻塞处理策略 |
||||
|
jobinfo_field_executorFailRetryCount=失败重试次数 |
||||
|
jobinfo_field_executorFailRetryCount_placeholder=失败重试次数,大于零时生效 |
||||
|
jobinfo_script_location=脚本位置 |
||||
|
jobinfo_shard_index=分片序号 |
||||
|
jobinfo_shard_total=分片总数 |
||||
|
jobinfo_opt_stop=停止 |
||||
|
jobinfo_opt_start=启动 |
||||
|
jobinfo_opt_log=查询日志 |
||||
|
jobinfo_opt_run=执行一次 |
||||
|
jobinfo_opt_run_tips=请输入本次执行的机器地址,为空则从执行器获取 |
||||
|
jobinfo_opt_registryinfo=注册节点 |
||||
|
jobinfo_opt_next_time=下次执行时间 |
||||
|
jobinfo_glue_remark=源码备注 |
||||
|
jobinfo_glue_remark_limit=源码备注长度限制为4~100 |
||||
|
jobinfo_glue_rollback=版本回溯 |
||||
|
jobinfo_glue_jobid_unvalid=任务ID非法 |
||||
|
jobinfo_glue_gluetype_unvalid=该任务非GLUE模式 |
||||
|
jobinfo_field_executorTimeout_placeholder=任务超时时间,单位秒,大于零时生效 |
||||
|
schedule_type=调度类型 |
||||
|
schedule_type_none=无 |
||||
|
schedule_type_cron=CRON |
||||
|
schedule_type_fix_rate=固定速度 |
||||
|
schedule_type_fix_delay=固定延迟 |
||||
|
schedule_type_none_limit_start=当前调度类型禁止启动 |
||||
|
misfire_strategy=调度过期策略 |
||||
|
misfire_strategy_do_nothing=忽略 |
||||
|
misfire_strategy_fire_once_now=立即执行一次 |
||||
|
jobinfo_conf_base=基础配置 |
||||
|
jobinfo_conf_schedule=调度配置 |
||||
|
jobinfo_conf_job=任务配置 |
||||
|
jobinfo_conf_advanced=高级配置 |
||||
|
|
||||
|
## job log |
||||
|
joblog_name=调度日志 |
||||
|
joblog_status=状态 |
||||
|
joblog_status_all=全部 |
||||
|
joblog_status_suc=成功 |
||||
|
joblog_status_fail=失败 |
||||
|
joblog_status_running=进行中 |
||||
|
joblog_field_triggerTime=调度时间 |
||||
|
joblog_field_triggerCode=调度结果 |
||||
|
joblog_field_triggerMsg=调度备注 |
||||
|
joblog_field_handleTime=执行时间 |
||||
|
joblog_field_handleCode=执行结果 |
||||
|
joblog_field_handleMsg=执行备注 |
||||
|
joblog_field_executorAddress=执行器地址 |
||||
|
joblog_clean=清理 |
||||
|
joblog_clean_log=日志清理 |
||||
|
joblog_clean_type=清理方式 |
||||
|
joblog_clean_type_1=清理一个月之前日志数据 |
||||
|
joblog_clean_type_2=清理三个月之前日志数据 |
||||
|
joblog_clean_type_3=清理六个月之前日志数据 |
||||
|
joblog_clean_type_4=清理一年之前日志数据 |
||||
|
joblog_clean_type_5=清理一千条以前日志数据 |
||||
|
joblog_clean_type_6=清理一万条以前日志数据 |
||||
|
joblog_clean_type_7=清理三万条以前日志数据 |
||||
|
joblog_clean_type_8=清理十万条以前日志数据 |
||||
|
joblog_clean_type_9=清理所有日志数据 |
||||
|
joblog_clean_type_unvalid=清理类型参数异常 |
||||
|
joblog_handleCode_200=成功 |
||||
|
joblog_handleCode_500=失败 |
||||
|
joblog_handleCode_502=失败(超时) |
||||
|
joblog_kill_log=终止任务 |
||||
|
joblog_kill_log_limit=调度失败,无法终止日志 |
||||
|
joblog_kill_log_byman=人为操作,主动终止 |
||||
|
joblog_lost_fail=任务结果丢失,标记失败 |
||||
|
joblog_rolling_log=执行日志 |
||||
|
joblog_rolling_log_refresh=刷新 |
||||
|
joblog_rolling_log_triggerfail=任务发起调度失败,无法查看执行日志 |
||||
|
joblog_rolling_log_failoften=终止请求Rolling日志,请求失败次数超上限,可刷新页面重新加载日志 |
||||
|
joblog_logid_unvalid=日志ID非法 |
||||
|
|
||||
|
## job group |
||||
|
jobgroup_name=执行器管理 |
||||
|
jobgroup_list=执行器列表 |
||||
|
jobgroup_add=新增执行器 |
||||
|
jobgroup_edit=编辑执行器 |
||||
|
jobgroup_del=删除执行器 |
||||
|
jobgroup_field_title=名称 |
||||
|
jobgroup_field_addressType=注册方式 |
||||
|
jobgroup_field_addressType_0=自动注册 |
||||
|
jobgroup_field_addressType_1=手动录入 |
||||
|
jobgroup_field_addressType_limit=手动录入注册方式,机器地址不可为空 |
||||
|
jobgroup_field_registryList=机器地址 |
||||
|
jobgroup_field_registryList_unvalid=机器地址格式非法 |
||||
|
jobgroup_field_registryList_placeholder=请输入执行器地址列表,多地址逗号分隔 |
||||
|
jobgroup_field_appname_limit=限制以小写字母开头,由小写字母、数字和中划线组成 |
||||
|
jobgroup_field_appname_length=AppName长度限制为4~64 |
||||
|
jobgroup_field_title_length=名称长度限制为4~12 |
||||
|
jobgroup_field_order_digits=请输入整数 |
||||
|
jobgroup_field_orderrange=取值范围为1~1000 |
||||
|
jobgroup_del_limit_0=拒绝删除,该执行器使用中 |
||||
|
jobgroup_del_limit_1=拒绝删除, 系统至少保留一个执行器 |
||||
|
jobgroup_empty=不存在有效执行器,请联系管理员 |
||||
|
|
||||
|
## job conf |
||||
|
jobconf_block_SERIAL_EXECUTION=单机串行 |
||||
|
jobconf_block_DISCARD_LATER=丢弃后续调度 |
||||
|
jobconf_block_COVER_EARLY=覆盖之前调度 |
||||
|
jobconf_route_first=第一个 |
||||
|
jobconf_route_last=最后一个 |
||||
|
jobconf_route_round=轮询 |
||||
|
jobconf_route_random=随机 |
||||
|
jobconf_route_consistenthash=一致性HASH |
||||
|
jobconf_route_lfu=最不经常使用 |
||||
|
jobconf_route_lru=最近最久未使用 |
||||
|
jobconf_route_failover=故障转移 |
||||
|
jobconf_route_busyover=忙碌转移 |
||||
|
jobconf_route_shard=分片广播 |
||||
|
jobconf_idleBeat=空闲检测 |
||||
|
jobconf_beat=心跳检测 |
||||
|
jobconf_monitor=任务调度中心监控报警 |
||||
|
jobconf_monitor_detail=监控告警明细 |
||||
|
jobconf_monitor_alarm_title=告警类型 |
||||
|
jobconf_monitor_alarm_type=调度失败 |
||||
|
jobconf_monitor_alarm_content=告警内容 |
||||
|
jobconf_trigger_admin_adress=调度机器 |
||||
|
jobconf_trigger_exe_regtype=执行器-注册方式 |
||||
|
jobconf_trigger_exe_regaddress=执行器-地址列表 |
||||
|
jobconf_trigger_address_empty=调度失败:执行器地址为空 |
||||
|
jobconf_trigger_run=触发调度 |
||||
|
jobconf_trigger_child_run=触发子任务 |
||||
|
jobconf_callback_child_msg1={0}/{1} [任务ID={2}], 触发{3}, 触发备注: {4} <br> |
||||
|
jobconf_callback_child_msg2={0}/{1} [任务ID={2}], 触发失败, 触发备注: 任务ID格式错误 <br> |
||||
|
jobconf_trigger_type=任务触发类型 |
||||
|
jobconf_trigger_type_cron=Cron触发 |
||||
|
jobconf_trigger_type_manual=手动触发 |
||||
|
jobconf_trigger_type_parent=父任务触发 |
||||
|
jobconf_trigger_type_api=API触发 |
||||
|
jobconf_trigger_type_retry=失败重试触发 |
||||
|
jobconf_trigger_type_misfire=调度过期补偿 |
||||
|
|
||||
|
## user |
||||
|
user_manage=用户管理 |
||||
|
user_username=账号 |
||||
|
user_password=密码 |
||||
|
user_role=角色 |
||||
|
user_role_admin=管理员 |
||||
|
user_role_normal=普通用户 |
||||
|
user_permission=权限 |
||||
|
user_add=新增用户 |
||||
|
user_update=更新用户 |
||||
|
user_username_repeat=账号重复 |
||||
|
user_username_valid=限制以小写字母开头,由小写字母、数字组成 |
||||
|
user_password_update_placeholder=请输入新密码,为空则不更新密码 |
||||
|
user_update_loginuser_limit=禁止操作当前登录账号 |
||||
|
|
||||
|
## help |
||||
|
job_help=使用教程 |
||||
|
job_help_document=官方文档 |
@ -0,0 +1,276 @@ |
|||||
|
admin_name=任務調度中心 |
||||
|
admin_name_full=分布式任務調度平臺XXL-JOB |
||||
|
admin_version=2.4.1-SNAPSHOT |
||||
|
admin_i18n= |
||||
|
|
||||
|
## system |
||||
|
system_tips=系統提示 |
||||
|
system_ok=確定 |
||||
|
system_close=關閉 |
||||
|
system_save=儲存 |
||||
|
system_cancel=取消 |
||||
|
system_search=搜尋 |
||||
|
system_status=狀態 |
||||
|
system_opt=操作 |
||||
|
system_please_input=請輸入 |
||||
|
system_please_choose=请選擇 |
||||
|
system_success=成功 |
||||
|
system_fail=失敗 |
||||
|
system_add_suc=新增成功 |
||||
|
system_add_fail=新增失敗 |
||||
|
system_update_suc=更新成功 |
||||
|
system_update_fail=更新失敗 |
||||
|
system_all=全部 |
||||
|
system_api_error=API錯誤 |
||||
|
system_show=查看 |
||||
|
system_empty=無 |
||||
|
system_opt_suc=操作成功 |
||||
|
system_opt_fail=操作失敗 |
||||
|
system_opt_edit=編輯 |
||||
|
system_opt_del=刪除 |
||||
|
system_opt_copy=復制 |
||||
|
system_unvalid=非法 |
||||
|
system_not_found=不存在 |
||||
|
system_nav=導航 |
||||
|
system_digits=整數 |
||||
|
system_lengh_limit=長度限制 |
||||
|
system_permission_limit=權限控管 |
||||
|
system_welcome=歡迎 |
||||
|
|
||||
|
## daterangepicker |
||||
|
daterangepicker_ranges_recent_hour=最近一小時 |
||||
|
daterangepicker_ranges_today=今日 |
||||
|
daterangepicker_ranges_yesterday=昨日 |
||||
|
daterangepicker_ranges_this_month=本月 |
||||
|
daterangepicker_ranges_last_month=上個月 |
||||
|
daterangepicker_ranges_recent_week=最近一周 |
||||
|
daterangepicker_ranges_recent_month=最近一月 |
||||
|
daterangepicker_custom_name=自定義 |
||||
|
daterangepicker_custom_starttime=起始時間 |
||||
|
daterangepicker_custom_endtime=結束時間 |
||||
|
daterangepicker_custom_daysofweek=日,一,二,三,四,五,六 |
||||
|
daterangepicker_custom_monthnames=一月,二月,三月,四月,五月,六月,七月,八月,九月,十月,十一月,十二月 |
||||
|
|
||||
|
## dataTable |
||||
|
dataTable_sProcessing=處理中... |
||||
|
dataTable_sLengthMenu=每頁 _MENU_ 條記錄 |
||||
|
dataTable_sZeroRecords=沒有相符合記錄 |
||||
|
dataTable_sInfo=第 _PAGE_ 頁 ( 總共 _PAGES_ 頁,_TOTAL_ 條記錄 ) |
||||
|
dataTable_sInfoEmpty=無記錄 |
||||
|
dataTable_sInfoFiltered=(由 _MAX_ 項結果過濾) |
||||
|
dataTable_sSearch=搜尋 |
||||
|
dataTable_sEmptyTable=表中資料為空 |
||||
|
dataTable_sLoadingRecords=載入中... |
||||
|
dataTable_sFirst=首頁 |
||||
|
dataTable_sPrevious=上頁 |
||||
|
dataTable_sNext=下頁 |
||||
|
dataTable_sLast=末頁 |
||||
|
dataTable_sSortAscending=: 以升幂排序此列 |
||||
|
dataTable_sSortDescending=: 以降幂排序此列 |
||||
|
|
||||
|
## login |
||||
|
login_btn=登入 |
||||
|
login_remember_me=記住密碼 |
||||
|
login_username_placeholder=請輸入登入帳號 |
||||
|
login_password_placeholder=請輸入登入密碼 |
||||
|
login_username_empty=請輸入登入帳號 |
||||
|
login_username_lt_4=登入帳號不應低於4位數 |
||||
|
login_password_empty=請輸入登入密碼 |
||||
|
login_password_lt_4=登入密碼不應低於4位數 |
||||
|
login_success=登入成功 |
||||
|
login_fail=登入失敗 |
||||
|
login_param_empty=帳號或密碼為空值 |
||||
|
login_param_unvalid=帳號或密碼錯誤 |
||||
|
|
||||
|
## logout |
||||
|
logout_btn=登出 |
||||
|
logout_confirm=確認登出? |
||||
|
logout_success=登出成功 |
||||
|
logout_fail=登出失敗 |
||||
|
|
||||
|
## change pwd |
||||
|
change_pwd=修改密碼 |
||||
|
change_pwd_suc_to_logout=修改密碼成功,即將登出 |
||||
|
change_pwd_field_newpwd=新密碼 |
||||
|
|
||||
|
## dashboard |
||||
|
job_dashboard_name=運行報表 |
||||
|
job_dashboard_job_num=任務數量 |
||||
|
job_dashboard_job_num_tip=調度中心運行的任務數量 |
||||
|
job_dashboard_trigger_num=調度次數 |
||||
|
job_dashboard_trigger_num_tip=調度中心觸發的調度次數 |
||||
|
job_dashboard_jobgroup_num=執行器數量 |
||||
|
job_dashboard_jobgroup_num_tip=調度中心在線的執行器機器數量 |
||||
|
job_dashboard_report=調度報表 |
||||
|
job_dashboard_report_loaddata_fail=調度報表資料加載異常 |
||||
|
job_dashboard_date_report=日期分布圖 |
||||
|
job_dashboard_rate_report=成功比例圖 |
||||
|
|
||||
|
## job info |
||||
|
jobinfo_name=任務管理 |
||||
|
jobinfo_job=任務 |
||||
|
jobinfo_field_add=新增 |
||||
|
jobinfo_field_update=更新任務 |
||||
|
jobinfo_field_id=任務ID |
||||
|
jobinfo_field_jobgroup=執行器 |
||||
|
jobinfo_field_jobdesc=任務描述 |
||||
|
jobinfo_field_gluetype=運行模式 |
||||
|
jobinfo_field_executorparam=任務參數 |
||||
|
jobinfo_field_author=負責人 |
||||
|
jobinfo_field_timeout=任務超時秒數 |
||||
|
jobinfo_field_alarmemail=告警郵件 |
||||
|
jobinfo_field_alarmemail_placeholder=輸入多個告警郵件地址,請以逗號分隔 |
||||
|
jobinfo_field_executorRouteStrategy=路由策略 |
||||
|
jobinfo_field_childJobId=子任務ID |
||||
|
jobinfo_field_childJobId_placeholder=輸入子任務ID,如有多個請以逗號分隔 |
||||
|
jobinfo_field_executorBlockStrategy=阻塞處理策略 |
||||
|
jobinfo_field_executorFailRetryCount=失敗重試次數 |
||||
|
jobinfo_field_executorFailRetryCount_placeholder=失敗重試次數,大於零時生效 |
||||
|
jobinfo_script_location=腳本位置 |
||||
|
jobinfo_shard_index=分片序號 |
||||
|
jobinfo_shard_total=分片總數 |
||||
|
jobinfo_opt_stop=停止 |
||||
|
jobinfo_opt_start=啟動 |
||||
|
jobinfo_opt_log=查詢日誌 |
||||
|
jobinfo_opt_run=執行一次 |
||||
|
jobinfo_opt_run_tips=請輸入本次執行的機器地址,為空則從執行器獲取 |
||||
|
jobinfo_opt_registryinfo=注冊節點 |
||||
|
jobinfo_opt_next_time=下次執行時間 |
||||
|
jobinfo_glue_remark=源碼備註 |
||||
|
jobinfo_glue_remark_limit=源碼備註長度限制為4~100 |
||||
|
jobinfo_glue_rollback=版本回復 |
||||
|
jobinfo_glue_jobid_unvalid=任務ID非法 |
||||
|
jobinfo_glue_gluetype_unvalid=該任務非GLUE模式 |
||||
|
jobinfo_field_executorTimeout_placeholder=任務超時時間,單位秒,大於零時生效 |
||||
|
schedule_type=調度類型 |
||||
|
schedule_type_none=無 |
||||
|
schedule_type_cron=CRON |
||||
|
schedule_type_fix_rate=固定速度 |
||||
|
schedule_type_fix_delay=固定延遲 |
||||
|
schedule_type_none_limit_start=當前調度類型禁止啟動 |
||||
|
misfire_strategy=調度過期策略 |
||||
|
misfire_strategy_do_nothing=忽略 |
||||
|
misfire_strategy_fire_once_now=立即執行壹次 |
||||
|
jobinfo_conf_base=基礎配置 |
||||
|
jobinfo_conf_schedule=調度配置 |
||||
|
jobinfo_conf_job=任務配置 |
||||
|
jobinfo_conf_advanced=高級配置 |
||||
|
|
||||
|
## job log |
||||
|
joblog_name=調度日誌 |
||||
|
joblog_status=狀態 |
||||
|
joblog_status_all=全部 |
||||
|
joblog_status_suc=成功 |
||||
|
joblog_status_fail=失敗 |
||||
|
joblog_status_running=進行中 |
||||
|
joblog_field_triggerTime=調度時間 |
||||
|
joblog_field_triggerCode=調度結果 |
||||
|
joblog_field_triggerMsg=調度備註 |
||||
|
joblog_field_handleTime=執行時間 |
||||
|
joblog_field_handleCode=執行结果 |
||||
|
joblog_field_handleMsg=執行備註 |
||||
|
joblog_field_executorAddress=執行器地址 |
||||
|
joblog_clean=清理 |
||||
|
joblog_clean_log=日誌清理 |
||||
|
joblog_clean_type=清理方式 |
||||
|
joblog_clean_type_1=清理一個月之前日誌資料 |
||||
|
joblog_clean_type_2=清理三個月之前日誌資料 |
||||
|
joblog_clean_type_3=清理六個月之前日誌資料 |
||||
|
joblog_clean_type_4=清理一年之前日誌資料 |
||||
|
joblog_clean_type_5=清理一千條以前日誌資料 |
||||
|
joblog_clean_type_6=清理一萬條以前日誌資料 |
||||
|
joblog_clean_type_7=清理三萬條以前日誌資料 |
||||
|
joblog_clean_type_8=清理十萬條以前日誌資料 |
||||
|
joblog_clean_type_9=清理所有日誌資料 |
||||
|
joblog_clean_type_unvalid=清理類型參数異常 |
||||
|
joblog_handleCode_200=成功 |
||||
|
joblog_handleCode_500=失敗 |
||||
|
joblog_handleCode_502=失敗(超時) |
||||
|
joblog_kill_log=终止任務 |
||||
|
joblog_kill_log_limit=調度失敗,無法终止日誌 |
||||
|
joblog_kill_log_byman=人為操作,主動終止 |
||||
|
joblog_lost_fail=任務結果丟失,標記失敗 |
||||
|
joblog_rolling_log=執行日誌 |
||||
|
joblog_rolling_log_refresh=更新 |
||||
|
joblog_rolling_log_triggerfail=任務發起調度失敗,無法查看執行日誌 |
||||
|
joblog_rolling_log_failoften=終止請求Rolling日誌,請求失敗次數超上限,可刷新頁面重新加載日誌 |
||||
|
joblog_logid_unvalid=日誌ID非法 |
||||
|
|
||||
|
## job group |
||||
|
jobgroup_name=執行器管理 |
||||
|
jobgroup_list=執行器列表 |
||||
|
jobgroup_add=新增執行器 |
||||
|
jobgroup_edit=編輯執行器 |
||||
|
jobgroup_del=刪除執行器 |
||||
|
jobgroup_field_title=名稱 |
||||
|
jobgroup_field_addressType=注冊方式 |
||||
|
jobgroup_field_addressType_0=自動注冊 |
||||
|
jobgroup_field_addressType_1=手動登錄 |
||||
|
jobgroup_field_addressType_limit=手動登錄注冊方式,機器地址不可為空 |
||||
|
jobgroup_field_registryList=機器地址 |
||||
|
jobgroup_field_registryList_unvalid=機器地址格式非法 |
||||
|
jobgroup_field_registryList_placeholder=請輸入執行器地址列表,多個地址請以逗號分隔 |
||||
|
jobgroup_field_appname_limit=限制以小寫字母開頭,由小寫字母、數字和中划線組成 |
||||
|
jobgroup_field_appname_length=AppName長度限制為4~64 |
||||
|
jobgroup_field_title_length=名稱長度限制為4~12 |
||||
|
jobgroup_field_order_digits=請輸入整數 |
||||
|
jobgroup_field_orderrange=取值範圍為1~1000 |
||||
|
jobgroup_del_limit_0=拒絕刪除,該執行器使用中 |
||||
|
jobgroup_del_limit_1=拒絕删除,系统至少保留一個執行器 |
||||
|
jobgroup_empty=不存在有效執行器,請聯絡系統管理員 |
||||
|
|
||||
|
## job conf |
||||
|
jobconf_block_SERIAL_EXECUTION=單機串行 |
||||
|
jobconf_block_DISCARD_LATER=丢棄后續調度 |
||||
|
jobconf_block_COVER_EARLY=覆蓋之前調度 |
||||
|
jobconf_route_first=第一個 |
||||
|
jobconf_route_last=最後一個 |
||||
|
jobconf_route_round=輪詢 |
||||
|
jobconf_route_random=隨機 |
||||
|
jobconf_route_consistenthash=一致性HASH |
||||
|
jobconf_route_lfu=最不經常使用 |
||||
|
jobconf_route_lru=最近最久未使用 |
||||
|
jobconf_route_failover=故障轉移 |
||||
|
jobconf_route_busyover=忙碌轉移 |
||||
|
jobconf_route_shard=分片廣播 |
||||
|
jobconf_idleBeat=空閒檢測 |
||||
|
jobconf_beat=心跳檢測 |
||||
|
jobconf_monitor=任務調度中心監控告警 |
||||
|
jobconf_monitor_detail=監控告警明细 |
||||
|
jobconf_monitor_alarm_title=告警類型 |
||||
|
jobconf_monitor_alarm_type=調度失敗 |
||||
|
jobconf_monitor_alarm_content=告警内容 |
||||
|
jobconf_trigger_admin_adress=調度機器 |
||||
|
jobconf_trigger_exe_regtype=執行器-注冊方式 |
||||
|
jobconf_trigger_exe_regaddress=執行器-地址列表 |
||||
|
jobconf_trigger_address_empty=調度失敗:執行器地址為空 |
||||
|
jobconf_trigger_run=觸發調度 |
||||
|
jobconf_trigger_child_run=觸發子任務 |
||||
|
jobconf_callback_child_msg1={0}/{1} [任務ID={2}], 觸發{3}, 觸發備註: {4} <br> |
||||
|
jobconf_callback_child_msg2={0}/{1} [任務ID={2}], 觸發失败, 觸發備註: 任務ID格式錯誤 <br> |
||||
|
jobconf_trigger_type=任務觸發類型 |
||||
|
jobconf_trigger_type_cron=Cron觸發 |
||||
|
jobconf_trigger_type_manual=手動觸發 |
||||
|
jobconf_trigger_type_parent=父任務觸發 |
||||
|
jobconf_trigger_type_api=API觸發 |
||||
|
jobconf_trigger_type_retry=失敗重試觸發 |
||||
|
jobconf_trigger_type_misfire=調度過期補償 |
||||
|
|
||||
|
## user |
||||
|
user_manage=用户管理 |
||||
|
user_username=帳號 |
||||
|
user_password=密碼 |
||||
|
user_role=角色 |
||||
|
user_role_admin=管理員 |
||||
|
user_role_normal=普通用戶 |
||||
|
user_permission=權限 |
||||
|
user_add=新增用戶 |
||||
|
user_update=更新用戶 |
||||
|
user_username_repeat=帳號重複 |
||||
|
user_username_valid=限制以小寫字母開頭,由小寫字母、數字組成 |
||||
|
user_password_update_placeholder=請輸入新密碼,為空則不更新密碼 |
||||
|
user_update_loginuser_limit=禁止操作當前登入帳號 |
||||
|
|
||||
|
## help |
||||
|
job_help=使用教程 |
||||
|
job_help_document=官方文件 |
@ -0,0 +1,29 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<configuration debug="false" scan="true" scanPeriod="1 seconds"> |
||||
|
|
||||
|
<contextName>logback</contextName> |
||||
|
<property name="log.path" value="/data/applogs/xxl-job/xxl-job-admin.log"/> |
||||
|
|
||||
|
<appender name="console" class="ch.qos.logback.core.ConsoleAppender"> |
||||
|
<encoder> |
||||
|
<pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern> |
||||
|
</encoder> |
||||
|
</appender> |
||||
|
|
||||
|
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender"> |
||||
|
<file>${log.path}</file> |
||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> |
||||
|
<fileNamePattern>${log.path}.%d{yyyy-MM-dd}.zip</fileNamePattern> |
||||
|
</rollingPolicy> |
||||
|
<encoder> |
||||
|
<pattern>%date %level [%thread] %logger{36} [%file : %line] %msg%n |
||||
|
</pattern> |
||||
|
</encoder> |
||||
|
</appender> |
||||
|
|
||||
|
<root level="info"> |
||||
|
<appender-ref ref="console"/> |
||||
|
<appender-ref ref="file"/> |
||||
|
</root> |
||||
|
|
||||
|
</configuration> |
@ -0,0 +1,91 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" |
||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||
|
<mapper namespace="com.xxl.job.admin.dao.XxlJobGroupDao"> |
||||
|
|
||||
|
<resultMap id="XxlJobGroup" type="com.xxl.job.admin.core.model.XxlJobGroup" > |
||||
|
<result column="id" property="id" /> |
||||
|
<result column="app_name" property="appname" /> |
||||
|
<result column="title" property="title" /> |
||||
|
<result column="address_type" property="addressType" /> |
||||
|
<result column="address_list" property="addressList" /> |
||||
|
<result column="update_time" property="updateTime" /> |
||||
|
</resultMap> |
||||
|
|
||||
|
<sql id="Base_Column_List"> |
||||
|
t.id, |
||||
|
t.app_name, |
||||
|
t.title, |
||||
|
t.address_type, |
||||
|
t.address_list, |
||||
|
t.update_time |
||||
|
</sql> |
||||
|
|
||||
|
<select id="findAll" resultMap="XxlJobGroup"> |
||||
|
SELECT <include refid="Base_Column_List" /> |
||||
|
FROM xxl_job_group AS t |
||||
|
ORDER BY t.app_name, t.title, t.id ASC |
||||
|
</select> |
||||
|
|
||||
|
<select id="findByAddressType" parameterType="java.lang.Integer" resultMap="XxlJobGroup"> |
||||
|
SELECT <include refid="Base_Column_List" /> |
||||
|
FROM xxl_job_group AS t |
||||
|
WHERE t.address_type = #{addressType} |
||||
|
ORDER BY t.app_name, t.title, t.id ASC |
||||
|
</select> |
||||
|
|
||||
|
<insert id="save" parameterType="com.xxl.job.admin.core.model.XxlJobGroup" useGeneratedKeys="true" keyProperty="id" > |
||||
|
INSERT INTO xxl_job_group ( `app_name`, `title`, `address_type`, `address_list`, `update_time`) |
||||
|
values ( #{appname}, #{title}, #{addressType}, #{addressList}, #{updateTime} ); |
||||
|
</insert> |
||||
|
|
||||
|
<update id="update" parameterType="com.xxl.job.admin.core.model.XxlJobGroup" > |
||||
|
UPDATE xxl_job_group |
||||
|
SET `app_name` = #{appname}, |
||||
|
`title` = #{title}, |
||||
|
`address_type` = #{addressType}, |
||||
|
`address_list` = #{addressList}, |
||||
|
`update_time` = #{updateTime} |
||||
|
WHERE id = #{id} |
||||
|
</update> |
||||
|
|
||||
|
<delete id="remove" parameterType="java.lang.Integer" > |
||||
|
DELETE FROM xxl_job_group |
||||
|
WHERE id = #{id} |
||||
|
</delete> |
||||
|
|
||||
|
<select id="load" parameterType="java.lang.Integer" resultMap="XxlJobGroup"> |
||||
|
SELECT <include refid="Base_Column_List" /> |
||||
|
FROM xxl_job_group AS t |
||||
|
WHERE t.id = #{id} |
||||
|
</select> |
||||
|
|
||||
|
<select id="pageList" parameterType="java.util.HashMap" resultMap="XxlJobGroup"> |
||||
|
SELECT <include refid="Base_Column_List" /> |
||||
|
FROM xxl_job_group AS t |
||||
|
<trim prefix="WHERE" prefixOverrides="AND | OR" > |
||||
|
<if test="appname != null and appname != ''"> |
||||
|
AND t.app_name like CONCAT(CONCAT('%', #{appname}), '%') |
||||
|
</if> |
||||
|
<if test="title != null and title != ''"> |
||||
|
AND t.title like CONCAT(CONCAT('%', #{title}), '%') |
||||
|
</if> |
||||
|
</trim> |
||||
|
ORDER BY t.app_name, t.title, t.id ASC |
||||
|
LIMIT #{offset}, #{pagesize} |
||||
|
</select> |
||||
|
|
||||
|
<select id="pageListCount" parameterType="java.util.HashMap" resultType="int"> |
||||
|
SELECT count(1) |
||||
|
FROM xxl_job_group AS t |
||||
|
<trim prefix="WHERE" prefixOverrides="AND | OR" > |
||||
|
<if test="appname != null and appname != ''"> |
||||
|
AND t.app_name like CONCAT(CONCAT('%', #{appname}), '%') |
||||
|
</if> |
||||
|
<if test="title != null and title != ''"> |
||||
|
AND t.title like CONCAT(CONCAT('%', #{title}), '%') |
||||
|
</if> |
||||
|
</trim> |
||||
|
</select> |
||||
|
|
||||
|
</mapper> |
@ -0,0 +1,240 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" |
||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||
|
<mapper namespace="com.xxl.job.admin.dao.XxlJobInfoDao"> |
||||
|
|
||||
|
<resultMap id="XxlJobInfo" type="com.xxl.job.admin.core.model.XxlJobInfo" > |
||||
|
<result column="id" property="id" /> |
||||
|
|
||||
|
<result column="job_group" property="jobGroup" /> |
||||
|
<result column="job_desc" property="jobDesc" /> |
||||
|
|
||||
|
<result column="add_time" property="addTime" /> |
||||
|
<result column="update_time" property="updateTime" /> |
||||
|
|
||||
|
<result column="author" property="author" /> |
||||
|
<result column="alarm_email" property="alarmEmail" /> |
||||
|
|
||||
|
<result column="schedule_type" property="scheduleType" /> |
||||
|
<result column="schedule_conf" property="scheduleConf" /> |
||||
|
<result column="misfire_strategy" property="misfireStrategy" /> |
||||
|
|
||||
|
<result column="executor_route_strategy" property="executorRouteStrategy" /> |
||||
|
<result column="executor_handler" property="executorHandler" /> |
||||
|
<result column="executor_param" property="executorParam" /> |
||||
|
<result column="executor_block_strategy" property="executorBlockStrategy" /> |
||||
|
<result column="executor_timeout" property="executorTimeout" /> |
||||
|
<result column="executor_fail_retry_count" property="executorFailRetryCount" /> |
||||
|
|
||||
|
<result column="glue_type" property="glueType" /> |
||||
|
<result column="glue_source" property="glueSource" /> |
||||
|
<result column="glue_remark" property="glueRemark" /> |
||||
|
<result column="glue_updatetime" property="glueUpdatetime" /> |
||||
|
|
||||
|
<result column="child_jobid" property="childJobId" /> |
||||
|
|
||||
|
<result column="trigger_status" property="triggerStatus" /> |
||||
|
<result column="trigger_last_time" property="triggerLastTime" /> |
||||
|
<result column="trigger_next_time" property="triggerNextTime" /> |
||||
|
</resultMap> |
||||
|
|
||||
|
<sql id="Base_Column_List"> |
||||
|
t.id, |
||||
|
t.job_group, |
||||
|
t.job_desc, |
||||
|
t.add_time, |
||||
|
t.update_time, |
||||
|
t.author, |
||||
|
t.alarm_email, |
||||
|
t.schedule_type, |
||||
|
t.schedule_conf, |
||||
|
t.misfire_strategy, |
||||
|
t.executor_route_strategy, |
||||
|
t.executor_handler, |
||||
|
t.executor_param, |
||||
|
t.executor_block_strategy, |
||||
|
t.executor_timeout, |
||||
|
t.executor_fail_retry_count, |
||||
|
t.glue_type, |
||||
|
t.glue_source, |
||||
|
t.glue_remark, |
||||
|
t.glue_updatetime, |
||||
|
t.child_jobid, |
||||
|
t.trigger_status, |
||||
|
t.trigger_last_time, |
||||
|
t.trigger_next_time |
||||
|
</sql> |
||||
|
|
||||
|
<select id="pageList" parameterType="java.util.HashMap" resultMap="XxlJobInfo"> |
||||
|
SELECT <include refid="Base_Column_List" /> |
||||
|
FROM xxl_job_info AS t |
||||
|
<trim prefix="WHERE" prefixOverrides="AND | OR" > |
||||
|
<if test="jobGroup gt 0"> |
||||
|
AND t.job_group = #{jobGroup} |
||||
|
</if> |
||||
|
<if test="triggerStatus gte 0"> |
||||
|
AND t.trigger_status = #{triggerStatus} |
||||
|
</if> |
||||
|
<if test="jobDesc != null and jobDesc != ''"> |
||||
|
AND t.job_desc like CONCAT(CONCAT('%', #{jobDesc}), '%') |
||||
|
</if> |
||||
|
<if test="executorHandler != null and executorHandler != ''"> |
||||
|
AND t.executor_handler like CONCAT(CONCAT('%', #{executorHandler}), '%') |
||||
|
</if> |
||||
|
<if test="author != null and author != ''"> |
||||
|
AND t.author like CONCAT(CONCAT('%', #{author}), '%') |
||||
|
</if> |
||||
|
</trim> |
||||
|
ORDER BY id DESC |
||||
|
LIMIT #{offset}, #{pagesize} |
||||
|
</select> |
||||
|
|
||||
|
<select id="pageListCount" parameterType="java.util.HashMap" resultType="int"> |
||||
|
SELECT count(1) |
||||
|
FROM xxl_job_info AS t |
||||
|
<trim prefix="WHERE" prefixOverrides="AND | OR" > |
||||
|
<if test="jobGroup gt 0"> |
||||
|
AND t.job_group = #{jobGroup} |
||||
|
</if> |
||||
|
<if test="triggerStatus gte 0"> |
||||
|
AND t.trigger_status = #{triggerStatus} |
||||
|
</if> |
||||
|
<if test="jobDesc != null and jobDesc != ''"> |
||||
|
AND t.job_desc like CONCAT(CONCAT('%', #{jobDesc}), '%') |
||||
|
</if> |
||||
|
<if test="executorHandler != null and executorHandler != ''"> |
||||
|
AND t.executor_handler like CONCAT(CONCAT('%', #{executorHandler}), '%') |
||||
|
</if> |
||||
|
<if test="author != null and author != ''"> |
||||
|
AND t.author like CONCAT(CONCAT('%', #{author}), '%') |
||||
|
</if> |
||||
|
</trim> |
||||
|
</select> |
||||
|
|
||||
|
<insert id="save" parameterType="com.xxl.job.admin.core.model.XxlJobInfo" useGeneratedKeys="true" keyProperty="id" > |
||||
|
INSERT INTO xxl_job_info ( |
||||
|
job_group, |
||||
|
job_desc, |
||||
|
add_time, |
||||
|
update_time, |
||||
|
author, |
||||
|
alarm_email, |
||||
|
schedule_type, |
||||
|
schedule_conf, |
||||
|
misfire_strategy, |
||||
|
executor_route_strategy, |
||||
|
executor_handler, |
||||
|
executor_param, |
||||
|
executor_block_strategy, |
||||
|
executor_timeout, |
||||
|
executor_fail_retry_count, |
||||
|
glue_type, |
||||
|
glue_source, |
||||
|
glue_remark, |
||||
|
glue_updatetime, |
||||
|
child_jobid, |
||||
|
trigger_status, |
||||
|
trigger_last_time, |
||||
|
trigger_next_time |
||||
|
) VALUES ( |
||||
|
#{jobGroup}, |
||||
|
#{jobDesc}, |
||||
|
#{addTime}, |
||||
|
#{updateTime}, |
||||
|
#{author}, |
||||
|
#{alarmEmail}, |
||||
|
#{scheduleType}, |
||||
|
#{scheduleConf}, |
||||
|
#{misfireStrategy}, |
||||
|
#{executorRouteStrategy}, |
||||
|
#{executorHandler}, |
||||
|
#{executorParam}, |
||||
|
#{executorBlockStrategy}, |
||||
|
#{executorTimeout}, |
||||
|
#{executorFailRetryCount}, |
||||
|
#{glueType}, |
||||
|
#{glueSource}, |
||||
|
#{glueRemark}, |
||||
|
#{glueUpdatetime}, |
||||
|
#{childJobId}, |
||||
|
#{triggerStatus}, |
||||
|
#{triggerLastTime}, |
||||
|
#{triggerNextTime} |
||||
|
); |
||||
|
<!--<selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id"> |
||||
|
SELECT LAST_INSERT_ID() |
||||
|
/*SELECT @@IDENTITY AS id*/ |
||||
|
</selectKey>--> |
||||
|
</insert> |
||||
|
|
||||
|
<select id="loadById" parameterType="java.util.HashMap" resultMap="XxlJobInfo"> |
||||
|
SELECT <include refid="Base_Column_List" /> |
||||
|
FROM xxl_job_info AS t |
||||
|
WHERE t.id = #{id} |
||||
|
</select> |
||||
|
|
||||
|
<update id="update" parameterType="com.xxl.job.admin.core.model.XxlJobInfo" > |
||||
|
UPDATE xxl_job_info |
||||
|
SET |
||||
|
job_group = #{jobGroup}, |
||||
|
job_desc = #{jobDesc}, |
||||
|
update_time = #{updateTime}, |
||||
|
author = #{author}, |
||||
|
alarm_email = #{alarmEmail}, |
||||
|
schedule_type = #{scheduleType}, |
||||
|
schedule_conf = #{scheduleConf}, |
||||
|
misfire_strategy = #{misfireStrategy}, |
||||
|
executor_route_strategy = #{executorRouteStrategy}, |
||||
|
executor_handler = #{executorHandler}, |
||||
|
executor_param = #{executorParam}, |
||||
|
executor_block_strategy = #{executorBlockStrategy}, |
||||
|
executor_timeout = ${executorTimeout}, |
||||
|
executor_fail_retry_count = ${executorFailRetryCount}, |
||||
|
glue_type = #{glueType}, |
||||
|
glue_source = #{glueSource}, |
||||
|
glue_remark = #{glueRemark}, |
||||
|
glue_updatetime = #{glueUpdatetime}, |
||||
|
child_jobid = #{childJobId}, |
||||
|
trigger_status = #{triggerStatus}, |
||||
|
trigger_last_time = #{triggerLastTime}, |
||||
|
trigger_next_time = #{triggerNextTime} |
||||
|
WHERE id = #{id} |
||||
|
</update> |
||||
|
|
||||
|
<delete id="delete" parameterType="java.util.HashMap"> |
||||
|
DELETE |
||||
|
FROM xxl_job_info |
||||
|
WHERE id = #{id} |
||||
|
</delete> |
||||
|
|
||||
|
<select id="getJobsByGroup" parameterType="java.util.HashMap" resultMap="XxlJobInfo"> |
||||
|
SELECT <include refid="Base_Column_List" /> |
||||
|
FROM xxl_job_info AS t |
||||
|
WHERE t.job_group = #{jobGroup} |
||||
|
</select> |
||||
|
|
||||
|
<select id="findAllCount" resultType="int"> |
||||
|
SELECT count(1) |
||||
|
FROM xxl_job_info |
||||
|
</select> |
||||
|
|
||||
|
|
||||
|
<select id="scheduleJobQuery" parameterType="java.util.HashMap" resultMap="XxlJobInfo"> |
||||
|
SELECT <include refid="Base_Column_List" /> |
||||
|
FROM xxl_job_info AS t |
||||
|
WHERE t.trigger_status = 1 |
||||
|
and t.trigger_next_time <![CDATA[ <= ]]> #{maxNextTime} |
||||
|
ORDER BY id ASC |
||||
|
LIMIT #{pagesize} |
||||
|
</select> |
||||
|
|
||||
|
<update id="scheduleUpdate" parameterType="com.xxl.job.admin.core.model.XxlJobInfo" > |
||||
|
UPDATE xxl_job_info |
||||
|
SET |
||||
|
trigger_last_time = #{triggerLastTime}, |
||||
|
trigger_next_time = #{triggerNextTime}, |
||||
|
trigger_status = #{triggerStatus} |
||||
|
WHERE id = #{id} |
||||
|
</update> |
||||
|
|
||||
|
</mapper> |
@ -0,0 +1,71 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" |
||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||
|
<mapper namespace="com.xxl.job.admin.dao.XxlJobLogGlueDao"> |
||||
|
|
||||
|
<resultMap id="XxlJobLogGlue" type="com.xxl.job.admin.core.model.XxlJobLogGlue" > |
||||
|
<result column="id" property="id" /> |
||||
|
<result column="job_id" property="jobId" /> |
||||
|
<result column="glue_type" property="glueType" /> |
||||
|
<result column="glue_source" property="glueSource" /> |
||||
|
<result column="glue_remark" property="glueRemark" /> |
||||
|
<result column="add_time" property="addTime" /> |
||||
|
<result column="update_time" property="updateTime" /> |
||||
|
</resultMap> |
||||
|
|
||||
|
<sql id="Base_Column_List"> |
||||
|
t.id, |
||||
|
t.job_id, |
||||
|
t.glue_type, |
||||
|
t.glue_source, |
||||
|
t.glue_remark, |
||||
|
t.add_time, |
||||
|
t.update_time |
||||
|
</sql> |
||||
|
|
||||
|
<insert id="save" parameterType="com.xxl.job.admin.core.model.XxlJobLogGlue" useGeneratedKeys="true" keyProperty="id" > |
||||
|
INSERT INTO xxl_job_logglue ( |
||||
|
`job_id`, |
||||
|
`glue_type`, |
||||
|
`glue_source`, |
||||
|
`glue_remark`, |
||||
|
`add_time`, |
||||
|
`update_time` |
||||
|
) VALUES ( |
||||
|
#{jobId}, |
||||
|
#{glueType}, |
||||
|
#{glueSource}, |
||||
|
#{glueRemark}, |
||||
|
#{addTime}, |
||||
|
#{updateTime} |
||||
|
); |
||||
|
<!--<selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id"> |
||||
|
SELECT LAST_INSERT_ID() |
||||
|
</selectKey>--> |
||||
|
</insert> |
||||
|
|
||||
|
<select id="findByJobId" parameterType="java.lang.Integer" resultMap="XxlJobLogGlue"> |
||||
|
SELECT <include refid="Base_Column_List" /> |
||||
|
FROM xxl_job_logglue AS t |
||||
|
WHERE t.job_id = #{jobId} |
||||
|
ORDER BY id DESC |
||||
|
</select> |
||||
|
|
||||
|
<delete id="removeOld" > |
||||
|
DELETE FROM xxl_job_logglue |
||||
|
WHERE id NOT in( |
||||
|
SELECT id FROM( |
||||
|
SELECT id FROM xxl_job_logglue |
||||
|
WHERE `job_id` = #{jobId} |
||||
|
ORDER BY update_time desc |
||||
|
LIMIT 0, #{limit} |
||||
|
) t1 |
||||
|
) AND `job_id` = #{jobId} |
||||
|
</delete> |
||||
|
|
||||
|
<delete id="deleteByJobId" parameterType="java.lang.Integer" > |
||||
|
DELETE FROM xxl_job_logglue |
||||
|
WHERE `job_id` = #{jobId} |
||||
|
</delete> |
||||
|
|
||||
|
</mapper> |
@ -0,0 +1,273 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" |
||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||
|
<mapper namespace="com.xxl.job.admin.dao.XxlJobLogDao"> |
||||
|
|
||||
|
<resultMap id="XxlJobLog" type="com.xxl.job.admin.core.model.XxlJobLog" > |
||||
|
<result column="id" property="id" /> |
||||
|
|
||||
|
<result column="job_group" property="jobGroup" /> |
||||
|
<result column="job_id" property="jobId" /> |
||||
|
|
||||
|
<result column="executor_address" property="executorAddress" /> |
||||
|
<result column="executor_handler" property="executorHandler" /> |
||||
|
<result column="executor_param" property="executorParam" /> |
||||
|
<result column="executor_sharding_param" property="executorShardingParam" /> |
||||
|
<result column="executor_fail_retry_count" property="executorFailRetryCount" /> |
||||
|
|
||||
|
<result column="trigger_time" property="triggerTime" /> |
||||
|
<result column="trigger_code" property="triggerCode" /> |
||||
|
<result column="trigger_msg" property="triggerMsg" /> |
||||
|
|
||||
|
<result column="handle_time" property="handleTime" /> |
||||
|
<result column="handle_code" property="handleCode" /> |
||||
|
<result column="handle_msg" property="handleMsg" /> |
||||
|
|
||||
|
<result column="alarm_status" property="alarmStatus" /> |
||||
|
</resultMap> |
||||
|
|
||||
|
<sql id="Base_Column_List"> |
||||
|
t.id, |
||||
|
t.job_group, |
||||
|
t.job_id, |
||||
|
t.executor_address, |
||||
|
t.executor_handler, |
||||
|
t.executor_param, |
||||
|
t.executor_sharding_param, |
||||
|
t.executor_fail_retry_count, |
||||
|
t.trigger_time, |
||||
|
t.trigger_code, |
||||
|
t.trigger_msg, |
||||
|
t.handle_time, |
||||
|
t.handle_code, |
||||
|
t.handle_msg, |
||||
|
t.alarm_status |
||||
|
</sql> |
||||
|
|
||||
|
<select id="pageList" resultMap="XxlJobLog"> |
||||
|
SELECT <include refid="Base_Column_List" /> |
||||
|
FROM xxl_job_log AS t |
||||
|
<trim prefix="WHERE" prefixOverrides="AND | OR" > |
||||
|
<if test="jobId==0 and jobGroup gt 0"> |
||||
|
AND t.job_group = #{jobGroup} |
||||
|
</if> |
||||
|
<if test="jobId gt 0"> |
||||
|
AND t.job_id = #{jobId} |
||||
|
</if> |
||||
|
<if test="triggerTimeStart != null"> |
||||
|
AND t.trigger_time <![CDATA[ >= ]]> #{triggerTimeStart} |
||||
|
</if> |
||||
|
<if test="triggerTimeEnd != null"> |
||||
|
AND t.trigger_time <![CDATA[ <= ]]> #{triggerTimeEnd} |
||||
|
</if> |
||||
|
<if test="logStatus == 1" > |
||||
|
AND t.handle_code = 200 |
||||
|
</if> |
||||
|
<if test="logStatus == 2" > |
||||
|
AND ( |
||||
|
t.trigger_code NOT IN (0, 200) OR |
||||
|
t.handle_code NOT IN (0, 200) |
||||
|
) |
||||
|
</if> |
||||
|
<if test="logStatus == 3" > |
||||
|
AND t.trigger_code = 200 |
||||
|
AND t.handle_code = 0 |
||||
|
</if> |
||||
|
</trim> |
||||
|
ORDER BY t.trigger_time DESC |
||||
|
LIMIT #{offset}, #{pagesize} |
||||
|
</select> |
||||
|
|
||||
|
<select id="pageListCount" resultType="int"> |
||||
|
SELECT count(1) |
||||
|
FROM xxl_job_log AS t |
||||
|
<trim prefix="WHERE" prefixOverrides="AND | OR" > |
||||
|
<if test="jobId==0 and jobGroup gt 0"> |
||||
|
AND t.job_group = #{jobGroup} |
||||
|
</if> |
||||
|
<if test="jobId gt 0"> |
||||
|
AND t.job_id = #{jobId} |
||||
|
</if> |
||||
|
<if test="triggerTimeStart != null"> |
||||
|
AND t.trigger_time <![CDATA[ >= ]]> #{triggerTimeStart} |
||||
|
</if> |
||||
|
<if test="triggerTimeEnd != null"> |
||||
|
AND t.trigger_time <![CDATA[ <= ]]> #{triggerTimeEnd} |
||||
|
</if> |
||||
|
<if test="logStatus == 1" > |
||||
|
AND t.handle_code = 200 |
||||
|
</if> |
||||
|
<if test="logStatus == 2" > |
||||
|
AND ( |
||||
|
t.trigger_code NOT IN (0, 200) OR |
||||
|
t.handle_code NOT IN (0, 200) |
||||
|
) |
||||
|
</if> |
||||
|
<if test="logStatus == 3" > |
||||
|
AND t.trigger_code = 200 |
||||
|
AND t.handle_code = 0 |
||||
|
</if> |
||||
|
</trim> |
||||
|
</select> |
||||
|
|
||||
|
<select id="load" parameterType="java.lang.Long" resultMap="XxlJobLog"> |
||||
|
SELECT <include refid="Base_Column_List" /> |
||||
|
FROM xxl_job_log AS t |
||||
|
WHERE t.id = #{id} |
||||
|
</select> |
||||
|
|
||||
|
|
||||
|
<insert id="save" parameterType="com.xxl.job.admin.core.model.XxlJobLog" useGeneratedKeys="true" keyProperty="id" > |
||||
|
INSERT INTO xxl_job_log ( |
||||
|
`job_group`, |
||||
|
`job_id`, |
||||
|
`trigger_time`, |
||||
|
`trigger_code`, |
||||
|
`handle_code` |
||||
|
) VALUES ( |
||||
|
#{jobGroup}, |
||||
|
#{jobId}, |
||||
|
#{triggerTime}, |
||||
|
#{triggerCode}, |
||||
|
#{handleCode} |
||||
|
); |
||||
|
<!--<selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id"> |
||||
|
SELECT LAST_INSERT_ID() |
||||
|
</selectKey>--> |
||||
|
</insert> |
||||
|
|
||||
|
<update id="updateTriggerInfo" > |
||||
|
UPDATE xxl_job_log |
||||
|
SET |
||||
|
`trigger_time`= #{triggerTime}, |
||||
|
`trigger_code`= #{triggerCode}, |
||||
|
`trigger_msg`= #{triggerMsg}, |
||||
|
`executor_address`= #{executorAddress}, |
||||
|
`executor_handler`=#{executorHandler}, |
||||
|
`executor_param`= #{executorParam}, |
||||
|
`executor_sharding_param`= #{executorShardingParam}, |
||||
|
`executor_fail_retry_count`= #{executorFailRetryCount} |
||||
|
WHERE `id`= #{id} |
||||
|
</update> |
||||
|
|
||||
|
<update id="updateHandleInfo"> |
||||
|
UPDATE xxl_job_log |
||||
|
SET |
||||
|
`handle_time`= #{handleTime}, |
||||
|
`handle_code`= #{handleCode}, |
||||
|
`handle_msg`= #{handleMsg} |
||||
|
WHERE `id`= #{id} |
||||
|
</update> |
||||
|
|
||||
|
<delete id="delete" > |
||||
|
delete from xxl_job_log |
||||
|
WHERE job_id = #{jobId} |
||||
|
</delete> |
||||
|
|
||||
|
<!--<select id="triggerCountByDay" resultType="java.util.Map" > |
||||
|
SELECT |
||||
|
DATE_FORMAT(trigger_time,'%Y-%m-%d') triggerDay, |
||||
|
COUNT(handle_code) triggerDayCount, |
||||
|
SUM(CASE WHEN (trigger_code in (0, 200) and handle_code = 0) then 1 else 0 end) as triggerDayCountRunning, |
||||
|
SUM(CASE WHEN handle_code = 200 then 1 else 0 end) as triggerDayCountSuc |
||||
|
FROM xxl_job_log |
||||
|
WHERE trigger_time BETWEEN #{from} and #{to} |
||||
|
GROUP BY triggerDay |
||||
|
ORDER BY triggerDay |
||||
|
</select>--> |
||||
|
|
||||
|
<select id="findLogReport" resultType="java.util.Map" > |
||||
|
SELECT |
||||
|
COUNT(handle_code) triggerDayCount, |
||||
|
SUM(CASE WHEN (trigger_code in (0, 200) and handle_code = 0) then 1 else 0 end) as triggerDayCountRunning, |
||||
|
SUM(CASE WHEN handle_code = 200 then 1 else 0 end) as triggerDayCountSuc |
||||
|
FROM xxl_job_log |
||||
|
WHERE trigger_time BETWEEN #{from} and #{to} |
||||
|
</select> |
||||
|
|
||||
|
<select id="findClearLogIds" resultType="long" > |
||||
|
SELECT id FROM xxl_job_log |
||||
|
<trim prefix="WHERE" prefixOverrides="AND | OR" > |
||||
|
<if test="jobGroup gt 0"> |
||||
|
AND job_group = #{jobGroup} |
||||
|
</if> |
||||
|
<if test="jobId gt 0"> |
||||
|
AND job_id = #{jobId} |
||||
|
</if> |
||||
|
<if test="clearBeforeTime != null"> |
||||
|
AND trigger_time <![CDATA[ <= ]]> #{clearBeforeTime} |
||||
|
</if> |
||||
|
<if test="clearBeforeNum gt 0"> |
||||
|
AND id NOT in( |
||||
|
SELECT id FROM( |
||||
|
SELECT id FROM xxl_job_log AS t |
||||
|
<trim prefix="WHERE" prefixOverrides="AND | OR" > |
||||
|
<if test="jobGroup gt 0"> |
||||
|
AND t.job_group = #{jobGroup} |
||||
|
</if> |
||||
|
<if test="jobId gt 0"> |
||||
|
AND t.job_id = #{jobId} |
||||
|
</if> |
||||
|
</trim> |
||||
|
ORDER BY t.trigger_time desc |
||||
|
LIMIT 0, #{clearBeforeNum} |
||||
|
) t1 |
||||
|
) |
||||
|
</if> |
||||
|
</trim> |
||||
|
order by id asc |
||||
|
LIMIT #{pagesize} |
||||
|
</select> |
||||
|
|
||||
|
<delete id="clearLog" > |
||||
|
delete from xxl_job_log |
||||
|
WHERE id in |
||||
|
<foreach collection="logIds" item="item" open="(" close=")" separator="," > |
||||
|
#{item} |
||||
|
</foreach> |
||||
|
</delete> |
||||
|
|
||||
|
<select id="findFailJobLogIds" resultType="long" > |
||||
|
SELECT id FROM `xxl_job_log` |
||||
|
WHERE !( |
||||
|
(trigger_code in (0, 200) and handle_code = 0) |
||||
|
OR |
||||
|
(handle_code = 200) |
||||
|
) |
||||
|
AND `alarm_status` = 0 |
||||
|
ORDER BY id ASC |
||||
|
LIMIT #{pagesize} |
||||
|
</select> |
||||
|
|
||||
|
<update id="updateAlarmStatus" > |
||||
|
UPDATE xxl_job_log |
||||
|
SET |
||||
|
`alarm_status` = #{newAlarmStatus} |
||||
|
WHERE `id`= #{logId} AND `alarm_status` = #{oldAlarmStatus} |
||||
|
</update> |
||||
|
|
||||
|
<select id="findLostJobIds" resultType="long" > |
||||
|
SELECT |
||||
|
t.id |
||||
|
FROM |
||||
|
xxl_job_log t |
||||
|
LEFT JOIN xxl_job_registry t2 ON t.executor_address = t2.registry_value |
||||
|
WHERE |
||||
|
t.trigger_code = 200 |
||||
|
AND t.handle_code = 0 |
||||
|
AND t.trigger_time <![CDATA[ <= ]]> #{losedTime} |
||||
|
AND t2.id IS NULL; |
||||
|
</select> |
||||
|
<!-- |
||||
|
SELECT t.id |
||||
|
FROM xxl_job_log AS t |
||||
|
WHERE t.trigger_code = 200 |
||||
|
and t.handle_code = 0 |
||||
|
and t.trigger_time <![CDATA[ <= ]]> #{losedTime} |
||||
|
and t.executor_address not in ( |
||||
|
SELECT t2.registry_value |
||||
|
FROM xxl_job_registry AS t2 |
||||
|
) |
||||
|
--> |
||||
|
|
||||
|
</mapper> |
@ -0,0 +1,62 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" |
||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||
|
<mapper namespace="com.xxl.job.admin.dao.XxlJobLogReportDao"> |
||||
|
|
||||
|
<resultMap id="XxlJobLogReport" type="com.xxl.job.admin.core.model.XxlJobLogReport" > |
||||
|
<result column="id" property="id" /> |
||||
|
<result column="trigger_day" property="triggerDay" /> |
||||
|
<result column="running_count" property="runningCount" /> |
||||
|
<result column="suc_count" property="sucCount" /> |
||||
|
<result column="fail_count" property="failCount" /> |
||||
|
</resultMap> |
||||
|
|
||||
|
<sql id="Base_Column_List"> |
||||
|
t.id, |
||||
|
t.trigger_day, |
||||
|
t.running_count, |
||||
|
t.suc_count, |
||||
|
t.fail_count |
||||
|
</sql> |
||||
|
|
||||
|
<insert id="save" parameterType="com.xxl.job.admin.core.model.XxlJobLogReport" useGeneratedKeys="true" keyProperty="id" > |
||||
|
INSERT INTO xxl_job_log_report ( |
||||
|
`trigger_day`, |
||||
|
`running_count`, |
||||
|
`suc_count`, |
||||
|
`fail_count` |
||||
|
) VALUES ( |
||||
|
#{triggerDay}, |
||||
|
#{runningCount}, |
||||
|
#{sucCount}, |
||||
|
#{failCount} |
||||
|
); |
||||
|
<!--<selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id"> |
||||
|
SELECT LAST_INSERT_ID() |
||||
|
</selectKey>--> |
||||
|
</insert> |
||||
|
|
||||
|
<update id="update" > |
||||
|
UPDATE xxl_job_log_report |
||||
|
SET `running_count` = #{runningCount}, |
||||
|
`suc_count` = #{sucCount}, |
||||
|
`fail_count` = #{failCount} |
||||
|
WHERE `trigger_day` = #{triggerDay} |
||||
|
</update> |
||||
|
|
||||
|
<select id="queryLogReport" resultMap="XxlJobLogReport"> |
||||
|
SELECT <include refid="Base_Column_List" /> |
||||
|
FROM xxl_job_log_report AS t |
||||
|
WHERE t.trigger_day between #{triggerDayFrom} and #{triggerDayTo} |
||||
|
ORDER BY t.trigger_day ASC |
||||
|
</select> |
||||
|
|
||||
|
<select id="queryLogReportTotal" resultMap="XxlJobLogReport"> |
||||
|
SELECT |
||||
|
SUM(running_count) running_count, |
||||
|
SUM(suc_count) suc_count, |
||||
|
SUM(fail_count) fail_count |
||||
|
FROM xxl_job_log_report AS t |
||||
|
</select> |
||||
|
|
||||
|
</mapper> |
@ -0,0 +1,62 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" |
||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||
|
<mapper namespace="com.xxl.job.admin.dao.XxlJobRegistryDao"> |
||||
|
|
||||
|
<resultMap id="XxlJobRegistry" type="com.xxl.job.admin.core.model.XxlJobRegistry" > |
||||
|
<result column="id" property="id" /> |
||||
|
<result column="registry_group" property="registryGroup" /> |
||||
|
<result column="registry_key" property="registryKey" /> |
||||
|
<result column="registry_value" property="registryValue" /> |
||||
|
<result column="update_time" property="updateTime" /> |
||||
|
</resultMap> |
||||
|
|
||||
|
<sql id="Base_Column_List"> |
||||
|
t.id, |
||||
|
t.registry_group, |
||||
|
t.registry_key, |
||||
|
t.registry_value, |
||||
|
t.update_time |
||||
|
</sql> |
||||
|
|
||||
|
<select id="findDead" parameterType="java.util.HashMap" resultType="java.lang.Integer" > |
||||
|
SELECT t.id |
||||
|
FROM xxl_job_registry AS t |
||||
|
WHERE t.update_time <![CDATA[ < ]]> DATE_ADD(#{nowTime},INTERVAL -#{timeout} SECOND) |
||||
|
</select> |
||||
|
|
||||
|
<delete id="removeDead" parameterType="java.lang.Integer" > |
||||
|
DELETE FROM xxl_job_registry |
||||
|
WHERE id in |
||||
|
<foreach collection="ids" item="item" open="(" close=")" separator="," > |
||||
|
#{item} |
||||
|
</foreach> |
||||
|
</delete> |
||||
|
|
||||
|
<select id="findAll" parameterType="java.util.HashMap" resultMap="XxlJobRegistry"> |
||||
|
SELECT <include refid="Base_Column_List" /> |
||||
|
FROM xxl_job_registry AS t |
||||
|
WHERE t.update_time <![CDATA[ > ]]> DATE_ADD(#{nowTime},INTERVAL -#{timeout} SECOND) |
||||
|
</select> |
||||
|
|
||||
|
<update id="registryUpdate" > |
||||
|
UPDATE xxl_job_registry |
||||
|
SET `update_time` = #{updateTime} |
||||
|
WHERE `registry_group` = #{registryGroup} |
||||
|
AND `registry_key` = #{registryKey} |
||||
|
AND `registry_value` = #{registryValue} |
||||
|
</update> |
||||
|
|
||||
|
<insert id="registrySave" > |
||||
|
INSERT INTO xxl_job_registry( `registry_group` , `registry_key` , `registry_value`, `update_time`) |
||||
|
VALUES( #{registryGroup} , #{registryKey} , #{registryValue}, #{updateTime}) |
||||
|
</insert> |
||||
|
|
||||
|
<delete id="registryDelete" > |
||||
|
DELETE FROM xxl_job_registry |
||||
|
WHERE registry_group = #{registryGroup} |
||||
|
AND registry_key = #{registryKey} |
||||
|
AND registry_value = #{registryValue} |
||||
|
</delete> |
||||
|
|
||||
|
</mapper> |
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue