之前在使用springmvc的时候可以通过在web.xml中配置404指向对应的页面,但是在spring boot是没有web.xml的,如果没有任何配置的话我们会得到下面的返回
那么我想spring boot肯定为我们准备好了对应的解决方案,那就是BasicErrorController,这个继承自AbstractErrorController,而且是在没有其他实现的时候,这个默认的ErrorController才会生效,我们可以看到ErrorMvcAutoConfiguration里面的声明,里面的ConditionalOnMissingBean就是这个意思
@Bean
@ConditionalOnMissingBean(value = ErrorController.class, search = SearchStrategy.CURRENT)
public BasicErrorController basicErrorController(ErrorAttributes errorAttributes) {
return new BasicErrorController(errorAttributes, this.serverProperties.getError(),
this.errorViewResolvers);
}
下面我们关注一下BasicErrorController里面的两个方法,一个方法对面的是我们上面浏览器访问的的那个返回,一个application/json的post请求返回,他们返回了自己预先定义的数据,这里我们注意下一个细节,就是ModelAndView modelAndView = resolveErrorView(request, response, status, model)这一行,我们进去看下他的源码,就会知道,这里去拿返回的时候,它会默认去项目的资源目录根据请求的状态码获取html文件返回,所以如果只支持浏览器访问的get方式的话,我们直接定义好对应的html文件就可以了,spring boot静态默认的默认目录是static,这里去error下去找view,那么只要在/resources/static/error/目录下定义文件就行
@RequestMapping(produces = "text/html")
public ModelAndView errorHtml(HttpServletRequest request,
HttpServletResponse response) {
HttpStatus status = getStatus(request);
Map model = Collections.unmodifiableMap(getErrorAttributes(
request, isIncludeStackTrace(request, MediaType.TEXT_HTML)));
response.setStatus(status.value());
ModelAndView modelAndView = resolveErrorView(request, response, status, model);
return (modelAndView == null ? new ModelAndView("error", model) : modelAndView);
}
@RequestMapping
@ResponseBody
public ResponseEntity
但是我们更多的是接口请求,而且这样灵活性太差,所以我们还是自己定义一个ErrorController比较合适,然后重写这两个方法,errorHtml这个基本和BasicErrorController一样,只要定义好静态文件就行,对于error方法,我们返回自己系统定义的json格式数据,下面是具体实现,类的其他代码直接参考BasicErrorController的就行,定义完自己的ExceptionController之后,还需要一个配置类的
@RequestMapping(produces = "text/html")
public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
HttpStatus status = getStatus(request);
log.error("接口请求错误,http status:{}", status);
Map model = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.TEXT_HTML));
JsonResult
@Configuration
@ConditionalOnWebApplication
@ConditionalOnClass({Servlet.class, DispatcherServlet.class})
@AutoConfigureBefore(WebMvcAutoConfiguration.class)
@EnableConfigurationProperties(ResourceProperties.class)
public class ExceptionControllerConfig {
private final ServerProperties serverProperties;
private final List errorViewResolvers;
public ExceptionControllerConfig(ServerProperties serverProperties,
ObjectProvider> errorViewResolversProvider) {
this.serverProperties = serverProperties;
this.errorViewResolvers = errorViewResolversProvider.getIfAvailable();
}
@Bean
public ExceptionController exceptionController(ErrorAttributes errorAttributes) {
return new ExceptionController(errorAttributes, this.serverProperties.getError(), this.errorViewResolvers);
}
}
这样我们就定义好了自己的错误控制器,可以根据不同的请求状态码返回自己的数据;
还有一种做法
还有一种做法就是通过spring boot的配置直接完成,这样配置的顾名思义,就是在没有handler的时候直接作为异常抛出,这样我们的全局异常捕获器就能够捕获到了,然后根据不同的状态码返回就行,但是这里需要看到的是有个add-mappings:false,就是这种情况下静态资源是要不能访问的,其实是因为静态资源是直接访问,不需要控制器,所以要配置成false;如果你的项目仅仅是作为接口服务的话,那么这种方式来的更加的简单,我本来也是这么做的,但是我的项目里面使用了swagger,这个东西暴露出去的api是动态生成的静态文件,如果这样配置之后,swagger也不能用了,所以我还是使用了第一种方式进行捕获error
spring:
mvc:
throw-exception-if-no-handler-found: true
resources:
add-mappings: false