问题描述
我使用 Java 11 和 Spring-Boot 2.1.6,我正在开发一个微服务,它为 2 个不同的实体执行 CRUD 操作,这些实体存储在一个数据库中的不同模式中。
在这个微服务中,我有两个 RestControllers,它们分别接收每个实体的 crud 请求。此外,我有 1 个 GlobalExceptionHandler 处理 2 个控制器的所有异常,并在其方法中记录错误。
例如在每个控制器中,我都有一个 POST 方法。在某个异常时,我必须在 GlobalExceptionHandler 中将某个日志打印到控制台。
例如,对于第一个实体:
如果出现无效数据,则:“E-022:无效数据出现:[描述]。”;
如果数据有效,但我们有唯一约束:“E-03:将数据存储在数据库中时出错[说明]。”;
但是对于另一个实体,我必须编写其他日志,因此我无法直接在方法中记录错误, 因为不同的控制器使用这些方法。
每个方法构造 ResponseEntity ,其中包含一个在 GlobalExceptionHandler 中构造的自定义错误,现在我已经在constructError() 中编写了开关来检查哪个控制器(现在仅用于第一个控制器 "/forEntity1" )和哪个 HTTP 方法抛出了一个异常(在我看来,开关看起来也不是很好)。而且,我还得认出抛出了哪个异常,才能写出相应的日志。
问题是:一般来说,哪种方法更适合记录错误或处理异常?也许我应该为每个控制器编写 2 个 GlobalExceptionHandlers?或者它可以在一个ExceptionHandler中干净正确地实现?
现在,我有这样的 GlobalExceptionHandler:
@ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
private static final Logger LOG = LogManager.getLogger();
@ExceptionHandler(Exception.class)
public ResponseEntity<ApiError> handleUnexpectedServerException(Exception e,HttpServletRequest request) {
return new ResponseEntity<>(
constructError(e.getMessage(),HttpStatus.INTERNAL_SERVER_ERROR,request),constructHeader(),HttpStatus.INTERNAL_SERVER_ERROR);
}
@ExceptionHandler(DataIntegrityViolationException.class)
public ResponseEntity<ApiError> handleDataIntegrityViolationException(DataIntegrityViolationException e,HttpServletRequest request) {
return new ResponseEntity<>(
constructError(e.getMostSpecificCause().getMessage(),HttpStatus.BAD_REQUEST,HttpStatus.BAD_REQUEST);
}
@Override
protected ResponseEntity<Object> handleHttpMessageNotReadable(HttpMessageNotReadableException ex,HttpHeaders headers,HttpStatus status,WebRequest request) {
return new ResponseEntity<>(constructError(ex.getMessage(),((ServletWebRequest) request).getRequest()),HttpStatus.BAD_REQUEST);
}
@Override
protected ResponseEntity<Object> handleHttpMediaTypeNotSupported(HttpMediaTypeNotSupportedException ex,HttpStatus.UNSUPPORTED_MEDIA_TYPE,HttpStatus.UNSUPPORTED_MEDIA_TYPE);
}
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex,WebRequest request) {
String errorString = ex
.getBindingResult()
.getFieldErrors().stream()
.map(fieldError -> fieldError.getField() + " : " + fieldError.getDefaultMessage())
.collect(Collectors.joining("; "));
return new ResponseEntity<>(constructError(errorString,HttpStatus.BAD_REQUEST);
}
private ApiError constructError(String errorMessage,HttpServletRequest request) {
ApiError error = new ApiError(status.value(),status.getReasonPhrase(),errorMessage);
if (request.getRequestURI().contains("/forEntity1")) {
String message;
switch (request.getmethod()) {
case "POST":
message = "E-03: Error when storing the data in the DB "; break;
case "GET":
message = "E-11: Data retrieval error "; break;
default:
message = "";
}
LOG.error(message + "(" + errorMessage + ")");
}
LOG.error(errorMessage);
LOG.debug("Generated error:\n" + error);
return error;
}
private HttpHeaders constructHeader() {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
headers.set(HttpHeaders.DATE,CUSTOM_DATE_FORMATTER.withZone(GMT).format(zoneddatetime.Now()));
return headers;
}
}
如果您需要任何说明,请立即告诉我并提前谢谢您!
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)