Новый ответ (2016-04-20)
Использование Spring Boot 1.3.1.RELEASE
Новый шаг 1. Легко и менее навязчиво добавить следующие свойства в application.properties:
spring.mvc.throw-exception-if-no-handler-found=true
spring.resources.add-mappings=false
Гораздо проще, чем изменить существующий экземпляр DispatcherServlet (как показано ниже)! - JO '
При работе с полным RESTful-приложением очень важно отключить автоматическое сопоставление статических ресурсов, поскольку, если вы используете конфигурацию Spring Boot для обработки статических ресурсов, обработчик ресурсов будет обрабатывать запрос (он упорядочен последним и сопоставлен с / ** это означает, что он принимает любые запросы, которые не были обработаны каким-либо другим обработчиком в приложении), поэтому у сервлета-диспетчера нет возможности вызвать исключение.
Новый ответ (2015-12-04)
Использование Spring Boot 1.2.7.RELEASE
Новый шаг 1 - я нашел гораздо менее навязчивый способ установки флага "throExceptionIfNoHandlerFound". Замените приведенный ниже код замены DispatcherServlet (Шаг 1) следующим образом в классе инициализации вашего приложения:
@ComponentScan()
@EnableAutoConfiguration
public class MyApplication extends SpringBootServletInitializer {
private static Logger LOG = LoggerFactory.getLogger(MyApplication.class);
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(MyApplication.class, args);
DispatcherServlet dispatcherServlet = (DispatcherServlet)ctx.getBean("dispatcherServlet");
dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
}
В этом случае мы устанавливаем флаг в существующем DispatcherServlet, который сохраняет любую автоконфигурацию средой Spring Boot.
Еще одна вещь, которую я нашел - аннотация @EnableWebMvc смертельно опасна для Spring Boot. Да, эта аннотация позволяет, например, перехватывать все исключения контроллера, как описано ниже, но также убивает МНОГО полезной автоматической конфигурации, которую обычно обеспечивает Spring Boot. Используйте эту аннотацию с особой осторожностью при использовании Spring Boot.
Оригинальный ответ:
После долгих исследований и отслеживания решений, опубликованных здесь (спасибо за помощь!) И немалого количества трассировки времени выполнения в коде Spring, я наконец нашел конфигурацию, которая будет обрабатывать все исключения (не ошибки, а чтение) в том числе 404 с.
Шаг 1 - скажите SpringBoot прекратить использование MVC для ситуаций «обработчик не найден». Мы хотим, чтобы Spring генерировал исключение, а не возвращал клиенту перенаправление представления на «/ error». Для этого вам нужно иметь запись в одном из ваших классов конфигурации:
// NEW CODE ABOVE REPLACES THIS! (2015-12-04)
@Configuration
public class MyAppConfig {
@Bean // Magic entry
public DispatcherServlet dispatcherServlet() {
DispatcherServlet ds = new DispatcherServlet();
ds.setThrowExceptionIfNoHandlerFound(true);
return ds;
}
}
Недостатком этого является то, что он заменяет сервлет диспетчера по умолчанию. Для нас это еще не проблема, без каких-либо побочных эффектов или проблем с выполнением. Если вы собираетесь делать что-то еще с сервлетом-диспетчером по другим причинам, это место для них.
Шаг 2 - Теперь, когда весенняя загрузка выдает исключение, когда обработчик не найден, это исключение может быть обработано с любыми другими в унифицированном обработчике исключений:
@EnableWebMvc
@ControllerAdvice
public class ServiceExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler(Throwable.class)
@ResponseBody
ResponseEntity<Object> handleControllerException(HttpServletRequest req, Throwable ex) {
ErrorResponse errorResponse = new ErrorResponse(ex);
if(ex instanceof ServiceException) {
errorResponse.setDetails(((ServiceException)ex).getDetails());
}
if(ex instanceof ServiceHttpException) {
return new ResponseEntity<Object>(errorResponse,((ServiceHttpException)ex).getStatus());
} else {
return new ResponseEntity<Object>(errorResponse,HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@Override
protected ResponseEntity<Object> handleNoHandlerFoundException(NoHandlerFoundException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
Map<String,String> responseBody = new HashMap<>();
responseBody.put("path",request.getContextPath());
responseBody.put("message","The URL you have reached is not in service at this time (404).");
return new ResponseEntity<Object>(responseBody,HttpStatus.NOT_FOUND);
}
...
}
Имейте в виду, что я думаю, что аннотация "@EnableWebMvc" здесь важна. Кажется, что ничего из этого не работает без него. И все - ваше загрузочное приложение Spring теперь будет перехватывать все исключения, включая 404, в вышеприведенном классе обработчиков, и вы можете делать с ними, как вам угодно.
И последнее замечание - похоже, нет способа заставить его ловить ошибочные ошибки. У меня есть дурацкая идея использовать аспекты для отлова ошибок и превращения их в исключения, с которыми может справиться приведенный выше код, но у меня еще не было времени, чтобы на самом деле попытаться реализовать это. Надеюсь, это кому-нибудь поможет.
Любые комментарии / исправления / улучшения будут оценены.