自学内容网 自学内容网

SpringBoot实现接口:统一返回值、全局异常处理、Swagger接口文档


在 Spring Boot 应用中实现统一返回值和全局异常处理可以带来多方面的好处,这些好处不仅提升了代码的可读性和可维护性,还增强了应用的健壮性和用户体验。以下是一些具体的好处:

代码一致性:

  • 通过定义统一的返回值格式,可以确保整个应用中的API响应结构保持一致。
  • 统一的异常处理机制使得错误信息的返回方式也保持一致,便于前端开发者理解和处理。

可维护性:

  • 集中管理返回值和异常处理逻辑,减少了代码重复,降低了维护成本。
  • 当需要修改返回格式或异常处理逻辑时,只需在统一的地方进行修改,无需逐个API进行更改。

可读性和易用性:

  • 统一的返回值格式使得API文档更加清晰明了,前端开发者可以更容易地理解和使用API。
  • 全局异常处理可以提供详细的错误信息,帮助开发者快速定位问题。

健壮性:

  • 全局异常处理能够捕获和处理应用中的各种异常,避免应用崩溃或返回不友好的错误信息。
  • 通过自定义异常类型,可以更精确地控制异常的处理方式,提高应用的稳定性和安全性。

1、创建项目

(1)创建 SpringBoot 项目,项目结构如下图:

(2)添加 Maven 依赖

在 pom.xml 配置文件中添加 Swagger2、 Slf4j、Lombok 插件依赖。

<!-- Lombok 依赖 -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.34</version>
    <scope>provided</scope>
</dependency>

<!-- Slf4j的依赖 -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.25</version>
</dependency>

<!-- Swagger依赖-->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
</dependency>

<!-- Swagger-UI依赖 -->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.9.2</version>
</dependency>

(3)配置相关信息

将默认的 application.properties 文件的后缀修改为“.yml”,即配置文件名称为:application.yml,并配置以下信息:

#主配置文件
server:
  port: 8085

2、实现统一返回值

通过定义统一的返回值格式,可以确保整个应用中的API响应结构保持一致。统一的返回值格式使得API文档更加清晰明了,前端开发者可以更容易地理解和使用API。

(1)在 model.ApiModel 包中,创建 ApiResponseCode 枚举(响应结果编码枚举)。

package com.pjb.business.model.ApiModel;

/**
 * 响应结果编码枚举
 * @author pan_junbiao
 **/
public enum ApiResponseCode
{
    SUCCESS(200000, "操作成功"),
    FAILURE(300000, "操作失败"),
    PARAMETER_ERROR(300001, "参数有误"),
    UNKNOWN_ERROR(300002, "未知错误"),
    EXIST_ACCOUNT_CODE(300003, "账户已存在"),
    UNAUTHORIZED(40001, "认证失败"),
    FORBIDDEN(400002, "无权操作"),
    NOT_FOUND(400004, "资源不存在"),
    INTERNAL_SERVER_ERROR(500001, "服务器内部错误"),
    SERVICE_UNAVAILABLE(500002, "服务暂不可用");

    private final int code;
    private final String message;

    ApiResponseCode(int code, String message) {
        this.code = code;
        this.message = message;
    }

    public int getCode() {
        return code;
    }

    public String getMessage() {
        return message;
    }
}

(2)在 model.ApiModel 包中,创建 ApiResponseResult 类(响应结果类)。

package com.pjb.business.model.ApiModel;

import lombok.Data;

/**
 * 响应结果类
 * @author pan_junbiao
 **/
@Data
public class ApiResponseResult<T> {
    private int code;
    private String message;
    private T data;

    public ApiResponseResult(ApiResponseCode apiResponseCode) {
        this.code = apiResponseCode.getCode();
        this.message = apiResponseCode.getMessage();
    }

    public ApiResponseResult(ApiResponseCode apiResponseCode, T data) {
        this.code = apiResponseCode.getCode();
        this.message = apiResponseCode.getMessage();
        this.data = data;
    }
}

3、全局异常处理

全局异常处理可以提供详细的错误信息,帮助开发者快速定位问题。统一的异常处理机制使得错误信息的返回方式也保持一致,便于前端开发者理解和处理。

详细的全局异常处理,请点击浏览文章:《SpringBoot使用@ControllerAdvice和@ExceptionHandler注解实现全局异常处理》

(1)在 exception 包中,创建 ApiResponseException 类(Api操作异常类)。

package com.pjb.business.exception;

import com.pjb.business.model.ApiModel.ApiResponseCode;
import lombok.Data;

/**
 * Api操作异常类
 * 注意:如果继承的是Exception类,那么Spring的事务管理将会失效,
 * 只有继承RuntimeException类才使Spring的事务管理不会失效
 * @author pan_junbiao
 **/
@Data
public class ApiResponseException extends RuntimeException
{
    private ApiResponseCode apiResponseCode; //错误编码信息

    public ApiResponseException(ApiResponseCode apiResponseCode)
    {
        super(apiResponseCode.getMessage());
        this.apiResponseCode = apiResponseCode;
    }
}

(2)在 exception 包中,创建 GlobalExceptionHandler 类(全局异常处理器)。

package com.pjb.business.exception;

import com.pjb.business.model.ApiModel.ApiResponseCode;
import com.pjb.business.model.ApiModel.ApiResponseResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * 全局异常处理器
 * 基于@ControllerAdvice和@ExceptionHandler注解
 * @author pan_junbiao
 **/
@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler
{
    /**
     * 自定义业务异常处理:Api操作异常类
     */
    @ExceptionHandler(ApiResponseException.class)
    @ResponseBody
    public ApiResponseResult businessExceptionHandler(ApiResponseException ex)
    {
        //错误信息
        ApiResponseCode apiResponseCode = ex.getApiResponseCode();

        //记录异常日志
        log.error("[API操作异常] 错误编码:{} 错误信息:{}",apiResponseCode.getCode(),apiResponseCode.getMessage());

        //返回错误信息
        return new ApiResponseResult(apiResponseCode);
    }

    /**
     * 系统异常
     */
    @ExceptionHandler(Exception.class)
    public ApiResponseResult exceptionHandler(Exception ex)
    {
        //记录异常日志
        log.error("[系统异常]" + ex.toString());

        //返回错误页面
        return new ApiResponseResult(ApiResponseCode.UNKNOWN_ERROR);
    }

}

4、整合 Swagger 实现接口文档

在项目开发中,一般都是前后端分离开发的,需要由前后端工程师共同定义接口,编写接口文档,之后大家都根据这个接口文档进行开发、维护。为了便于编写和维护稳定,可以使用Swagger来编写API接口文档,以提升团队的沟通效率。

详细Swagger的使用方法,请点击浏览文章:《SpringBoot整合Swagger实现接口文档》

(1)在 config 包中,创建 SwaggerConfig 类(Swagger 配置类)。

package com.pjb.business.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
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;

/**
 * Swagger 配置类
 * @author pan_junbiao
 **/
@Configuration
@EnableSwagger2
public class SwaggerConfig
{
    /**
     * 创建API应用
     */
    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.pjb.business.controller"))
                .paths(PathSelectors.any())
                .build();
    }

    /**
     * 创建该API的基本信息(这些基本信息会展现在文档页面中)
     * 访问地址:http://项目实际地址/swagger-ui.html
     */
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("用户信息管理系统API")
                .description("RESTful APIs")
                .termsOfServiceUrl("http://localhost:8085/")
                .contact("long")
                .version("1.0")
                .build();
    }
}

5、综合实例

【实例】使用 Spring Boot 实现用户信息的查询、新增、修改、删除接口。

(1)在 entity 包中,创建 UserInfo 类(用户信息实体类)。

package com.pjb.business.entity;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

/**
 * 用户信息实体类
 * @author pan_junbiao
 **/
@Data
@ApiModel(value="用户信息实体类")
public class UserInfo
{
    @ApiModelProperty("用户编号")
    private Long userId;

    @ApiModelProperty("用户名称")
    private String userName;

    @ApiModelProperty("博客信息")
    private String blogName;

    @ApiModelProperty("博客地址")
    private String blogUrl;
}

(2)在 controller 包中,创建 UserController 类(用户信息控制器)。

package com.pjb.business.controller;

import com.pjb.business.entity.UserInfo;
import com.pjb.business.exception.ApiResponseException;
import com.pjb.business.model.ApiModel.ApiResponseCode;
import com.pjb.business.model.ApiModel.ApiResponseResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;

/**
 * 用户信息控制器类
 * @author pan_junbiao
 **/
@RestController
@RequestMapping("/user")
@Api(description = "用户信息控制器")
public class UserController
{
    /**
     * 查询用户信息
     */
    @ApiOperation(value = "查询用户信息")
    @RequestMapping(value = "/getUserInfo/{id}", method = RequestMethod.GET)
    public ApiResponseResult<UserInfo> getUserInfo(@PathVariable("id") Long userId)
    {
        if (userId <= 0)
        {
            //使用:全局异常处理
            throw new ApiResponseException(ApiResponseCode.PARAMETER_ERROR);
        }

        UserInfo userInfo = new UserInfo();
        userInfo.setUserId(userId);
        userInfo.setUserName("pan_junbiao的博客");
        userInfo.setBlogName("您好,欢迎访问 pan_junbiao的博客");
        userInfo.setBlogUrl("https://blog.csdn.net/pan_junbiao");

        //使用:统一返回值
        return new ApiResponseResult(ApiResponseCode.SUCCESS, userInfo);
    }

    /**
     * 新增用户信息
     */
    @ApiOperation(value = "新增用户信息")
    @RequestMapping(value = "/addUserInfo", method = RequestMethod.POST)
    public ApiResponseResult<Boolean> addUserInfo(@RequestBody UserInfo userInfo)
    {
        if (userInfo == null)
        {
            //使用:全局异常处理
            throw new ApiResponseException(ApiResponseCode.PARAMETER_ERROR);
        }

        //使用:统一返回值
        return new ApiResponseResult(ApiResponseCode.SUCCESS, true);
    }

    /**
     * 修改用户信息
     */
    @ApiOperation(value = "修改用户信息")
    @RequestMapping(value = "/updateUserInfo", method = RequestMethod.POST)
    public ApiResponseResult<Boolean> updateUserInfo(@RequestBody UserInfo userInfo)
    {
        if (userInfo == null && userInfo.getUserId() <= 0)
        {
            //使用:全局异常处理
            throw new ApiResponseException(ApiResponseCode.PARAMETER_ERROR);
        }

        //使用:统一返回值
        return new ApiResponseResult(ApiResponseCode.SUCCESS, true);
    }

    /**
     * 删除用户信息
     */
    @ApiOperation(value = "删除用户信息")
    @RequestMapping(value = "/deleteUserInfo/{id}", method = RequestMethod.POST)
    public ApiResponseResult<Boolean> deleteUserInfo(@PathVariable("id") Long userId)
    {
        if (userId <= 0)
        {
            //使用:全局异常处理
            throw new ApiResponseException(ApiResponseCode.PARAMETER_ERROR);
        }

        //使用:统一返回值
        return new ApiResponseResult(ApiResponseCode.SUCCESS, true);
    }
}

查看 Swagger 接口文档:

启动项目,访问 http://127.0.0.1:8085/swagger-ui.html 就能看到所展示的RESTful API的页面,可以通过单击具体的API测试请求,来查看代码中配置的信息,以及参数的描述信息。

查询用户信息:

查看全局异常:


原文地址:https://blog.csdn.net/pan_junbiao/article/details/142954665

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!