如何在 spring 启动时动态更改 @Scheduler cron 表达式?
How can I change @Scheduler cron expression dynamically in spring boot?
我正在尝试在特定时间呼叫 API。
但有时 api 调用可能会失败,所以我做了一个逻辑来检查 api 调用何时失败。
确认api调用失败后,我想将@Schedulercron表达式从当前的cron表达式更改为15分钟后。
如何动态更改 cron 表达式?
下面是我的API调用代码。
@Scheduled(cron="0 9 19 * * *", zone = "Asia/Seoul")
public void callAPi() throws InterruptedException {
swrList = new ArrayList<>();
List<GeoInfo> giList = gs.getGeoXY();
for(GeoInfo gi : giList) {
ShortWeatherReq swr = new ShortWeatherReq(APK.getApiKey(),"1",gi.getX(),gi.getY());
swr.setBaseDate(); //현재 날짜로 baseDate를 설정하는 메소드를 호출
swr.setNx(gi.getX()); //x좌표값 저장
swr.setNy(gi.getY()); //y좌표값 저장
swrList.add(swr); //list에 swr 추가
}
for(GeoInfo gi : giList) {
ShortWeatherReq swr = new ShortWeatherReq(APK.getApiKey(),"2",gi.getX(),gi.getY());
swr.setBaseDate(); //현재 날짜로 baseDate를 설정하는 메소드를 호출
swr.setNx(gi.getX()); //x좌표값 저장
swr.setNy(gi.getY()); //y좌표값 저장
swrList.add(swr); //list에 swr 추가
}
//위 객체를 가지고 이제 API를 호출할수 있게 Service에게 전해줘야 함
sws.setSwrList(swrList);
temperList = sws.callSW(); // API 통신 Service 호출
//Confirming API call failure
if(temperList.isEmpty()) { //온도 리스트가 비어있다면 진입
logger.warn("TemperList is empty");
//이제 여기서 메일을 보내주는 서비스를 만들어서 메일 전송을 해줘야 함
ms.sendErrorMail();
logger.info("-------------------");
logger.info("API Connection Fail");
}else {
logger.info("-------------------");
logger.info("API ConnectionSuccess");
logger.info("-------------------");
//List에 담긴 온도 DB에 저장
for(int i = 0;i<temperList.size();i++) {
Temperature temp = temperList.get(i);
ts.saveTemp(temp);
}
logger.info("DB Store Success");
}
}
首先,您应该在 App
class 上激活 Spring Retry
。
@SpringBootApplication
@EnableScheduling
@EnableRetry
public class App {
// something
}
然后您需要将 @Retryable
添加到您用作 @Scheduled
的方法中。
@Scheduled(cron="0 9 19 * * *", zone = "Asia/Seoul")
// Add this line
@Retryable(maxAttempts = 3, backoff = @Backoff(delay = 1000), value={ApiCallException.class})
public void callAPi() throws InterruptedException {
swrList = new ArrayList<>();
List<GeoInfo> giList = gs.getGeoXY();
for(GeoInfo gi : giList) {
ShortWeatherReq swr = new ShortWeatherReq(APK.getApiKey(),"1",gi.getX(),gi.getY());
swr.setBaseDate(); //현재 날짜로 baseDate를 설정하는 메소드를 호출
swr.setNx(gi.getX()); //x좌표값 저장
swr.setNy(gi.getY()); //y좌표값 저장
swrList.add(swr); //list에 swr 추가
}
for(GeoInfo gi : giList) {
ShortWeatherReq swr = new ShortWeatherReq(APK.getApiKey(),"2",gi.getX(),gi.getY());
swr.setBaseDate(); //현재 날짜로 baseDate를 설정하는 메소드를 호출
swr.setNx(gi.getX()); //x좌표값 저장
swr.setNy(gi.getY()); //y좌표값 저장
swrList.add(swr); //list에 swr 추가
}
//위 객체를 가지고 이제 API를 호출할수 있게 Service에게 전해줘야 함
sws.setSwrList(swrList);
temperList = sws.callSW(); // API 통신 Service 호출
//Confirming API call failure
if(temperList.isEmpty()) { //온도 리스트가 비어있다면 진입
// Add this line
throw new ApiCallException("API Connection Fail")
}else {
logger.info("-------------------");
logger.info("API ConnectionSuccess");
logger.info("-------------------");
//List에 담긴 온도 DB에 저장
for(int i = 0;i<temperList.size();i++) {
Temperature temp = temperList.get(i);
ts.saveTemp(temp);
}
logger.info("DB Store Success");
}
}
这里是用@Retryable
注解设置backoff
参数,设置你想要的下一个运行时。在与BackOffPolicies
相关的Spring Retry
文档中,做了如下定义。
When retrying after a transient failure, it often helps to wait a bit before trying again, because usually the failure is caused by some problem that can only be resolved by waiting. If a RetryCallback fails, the RetryTemplate can pause execution according to the BackoffPolicy.
您可以找到有关 Spring Retry
here 的详细信息。
虽然我的回答没有提供动态更改的 cron 语句,但我希望它能解决您的问题。
我正在尝试在特定时间呼叫 API。 但有时 api 调用可能会失败,所以我做了一个逻辑来检查 api 调用何时失败。
确认api调用失败后,我想将@Schedulercron表达式从当前的cron表达式更改为15分钟后。
如何动态更改 cron 表达式?
下面是我的API调用代码。
@Scheduled(cron="0 9 19 * * *", zone = "Asia/Seoul")
public void callAPi() throws InterruptedException {
swrList = new ArrayList<>();
List<GeoInfo> giList = gs.getGeoXY();
for(GeoInfo gi : giList) {
ShortWeatherReq swr = new ShortWeatherReq(APK.getApiKey(),"1",gi.getX(),gi.getY());
swr.setBaseDate(); //현재 날짜로 baseDate를 설정하는 메소드를 호출
swr.setNx(gi.getX()); //x좌표값 저장
swr.setNy(gi.getY()); //y좌표값 저장
swrList.add(swr); //list에 swr 추가
}
for(GeoInfo gi : giList) {
ShortWeatherReq swr = new ShortWeatherReq(APK.getApiKey(),"2",gi.getX(),gi.getY());
swr.setBaseDate(); //현재 날짜로 baseDate를 설정하는 메소드를 호출
swr.setNx(gi.getX()); //x좌표값 저장
swr.setNy(gi.getY()); //y좌표값 저장
swrList.add(swr); //list에 swr 추가
}
//위 객체를 가지고 이제 API를 호출할수 있게 Service에게 전해줘야 함
sws.setSwrList(swrList);
temperList = sws.callSW(); // API 통신 Service 호출
//Confirming API call failure
if(temperList.isEmpty()) { //온도 리스트가 비어있다면 진입
logger.warn("TemperList is empty");
//이제 여기서 메일을 보내주는 서비스를 만들어서 메일 전송을 해줘야 함
ms.sendErrorMail();
logger.info("-------------------");
logger.info("API Connection Fail");
}else {
logger.info("-------------------");
logger.info("API ConnectionSuccess");
logger.info("-------------------");
//List에 담긴 온도 DB에 저장
for(int i = 0;i<temperList.size();i++) {
Temperature temp = temperList.get(i);
ts.saveTemp(temp);
}
logger.info("DB Store Success");
}
}
首先,您应该在 App
class 上激活 Spring Retry
。
@SpringBootApplication
@EnableScheduling
@EnableRetry
public class App {
// something
}
然后您需要将 @Retryable
添加到您用作 @Scheduled
的方法中。
@Scheduled(cron="0 9 19 * * *", zone = "Asia/Seoul")
// Add this line
@Retryable(maxAttempts = 3, backoff = @Backoff(delay = 1000), value={ApiCallException.class})
public void callAPi() throws InterruptedException {
swrList = new ArrayList<>();
List<GeoInfo> giList = gs.getGeoXY();
for(GeoInfo gi : giList) {
ShortWeatherReq swr = new ShortWeatherReq(APK.getApiKey(),"1",gi.getX(),gi.getY());
swr.setBaseDate(); //현재 날짜로 baseDate를 설정하는 메소드를 호출
swr.setNx(gi.getX()); //x좌표값 저장
swr.setNy(gi.getY()); //y좌표값 저장
swrList.add(swr); //list에 swr 추가
}
for(GeoInfo gi : giList) {
ShortWeatherReq swr = new ShortWeatherReq(APK.getApiKey(),"2",gi.getX(),gi.getY());
swr.setBaseDate(); //현재 날짜로 baseDate를 설정하는 메소드를 호출
swr.setNx(gi.getX()); //x좌표값 저장
swr.setNy(gi.getY()); //y좌표값 저장
swrList.add(swr); //list에 swr 추가
}
//위 객체를 가지고 이제 API를 호출할수 있게 Service에게 전해줘야 함
sws.setSwrList(swrList);
temperList = sws.callSW(); // API 통신 Service 호출
//Confirming API call failure
if(temperList.isEmpty()) { //온도 리스트가 비어있다면 진입
// Add this line
throw new ApiCallException("API Connection Fail")
}else {
logger.info("-------------------");
logger.info("API ConnectionSuccess");
logger.info("-------------------");
//List에 담긴 온도 DB에 저장
for(int i = 0;i<temperList.size();i++) {
Temperature temp = temperList.get(i);
ts.saveTemp(temp);
}
logger.info("DB Store Success");
}
}
这里是用@Retryable
注解设置backoff
参数,设置你想要的下一个运行时。在与BackOffPolicies
相关的Spring Retry
文档中,做了如下定义。
When retrying after a transient failure, it often helps to wait a bit before trying again, because usually the failure is caused by some problem that can only be resolved by waiting. If a RetryCallback fails, the RetryTemplate can pause execution according to the BackoffPolicy.
您可以找到有关 Spring Retry
here 的详细信息。
虽然我的回答没有提供动态更改的 cron 语句,但我希望它能解决您的问题。