Рубрики
Без рубрики

Обрабатывайте Весенние Исключения Как Профессионал

Типичная Обработка Исключений В Java ☕️ В Java это обычное дело – пытаться поймать части… Помечено как веб-разработчик, java, учебник, программирование.

Типичная Обработка Исключений В Java ☕ ️

В Java принято пытаться перехватить части нашего кода, которые по какой-то причине терпят неудачу

  • Отсутствующие файлы, поврежденные данные и т.д…
try{  
    buggyMethod();  
    return "Done!";  
}catch (RuntimeException e){  
    return "An error happened!";  
}

Обработка Исключений Весной 🍃

Давайте рассмотрим рабочий процесс Spring как веб-фреймворк:

  1. Выслушивайте запросы клиента.
  2. Выполните некоторые действия, основанные на нашей бизнес-логике.
  3. Верните клиенту ответ, содержащий результат нашей работы.

Теперь мы в идеале хотим перехватить любое исключение (ошибку), которое может возникнуть на уровне 2 (принятие мер). Мы можем написать блок try catch для каждого метода контроллера, который обрабатывает исключения стандартным способом 🙌 🏽

@RestController
@RequiredArgsConstructor  
public class TestController  
{
    private final ExceptionHandler exceptionHandler;

    @GetMapping("/test1")  
    public void test1(){  
        try{  
          // test 1 things  
      }catch (Exception e){  
          exceptionHandler.handleException(e);  
      }  
    }  
    @GetMapping("/test2")  
    public void test2(){  
        try{  
          // test 2 things  
      }catch (Exception e){  
         exceptionHandler.handleException(e);  
      }  
    }
}

👎 🏽 Проблема с этим подходом, однако, заключается в том, что он становится довольно утомительным, когда у нас есть еще много методов контроллера.

Зачем фиксировать все исключения? и не просто позволить им произойти? 🤷🏼

  • Мы хотим, чтобы наше приложение было удобным для пользователя и обрабатывало все крайние случаи, поэтому мы хотим, чтобы оно возвращало ответы в стандартном формате.
  • Мы также можем захотеть занести эти исключения в список невыполненных работ, чтобы вернуться к ним и исследовать их, или делать с ними все, что нам заблагорассудится.

@ControllerAdvice Спешит На Помощь 💪🏾

Идея состоит в том, что мы объявляем метод, который будет обрабатывать любые необработанные исключения в приложении.

Как это сделать? 👀

Во-первых, нам нужно объявить класс и аннотировать его с помощью @ControllerAdvice . Затем мы объявляем методы, каждый из которых обрабатывает класс исключений.

@ControllerAdvice @Slf4j  
public class GlobalErrorHandler  
{  
    @ResponseStatus(INTERNAL_SERVER_ERROR)  
    @ResponseBody  
    @ExceptionHandler(Exception.class)  
    public String methodArgumentNotValidException(Exception ex) {  
        // you can take actions based on the exception  
        log.error("An unexpected error has happened", ex);  
        return "An internal error has happened, please report the incident";  
  }
    @ResponseStatus(BAD_REQUEST)  
    @ResponseBody  
    @ExceptionHandler(InvalidParameterException.class)  
    public String invalidParameterException(InvalidParameterException ex){  
        return "This is a BAD REQUEST";  
   }  
}

Что делает приведенный выше код? ☝️

  • Объявляет два метода, которые будут выполняться всякий раз, когда возникает исключение класса Исключение , Исключение InvalidParameterException (или их подкласс) выбрасывается и не обрабатывается локально в их потоке выполнения.
  • Они возвращают клиенту строковый ответ.

Обратите внимание, что мы можем указать более одного обработчика в классе с аннотацией @ControllerAdvice .

Теперь давайте закодируем некоторые конечные точки для проверки. Давайте закодируем три конечные точки

  • Тот, который обрабатывает выданное исключение.
  • Два других оставляют обработку глобальному обработчику исключений
@RestController @RequiredArgsConstructor  
public class TestController  
{  
    @GetMapping("/buggyMethod")  
    public String testMeWithExceptionHandler(){  
        try{  
            buggyMethod();  
            return "Done!";  
      }catch (RuntimeException e){  
            return "An error happened!";  
        }  
    }  
    @GetMapping("/potentialBuggyMethod")  
    public String testMeWithoutExceptionHandler(){  
        undercoverBuggyMethod();  
        return "Done!";  
      }  
    @PostMapping("/invalidParamMethod")  
    public String testForInvalidParam(){  
        buggyParameters();  
        return "Done";  
    }  
    private void buggyMethod(){  
        throw new RuntimeException();  
    }  
    private void undercoverBuggyMethod(){  
        throw new RuntimeException("oops");  
    }  
    private void buggyParameters(){  
        throw new InvalidParameterException();  
    } 
}

Давайте Проверим Это С Помощью Некоторых Тестов 🧠

@WebMvcTest(controllers = TestController.class)  
public class GlobalExceptionHandlerTest  
{  
  @Autowired  
  private MockMvc mockMvc;  

  @Test  
  public void givenAGetRequestToBuggyEndPoint_DetectErrorMessage() throws Exception  
    {  
        MvcResult mvcResult = mockMvc  
                .perform(get("/buggyMethod"))  
                .andExpect(status().isOk())  
                .andReturn();  
        String response = mvcResult.getResponse().getContentAsString();  
        assertEquals(response, "An error happened!");  
  }  
    @Test  
  public void givenAGetRequestToPotentialBuggyMethod_DetectErrorMessage() throws Exception  
    {  
        MvcResult mvcResult = mockMvc  
                .perform(get("/potentialBuggyMethod"))  
                .andExpect(status().is5xxServerError())  
                .andReturn();  
        String response = mvcResult.getResponse().getContentAsString();  
        assertEquals(response, "An internal error has happened, please report the incident");  
  }
  @Test  
public void givenAPostRequestToBuggyMethod_DetectInvalidParameterErrorMessage() throws Exception  
{  
    MvcResult mvcResult = mockMvc  
            .perform(post("/invalidParamMethod"))  
            .andExpect(status().isBadRequest())  
            .andReturn();  
      String response = mvcResult.getResponse().getContentAsString();  
      assertEquals(response, "This is a BAD REQUEST");  
    }  
}

Вывод 👈

Неожиданные и общие ошибки должны обрабатываться элегантно, чтобы обеспечить бесперебойную работу наших клиентов приложений. Лучше всего это сделать с помощью Spring ControllerAdvice .

Ознакомьтесь с этой статьей для получения более подробной информации об обработке ошибок для REST с помощью Spring 👈

Проверьте код на GitHub🥷

Оригинал: “https://dev.to/jarjanazy/handle-spring-exceptions-like-a-pro-1m5e”