Spring @ControllerAdvice не применяется, если указан packageName или assignableTypes - PullRequest
1 голос
/ 10 марта 2020

Пример проекта, демонстрирующего проблему, можно найти по адресу: https://github.com/dirkbolte/javaexceptionhandlertest

У меня есть контроллер, который объявлен для производства JSON содержимого:

@RestController
public class TestController {

    @GetMapping(value = "exception", produces = MediaType.APPLICATION_JSON_VALUE)
    public void test() {
    }
}

Соответствующий совет контроллера должен сопоставить любое исключение с BAD_REQUEST:

@RestControllerAdvice
public class MyExceptionHandler {
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(value = Exception.class)
    public void exceptionhandler() {
    }
}

. Я проверяю, что вызов с неправильным заголовком accept приводит к правильному коду ответа об ошибке (поскольку procudes указывает что-то другое):

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
class TestControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void test() throws Exception {
        mockMvc.perform(
            MockMvcRequestBuilders.get("/exception")
                                  .accept(MediaType.APPLICATION_PDF)
        ).andExpect(status().isBadRequest());
    }
}

Код выше "успешно завершается неудачей" :-). В моем производственном коде я хочу ограничить рекомендацию контроллера определенным контроллером (или определенным пакетом), поэтому я указал assignableTypes на @ControllerAdvice: @RestControllerAdvice(assignableTypes = TestController.class). Теперь тест не пройден, так как обработчик исключений больше не вызывается. То же самое происходит при указании basePackages или basePackageClasses - или при использовании интерфейса.

Версия на GitHub показывает ошибку теста, поэтому я надеюсь, что ее легко воспроизвести.

Как я могу явно использовать ControllerAdvice для одного или нескольких контроллеров?

1 Ответ

1 голос
/ 11 марта 2020

Запрошенный URL не будет привязан к какому-либо методу контроллера. Это приведет к ошибке Status 406 (из-за указанного типа подтверждения). Поскольку из методов Controller не выдается никаких исключений, ControllerAdvice не будет вызываться.

На уровне диспетчера org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver#getExceptionHandlerMethod будет вызываться с handlerMethod = null, поэтому применяются только общие c рекомендации контроллера.

Здесь будет работать ControllerAdvice, если запрос содержит дополнительные метаданные, для которых настроен метод контроллера, и / или из этого метода выдается исключение.

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