Home | 简体中文 | 繁体中文 | 杂文 | Github | 知乎专栏 | Facebook | Linkedin | Youtube | 打赏(Donations) | About
知乎专栏

38.2. spring-retry

38.2.1. spring-retry 依赖

添加依赖

			
		<dependency>
            <groupId>org.springframework.retry</groupId>
            <artifactId>spring-retry</artifactId>
            <version>2.0.12</version>
        </dependency>
			
			

38.2.2. @EnableRetry 启用重试

			
package cn.aigcsst;

import cn.aigcsst.websocket.WebsocketEndpoint;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.retry.annotation.EnableRetry;
import org.springframework.scheduling.annotation.EnableAsync;

@SpringBootApplication
@EnableJpaRepositories
@EnableAutoConfiguration
@EnableCaching
@EnableAsync
@EnableRetry
public class Application {
    private static final Logger logger = LoggerFactory.getLogger(Application.class);

    @Value("${spring.application.name}")
    public String name;

    static void main(String[] args) {
        ConfigurableApplicationContext applicationContext = SpringApplication.run(Application.class, args);
        WebsocketEndpoint.setApplicationContext(applicationContext);
    }

    @PostConstruct
    public void init() {
        logger.info(String.format("==================== %s 系统启动 ====================", name));
    }

    @PreDestroy
    public void destroy() {
        logger.info(String.format("==================== %s 系统销毁 ====================", name));
    }

}			
			
			

38.2.3. 

			
package cn.aigcsst.controller.debug;

import cn.aigcsst.annotation.TokenPass;
import cn.aigcsst.service.AiService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.retry.annotation.Retryable;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Slf4j
@TokenPass
@RequestMapping("/test")
public class TestController {

    @GetMapping
    @Retryable(RuntimeException.class)
    public void index() {
        log.warn("Test");
        throw new RuntimeException();
    }
}
			
			
			

输出日志

			
api  | 2026-01-12 17:52:53.288  WARN  --- [tomcat-handler-0] c.a.controller.debug.TestController      : Test <- index:23
api  | 2026-01-12 17:52:53.303  WARN  --- [tomcat-handler-0] cn.aigcsst.service.AiService             : ---> Test ---> <- agent:42
api  | 2026-01-12 17:52:54.305  WARN  --- [tomcat-handler-0] cn.aigcsst.service.AiService             : ---> Test ---> <- agent:42
api  | 2026-01-12 17:52:55.306  WARN  --- [tomcat-handler-0] cn.aigcsst.service.AiService             : ---> Test ---> <- agent:42
api  | 2026-01-12 17:52:55.308 ERROR  --- [tomcat-handler-0] c.aigcsst.config.GloablControllerAdvice  : RuntimeException: null <- handleException:19			
			
			

38.2.4. 高级用法

			
    @Retryable(value = RuntimeException.class, maxAttempts = 2, backoff = @Backoff(delay = 1000, multiplier = 2))
    public void service() {
        Random random = new Random();
        int i = random.nextInt();
        if (i == 0) {
            System.out.println("i = " + i + " " + LocalDateTime.now());
            throw new RuntimeException("service failed!");
        }
    }