异常处理切入点布局如下:
一、网关层
@RestController
public class ErrorHandlerController implements ErrorController {
private final ErrorAttributes errorAttributes;
@Autowired
public ErrorHandlerController(ErrorAttributes errorAttributes) {
this.errorAttributes = errorAttributes;
}
/**
* 出异常后进入该方法,交由下面的方法处理
*/
@Override
public String getErrorPath() {
return "/error";
}
@RequestMapping("/error")
public Object error(HttpServletRequest request, HttpServletResponse response) {
WebRequest webRequest = new ServletWebRequest(request);
Map<String, Object> errorAttributes = this.errorAttributes.getErrorAttributes(webRequest, true);
String msg = errorAttributes.getOrDefault("message", "not found").toString();
String code = errorAttributes.getOrDefault("code", 404).toString();
if (AuthExceptionEnum.TOKEN_EXPIRE.getCode().toString().equals(code)) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
}
return ResponseData.error(Integer.valueOf(code), msg);
}
@Bean
public AbstractTokenValidService jwtTokenValidServiceImpl(){
return new JwtAbstractTokenValidServiceImpl();
}
private class NosErrorAttributes extends DefaultErrorAttributes {
@Override
public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
RequestContext currentContext = RequestContext.getCurrentContext();
Throwable throwable = currentContext.getThrowable();
if (throwable instanceof ZuulException) {
ZuulException zuulException = (ZuulException) throwable;
Throwable cause = zuulException.getCause();
if (cause instanceof ServiceException) {
ServiceException serviceException = (ServiceException) cause;
return BeanUtil.beanToMap(ResponseData.error(serviceException.getCode(), serviceException.getMessage()));
}
}
return BeanUtil.beanToMap(ResponseData.error(CoreExceptionEnum.SERVICE_ERROR.getCode(), CoreExceptionEnum.SERVICE_ERROR.getMessage()));
}
}
二、Feign
@Component
public class FeignErrorDecoder implements ErrorDecoder {
@Override
public Exception decode(String methodKey, Response response) {
/*
解析responseBody内容,解析异常抛出ServiceException
*/
String responseBody;
try {
if (response == null || response.body() == null) {
if (response != null && response.status() == 404) {
return new ServiceException(CoreExceptionEnum.REMOTE_SERVICE_NULL);
} else {
return new ServiceException(CoreExceptionEnum.SERVICE_ERROR);
}
}
responseBody = IoUtil.read(response.body().asInputStream(), "UTF-8");
} catch (IOException e) {
return new ServiceException(CoreExceptionEnum.IO_ERROR);
}
/*
json反序列化
*/
JSONObject jsonObject = JSONObject.parseObject(responseBody);
Integer code = jsonObject.getInteger("code");
String message = jsonObject.getString("message");
if (ToolUtil.isEmpty(message)) {
message = CoreExceptionEnum.SERVICE_ERROR.getMessage();
}
if (code == null) {
Integer status = jsonObject.getInteger("status");
if (status == null) {
return new ServiceException(CoreExceptionEnum.SERVICE_ERROR.getCode(), message);
} else {
return new ServiceException(status, message);
}
} else {
return new ServiceException(code, message);
}
}
}
三、微服务
@ControllerAdvice
@Slf4j
public class DefaultExceptionHandler {
/**
* 拦截业务异常
*/
@ExceptionHandler(ServiceException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public ResponseData notFount(ServiceException e) {
log.info("业务异常:", e);
return ResponseData.error(e.getCode(), e.getErrorMessage());
}
/**
* 拦截未知的运行时异常
*/
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public ResponseData serverError(Exception e) {
log.error("运行时异常:", e);
return ResponseData.error(CoreExceptionEnum.SERVICE_ERROR.getCode(), CoreExceptionEnum.SERVICE_ERROR.getMessage());
}
}
附: SpringBoot默认异常处理器
BasicErrorController
@RequestMapping(
produces = {"text/html"}
)
public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
HttpStatus status = this.getStatus(request);
Map<String, Object> model = Collections.unmodifiableMap(this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.TEXT_HTML)));
response.setStatus(status.value());
ModelAndView modelAndView = this.resolveErrorView(request, response, status, model);
return modelAndView != null ? modelAndView : new ModelAndView("error", model);
}
@RequestMapping
@ResponseBody
public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
Map<String, Object> body = this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.ALL));
HttpStatus status = this.getStatus(request);
return new ResponseEntity(body, status);
}