1.在启动类上增加注解(proxyTargetClass=true表示使用cglib代理)
@EnableRetry(proxyTargetClass=true)
2.需要重试的方法必须要单独写在一个service里面(就是调用和被调用不能写在同一个类里面)
@Service("sendEmailService")
public class SendEmailService {
private final Logger log = LoggerFactory.getLogger(SendEmailService.class);
@Autowired
private RestTemplate restTemplate;
// 邮件发送计数器
int count = 0;
/**
* 这是发送Excel到邮件的方法
* @param subject 邮件主题
* @param text 邮件正文
* @param to 收件人,多个用英文逗号分隔
* @param resource 邮件附件
* @throws RestClientException 调用接口不通返回的异常
*/
@Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 2000L, multiplier = 1.5))
// maxAttempts 表示调用次数,delay表示重试延迟,multiplier表示指定延迟的倍数
public void sendEmail(String subject, String text, String to, FileSystemResource resource) throws RestClientException {
// 异常必须抛出去,不能try-catch
log.info("正在尝试第" + ++count + "/3次发送");
MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
// 封装邮件主题
param.add("subject", ZWDateUtil.getDate() + subject);
// 封装邮件内容
param.add("text", text);
// 封装邮件附件
param.add("files", resource);
// 封装邮件收件人
param.add("to", to);
MimeMailMessage mimeMailMessage = restTemplate.postForObject("http://xxx-service/api/xxxController/xxxMimeMail", param, MimeMailMessage.class);
if ("ok".equals(mimeMailMessage.getStatus())) {
// 重置计数器
count = 0;
log.info("自动发送成功");
} else {
log.error("自动发送失败");
throw new RestClientException("状态不是OK,手动抛出异常!");
}
}
/**
* 这是一个兜底的方法,尝试次数达到上限之后会进入这个方法
*
* @param resource 封装的Excel附件
*/
@Recover
public void recover(RestClientException e) {
// 重置计数器
count = 0;
log.error("三次尝试发邮件均失败");
}
}
3.在需要调用重试方法的类的注入service,然后xxxService.sendEmail(xxx,xxx,xxx,xxx)直接调用即可