Spring Boot: как передать ошибки через JSON ответ? - PullRequest
1 голос
/ 23 февраля 2020

У меня очень простое c приложение OpenWeathermap, созданное с помощью Spring Boot, и когда город не найден, OpenWeathermap возвращает {"cod":"404","message":"city not found"}, но я не могу передать его из бэкэнда в мой интерфейс как JSON. Мой ответ веб-интерфейса просто Error: Request failed with status code 500.

Я обрабатываю ответы от бэкэнда до веб-интерфейса как JSON объект и анализирую данные о погоде на фронте.

Мой Controller выглядит следующим образом

@RestController
@RequestMapping("/backend")
public class Controller {

    @GetMapping("/{CITY}")
    public @ResponseBody Object getWeather(@PathVariable String CITY) {

        Object response = WeatherAPI.getCity(CITY);
        return response;
    }

, а мой класс WeatherAPI выглядит следующим образом

public class WeatherAPI {

    public static Object getCity(String CITY) {

        RestTemplate template = new RestTemplate();
        ResponseEntity<Object> response = template.getForEntity("https://api.openweathermap.org/data/2.5/weather?q=" + CITY + "&units=metric&lang=fi&appid=" + API-KEY-HERE, Object.class);
        return response;
    }
}

Я пробовал, например, так: https://mkyong.com/spring-boot/spring-rest-error-handling-example/ и изменил мой код следующим образом:

return response.orElseThrow(() -> new NotFoundException());, но там написано .orElseThrow is undefined for the type

Как передать ошибку «город не найден» с правильным кодом состояния на мой интерфейс?

Ответы [ 7 ]

4 голосов
/ 23 февраля 2020

Вы можете использовать общие обработчики ошибок, такие как ControllerAdvice , которые могут обрабатывать некоторые определенные c типы исключений.

С учетом этого механизма мы можем адаптировать ваш код в следующем way:

  1. Исключения из API погоды будут учитываться и обрабатываться в соответствии с рекомендациями для определенного контроллера
  2. Ваша служба сгенерирует специальное исключение для этого варианта использования
  3. ControllerAdvice будет знать, какой код ошибки отправлять обратно клиенту.

Некоторые минимальные конфигурации:

  1. Добавление controllerAdvice в платформу Spring mvc, чтобы при отсутствии данных для города вы могли вернуть код 404 обратно
@ControllerAdvice
public class GlobalExceptionHandler {
    /** Provides handling for exceptions throughout this service. */
    @ExceptionHandler({ CityWeatherNotFountException.class })
    @ResponseCode(HttpStatus.NOT_FOUND)
    public final ResponseEntity<ApiError> handleException(Exception ex, WebRequest request) {
Адаптируйте реализацию службы так, чтобы она учитывала следующее:
public class WeatherAPI {

    public static Object getCity(String CITY) {

        try{

       RestTemplate template = new RestTemplate();
        ResponseEntity<Object> response = template.getForEntity("https://api.openweathermap.org/data/2.5/weather?q=" + CITY + "&units=metric&lang=fi&appid=" + API-KEY-HERE, Object.class);
        return response;}

     catch(RestException ex){
        throw new CityWeatherNotFountException(ex);}
    }
}
1 голос
/ 23 февраля 2020

Попробуйте это:

Обновите Controller до этого:

   @RestController
   @RequestMapping("/backend")
   public class Controller {

        @GetMapping("/{CITY}")
        public ResponseEntity<Object> getWeather(@PathVariable String CITY) {
            Object response = WeatherAPI.getCity(CITY);
            if(response == null) {
               return new ResponseEntity<Object>("city not found", HttpStatus.PAGE_NOT_FOUND);
            }
            return new ResponseEntity<Object>(response, HttpStatus.OK);
        }

   }

Обновите WeatherAPI до этого:

public class WeatherAPI {

    public static Object getCity(String CITY) {
        RestTemplate template = new RestTemplate();
        Object response = template.getForEntity("https://api.openweathermap.org/data/2.5/weather?q=" + CITY + "&units=metric&lang=fi&appid=" + API-KEY-HERE, Object.class);
        return response;
    }
}

Это должно работать соответственно.

1 голос
/ 23 февраля 2020

Во-первых, я думаю, вы должны попытаться понять реализацию @RestController. Эта аннотация включает аннотации @Controller и @ResponseBody, которые упрощают реализацию контроллера ( дополнительная информация здесь ).

Во-вторых, вы не можете использовать orElseThrow, потому что это метод, представленный в классе Optional ( подробнее здесь ). В данном примере не используется какой-либо необязательный объект. Я думаю, что вы должны учиться на примерах (проверить это), предоставленных по ссылке mkyong. Ваш приведенный пример слишком далек от примеров mkyong.

Для вашего реального вопроса вы можете изменить свой код следующим образом: Вы можете использовать класс HttpServletResponse, чтобы вернуть желаемый статус и сообщение об ошибке. Вам не нужно указывать @ResponseBody, поскольку @RestController автоматически сделает это за вас.

    @RestController()
    @RequestMapping("/backend")
    public class Controller {

    @GetMapping("/{city}")
    public ResponseObject getWeather(@PathVariable String city, HttpServletResponse response) {

        ResponseObject response = WeatherAPI.getCity(city);

        if (response == null) {
            return response.sendError(HttpStatus.PAGE_NOT_FOUND.value(), "message here");
        }

        return response;
    }

Наконец, я не уверен, почему вы используете метод stati c в качестве примера. Вы должны создать сервисный слой, используя @Service для вашего WeatherAPI.

1 голос
/ 23 февраля 2020

Реализация общего пользовательского -> RestTemplateResponseErrorHandler для обработки ошибок клиента c и сервера c при вызове вызовов RestTemplate.

Ссылка: https://www.baeldung.com/spring-rest-template-error-handling для примера использования Spring boot и Spring 5 аналогичного варианта использования.

1 голос
/ 23 февраля 2020

RestTemplate сгенерирует исключение для любых сообщений об ошибках. Вы можете заключить вызов template.getForEntity в блок try-catch и обрабатывать исключения, возвращая сообщение в любом формате, который вы хотите.

Исключение, которое вы ищете: HttpStatusCodeException.

0 голосов
/ 24 февраля 2020

Использовать ResponseEntity

@RestController
@RequestMapping("/backend")
public class Controller {

    @GetMapping("/{CITY}")
    public ResponseEntity<?> Object getWeather(@PathVariable String CITY) {

        Object response = WeatherAPI.getCity(CITY);
        if (response != null) {
         return new ResponseEntity<Object>(response, HttpStatus.OK);
        } else {
          return new ResponseEntity<String>("City Not Found", HttpStatus.Not_Found);
       }
    }

ResponseEntity также возвращает код состояния, например 200, для успеха 404 для не найденного и т. Д. c и привязывается к вашему ответу

0 голосов
/ 24 февраля 2020

Спасибо всем за ваши ответы. Я действительно ценю это, и я люблю изучать, как работает весь этот код. Я должен еще глубже погрузиться в документацию по Spring Boot, сделать несколько обучающих программ и продолжить изучение этой темы c. Я попробовал некоторые ответы, но на самом деле они не работали.

Вот как я решил проблему:

        try {
            ResponseEntity<Object> response = template.getForEntity("https://api.openweathermap.org/data/2.5/" + QUERY
                    + "?q=" + CITY + "&units=metric&lang=fi&appid=" + API_KEY, Object.class);
            return response;
        } catch (HttpStatusCodeException exception) {
            return exception.getResponseBodyAsString();
        }

Заявление: return exception.getResponseBodyAsString(); вернул ответ об ошибке моему веб-интерфейсу, который Я мог бы разобрать с JavaScript, сохранить в массив и тому подобное и представить пользователю.

Я все еще хотел бы научиться отлавливать больше ошибок и выводить их на веб-интерфейс, чтобы я мог создать "панель администратора" "чтобы увидеть и записать все, что происходит на сервере. Я действительно заинтересован в изучении Java и среды Spring Boot.

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

Еще раз спасибо всем за поддержку и подробные описания.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...