From 9129d7f0581372bb33fd76ed6caece7cb5df6997 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=8A=9B?= Date: Mon, 18 Jul 2022 17:43:16 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AC=AC=E4=B8=89=E6=96=B9=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E8=8E=B7=E5=8F=96token?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- APIService/pom.xml | 8 + .../controller/TestApiServiceController.java | 26 ++ .../com/storeroom/service/ApiService.java | 10 + .../com/storeroom/service/dto/ResultDto.java | 19 ++ .../service/impl/ApiServiceImpl.java | 44 +++ common/pom.xml | 10 + .../storeroom/config/RestTempleConfig.java | 33 ++ .../com/storeroom/utils/FastjsonUtils.java | 115 +++++++ .../java/com/storeroom/utils/HttpUtils.java | 318 ++++++++++++++++++ common/src/test/java/TestHttp.java | 34 ++ .../service/dto/DeviceSpecParamDto.java | 1 - .../modules/quartz/config/JobRunner.java | 36 ++ .../modules/quartz/config/QuartzConfig.java | 33 ++ .../modules/quartz/domain/QuartzJob.java | 68 ++++ .../modules/quartz/domain/QuartzLog.java | 50 +++ .../repository/QuartzJobRepository.java | 16 + .../repository/QuartzLogRepository.java | 8 + .../quartz/service/QuartzJobService.java | 104 ++++++ .../quartz/service/dto/JobQueryCriteria.java | 21 ++ .../service/impl/QuartzJobServiceImpl.java | 180 ++++++++++ .../modules/quartz/task/TestTask.java | 24 ++ .../modules/quartz/utils/ExecutionJob.java | 99 ++++++ .../modules/quartz/utils/QuartzManage.java | 157 +++++++++ .../modules/quartz/utils/QuartzRunnable.java | 41 +++ 24 files changed, 1454 insertions(+), 1 deletion(-) create mode 100644 APIService/src/main/java/com/storeroom/controller/TestApiServiceController.java create mode 100644 APIService/src/main/java/com/storeroom/service/ApiService.java create mode 100644 APIService/src/main/java/com/storeroom/service/dto/ResultDto.java create mode 100644 APIService/src/main/java/com/storeroom/service/impl/ApiServiceImpl.java create mode 100644 common/src/main/java/com/storeroom/config/RestTempleConfig.java create mode 100644 common/src/main/java/com/storeroom/utils/FastjsonUtils.java create mode 100644 common/src/main/java/com/storeroom/utils/HttpUtils.java create mode 100644 common/src/test/java/TestHttp.java create mode 100644 system/src/main/java/com/storeroom/modules/quartz/config/JobRunner.java create mode 100644 system/src/main/java/com/storeroom/modules/quartz/config/QuartzConfig.java create mode 100644 system/src/main/java/com/storeroom/modules/quartz/domain/QuartzJob.java create mode 100644 system/src/main/java/com/storeroom/modules/quartz/domain/QuartzLog.java create mode 100644 system/src/main/java/com/storeroom/modules/quartz/repository/QuartzJobRepository.java create mode 100644 system/src/main/java/com/storeroom/modules/quartz/repository/QuartzLogRepository.java create mode 100644 system/src/main/java/com/storeroom/modules/quartz/service/QuartzJobService.java create mode 100644 system/src/main/java/com/storeroom/modules/quartz/service/dto/JobQueryCriteria.java create mode 100644 system/src/main/java/com/storeroom/modules/quartz/service/impl/QuartzJobServiceImpl.java create mode 100644 system/src/main/java/com/storeroom/modules/quartz/task/TestTask.java create mode 100644 system/src/main/java/com/storeroom/modules/quartz/utils/ExecutionJob.java create mode 100644 system/src/main/java/com/storeroom/modules/quartz/utils/QuartzManage.java create mode 100644 system/src/main/java/com/storeroom/modules/quartz/utils/QuartzRunnable.java diff --git a/APIService/pom.xml b/APIService/pom.xml index 5d20796..84154ef 100644 --- a/APIService/pom.xml +++ b/APIService/pom.xml @@ -17,4 +17,12 @@ 17 + + + com.storeroom + common + 1.0 + + + \ No newline at end of file diff --git a/APIService/src/main/java/com/storeroom/controller/TestApiServiceController.java b/APIService/src/main/java/com/storeroom/controller/TestApiServiceController.java new file mode 100644 index 0000000..c301e7c --- /dev/null +++ b/APIService/src/main/java/com/storeroom/controller/TestApiServiceController.java @@ -0,0 +1,26 @@ +package com.storeroom.controller; + + +import com.storeroom.annotaion.rest.AnonymousGetMapping; +import com.storeroom.service.ApiService; +import com.storeroom.utils.ApiResponse; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/service/") +@Api(tags = "测试第三方接口") +@RequiredArgsConstructor +public class TestApiServiceController { + + private final ApiService apiService; + + @ApiOperation("获取库房token") + @AnonymousGetMapping("token") + public ApiResponse getToken() { + return ApiResponse.success(apiService.getToken()); + } +} diff --git a/APIService/src/main/java/com/storeroom/service/ApiService.java b/APIService/src/main/java/com/storeroom/service/ApiService.java new file mode 100644 index 0000000..862b35d --- /dev/null +++ b/APIService/src/main/java/com/storeroom/service/ApiService.java @@ -0,0 +1,10 @@ +package com.storeroom.service; + +public interface ApiService { + + /** + * 获取环控token + * @return / + */ + String getToken(); +} diff --git a/APIService/src/main/java/com/storeroom/service/dto/ResultDto.java b/APIService/src/main/java/com/storeroom/service/dto/ResultDto.java new file mode 100644 index 0000000..321ef06 --- /dev/null +++ b/APIService/src/main/java/com/storeroom/service/dto/ResultDto.java @@ -0,0 +1,19 @@ +package com.storeroom.service.dto; + + +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; +import java.util.List; + +@Getter +@Setter +public class ResultDto implements Serializable { + + private String Status; + + private String Message; + + private List Data; +} diff --git a/APIService/src/main/java/com/storeroom/service/impl/ApiServiceImpl.java b/APIService/src/main/java/com/storeroom/service/impl/ApiServiceImpl.java new file mode 100644 index 0000000..17c1147 --- /dev/null +++ b/APIService/src/main/java/com/storeroom/service/impl/ApiServiceImpl.java @@ -0,0 +1,44 @@ +package com.storeroom.service.impl; + +import com.storeroom.exception.BaseException; +import com.storeroom.service.ApiService; +import com.storeroom.utils.FastjsonUtils; +import com.storeroom.utils.HttpUtils; +import lombok.SneakyThrows; +import org.apache.http.HttpResponse; +import org.apache.http.util.EntityUtils; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.Map; + + +@Service +public class ApiServiceImpl implements ApiService { + + String access_token = ""; + + @SneakyThrows + @Override + public String getToken() { + + //根据code 换取access token + HashMap map = new HashMap<>(); + map.put("Content-type", "application/json"); + HttpResponse response = HttpUtils.doGet("http://jiton.8800.org:800", "/Api/Third/GetToken", "GET", map, null); + if (response.getStatusLine().getStatusCode() == 200) { + String s = EntityUtils.toString(response.getEntity()); + Map dateMap = FastjsonUtils.toJavaMap(s); + dateMap.forEach((k, v) -> { + if (k.equals("Data")) { + Map Data = FastjsonUtils.toJavaMap(v.toString()); + access_token = Data.get("access_token").toString(); + } + }); + return access_token; + } else { + throw new BaseException("访问失败" + response.getStatusLine().getStatusCode() + ""); + } + + } +} diff --git a/common/pom.xml b/common/pom.xml index a920517..179bdfa 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -27,6 +27,16 @@ hibernate-validator 7.0.4.Final + + + org.apache.httpcomponents + httpcore + 4.4.15 + + + org.apache.httpcomponents + httpclient + \ No newline at end of file diff --git a/common/src/main/java/com/storeroom/config/RestTempleConfig.java b/common/src/main/java/com/storeroom/config/RestTempleConfig.java new file mode 100644 index 0000000..741df15 --- /dev/null +++ b/common/src/main/java/com/storeroom/config/RestTempleConfig.java @@ -0,0 +1,33 @@ +package com.storeroom.config; + + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.web.client.RestTemplate; + + +@Configuration +public class RestTempleConfig { + // 启动的时候要注意,由于我们在controller中注入了RestTemplate,所以启动的时候需要实例化该类的一个实例 + @Autowired + private RestTemplateBuilder builder; + + // 使用RestTemplateBuilder来实例化RestTemplate对象,spring默认已经注入了RestTemplateBuilder实例 + @Bean + public RestTemplate restTemplate() { + return builder.build(); + } + + @Bean + public RestTemplate customRestTemplate() { + HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory(); + httpRequestFactory.setConnectionRequestTimeout(3000); + httpRequestFactory.setConnectTimeout(3000); + httpRequestFactory.setReadTimeout(3000); + return new RestTemplate(httpRequestFactory); + } +} + diff --git a/common/src/main/java/com/storeroom/utils/FastjsonUtils.java b/common/src/main/java/com/storeroom/utils/FastjsonUtils.java new file mode 100644 index 0000000..df2f76a --- /dev/null +++ b/common/src/main/java/com/storeroom/utils/FastjsonUtils.java @@ -0,0 +1,115 @@ +package com.storeroom.utils; + +import com.alibaba.fastjson.*; +import com.alibaba.fastjson.serializer.SerializerFeature; +import com.alibaba.fastjson.util.ParameterizedTypeImpl; + +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +public class FastjsonUtils { + + public static ParameterizedType makeJavaType(Type rawType, Type... typeArguments) { + return new ParameterizedTypeImpl(typeArguments, null, rawType); + } + + public static String toString(Object value) { + if (Objects.isNull(value)) { + return null; + } + if (value instanceof String) { + return (String) value; + } + return toJSONString(value); + } + + public static String toJSONString(Object value) { + return JSON.toJSONString(value, SerializerFeature.DisableCircularReferenceDetect); + } + + public static String toPrettyString(Object value) { + return JSON.toJSONString(value, SerializerFeature.DisableCircularReferenceDetect + , SerializerFeature.PrettyFormat); + } + + public static Object fromJavaObject(Object value) { + Object result = null; + if (Objects.nonNull(value) && (value instanceof String)) { + result = parseObject((String) value); + } else { + result = JSON.toJSON(value); + } + return result; + } + + public static Object parseObject(String content) { + return JSON.parseObject(content, Object.class); + } + + public static Object getJsonElement(JSONObject node, String name) { + return node.get(name); + } + + public static Object getJsonElement(JSONArray node, int index) { + return node.get(index); + } + + public static T toJavaObject(JSON node, Class clazz) { + return node.toJavaObject(clazz); + } + + public static T toJavaObject(JSON node, Type type) { + return node.toJavaObject(type); + } + + public static T toJavaObject(JSON node, TypeReference typeReference) { + return node.toJavaObject(typeReference); + } + + public static List toJavaList(JSON node, Class clazz) { + return node.toJavaObject(new TypeReference>(clazz){}); + } + + public static List toJavaList(JSON node) { + return node.toJavaObject(new TypeReference>(){}); + } + + public static Map toJavaMap(JSON node, Class clazz) { + return node.toJavaObject(new TypeReference>(clazz){}); + } + + public static Map toJavaMap(JSON node) { + return node.toJavaObject(new TypeReference>(){}); + } + + public static T toJavaObject(String content, Class clazz) { + return JSON.parseObject(content, clazz); + } + + public static T toJavaObject(String content, Type type) { + return JSON.parseObject(content, type); + } + + public static T toJavaObject(String content, TypeReference typeReference) { + return JSON.parseObject(content, typeReference); + } + + public static List toJavaList(String content, Class clazz) { + return JSON.parseObject(content, new TypeReference>(clazz){}); + } + + public static List toJavaList(String content) { + return JSON.parseObject(content, new TypeReference>(){}); + } + + public static Map toJavaMap(String content, Class clazz) { + return JSON.parseObject(content, new TypeReference>(clazz){}); + } + + public static Map toJavaMap(String content) { + return JSON.parseObject(content, new TypeReference>(){}); + } +} diff --git a/common/src/main/java/com/storeroom/utils/HttpUtils.java b/common/src/main/java/com/storeroom/utils/HttpUtils.java new file mode 100644 index 0000000..110e281 --- /dev/null +++ b/common/src/main/java/com/storeroom/utils/HttpUtils.java @@ -0,0 +1,318 @@ +package com.storeroom.utils; + + +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.client.HttpClient; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.conn.ClientConnectionManager; +import org.apache.http.conn.scheme.Scheme; +import org.apache.http.conn.scheme.SchemeRegistry; +import org.apache.http.conn.ssl.SSLSocketFactory; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.message.BasicNameValuePair; + +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + + +public class HttpUtils { + /** + * get + * 发送get请求 + * + * @param host 主机地址 + * @param path 请求路径 + * @param method 请求方法 get + * @param headers 请求头数据,使用map封装 + * @param querys 请求参数,使用map封装 + * @return + * @throws Exception + */ + public static HttpResponse doGet(String host, String path, String method, + Map headers, + Map querys) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpGet request = new HttpGet(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + return httpClient.execute(request); + } + + /** + * post form + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param bodys 请求体,使用map封装 + * @return + * @throws Exception + */ + public static HttpResponse doPost(String host, String path, String method, + Map headers, + Map querys, + Map bodys) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPost request = new HttpPost(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (bodys != null) { + List nameValuePairList = new ArrayList(); + + for (String key : bodys.keySet()) { + nameValuePairList.add(new BasicNameValuePair(key, bodys.get(key))); + } + UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nameValuePairList, "utf-8"); + formEntity.setContentType("application/x-www-form-urlencoded; charset=UTF-8"); + request.setEntity(formEntity); + } + + return httpClient.execute(request); + } + + /** + * Post String + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param body + * @return + * @throws Exception + */ + public static HttpResponse doPost(String host, String path, String method, + Map headers, + Map querys, + String body) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPost request = new HttpPost(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (StringUtils.isNotBlank(body)) { + request.setEntity(new StringEntity(body, "utf-8")); + } + + return httpClient.execute(request); + } + + /** + * Post stream + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param body + * @return + * @throws Exception + */ + public static HttpResponse doPost(String host, String path, String method, + Map headers, + Map querys, + byte[] body) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPost request = new HttpPost(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (body != null) { + request.setEntity(new ByteArrayEntity(body)); + } + + return httpClient.execute(request); + } + + /** + * Put String + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param body + * @return + * @throws Exception + */ + public static HttpResponse doPut(String host, String path, String method, + Map headers, + Map querys, + String body) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPut request = new HttpPut(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (StringUtils.isNotBlank(body)) { + request.setEntity(new StringEntity(body, "utf-8")); + } + + return httpClient.execute(request); + } + + /** + * Put stream + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param body + * @return + * @throws Exception + */ + public static HttpResponse doPut(String host, String path, String method, + Map headers, + Map querys, + byte[] body) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPut request = new HttpPut(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (body != null) { + request.setEntity(new ByteArrayEntity(body)); + } + + return httpClient.execute(request); + } + + /** + * Delete + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @return + * @throws Exception + */ + public static HttpResponse doDelete(String host, String path, String method, + Map headers, + Map querys) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpDelete request = new HttpDelete(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + return httpClient.execute(request); + } + + private static String buildUrl(String host, String path, Map querys) throws UnsupportedEncodingException { + StringBuilder sbUrl = new StringBuilder(); + sbUrl.append(host); + if (!StringUtils.isBlank(path)) { + sbUrl.append(path); + } + if (null != querys) { + StringBuilder sbQuery = new StringBuilder(); + for (Map.Entry query : querys.entrySet()) { + if (0 < sbQuery.length()) { + sbQuery.append("&"); + } + if (StringUtils.isBlank(query.getKey()) && !StringUtils.isBlank(query.getValue())) { + sbQuery.append(query.getValue()); + } + if (!StringUtils.isBlank(query.getKey())) { + sbQuery.append(query.getKey()); + if (!StringUtils.isBlank(query.getValue())) { + sbQuery.append("="); + sbQuery.append(URLEncoder.encode(query.getValue(), "utf-8")); + } + } + } + if (0 < sbQuery.length()) { + sbUrl.append("?").append(sbQuery); + } + } + + return sbUrl.toString(); + } + + private static HttpClient wrapClient(String host) { + HttpClient httpClient = new DefaultHttpClient(); + if (host.startsWith("https://")) { + sslClient(httpClient); + } + + return httpClient; + } + + private static void sslClient(HttpClient httpClient) { + try { + SSLContext ctx = SSLContext.getInstance("TLS"); + X509TrustManager tm = new X509TrustManager() { + public X509Certificate[] getAcceptedIssuers() { + return null; + } + + public void checkClientTrusted(X509Certificate[] xcs, String str) { + + } + + public void checkServerTrusted(X509Certificate[] xcs, String str) { + + } + }; + ctx.init(null, new TrustManager[]{tm}, null); + SSLSocketFactory ssf = new SSLSocketFactory(ctx); + ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + ClientConnectionManager ccm = httpClient.getConnectionManager(); + SchemeRegistry registry = ccm.getSchemeRegistry(); + registry.register(new Scheme("https", 443, ssf)); + } catch (KeyManagementException ex) { + throw new RuntimeException(ex); + } catch (NoSuchAlgorithmException ex) { + throw new RuntimeException(ex); + } + } +} + + diff --git a/common/src/test/java/TestHttp.java b/common/src/test/java/TestHttp.java new file mode 100644 index 0000000..48612da --- /dev/null +++ b/common/src/test/java/TestHttp.java @@ -0,0 +1,34 @@ +import com.storeroom.utils.FastjsonUtils; +import com.storeroom.utils.HttpUtils; +import org.apache.http.HttpResponse; +import org.apache.http.util.EntityUtils; +import org.junit.jupiter.api.Test; + + +import java.util.HashMap; + +public class TestHttp { + + @Test + void test1() throws Exception { + //根据code 换取access token + HashMap map = new HashMap<>(); + map.put("Content-type", "application/json"); + + HttpResponse response = HttpUtils.doGet("http://jiton.8800.org:800", "/Api/Third/GetToken", "GET", map, null); + if (response.getStatusLine().getStatusCode() == 200) { + System.out.println("访问成功"); + //将获取的结果转换为json字符串形式 + String s = EntityUtils.toString(response.getEntity()); + Object a = FastjsonUtils.toJavaMap(s); + System.out.println(a); + //使用fastjson将字符串转换为需要的对象 +// JSON.parseObject() +// public static JSONObject parseObject(String text, Feature... features) + } else { + System.out.println("访问失败" + response.getStatusLine().getStatusCode()); + } + + } + +} diff --git a/storeroom/src/main/java/com/storeroom/modules/device/service/dto/DeviceSpecParamDto.java b/storeroom/src/main/java/com/storeroom/modules/device/service/dto/DeviceSpecParamDto.java index 2cdac2a..626482f 100644 --- a/storeroom/src/main/java/com/storeroom/modules/device/service/dto/DeviceSpecParamDto.java +++ b/storeroom/src/main/java/com/storeroom/modules/device/service/dto/DeviceSpecParamDto.java @@ -1,6 +1,5 @@ package com.storeroom.modules.device.service.dto; -import com.alibaba.fastjson.annotation.JSONField; import com.storeroom.base.BaseDTO; import com.storeroom.modules.device.domain.DeviceInfo; import lombok.Getter; diff --git a/system/src/main/java/com/storeroom/modules/quartz/config/JobRunner.java b/system/src/main/java/com/storeroom/modules/quartz/config/JobRunner.java new file mode 100644 index 0000000..430e70e --- /dev/null +++ b/system/src/main/java/com/storeroom/modules/quartz/config/JobRunner.java @@ -0,0 +1,36 @@ +package com.storeroom.modules.quartz.config; + +import com.storeroom.modules.quartz.domain.QuartzJob; +import com.storeroom.modules.quartz.repository.QuartzJobRepository; +import com.storeroom.modules.quartz.utils.QuartzManage; +import lombok.RequiredArgsConstructor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.stereotype.Component; + +import java.util.List; + + +@Component +@RequiredArgsConstructor +public class JobRunner implements ApplicationRunner { + + private static final Logger log = LoggerFactory.getLogger(JobRunner.class); + private final QuartzJobRepository quartzJobRepository; + private final QuartzManage quartzManage; + + /** + * 项目启动时重新激活启用的定时任务 + * + * @param applicationArguments / + */ + @Override + public void run(ApplicationArguments applicationArguments) { + log.info("--------------------注入系统定时任务------------------"); + List quartzJobs = quartzJobRepository.findByIsPauseIsFalse(); + quartzJobs.forEach(quartzManage::addJob); + log.info("--------------------定时任务注入完成------------------"); + } +} diff --git a/system/src/main/java/com/storeroom/modules/quartz/config/QuartzConfig.java b/system/src/main/java/com/storeroom/modules/quartz/config/QuartzConfig.java new file mode 100644 index 0000000..fb2635d --- /dev/null +++ b/system/src/main/java/com/storeroom/modules/quartz/config/QuartzConfig.java @@ -0,0 +1,33 @@ +package com.storeroom.modules.quartz.config; + + +import org.quartz.spi.TriggerFiredBundle; +import org.springframework.beans.factory.config.AutowireCapableBeanFactory; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.quartz.AdaptableJobFactory; +import org.springframework.stereotype.Component; + +@Configuration +public class QuartzConfig { + + /** + * 解决Job中注入Spring Bean为null的问题 + */ + @Component("quartzJobFactory") + public static class QuartzJobFactory extends AdaptableJobFactory { + + private final AutowireCapableBeanFactory capableBeanFactory; + + public QuartzJobFactory(AutowireCapableBeanFactory capableBeanFactory) { + this.capableBeanFactory = capableBeanFactory; + } + + @Override + protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception { + //调用父类的方法,把Job注入到spring中 + Object jobInstance = super.createJobInstance(bundle); + capableBeanFactory.autowireBean(jobInstance); + return jobInstance; + } + } +} diff --git a/system/src/main/java/com/storeroom/modules/quartz/domain/QuartzJob.java b/system/src/main/java/com/storeroom/modules/quartz/domain/QuartzJob.java new file mode 100644 index 0000000..021f4bc --- /dev/null +++ b/system/src/main/java/com/storeroom/modules/quartz/domain/QuartzJob.java @@ -0,0 +1,68 @@ +package com.storeroom.modules.quartz.domain; + +import com.storeroom.base.BaseEntity; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; + +import javax.persistence.*; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.io.Serializable; + + +@Getter +@Setter +@Entity +@Table(name = "sys_quartz_job") +public class QuartzJob extends BaseEntity implements Serializable { + + public static final String JOB_KEY = "JOB_KEY"; + + @Id + @Column(name = "job_id") + @NotNull(groups = {Update.class}) + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Transient + @ApiModelProperty(value = "用于子任务唯一标识", hidden = true) + private String uuid; + + @ApiModelProperty(value = "定时器名称") + private String jobName; + + @NotBlank + @ApiModelProperty(value = "Bean名称") + private String beanName; + + @NotBlank + @ApiModelProperty(value = "方法名称") + private String methodName; + + @ApiModelProperty(value = "参数") + private String params; + + @NotBlank + @ApiModelProperty(value = "cron表达式") + private String cronExpression; + + @ApiModelProperty(value = "状态,暂时或启动") + private Boolean isPause = false; + + @ApiModelProperty(value = "负责人") + private String personInCharge; + + @ApiModelProperty(value = "报警邮箱") + private String email; + + @ApiModelProperty(value = "子任务") + private String subTask; + + @ApiModelProperty(value = "失败后暂停") + private Boolean pauseAfterFailure; + + @NotBlank + @ApiModelProperty(value = "备注") + private String description; +} diff --git a/system/src/main/java/com/storeroom/modules/quartz/domain/QuartzLog.java b/system/src/main/java/com/storeroom/modules/quartz/domain/QuartzLog.java new file mode 100644 index 0000000..b22ca12 --- /dev/null +++ b/system/src/main/java/com/storeroom/modules/quartz/domain/QuartzLog.java @@ -0,0 +1,50 @@ +package com.storeroom.modules.quartz.domain; + + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.hibernate.annotations.CreationTimestamp; + +import javax.persistence.*; +import java.io.Serializable; +import java.sql.Timestamp; + +@Entity +@Data +@Table(name = "sys_quartz_log") +public class QuartzLog implements Serializable { + + @Id + @Column(name = "log_id") + @ApiModelProperty(value = "ID", hidden = true) + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ApiModelProperty(value = "任务名称", hidden = true) + private String jobName; + + @ApiModelProperty(value = "bean名称", hidden = true) + private String beanName; + + @ApiModelProperty(value = "方法名称", hidden = true) + private String methodName; + + @ApiModelProperty(value = "参数", hidden = true) + private String params; + + @ApiModelProperty(value = "cron表达式", hidden = true) + private String cronExpression; + + @ApiModelProperty(value = "状态", hidden = true) + private Boolean isSuccess; + + @ApiModelProperty(value = "异常详情", hidden = true) + private String exceptionDetail; + + @ApiModelProperty(value = "执行耗时", hidden = true) + private Long time; + + @CreationTimestamp + @ApiModelProperty(value = "创建时间", hidden = true) + private Timestamp createTime; +} diff --git a/system/src/main/java/com/storeroom/modules/quartz/repository/QuartzJobRepository.java b/system/src/main/java/com/storeroom/modules/quartz/repository/QuartzJobRepository.java new file mode 100644 index 0000000..97742d3 --- /dev/null +++ b/system/src/main/java/com/storeroom/modules/quartz/repository/QuartzJobRepository.java @@ -0,0 +1,16 @@ +package com.storeroom.modules.quartz.repository; + +import com.storeroom.modules.quartz.domain.QuartzJob; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; + +import java.util.List; + +public interface QuartzJobRepository extends JpaRepository, JpaSpecificationExecutor { + + /** + * 查询启用的任务 + * @return List + */ + List findByIsPauseIsFalse(); +} diff --git a/system/src/main/java/com/storeroom/modules/quartz/repository/QuartzLogRepository.java b/system/src/main/java/com/storeroom/modules/quartz/repository/QuartzLogRepository.java new file mode 100644 index 0000000..a694ff8 --- /dev/null +++ b/system/src/main/java/com/storeroom/modules/quartz/repository/QuartzLogRepository.java @@ -0,0 +1,8 @@ +package com.storeroom.modules.quartz.repository; + +import com.storeroom.modules.quartz.domain.QuartzLog; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; + +public interface QuartzLogRepository extends JpaRepository, JpaSpecificationExecutor { +} diff --git a/system/src/main/java/com/storeroom/modules/quartz/service/QuartzJobService.java b/system/src/main/java/com/storeroom/modules/quartz/service/QuartzJobService.java new file mode 100644 index 0000000..5670339 --- /dev/null +++ b/system/src/main/java/com/storeroom/modules/quartz/service/QuartzJobService.java @@ -0,0 +1,104 @@ +package com.storeroom.modules.quartz.service; + +import com.storeroom.modules.quartz.domain.QuartzJob; +import com.storeroom.modules.quartz.domain.QuartzLog; +import com.storeroom.modules.system.service.dto.JobQueryCriteria; +import org.springframework.data.domain.Pageable; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.List; +import java.util.Set; + +public interface QuartzJobService { + + /** + * 分页查询 + * @param criteria 条件 + * @param pageable 分页参数 + * @return / + */ + Object queryAll(JobQueryCriteria criteria, Pageable pageable); + + /** + * 查询全部 + * @param criteria 条件 + * @return / + */ + List queryAll(JobQueryCriteria criteria); + + /** + * 分页查询日志 + * @param criteria 条件 + * @param pageable 分页参数 + * @return / + */ + Object queryAllLog(JobQueryCriteria criteria, Pageable pageable); + + /** + * 查询全部 + * @param criteria 条件 + * @return / + */ + List queryAllLog(JobQueryCriteria criteria); + + /** + * 创建 + * @param resources / + */ + void create(QuartzJob resources); + + /** + * 编辑 + * @param resources / + */ + void update(QuartzJob resources); + + /** + * 删除任务 + * @param ids / + */ + void delete(Set ids); + + /** + * 根据ID查询 + * @param id ID + * @return / + */ + QuartzJob findById(Long id); + + /** + * 更改定时任务状态 + * @param quartzJob / + */ + void updateIsPause(QuartzJob quartzJob); + + /** + * 立即执行定时任务 + * @param quartzJob / + */ + void execution(QuartzJob quartzJob); + + /** + * 导出定时任务 + * @param queryAll 待导出的数据 + * @param response / + * @throws IOException / + */ + void download(List queryAll, HttpServletResponse response) throws IOException; + + /** + * 导出定时任务日志 + * @param queryAllLog 待导出的数据 + * @param response / + * @throws IOException / + */ + void downloadLog(List queryAllLog, HttpServletResponse response) throws IOException; + + /** + * 执行子任务 + * @param tasks / + * @throws InterruptedException / + */ + void executionSubJob(String[] tasks) throws InterruptedException; +} diff --git a/system/src/main/java/com/storeroom/modules/quartz/service/dto/JobQueryCriteria.java b/system/src/main/java/com/storeroom/modules/quartz/service/dto/JobQueryCriteria.java new file mode 100644 index 0000000..993a8d5 --- /dev/null +++ b/system/src/main/java/com/storeroom/modules/quartz/service/dto/JobQueryCriteria.java @@ -0,0 +1,21 @@ +package com.storeroom.modules.quartz.service.dto; + + +import com.storeroom.annotaion.Query; +import lombok.Data; + +import java.sql.Timestamp; +import java.util.List; + +@Data +public class JobQueryCriteria { + + @Query(type = Query.Type.INNER_LIKE) + private String jobName; + + @Query + private Boolean isSuccess; + + @Query(type = Query.Type.BETWEEN) + private List createTime; +} diff --git a/system/src/main/java/com/storeroom/modules/quartz/service/impl/QuartzJobServiceImpl.java b/system/src/main/java/com/storeroom/modules/quartz/service/impl/QuartzJobServiceImpl.java new file mode 100644 index 0000000..e8e654d --- /dev/null +++ b/system/src/main/java/com/storeroom/modules/quartz/service/impl/QuartzJobServiceImpl.java @@ -0,0 +1,180 @@ +package com.storeroom.modules.quartz.service.impl; + +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.StrUtil; +import com.storeroom.exception.BaseException; +import com.storeroom.modules.quartz.domain.QuartzJob; +import com.storeroom.modules.quartz.domain.QuartzLog; +import com.storeroom.modules.quartz.repository.QuartzJobRepository; +import com.storeroom.modules.quartz.repository.QuartzLogRepository; +import com.storeroom.modules.quartz.service.QuartzJobService; +import com.storeroom.modules.quartz.utils.QuartzManage; +import com.storeroom.modules.system.service.dto.JobQueryCriteria; +import com.storeroom.utils.*; +import lombok.RequiredArgsConstructor; +import org.quartz.CronExpression; +import org.springframework.data.domain.Pageable; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.*; + + +@RequiredArgsConstructor +@Service(value = "quartzJobService") +public class QuartzJobServiceImpl implements QuartzJobService { + + private final QuartzJobRepository quartzJobRepository; + private final QuartzLogRepository quartzLogRepository; + private final QuartzManage quartzManage; + private final RedisUtils redisUtils; + + @Override + public Object queryAll(JobQueryCriteria criteria, Pageable pageable){ + return PageUtil.toPage(quartzJobRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable)); + } + + @Override + public Object queryAllLog(JobQueryCriteria criteria, Pageable pageable){ + return PageUtil.toPage(quartzLogRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable)); + } + + @Override + public List queryAll(JobQueryCriteria criteria) { + return quartzJobRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)); + } + + @Override + public List queryAllLog(JobQueryCriteria criteria) { + return quartzLogRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)); + } + + @Override + public QuartzJob findById(Long id) { + QuartzJob quartzJob = quartzJobRepository.findById(id).orElseGet(QuartzJob::new); + ValidationUtil.isNull(quartzJob.getId(),"QuartzJob","id",id); + return quartzJob; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void create(QuartzJob resources) { + if (!CronExpression.isValidExpression(resources.getCronExpression())){ + throw new BaseException("cron表达式格式错误"); + } + resources = quartzJobRepository.save(resources); + quartzManage.addJob(resources); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void update(QuartzJob resources) { + if (!CronExpression.isValidExpression(resources.getCronExpression())){ + throw new BaseException("cron表达式格式错误"); + } + if(StringUtils.isNotBlank(resources.getSubTask())){ + List tasks = Arrays.asList(resources.getSubTask().split("[,,]")); + if (tasks.contains(resources.getId().toString())) { + throw new BaseException("子任务中不能添加当前任务ID"); + } + } + resources = quartzJobRepository.save(resources); + quartzManage.updateJobCron(resources); + } + + @Override + public void updateIsPause(QuartzJob quartzJob) { + if (quartzJob.getIsPause()) { + quartzManage.resumeJob(quartzJob); + quartzJob.setIsPause(false); + } else { + quartzManage.pauseJob(quartzJob); + quartzJob.setIsPause(true); + } + quartzJobRepository.save(quartzJob); + } + + @Override + public void execution(QuartzJob quartzJob) { + quartzManage.runJobNow(quartzJob); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void delete(Set ids) { + for (Long id : ids) { + QuartzJob quartzJob = findById(id); + quartzManage.deleteJob(quartzJob); + quartzJobRepository.delete(quartzJob); + } + } + + @Async + @Override + @Transactional(rollbackFor = Exception.class) + public void executionSubJob(String[] tasks) throws InterruptedException { + for (String id : tasks) { + if (StrUtil.isBlank(id)) { + // 如果是手动清除子任务id,会出现id为空字符串的问题 + continue; + } + QuartzJob quartzJob = findById(Long.parseLong(id)); + // 执行任务 + String uuid = NanoIdUtils.randomNanoId(); + quartzJob.setUuid(uuid); + // 执行任务 + execution(quartzJob); + // 获取执行状态,如果执行失败则停止后面的子任务执行 + Boolean result = (Boolean) redisUtils.get(uuid); + while (result == null) { + // 休眠5秒,再次获取子任务执行情况 + Thread.sleep(5000); + result = (Boolean) redisUtils.get(uuid); + } + if(!result){ + redisUtils.del(uuid); + break; + } + } + } + + @Override + public void download(List quartzJobs, HttpServletResponse response) throws IOException { + List> list = new ArrayList<>(); + for (QuartzJob quartzJob : quartzJobs) { + Map map = new LinkedHashMap<>(); + map.put("任务名称", quartzJob.getJobName()); + map.put("Bean名称", quartzJob.getBeanName()); + map.put("执行方法", quartzJob.getMethodName()); + map.put("参数", quartzJob.getParams()); + map.put("表达式", quartzJob.getCronExpression()); + map.put("状态", quartzJob.getIsPause() ? "暂停中" : "运行中"); + map.put("描述", quartzJob.getDescription()); + map.put("创建日期", quartzJob.getCreateTime()); + list.add(map); + } + FileUtil.downloadExcel(list, response); + } + + @Override + public void downloadLog(List queryAllLog, HttpServletResponse response) throws IOException { + List> list = new ArrayList<>(); + for (QuartzLog quartzLog : queryAllLog) { + Map map = new LinkedHashMap<>(); + map.put("任务名称", quartzLog.getJobName()); + map.put("Bean名称", quartzLog.getBeanName()); + map.put("执行方法", quartzLog.getMethodName()); + map.put("参数", quartzLog.getParams()); + map.put("表达式", quartzLog.getCronExpression()); + map.put("异常详情", quartzLog.getExceptionDetail()); + map.put("耗时/毫秒", quartzLog.getTime()); + map.put("状态", quartzLog.getIsSuccess() ? "成功" : "失败"); + map.put("创建日期", quartzLog.getCreateTime()); + list.add(map); + } + FileUtil.downloadExcel(list, response); + } +} diff --git a/system/src/main/java/com/storeroom/modules/quartz/task/TestTask.java b/system/src/main/java/com/storeroom/modules/quartz/task/TestTask.java new file mode 100644 index 0000000..dbbb718 --- /dev/null +++ b/system/src/main/java/com/storeroom/modules/quartz/task/TestTask.java @@ -0,0 +1,24 @@ +package com.storeroom.modules.quartz.task; + + +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; + +@Slf4j +@Async +@Component +public class TestTask { + + public void run(){ + log.info("run 执行成功"); + } + + public void run1(String str){ + log.info("run1 执行成功,参数为: {}" + str); + } + + public void run2(){ + log.info("run2 执行成功"); + } +} diff --git a/system/src/main/java/com/storeroom/modules/quartz/utils/ExecutionJob.java b/system/src/main/java/com/storeroom/modules/quartz/utils/ExecutionJob.java new file mode 100644 index 0000000..40b1275 --- /dev/null +++ b/system/src/main/java/com/storeroom/modules/quartz/utils/ExecutionJob.java @@ -0,0 +1,99 @@ +package com.storeroom.modules.quartz.utils; + +import cn.hutool.extra.template.Template; +import cn.hutool.extra.template.TemplateConfig; +import cn.hutool.extra.template.TemplateEngine; +import cn.hutool.extra.template.TemplateUtil; +import com.storeroom.modules.quartz.domain.QuartzJob; +import com.storeroom.modules.quartz.domain.QuartzLog; +import com.storeroom.modules.quartz.repository.QuartzLogRepository; +import com.storeroom.modules.quartz.service.QuartzJobService; +import com.storeroom.utils.RedisUtils; +import com.storeroom.utils.SpringContextHolder; +import com.storeroom.utils.StringUtils; +import com.storeroom.utils.ThrowableUtil; +import org.quartz.JobExecutionContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.quartz.QuartzJobBean; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + + +@Async +public class ExecutionJob extends QuartzJobBean { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + + @Override + public void executeInternal(JobExecutionContext context) { + // 创建单个线程 + ExecutorService executor = Executors.newSingleThreadExecutor(); + // 获取任务 + QuartzJob quartzJob = (QuartzJob) context.getMergedJobDataMap().get(QuartzJob.JOB_KEY); + // 获取spring bean + QuartzLogRepository quartzLogRepository = SpringContextHolder.getBean(QuartzLogRepository.class); + QuartzJobService quartzJobService = SpringContextHolder.getBean(QuartzJobService.class); + RedisUtils redisUtils = SpringContextHolder.getBean(RedisUtils.class); + + String uuid = quartzJob.getUuid(); + + QuartzLog log = new QuartzLog(); + log.setJobName(quartzJob.getJobName()); + log.setBeanName(quartzJob.getBeanName()); + log.setMethodName(quartzJob.getMethodName()); + log.setParams(quartzJob.getParams()); + long startTime = System.currentTimeMillis(); + log.setCronExpression(quartzJob.getCronExpression()); + try { + // 执行任务 + QuartzRunnable task = new QuartzRunnable(quartzJob.getBeanName(), quartzJob.getMethodName(), quartzJob.getParams()); + Future future = executor.submit(task); + future.get(); + long times = System.currentTimeMillis() - startTime; + log.setTime(times); + if(StringUtils.isNotBlank(uuid)) { + redisUtils.set(uuid, true); + } + // 任务状态 + log.setIsSuccess(true); + logger.info("任务执行成功,任务名称:" + quartzJob.getJobName() + ", 执行时间:" + times + "毫秒"); + // 判断是否存在子任务 + if(StringUtils.isNotBlank(quartzJob.getSubTask())){ + String[] tasks = quartzJob.getSubTask().split("[,,]"); + // 执行子任务 + quartzJobService.executionSubJob(tasks); + } + } catch (Exception e) { + if(StringUtils.isNotBlank(uuid)) { + redisUtils.set(uuid, false); + } + logger.error("任务执行失败,任务名称:" + quartzJob.getJobName()); + long times = System.currentTimeMillis() - startTime; + log.setTime(times); + // 任务状态 0:成功 1:失败 + log.setIsSuccess(false); + log.setExceptionDetail(ThrowableUtil.getStackTrace(e)); + // 任务如果失败了则暂停 + if(quartzJob.getPauseAfterFailure() != null && quartzJob.getPauseAfterFailure()){ + quartzJob.setIsPause(false); + //更新状态 + quartzJobService.updateIsPause(quartzJob); + } + + } finally { + quartzLogRepository.save(log); + executor.shutdown(); + } + } + + +} diff --git a/system/src/main/java/com/storeroom/modules/quartz/utils/QuartzManage.java b/system/src/main/java/com/storeroom/modules/quartz/utils/QuartzManage.java new file mode 100644 index 0000000..ed55eda --- /dev/null +++ b/system/src/main/java/com/storeroom/modules/quartz/utils/QuartzManage.java @@ -0,0 +1,157 @@ +package com.storeroom.modules.quartz.utils; + + +import com.storeroom.exception.BaseException; +import com.storeroom.modules.quartz.domain.QuartzJob; +import lombok.extern.slf4j.Slf4j; +import org.quartz.*; +import org.quartz.impl.triggers.CronTriggerImpl; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.Date; + +import static org.quartz.TriggerBuilder.newTrigger; + +@Slf4j +@Component +public class QuartzManage { + + private static final String JOB_NAME = "TASK_"; + + @Resource + private Scheduler scheduler; + + public void addJob(QuartzJob quartzJob){ + try { + // 构建job信息 + JobDetail jobDetail = JobBuilder.newJob(ExecutionJob.class). + withIdentity(JOB_NAME + quartzJob.getId()).build(); + + //通过触发器名和cron 表达式创建 Trigger + Trigger cronTrigger = newTrigger() + .withIdentity(JOB_NAME + quartzJob.getId()) + .startNow() + .withSchedule(CronScheduleBuilder.cronSchedule(quartzJob.getCronExpression())) + .build(); + + cronTrigger.getJobDataMap().put(QuartzJob.JOB_KEY, quartzJob); + + //重置启动时间 + ((CronTriggerImpl)cronTrigger).setStartTime(new Date()); + + //执行定时任务 + scheduler.scheduleJob(jobDetail,cronTrigger); + + // 暂停任务 + if (quartzJob.getIsPause()) { + pauseJob(quartzJob); + } + } catch (Exception e){ + log.error("创建定时任务失败", e); + throw new BaseException("创建定时任务失败"); + } + } + + /** + * 更新job cron表达式 + * @param quartzJob / + */ + public void updateJobCron(QuartzJob quartzJob){ + try { + TriggerKey triggerKey = TriggerKey.triggerKey(JOB_NAME + quartzJob.getId()); + CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); + // 如果不存在则创建一个定时任务 + if(trigger == null){ + addJob(quartzJob); + trigger = (CronTrigger) scheduler.getTrigger(triggerKey); + } + CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(quartzJob.getCronExpression()); + trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build(); + //重置启动时间 + ((CronTriggerImpl)trigger).setStartTime(new Date()); + trigger.getJobDataMap().put(QuartzJob.JOB_KEY,quartzJob); + + scheduler.rescheduleJob(triggerKey, trigger); + // 暂停任务 + if (quartzJob.getIsPause()) { + pauseJob(quartzJob); + } + } catch (Exception e){ + log.error("更新定时任务失败", e); + throw new BaseException("更新定时任务失败"); + } + + } + + /** + * 删除一个job + * @param quartzJob / + */ + public void deleteJob(QuartzJob quartzJob){ + try { + JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getId()); + scheduler.pauseJob(jobKey); + scheduler.deleteJob(jobKey); + } catch (Exception e){ + log.error("删除定时任务失败", e); + throw new BaseException("删除定时任务失败"); + } + } + + /** + * 恢复一个job + * @param quartzJob / + */ + public void resumeJob(QuartzJob quartzJob){ + try { + TriggerKey triggerKey = TriggerKey.triggerKey(JOB_NAME + quartzJob.getId()); + CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); + // 如果不存在则创建一个定时任务 + if(trigger == null) { + addJob(quartzJob); + } + JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getId()); + scheduler.resumeJob(jobKey); + } catch (Exception e){ + log.error("恢复定时任务失败", e); + throw new BaseException("恢复定时任务失败"); + } + } + + /** + * 立即执行job + * @param quartzJob / + */ + public void runJobNow(QuartzJob quartzJob){ + try { + TriggerKey triggerKey = TriggerKey.triggerKey(JOB_NAME + quartzJob.getId()); + CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); + // 如果不存在则创建一个定时任务 + if(trigger == null) { + addJob(quartzJob); + } + JobDataMap dataMap = new JobDataMap(); + dataMap.put(QuartzJob.JOB_KEY, quartzJob); + JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getId()); + scheduler.triggerJob(jobKey,dataMap); + } catch (Exception e){ + log.error("定时任务执行失败", e); + throw new BaseException("定时任务执行失败"); + } + } + + /** + * 暂停一个job + * @param quartzJob / + */ + public void pauseJob(QuartzJob quartzJob){ + try { + JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getId()); + scheduler.pauseJob(jobKey); + } catch (Exception e){ + log.error("定时任务暂停失败", e); + throw new BaseException("定时任务暂停失败"); + } + } +} diff --git a/system/src/main/java/com/storeroom/modules/quartz/utils/QuartzRunnable.java b/system/src/main/java/com/storeroom/modules/quartz/utils/QuartzRunnable.java new file mode 100644 index 0000000..d7fbf4e --- /dev/null +++ b/system/src/main/java/com/storeroom/modules/quartz/utils/QuartzRunnable.java @@ -0,0 +1,41 @@ +package com.storeroom.modules.quartz.utils; + +import com.storeroom.utils.SpringContextHolder; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.util.ReflectionUtils; + +import java.lang.reflect.Method; +import java.util.concurrent.Callable; + + +@Slf4j +public class QuartzRunnable implements Callable { + + private final Object target; + private final Method method; + private final String params; + + QuartzRunnable(String beanName, String methodName, String params) + throws NoSuchMethodException, SecurityException { + this.target = SpringContextHolder.getBean(beanName); + this.params = params; + if (StringUtils.isNotBlank(params)) { + this.method = target.getClass().getDeclaredMethod(methodName, String.class); + } else { + this.method = target.getClass().getDeclaredMethod(methodName); + } + } + + @Override + @SuppressWarnings("all") + public Object call() throws Exception { + ReflectionUtils.makeAccessible(method); + if (StringUtils.isNotBlank(params)) { + method.invoke(target, params); + } else { + method.invoke(target); + } + return null; + } +}