springboot项目统一接口超时机制以及异常捕获设计
因为不同的业务接口所需超时时间不同,例如上传或者下载,但是大多数接口都基本可以统一一个超时时间,同时捕获异常,方便上下游子系统设置超时时间能够包住,以及业务可以根据错误码更好地判断做对应的补偿措施,前端展示失败原因
主要设计:编写BaseController,提供请求统一入口,线程池提交请求并设置超时时间,超时时间可以自定义,定义一个函数式接口TemplateInterface,请求对象需要继承BaseRequestDTO,响应对象需要继承BaseResponseDTO
BaseController
public class BaseController {
private static final Logger logger = LoggerFactory.getLogger(BaseController.class);
protected static final JsonMapper JSON_MAPPER = JsonMapper.nonEmptyMapper();
@Autowired
@Qualifier("threadPoolTaskExecutor")
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
@Autowired
private BizSeqUtil bizSeqUtil;
protected static long timeout = 7000;//默认超时时间
public <T extends BaseResponseDTO, E extends BaseRequestDTO> T doExecute(HttpServletRequest httpServletRequest
, HttpServletResponse httpServletResponse, long timeout, E request, TemplateInterface<T, E> templateInterface, T timoutResponse, T exceptionResponse) {
//执行逻辑
setBizSeq(request);
try {
Future<T> future = threadPoolTaskExecutor.submit(() -> {
return templateInterface.apply(request);
});
T baseResponseDTO = future.get(timeout, TimeUnit.MILLISECONDS);
baseResponseDTO.setBizSeqNo(request.getBizSeqNo());
return baseResponseDTO;
} catch (TimeoutException e) {
logger.error("{}|submit request timeout exception:{}",request.getBizSeqNo(),e.getMessage());
timoutResponse.setBizSeqNo(request.getBizSeqNo());
return timoutResponse;
} catch (Exception e) {
logger.error("{}|submit request error:",request.getBizSeqNo(),e);
exceptionResponse.setBizSeqNo(request.getBizSeqNo());
return exceptionResponse;
}
}
//设置流水号
private <E extends BaseRequestDTO> void setBizSeq(E req) {
if (req.getBizSeqNo() != null && req.getBizSeqNo().length() > 0) {
return;
}
String bizSeqNo = bizSeqUtil.newBizSeq();
req.setBizSeqNo(bizSeqNo);
}
}
PlayerController继承BaseController
@RestController
@RequestMapping("/player")
@Slf4j
public class PlayerController extends BaseController {
@Autowired
private PlayerService playerService;
//@RequestCheck
@RequestMapping("/list")
public PlayerResponseDTO getPlayerList(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
@RequestBody PlayerRequestDTO requestDTO) {
log.info("getPlayerList requestDTO:{}", JSON_MAPPER.toJson(requestDTO));
PlayerResponseDTO timeoutResponse = new PlayerResponseDTO(ErrorStatus.TIMEOUT_EXCEPTION);//超时返回
PlayerResponseDTO errorResponse = new PlayerResponseDTO(ErrorStatus.SYSTEM_ERROR);//异常返回
return doExecute(httpServletRequest, httpServletResponse, timeout, requestDTO, (request -> {
PlayerResponseDTO responseDTO = playerService.getPlayerList(request);
log.info("getPlayerList responseDTO:{}", JSON_MAPPER.toJson(responseDTO));
return responseDTO;
}), timeoutResponse, errorResponse);
}
}
请求父类BaseRequestDTO和响应父类BaseResponseDTO
/**
* 请求父类
*/
public class BaseRequestDTO {
private String bizSeqNo;
//get set方法忽略
}
/**
* 响应父类
*/
public class BaseResponseDTO {
private String code = "0";
private String msg = "success";
private String bizSeqNo;
private Object data;
public BaseResponseDTO() {
}
public BaseResponseDTO(Object object) {
this.code = "0";
this.msg = "success";
this.data = object;
}
public BaseResponseDTO(ErrorStatus errorStatus) {
this.code = errorStatus.getErrCode();
this.msg = errorStatus.getErrMsg();
}
public BaseResponseDTO(String code,String msg) {
this.code = code;
this.msg = msg;
}
//get set方法忽略
}
定义一个函数式接口TemplateInterface,请求对象需要继承BaseRequestDTO,相应对象需要继承BaseResponseDTO
//<T extends BaseResponseDTO, E extends BaseRequestDTO>
@FunctionalInterface
public interface TemplateInterface<T , E> {
T apply(E r);
}
创建线程池
@Bean("threadPoolTaskExecutor")
public ThreadPoolTaskExecutor threadPoolExecutor(@Value("${threadPool.corePoolSize}") int corePoolSize,
@Value("${threadPool.maxPoolSize}") int maxPoolSize,
@Value("${threadPool.keepAliveSeconds}") int keepAliveSeconds,
@Value("${threadPool.queueCapacity}") int queueCapacity,
@Value("${threadPool.threadNamePrefix}") String threadNamePrefix
) {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(maxPoolSize);
executor.setKeepAliveSeconds(keepAliveSeconds);
executor.setQueueCapacity(queueCapacity);
executor.setThreadNamePrefix(threadNamePrefix);
executor.initialize();
return executor;
}
接口方法添加耗时逻辑,查看效果
public PlayerResponseDTO getPlayerList(PlayerRequestDTO requestDTO) {
//添加耗时逻辑,接口超时时间是7
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
TPlayer player = new TPlayer();
BeanUtils.copyProperties(requestDTO,player);
PageInfo page = requestDTO.getPage() == null ? new PageInfo() : requestDTO.getPage();
player.setPage(page);
List<TPlayer> list = playerDAO.selectPlayerList(player);
PlayerResponseDTO responseDTO = new PlayerResponseDTO();
responseDTO.setPlayerList(list);
return responseDTO;
}
达到预期效果文章来源:https://www.toymoban.com/news/detail-769211.html
文章来源地址https://www.toymoban.com/news/detail-769211.html
到了这里,关于springboot项目统一接口超时机制设计的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!