Spring Retry支持集成到Spring或者Spring Boot项目中,而它支持AOP的切面注入写法,所以在引入时必须引入aspectjweaver.jar包。
快速集成的代码样例:
@Configuration
@EnableRetrypublic class Application {
@Bean
public Service service() {
return new Service();
}
}
@Service
class Service {
@Retryable(RemoteAccessException.class)public service() {
// ... do something
}
}
下面是基于Spring Boot项目的集成步骤:
POM:
org.springframework.retry
spring-retry
org.aspectj
aspectjweaver
Service:
package com.jsoft.springboottest.springboottest1;
import java.time.LocalTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.remoting.RemoteAccessException;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
@Servicepublic class RemoteService {
private final static Logger logger = LoggerFactory.getLogger(RemoteService.class);
@Retryable(value= { RemoteAccessException.class }, maxAttempts = 3, backoff = @Backoff(delay = 5000l, multiplier = 1))public void call() throws Exception {
logger.info(LocalTime.now()+" do something...");
throw new RemoteAccessException("RPC调用异常");
}
@Recoverpublic void recover(RemoteAccessException e) {
logger.info(e.getMessage());
}
}
@Retryable注解
被注解的方法发生异常时会重试
value:指定发生的异常进行重试
include:和value一样,默认空,当exclude也为空时,所有异常都重试
exclude:指定异常不重试,默认空,当include也为空时,所有异常都重试
maxAttemps:重试次数,默认3
backoff:重试补偿机制,默认没有
@Backoff注解
delay:指定延迟后重试
multiplier:指定延迟的倍数,比如delay=5000l,multiplier=2时,第一次重试为5秒后,第二次为10秒,第三次为20秒
@Recover
当重试到达指定次数时,被注解的方法将被回调,可以在该方法中进行日志处理。需要注意的是发生的异常和入参类型一致时才会回调。
Controller:
package com.jsoft.springboottest.springboottest1.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.jsoft.springboottest.springboottest1.RemoteService;
@RestController
public class TestController {
@Autowired
private RemoteService remoteService;
@RequestMapping("/show")
public String show(){
try {
remoteService.call();
} catch (Exception e) {
// TODO Auto-generated catch block
//e.printStackTrace();
}
return "Hello World";
}
}
App:
package com.jsoft.springboottest.springboottest1;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.retry.annotation.EnableRetry;
/**
* Hello world!
*
*/
@SpringBootApplication
@EnableRetrypublic class App
{
public static void main( String[] args )
{
SpringApplication.run(App.class, args);
}
}
效果:
说明:
[email protected]..catch包裹,要在发放上抛出异常,不然不会触发。
4、在重试期间这个方法是同步的,如果使用类似Spring Cloud这种框架的熔断机制时,可以结合重试机制来重试后返回结果。
5、Spring Retry不只能注入方式去实现,还可以通过API的方式实现,类似熔断处理的机制就基于API方式实现会比较宽松。
参考: