Нова відповідь (2016-04-20)
Використання Spring Boot 1.3.1.RELEASE
Новий крок 1 - Додавати такі властивості до програми легко і менш нав'язливо:
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 викинула виняток замість того, щоб повертати клієнту переспрямування подання на "/ помилка". Для цього вам потрібно мати запис в одному з ваших класів конфігурації:
// 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, у вищевказаному класі обробника, і ви можете робити з ними як завгодно.
Останнє питання - здається, не існує способу отримати це, щоб зловити викинуті помилки. У мене є дурне уявлення про використання аспектів для вилучення помилок і перетворення їх на Винятки, з якими можна звернутись до вищевказаного коду, але я ще не встиг реально спробувати його реалізувати. Сподіваюся, що це комусь допоможе.
Будь-які коментарі / виправлення / удосконалення будуть вдячні.