Spring Boot配置Swagger与全局异常处理

@author 阿日哥

swagger的配置和全局异常处理基本上是Spring项目的一个必须环节了,做了几个项目之后觉得还是有必要总结一下的。

swagger配置

要进行swagger的配置,我们需要导入swagger ui和swagger2两个依赖,这里使用的版本是2.9.2。

swagger ui是用来渲染html界面的,记得不要忘了导入

<!--swagger2-->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>${swagger.version}</version>
</dependency>

<!--swagger-ui-->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>${swagger.version}</version>
</dependency>

下面是swagger的配置类:

package cn.edu.whu.reservoir.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

/**
 * @author thomas
 * @version 1.0
 * @date 2020/12/19 21:36 下午
 * swagger配置
 */
@Configuration
@EnableSwagger2
public class SwaggerConfig {

    @Bean
    public Docket docket() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
        .apis(RequestHandlerSelectors.basePackage("com.controller"))
                .build()
                .apiInfo(apiInfo());
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("标题")
                .description("描述")
                .termsOfServiceUrl("www.baidu.com")
                .version("1.0")
                .build();
    }
}

一个很简单的配置类,没什么好说的,配置了标题描述等基本属性。

注意加上@EnableSwagger2注解,表示启用swagger。

配置好了以后访问localhost:port/swagger-ui.html(其中port是你程序运行的端口号),就能看到swagger的ui界面了。

全局异常处理

首先我们需要在application.yaml中配置spring的两个属性:

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

第一个属性的作用是为静态资源添加一个url映射,我们要将它设置为false,否则之后spring mvc遇到404异常时就会跳转到默认的/error地址,渲染一个默认的错误html界面。

第二个属性的作用是将404异常向上抛出,以便我们之后统一进行异常处理。

全局异常处理的两种方案

关于全局统一异常处理,目前大概有两种实现方案,第一种是使用RestControllerAdvice注解(其实就是ControllerAdvice注解的restful版本),第二种则是直接实现Spring的ErrorController接口。

下面大致讲一讲两者的区别。

使用@RestControllerAdvice注解

使用@RestControllerAdvice注解来实现很简单。

首先写一个异常处理类,然后加上@RestControllerAdvice注解,写好对应异常处理的方法,在每个方法体上加上@ExceptionHandler()注解,value的值就是你对应的要处理的异常,方法的参数就是对应的异常类。然后就能愉快的自定义你的异常处理过程啦~

package cn.edu.whu.reservoir.component;

import cn.edu.whu.reservoir.api.CommonResult;
import cn.edu.whu.reservoir.api.ResultCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;

/**
 * @author thomas
 * @version 1.0
 * @date 2020/12/19 21:36 下午
 * 统一异常处理
 */
@Slf4j
@Component
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * NoHandlerFoundException 404 异常处理
     */
    @ExceptionHandler(value = NoHandlerFoundException.class)
    @ResponseStatus(HttpStatus.OK)
    public CommonResult<?> handleNotFoundException(NoHandlerFoundException e) throws Throwable {
        // 404不需要处理 直接返回就行
        return CommonResult.fail(ResultCode.NotFound);
    }

    @ExceptionHandler(value = NullPointerException.class)
    @ResponseStatus(HttpStatus.OK)
    public CommonResult<?> handleNullPointerException(NullPointerException e) throws Throwable {
        log.error(e.getMessage());
        return CommonResult.fail(ResultCode.InternalServerError);
    }

    @ExceptionHandler(value = MissingServletRequestParameterException.class)
    @ResponseStatus(HttpStatus.OK)
    public CommonResult<?> handleMissingServletRequestParameterException(MissingServletRequestParameterException e) throws Throwable {
        log.error(e.getMessage());
        return CommonResult.fail(ResultCode.InternalServerError);
    }

    @ExceptionHandler(value = Exception.class)
    @ResponseStatus(HttpStatus.OK)
    public CommonResult<?> handleException(Exception e) throws Throwable {
        log.error(e.getMessage());
        return CommonResult.fail(ResultCode.InternalServerError);
    }

}

实现ErrorController接口

ErrorController对比使用@ControllerAdvice主要是以下几点:

  • ErrorController可对全局错误进行处理,但是其获取不到异常的具体信息,同时也无法根据异常类型进行不同的响应,例如对自定义异常的处理
  • 而@ControllerAdvice可对全局异常进行捕获,包括自定义异常
  • 需要清楚的是,其是应用于对springmvc中的控制器抛出的异常进行处理,而对于404这样不会进入控制器处理的异常不起作用,所以此时还是要依靠ErrorController来处理

关于使用ErrorController的实现也很简单,我这里没有实现,直接贴上一篇文章:

SpringBoot实战(03):全局异常处理ErrorController

Q.E.D.


悟已往之不谏,知来者之可追