springboot中rest接口404等错误返回统一的json格式及抛出NoHandlerFoundException后静态资源的处理

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_36666651/article/details/81135139

一般使用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了。

猜你喜欢

转载自blog.csdn.net/qq_36666651/article/details/81135139