ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

解决springboot配置@ControllerAdvice不能捕获NoHandlerFoundException问题

2021-11-29 17:59:27  阅读:229  来源: 互联网

标签:NoHandlerFoundException return springboot param public ApiErrorResponse ex Contr


使用springboot开发一个RESTful API服务,配置了@ControllerAdvice,其它类型异常都能正常捕获,就是不能捕获NoHandlerFoundException,安装以往使用springmvc的经验,需要设置DispatcherServlet.throwExceptionIfNoHandlerFound,NoHandlerFoundException就会被DispatcherSevlet抛出,并被@ControllerAdvice捕获处理。想来springboot中自然也是可以的。

网上一搜发现,只需设置spring.mvc.throw-exception-if-no-handler-found=true即可。设置后依然无效!

再次搜索,还需要设置spring.resources.add-mappings=false,问题解决!

很奇怪,为什么禁用了资源映射后,问题就解决了呢?

研究DispatcherServlet源码发现,NoHandlerFoundException异常能否被抛出,关键在如下代码:

mappedHandler = getHandler(processedRequest);

if (mappedHandler == null || mappedHandler.getHandler() == null) {

    noHandlerFound(processedRequest, response);

    return;

}

只有第一句代码找不到对应该请求的处理器时,才会进入下面的noHandler方法去抛出NoHandlerFoundException异常。

通过测试发现,springboot的WebMvcAutoConfiguration会默认配置如下资源映射:

/映射到/static(或/public、/resources、/META-INF/resources) /webjars/ 映射到classpath:/META-INF/resources/webjars/ /**/favicon.ico映射favicon.ico文件.

这下就明白了,即使你的地址错误,仍然会匹配到/**这个静态资源映射地址,就不会进入noHandlerFound方法,自然不会抛出NoHandlerFoundException了。

所以,我们需要的就是改掉默认的静态资源映射访问路径就可以了。

配置如下属性,NoHandlerFoundException异常就能被@ControllerAdvice捕获了

spring.mvc.throw-exception-if-no-handler-found=true

spring.mvc.static-path-pattern=/statics/**

附上@ControllerAdvice代码:

/**

* ResponseEntityExceptionHandler预提供了一个处理Spring常见异常的Exceptionhandler

* @author wangyongjun

* @date 2018/4/19.

*/

@RestControllerAdvice

public class GlobalControllerExceptionHandler extends ResponseEntityExceptionHandler {

/**

* 覆盖handleExceptionInternal这个汇总处理方法,将响应数据替换为我们的{@link ApiErrorResponse}即可

* @param ex

* @param body

* @param headers

* @param status

* @param request

* @return

*/

@Override

protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body, HttpHeaders headers, HttpStatus status, WebRequest request) {

return new ResponseEntity<>(new ApiErrorResponse().setCode(String.valueOf(status.value())).setMsg(ex.getMessage()), status);

}

/**

* 400错误,bad request

* @param ex

* @return

*/

@ExceptionHandler(value = { IllegalArgumentException.class,Exception400.class})

@ResponseStatus(HttpStatus.BAD_REQUEST)

public ApiErrorResponse badRequestException(Exception ex) {

return ApiErrorResponse.error400().setMsg(ex.getMessage());

}

/**

* 401错误,未授权

* @param ex

* @return

*/

@ExceptionHandler(value = { Exception401.class})

@ResponseStatus(HttpStatus.BAD_REQUEST)

public ApiErrorResponse unauthorizedException(Exception ex) {

return ApiErrorResponse.error401().setMsg(ex.getMessage());

}

/**

* 403错误,权限不足

* @param ex

* @return

*/

@ExceptionHandler(value = { Exception403.class})

@ResponseStatus(HttpStatus.BAD_REQUEST)

public ApiErrorResponse forbiddenException(Exception ex) {

return ApiErrorResponse.error403().setMsg(ex.getMessage());

}

/**

* 404错误,处理器不存在异常,资源不存在异常

* @param ex

* @return

*/

@ExceptionHandler(value = { Exception404.class })

@ResponseStatus(HttpStatus.NOT_FOUND)

public ApiErrorResponse noHandlerFoundException(Exception ex) {

return ApiErrorResponse.error404().setMsg(ex.getMessage());

}

/**

* 500异常

* @param ex

* @return

*/

@ExceptionHandler(value = {Exception500.class,Exception.class })

@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)

public ApiErrorResponse exception(Exception ex) {

return ApiErrorResponse.error500().setMsg(ex.getMessage());

}

}

我使用的是@RestControllerAdvice,异常处理的返回都会被解析为json,不做RESTful API的使用@ControllerAdvice即可。

spring预提供了一个ResponseEntityExceptionHandler,能处理大部分spring自己定义的异常,我们只需要覆盖handleExceptionInternal这个汇总处理方法,将返回的ResponseEntity的body部分替换为我们自己定义的ApiErrorResponse即可。

当然,你也可以自由地配置对其它异常的处理。

转自:https://my.oschina.net/u/3049656/blog/1798583

标签:NoHandlerFoundException,return,springboot,param,public,ApiErrorResponse,ex,Contr
来源: https://blog.csdn.net/yht520100/article/details/121615791

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有