2016-07-19 5 views
0

Я не уверен, почему, но @ControllerAdvice переопределяет код ответа, определенный на уровне Exception, используя аннотацию @ResponseStatus.@ControllerAdvice переопределяет исключение @ResponseStatus

Исключение:

@ResponseStatus(HttpStatus.BAD_REQUEST) 
public class GreetException extends RuntimeException {} 

Контроллер:

@RestController 
@RequestMapping("/") 
public class GreetController { 

    @RequestMapping(method = RequestMethod.GET) 
    public String greet() { 
     throw new GreetException(); 
    } 
} 

Controlle Совет:

@ControllerAdvice 
public class ExceptionConfiguration { 

    @ResponseStatus(HttpStatus.CONFLICT) 
    @ExceptionHandler(RuntimeException.class) 
    public void handleConflict() {} 
} 

Когда метод приветствия от GreetController получил ответ, это ответ 409 - КОНФЛИКТ. Поскольку я специально предоставил код ответа на уровне исключения, я ожидал, что это будет возвращенный код (400 - BAD_REQUEST).
Конечно, это слишком упрощенный пример, но мы определили совет контроллера с определением RuntimeException, чтобы мы могли назначить идентификатор для каждого исключения, которое не было обнаружено.

Каков правильный способ достижения ожидаемого поведения?

+0

в вас controllerAdvice класс, вы должны использовать класс GreetException, как ExceptionHandler вместо класса RuntimeException. ** @ ExceptionHandler (GreetException.класс) public void handleConflict() {} **. Последний класс, который будет выполняться при вызове исключения, будет вашим контроллером. – duardito

+1

Может быть [эта ссылка должна помочь] (http://www.ekiras.com/2016/02/how-to-do-exception-handling-in-springboot-rest-application.html) –

+0

@duardito Обработчик исключений для RuntimeException следует поймать все, что не было поймано. Поскольку я объявляю статус ответа для GreetException, я не ожидаю использовать обработчик RuntimeE. – mvlupan

ответ

3

Проблема с аннотированием исключения с @ResponseStatus заключается в том, что это только срабатывает, когда исключение не обрабатывается где-то еще.

Смотрите эту цитату из Spring article about exception handling in Spring MVC:

Когда аннотированный исключение из метода контроллера, а не обрабатывается в другом месте, он будет автоматически вызывать соответствующий ответ HTTP должен быть возвращен с указанным код_состояния ,

В той же статье описывается подход, чтобы заставить его работать, несмотря на наличие ControllerAdvice с общим обработчиком. См. Paragraph about ControllerAdvice.

То, что вы в основном должны сделать это повторно выдать исключение внутри общего обработчика, если он помечается @ResponseStatus:

@ControllerAdvice 
public class ExceptionConfiguration { 

    @ResponseStatus(HttpStatus.CONFLICT) 
    @ExceptionHandler(RuntimeException.class) 
    public void handleConflict(RuntimeException e) throws RuntimeException { 
    // Check for annotation 
    if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null) { 
     // Rethrow Exception 
     throw e; 
    } 
    else { 
     // Provide your general exception handling here 
    } 
    } 
} 
+0

Это, безусловно, правильный ответ. Я просмотрел статью перед публикацией здесь. В следующий раз я буду более осторожен. – mvlupan

1

Ваш ControllerAdvice не знает о GreetException, так что метание " HttpStatus.CONFLICT»вместо„HttpStatus.BAD_REQUEST“

Пожалуйста, найдите ниже пружинные документации по иому:

https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc

Пожалуйста, измените код ControllerAdvice, как показано ниже:

@ControllerAdvice 
public class ExceptionConfiguration { 

    @ResponseStatus(HttpStatus.CONFLICT) 
    @ExceptionHandler(RuntimeException.class) 
    public void handleRuntimeException() {} 

    @ResponseStatus(HttpStatus.BAD_REQUEST) 
    @ExceptionHandler(GreetException.class) 
    public void handleGreetException() {} 

} 
Смежные вопросы