springboot中rest接口404等错误返回统一的json格式及抛出NoHandlerFoundException后静态资源的处理
一般使用restful接口时我们会统一返回json数据,返回值格式大概如下:
{
"status": {
"code": 666,
"msg": "测试异常"
},
"data": "测试",
"idDone": true
}
idDone表示请求的地址或者类型不正确,这时候就要求我们处理404异常了,而在springboot中,404异常是进行了默认资源映射的,如果没有做特殊配置,我们的异常处理系统就会处理不到404请求(原因在文末),这样就不能统一返回值的格式,不能友好提示。
要捕获到404异常,然后进行统一返回值的处理其实也很简单。
第一步,关闭springboot的异常自动资源映射,让其抛出异常:
#出现错误时, 直接抛出异常
spring.mvc.throw-exception-if-no-handler-found=true
#关闭工程中的资源文件建立映射
spring.resources.add-mappings=false
然后在@ControllerAdvice异常处理类中判断404异常,提供友好的返回值即可:
@ExceptionHandler(Throwable.class)
@ResponseBody
public RespData<String> handleExceptions(Throwable e) {
RespData<String> respData = new RespData<>();
//处理请求地址错误的情况
if (e instanceof org.springframework.web.servlet.NoHandlerFoundException) {
respData.isDone(false);
return respData.status(RespCode.CODE_NOT_FOUND).data("请检查请求路径或者类型是否正确");
}
//其他的异常处理
.......
}
还一个注意点是我们返回值默认是使用Jackson序列化的,而在序列化is开头的参数是,会把开头的is自动去掉,所以我们需要在我们的返回值的属性isDone定义序列化名称,保证不会序列化出错。
@JsonProperty("isDone")
public boolean isDone() {
return isDone;
}
!!!@JsonProperty(“idDone”)注解要加在get方法上,加在字段上序列化会出现奇怪的结果,啥结果试试就知道了。
这样操作后,发现确实可以抛出NoHandlerFoundException异常了,但是由于我们上面配置关闭了静态资源映射,所以这时候我们项目的静态资源没法访问了,我们需要手动定义静态资源的映射,比如我们集成了swagger,会发现/swagger-ui.html页面没法访问了,我们需要手动定义静态资源映射:
@Configuration
public class WebAppConfigurer extends WebMvcConfigurationSupport {
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/","/static", "/public");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
super.addResourceHandlers(registry);
}
}
这样我们就可以在抛出NoHandlerFoundException异常的同时访问静态页面了。
在springboot的静态资源映射中,其中默认配置的/**映射到/static(或/public、/resources、/META-INF/resources)
其中默认配置的/webjars/**映射到classpath:/META-INF/resources/webjars/。
而抛出NoHandlerFoundException的条件我们可以从DispatcherServlet的源码中发现:
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
}
在路径不会被匹配的时候才会抛出NoHandlerFoundException异常,但是由于默认的匹配路径有/**,所以即使你的地址错误,仍然会匹配到 /**这个静态资源映射地址,就不会进入noHandlerFound方法,自然不会抛出NoHandlerFoundException了。
更多推荐
所有评论(0)