新答案 (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 实例(如下所示)要容易得多!- 乔
如果使用完整的RESTful应用程序,禁用静态资源的自动映射非常重要,因为如果您使用Spring Boot的默认配置来处理静态资源,那么资源处理程序将处理该请求(它是最后排序的并映射到/**,这意味着它拾取应用程序中任何其他处理程序尚未处理的任何请求),因此调度程序servlet没有机会引发异常。
新答案 (2015-12-04)
使用 Spring Boot 1.2.7.RELEASE
新步骤 1 -我发现了一种侵入性小得多的方法来设置“throExceptionIfNoHandlerFound”标志。将下面的 DispatcherServlet 替换代码(步骤 1)替换为应用程序初始化类中的 this 代码:
@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;
}
}
这样做的缺点是它取代了默认的调度程序 servlet。这对我们来说还不是问题,没有出现任何副作用或执行问题。如果您出于其他原因要对调度程序 servlet 执行任何其他操作,则可以在此处执行这些操作。
第 2 步 -现在,当找不到处理程序时,spring boot 将引发异常,因此可以在统一的异常处理程序中与任何其他异常一起处理该异常:
@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,您可以随意使用它们。
最后一点 - 似乎没有办法让它捕获抛出的错误。我有一个古怪的想法,即使用方面来捕获错误并将其转换为上述代码可以处理的异常,但我还没有时间实际尝试实现它。希望这有助于某人。
任何评论/更正/增强将不胜感激。