Springboot捕获全局异常404-NoHandlerFoundException及Swagger/静态路由处理

Posted OkidoGreen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Springboot捕获全局异常404-NoHandlerFoundException及Swagger/静态路由处理相关的知识,希望对你有一定的参考价值。

1、解决Spring MVC no handler抛出异常 - 简书 (jianshu.com)https://www.jianshu.com/p/80e7b7fc374e

现如今每一个网站都会有自己的404页面,但是作为一个纯后端的应用,肯定是没有静态资源的,这辈子也不可能会有静态资源

对于Spring MVC它有自己的一套404返回,例如这样


"timestamp": "2018-09-26T17:03:41.161+0800",
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/process-instance/overview1"

但是肯定不是我们所希望的

如果使用的是Spring Boot,可以在application.properties中设置

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

该参数对应的就是DispatcherServlet中的throwExceptionIfNoHandlerFound

再在全局异常处理中利用@ExceptionHandler捕获NoHandlerFoundException就可以了

但是并没有生效,原因是Spring会默认给你加上ResourceHttpRequestHandler这个handler,也就不会出现noHandler的情况了,该handler是用来处理资源使用的

spring.resources.add-mappings=false

如上配置就可以了

2、(667条消息) springboot捕获全局异常404,设置spring.resources.add-mappings=false 导致swagger访问不通_请假去看丈母娘的博客-CSDN博客_resources.add-mappingshttps://blog.csdn.net/INHERO/article/details/121531224

 mvc:
    throw-exception-if-no-handler-found: true
  resources:
    add-mappings: false


spring.resources.add-mappings=false 为静态资源设置默认处理
spring.mvc.throw-exception-if-no-handler-found=true

这样可以将自定义全局404异常方便Restful使用
但是spring.resources.add-mappings=false会导致swagger也不能访问。

如需swagger能正常访问,需指定swagger的静态资源处理。
处理流程:

@Configuration
@EnableSwagger2
@EnableSwaggerBootstrapUI
public class SwaggerConfiguration implements WebMvcConfigurer 
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) 
        registry.addResourceHandler("swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("doc.html")
                .addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
    

3、全局异常处理

使用说明:(667条消息) Spring的@ExceptionHandler注解使用方法_lkforce的博客-CSDN博客_exceptionhandler注解https://blog.csdn.net/lkforce/article/details/98494922

@ControllerAdvice
public class BaseExceptionHandler 

    private final static Logger logger = LoggerFactory.getLogger(BaseExceptionHandler.class);

    @ExceptionHandler(MissingServletRequestParameterException.class)
    @ResponseBody
    public ResponseEntity<ErrorResponse> noRequestHandlerFoundExceptionHandler(MissingServletRequestParameterException e) 

        String errorCode = "B0400";
        String errorMsg = "Bad Request";

        return new ResponseEntity<>(new ErrorResponse(errorCode, errorMsg), HttpStatus.BAD_REQUEST);
    

    @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
    @ResponseBody
    public ResponseEntity<ErrorResponse> handleHttpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException e) 
        String errorCode = "REQCTERROR";
        String errorMsg = "ContentType错误";
        return new ResponseEntity<>(new ErrorResponse(errorCode, errorMsg), HttpStatus.INTERNAL_SERVER_ERROR);
    

    @ExceptionHandler(MultipartException.class)
    @ResponseBody
    public ResponseEntity<ErrorResponse> handleMultipartException(MultipartException e) 
        String errorCode = "REQCTERROR";
        String errorMsg = "enctype must be multipart/form-data";
        logger.error(" MultipartException: " + e);
        return new ResponseEntity<>(new ErrorResponse(errorCode, errorMsg), HttpStatus.INTERNAL_SERVER_ERROR);
    

    @ExceptionHandler(NoHandlerFoundException.class)
    @ResponseBody
    public ResponseEntity<ErrorResponse> handleNoHandlerFoundException(Exception e) 
        String errorCode = "404";
        String errorMsg = "找不到对应资源";
        return new ResponseEntity<>(new ErrorResponse(errorCode, errorMsg), HttpStatus.NOT_FOUND);
    

    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    @ResponseBody
    public ResponseEntity<ErrorResponse> handleHttpRequestMethodNotSupportedException(Exception e) 
        String errorCode = "404";
        String errorMsg = "找不到对应资源";
        return new ResponseEntity<>(new ErrorResponse(errorCode, errorMsg), HttpStatus.NOT_FOUND);
    

    @ExceptionHandler(TokenTimeOutException.class)
    @ResponseBody
    public ResponseEntity<ErrorResponse> handleTokenTimeOutException(TokenTimeOutException e) 
        return new ResponseEntity<>(new ErrorResponse(e.getCode(), e.getMsg()), HttpStatus.NOT_FOUND);
    

    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ResponseEntity<ErrorResponse> handleException(Exception e) 
        String errorCode = "SYSERROR";
        String errorMsg = "系统繁忙,请稍后再试";
        if (e != null && e.getMessage() != null &&
                e.getMessage().contains("你的主机中的软件中止了一个已建立的连接")) 
            return null;
        
        if (e != null) 
            logger.error(" Exception: " + e.getClass().toString() + "\\n" + getExceptionAllinformation(e));
        
        return new ResponseEntity<>(new ErrorResponse(errorCode, errorMsg), HttpStatus.INTERNAL_SERVER_ERROR);
    

    @ExceptionHandler(ForbiddenException.class)
    @ResponseBody
    public ResponseEntity<ErrorResponse> handleForbiddenException(ForbiddenException e) 
        String errorCode = e.getCode();
        String errorMsg = e.getMsg();
        return new ResponseEntity<>(new ErrorResponse(errorCode, errorMsg), HttpStatus.FORBIDDEN);
    

    @ExceptionHandler(DLException.class)
    @ResponseBody
    public ResponseEntity<ErrorResponse> handleDLException(DLException e) 
        String errorCode = e.getCode();
        String errorMsg = e.getMsg();
        if(e instanceof ParamEncryptExcption)
            errorCode = "SYSERROR";
            errorMsg = "系统繁忙,请稍后再试";
        
        return new ResponseEntity<>(new ErrorResponse(errorCode, errorMsg), HttpStatus.INTERNAL_SERVER_ERROR);
    

    @ExceptionHandler(UndeclaredThrowableException.class)
    @ResponseBody
    public ResponseEntity<ErrorResponse> handleUndeclaredThrowableException(UndeclaredThrowableException e) 
        Throwable throwable = e.getUndeclaredThrowable();
        String errorCode = "";
        String errorMsg = "";
        if (throwable != null && throwable instanceof DLException) 
            errorCode = ((DLException) throwable).getCode();
            errorMsg = ((DLException) throwable).getMsg();
         else 
            errorCode = "SYSERROR";
            errorMsg = "系统繁忙,请稍后再试";
            logger.error(" Exception: " + e.getClass().toString() + "\\n" + getExceptionAllinformation(e));
        
        return new ResponseEntity<>(new ErrorResponse(errorCode, errorMsg), HttpStatus.INTERNAL_SERVER_ERROR);
    

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public ResponseEntity<ErrorResponse> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) 
        BindingResult result = e.getBindingResult();
        List<String> errors = new ArrayList<>();
        if (result.hasFieldErrors()) 
            List<FieldError> fieldErrorList = result.getFieldErrors();

            for (FieldError error : fieldErrorList) 

                // errors.add(error.getField() + ":" +error.getDefaultMessage());
                errors.add(error.getDefaultMessage());
            
        
        return new ResponseEntity<>(new ErrorResponse("400", errors.toString()), HttpStatus.BAD_REQUEST);
    

    public static String getExceptionAllinformation(Exception ex) 
        StringBuilder sOut = new StringBuilder();
        StackTraceElement[] trace = ex.getStackTrace();
        for (int i = 0; i < trace.length && i < 15; i++) 
            StackTraceElement s = trace[i];
            sOut.append("\\tat " + s + "\\r\\n");
        
        return sOut.toString();
    

以上是关于Springboot捕获全局异常404-NoHandlerFoundException及Swagger/静态路由处理的主要内容,如果未能解决你的问题,请参考以下文章

springboot全局捕获异常

SpringBoot全局捕获异常示例

springboot编程之全局异常捕获

springboot 全局捕获异常

springboot中添加全局异常捕获类

springBoot2.x 全局捕获异常