Spring Boot异常处理最佳实践

Jes*_*ssy 5 spring spring-boot

我有一个关于异常处理的简单问题。我目前有一个应用程序分为多个层:控制器、服务、存储库,我的问题如下:异常处理应该由控制器还是服务来完成?

例子:

控制器:

@PostMapping(value = "/{id}/parents", produces = "application/json; charset=utf-8")
public ResponseEntity<AccommodationRequestDTO> resident(@PathVariable Long id, @Valid @RequestBody ParentsAndUrgencyContactDTO parentsAndUrgencyContactDTO) {
    AccommodationRequestDTO saved;
    try {
        saved = this.service.parents(id, parentsAndUrgencyContactDTO);
    } catch (Exception e) {
        throw new ResponseStatusException(
                HttpStatus.INTERNAL_SERVER_ERROR,
                "Failed to save request", e);
    }
    return ResponseEntity.ok(saved);
}
Run Code Online (Sandbox Code Playgroud)

服务:

public AccommodationRequestDTO parents(Long id, ParentsAndUrgencyContactDTO parentsAndUrgencyContactDTO) {
    Optional<AccommodationRequest> accommodationRequest = repository.findById(id);

    if (accommodationRequest.isPresent()) {
        AccommodationRequest saved = accommodationRequest.get();
        Parent firstParent = parentMapper.toEntity(parentsAndUrgencyContactDTO.getFirstParent());
        Parent secondParent = parentMapper.toEntity(parentsAndUrgencyContactDTO.getSecondParent());

        firstParent = parentRepository.save(firstParent);
        secondParent = parentRepository.save(secondParent);

        saved.setFirstParent(firstParent);
        saved.setSecondParent(secondParent);
        saved = this.repository.save(saved);

        return mapper.toDTO(saved);
    } else {
        throw new ResponseStatusException(
                HttpStatus.NOT_FOUND, " with id " + id + " not found !");
    }

}
Run Code Online (Sandbox Code Playgroud)

最佳实践是什么,我应该从控制器中删除 try-catch 并将其放入我的服务中吗?因为使用此代码我的 404 异常被控制器捕获覆盖。

小智 8

如果你想抛出异常,请将其扔到服务层。

最好再定义一个名为Exception的包。

并在其中包含您的自定义异常、异常响应和异常处理程序。

我的代码结构如下:

package com.***.demo.exception;

public class DataNotFound extends EntityNotFoundException {
    public DataNotFound(String message) {
        super(message);
    }
}
Run Code Online (Sandbox Code Playgroud)
package com.***.demo.exception;

@Data
@AllArgsConstructor
public class ErrorDetails {
    private Date timestamp;
    private String message;
    private String details;
}
Run Code Online (Sandbox Code Playgroud)
package com.***.demo.exception;

@ControllerAdvice
public class MyExceptionHandler {

    @ExceptionHandler(DataNotFound.class)
    public ResponseEntity<?> dataNotFoundExceptionHandling(Exception exception, WebRequest request) {
        return new ResponseEntity<>(new ErrorDetails(new Date(), exception.getMessage(), request.getDescription(false)), HttpStatus.BAD_REQUEST);
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<?> globalExceptionHandling(Exception exception, WebRequest request) {
        return new ResponseEntity<>(new ErrorDetails(new Date(), exception.getMessage(), request.getDescription(false)), HttpStatus.INTERNAL_SERVER_ERROR);
    }
}
Run Code Online (Sandbox Code Playgroud)

希望你能得到答案。


小智 1

是的,您需要转向服务。您可以通过创建扩展 ResponseEntityExceptionHandler 的类来处理异常