貓頭鷹的深夜翻譯:Spring REST服務異常處理

前言

這篇教程主要專一於如何優雅的處理WEB中的異常。雖然咱們能夠手動的設置ResponseStatus ,可是還有更加優雅的方式將這部分邏輯隔離開來。Spring提供了整個應用層面的異常處理的抽象,而且只是要求您添加一些註釋 - 它會處理其餘全部內容。下面是一些代碼的示例面試

如何手動處理異常

下面的代碼中, DogController將返回一個ResponseEntity實例,該實例中包含返回的數據和HttpStatus屬性spring

  • 若是沒有拋出任何異常,則下面的代碼將會返回List<Dog>數據做爲響應體,以及200做爲狀態碼
  • 對於DogsNotFoundException,它返回空的響應體和404狀態碼
  • 對於DogServiceException, 它返回500狀態碼和空的響應體
@RestController
@RequestMapping("/dogs")
public class DogsController {
    @Autowired private final DogsService service;
    @GetMapping
    public ResponseEntity<List<Dog>> getDogs() {
        List<Dog> dogs;
        try {
            dogs = service.getDogs();
        } catch (DogsServiceException ex) {
            return new ResponseEntity<>(null, null, HttpStatus.INTERNAL_SERVER_ERROR);
        } catch (DogsNotFoundException ex) {
            return new ResponseEntity<>(null, null, HttpStatus.NOT_FOUND);
        }
        return new ResponseEntity<>(dogs, HttpStatus.OK);
    }
}

這種處理異常的方式最大的問題就在於代碼的重複。catch部分的代碼在不少其它地方也會使用到(好比刪除,更新等操做)微信

Controller Advice

Spring提供了一種更好的解決方法,也就是Controller Advice。它將處理異常的代碼在應用層面上集中管理。app

如今咱們的的DogsController的代碼更加簡單清晰了:spa

import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
import static org.springframework.http.HttpStatus.NOT_FOUND;

@ControllerAdvice
public class DogsServiceErrorAdvice {
    @ExceptionHandler({RuntimeException.class})
    public ResponseEntity<String> handleRunTimeException(RuntimeException e) {
        return error(INTERNAL_SERVER_ERROR, e);
    }
    @ExceptionHandler({DogsNotFoundException.class})
    public ResponseEntity<String> handleNotFoundException(DogsNotFoundException e) {
        return error(NOT_FOUND, e);
    }
    @ExceptionHandler({DogsServiceException.class})
    public ResponseEntity<String> handleDogsServiceException(DogsServiceException e){
        return error(INTERNAL_SERVER_ERROR, e);
    }
    private ResponseEntity<String> error(HttpStatus status, Exception e) {
        log.error("Exception : ", e);
        return ResponseEntity.status(status).body(e.getMessage());
    }
}
  • handleRunTimeException:這個方法會處理全部的RuntimeException並返回INTERNAL_SERVER_ERROR狀態碼
  • handleNotFoundException: 這個方法會處理DogsNotFoundException並返回NOT_FOUND狀態碼。
  • handleDogsServiceException: 這個方法會處理DogServiceException並返回INTERNAL_SERVER_ERROR狀態碼

這種實現的關鍵就在於在代碼中捕獲需檢查異常並將其做爲RuntimeException拋出。code

還能夠用@ResponseStatus將異常映射成狀態碼教程

@ControllerAdvice
public class DogsServiceErrorAdvice {
    @ResponseStatus(HttpStatus.NOT_FOUND)
    @ExceptionHandler({DogsNotFoundException.class})
    public void handle(DogsNotFoundException e) {}
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler({DogsServiceException.class, SQLException.class, NullPointerException.class})
    public void handle() {}
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler({DogsServiceValidationException.class})
    public void handle(DogsServiceValidationException e) {}
}

在自定義的異常上添加狀態碼

@ResponseStatus(HttpStatus.NOT_FOUND)
public class DogsNotFoundException extends RuntimeException {
    public DogsNotFoundException(String message) {
        super(message);
    }
}

clipboard.png
想要了解更多開發技術,面試教程以及互聯網公司內推,歡迎關注個人微信公衆號!將會不按期的發放福利哦~ip

相關文章
相關標籤/搜索