1、项目结构
2、定义异常类
2.1 ApiResultEnum类
package com.example.springbootmybatisplus.common;
public enum ApiResultEnum {
SUCCESS(200,"ok"),
FAILED(400,"请求失败"),
ERROR(500,"服务器错误"),
ERROR_NULL(501,"空指针异常"),
ERROR_CLASS_CAST(502,"类型转换异常"),
ERROR_RUNTION(503,"运行时异常"),
ERROR_IO(504,"上传文件异常"),
ERROR_MOTHODNOTSUPPORT(505,"请求方法错误"),
ERROR_TRY_AGAIN(506,"正在重试"),
ERROR_TRY_AGAIN_FAILED(507,"重试失败"),
//参数
PARAMETER_NULL(10001,"缺少参数或值为空"),
TRIGGER_GROUP_AND_NAME_SAME(10002,"组名和名称已存在"),
//账户
ACCOUNT_LOCK(20001,"账号已锁定"),
ACCOUNT_NOT_FOUND(20002,"找不到账户信息"),
ACCOUNT_PASSWARD_ERROR(20003,"用户名密码错误"),
ACCOUNT_EXIST(20004,"账号已存在"),
ACCOUNT_NOT_SUFFICIENT(20005,"账号余额不足"),
//权限
AUTH_NOT_HAVE(30001,"没有权限"),
AUTH_SIGN_NOT_MATCH(30002,"签名不匹配"),
FILE_IS_NULL(40001,"文件为空"),
FILE_NOT_PIC(40002,"不是图片类型文件"),
TASK_IS_RUNING(50001,"任务已启动,无法再起启动"),
TASK_IS_PAUSE(50002,"任务暂停,只可继续执行"),
TASK_NOT_RUNING(50003,"任务未执行,无法暂停"),
EMS_CODE_NOT_FOUND(60000,"物流编号找不到,请填写物流编号"),
;
private int status;
private String message;
public String getMessage() {
return message;
}
public int getStatus() {
return status;
}
private ApiResultEnum(int status,String message) {
this.status = status;
this.message = message;
}
}
2.2 ApiException类
package com.example.springbootmybatisplus.common;
public class ApiException extends RuntimeException {
private static final long serialVersionUID = 1L;
private int status;
private String message;
private Object data;
private Exception exception;
public ApiException() {
super();
}
public ApiException(String message) {
super(message);
this.message=message;
}
public ApiException(int status, String message, Object data, Exception exception) {
super(message,exception);
this.status = status;
this.message = message;
this.data = data;
this.exception = exception;
}
public ApiException(ApiResultEnum apiResultEnum) {
this(apiResultEnum.getStatus(),apiResultEnum.getMessage(),null,null);
}
public ApiException(ApiResultEnum apiResultEnum, Object data) {
this(apiResultEnum.getStatus(),apiResultEnum.getMessage(),data,null);
}
public ApiException(ApiResultEnum apiResultEnum, Object data, Exception exception) {
this(apiResultEnum.getStatus(),apiResultEnum.getMessage(),data,exception);
}
}
3、定义注解切面
3.1 注解IsTryAgain
package com.example.springbootmybatisplus.isTryAgainConfig;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface IsTryAgain {
}
3.2 定义异常TryAgainException类
package com.example.springbootmybatisplus.isTryAgainConfig;
import com.example.springbootmybatisplus.common.ApiException;
import com.example.springbootmybatisplus.common.ApiResultEnum;
public class TryAgainException extends ApiException {
public TryAgainException(ApiResultEnum apiResultEnum) {
super(apiResultEnum);
}
}
3.3 定义切面TryAgainAspect类
package com.example.springbootmybatisplus.isTryAgainConfig;
import com.example.springbootmybatisplus.common.ApiException;
import com.example.springbootmybatisplus.common.ApiResultEnum;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.transaction.annotation.Transactional;
@Aspect
@Configuration
public class TryAgainAspect implements Ordered {
/**
* 默认重试几次
*/
private static final int DEFAULT_MAX_RETRIES = 3;
private int maxRetries = DEFAULT_MAX_RETRIES;
private int order = 1;
public void setMaxRetries(int maxRetries) {
this.maxRetries = maxRetries;
}
public int getOrder() {
return this.order;
}
@Pointcut("@annotation(IsTryAgain)")
public void retryOnOptFailure() {
// pointcut mark
}
@Around("retryOnOptFailure()")
@Transactional(rollbackFor = Exception.class)
public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable {
int numAttempts = 0;
do {
numAttempts++;
try {
//再次执行业务代码、
Object proceed = pjp.proceed();
System.out.println("==重试成功==");
return proceed;
} catch (TryAgainException ex) {
if (numAttempts > maxRetries) {
//log failure information, and throw exception
// 如果大于 默认的重试机制 次数,我们这回就真正的抛出去了
throw new ApiException(ApiResultEnum.ERROR_TRY_AGAIN_FAILED);
}else{
//如果 没达到最大的重试次数,将再次执行
System.out.println("=====正在重试====="+numAttempts+"次");
}
}
} while (numAttempts <= this.maxRetries);
return null;
}
}
4、在service层使用@IsTryAgain注解并抛出异常,例如
@IsTryAgain
public String updateUser(User user) throws Exception{
Integer version=userMapper.selectById(user.getId()).getVersion();
user.setVersion(version);
userMapper.updateById(user);
return "OK";
}