对于多个控制器在 ExceptionHandler 中记录错误,哪种方法更好?

问题描述

我使用 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 (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...