在线接口调试工具-swagger

1、介绍

一般的前后端分离的项目,都会采用在线的接口工具进行调试,可以实时的展示接口的详细数据

Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务(swagger.io/)。 它的主要作用是:

  1. 使得前后端分离开发更加方便,有利于团队协作

  2. 接口的文档在线自动生成,降低后端开发人员编写接口文档的负担

  3. 功能测试

    Spring已经将Swagger纳入自身的标准,建立了Spring-swagger项目,现在叫Springfox。通过在项目中引入Springfox ,即可非常简单快捷的使用Swagger。

knife4j是为Java MVC框架集成Swagger生成Api文档的增强解决方案,前身是swagger-bootstrap-ui,取名kni4j是希望它能像一把匕首一样小巧,轻量,并且功能强悍!

目前,一般都使用knife4j框架。

2、项目集成

2.1、导入 knife4j 的maven坐标

java 复制代码
<!--  knife4j版接口文档 访问/doc.html-->
<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>knife4j-spring-boot-starter</artifactId>
</dependency>

2.2、在配置类中加入 knife4j 相关配置

java 复制代码
package com.zzyl.config;

import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import com.zzyl.properties.SwaggerConfigProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.autoconfigure.endpoint.web.CorsEndpointProperties;
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
import org.springframework.boot.actuate.autoconfigure.web.server.ManagementPortType;
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
import org.springframework.boot.actuate.endpoint.web.*;
import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointsSupplier;
import org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpointsSupplier;
import org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;
import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

@Configuration
@EnableConfigurationProperties(SwaggerConfigProperties.class)
@EnableKnife4j
@Import(BeanValidatorPluginsConfiguration.class)
public class SwaggerConfig {

    @Autowired
    SwaggerConfigProperties swaggerConfigProperties;

    @Bean(value = "defaultApi2")
    @ConditionalOnClass(SwaggerConfigProperties.class)
    public Docket defaultApi2() {
        // 构建API文档  文档类型为swagger2
        return new Docket(DocumentationType.SWAGGER_2)
            .select()
            // 配置 api扫描路径
            .apis(RequestHandlerSelectors.basePackage(swaggerConfigProperties.getSwaggerPath()))
            // 指定路径的设置  any代表所有路径
            .paths(PathSelectors.any())
            // api的基本信息
            .build().apiInfo(new ApiInfoBuilder()
                // api文档名称
                .title(swaggerConfigProperties.getTitle())
                // api文档描述
                .description(swaggerConfigProperties.getDescription())
                // api文档版本
                .version("1.0") // 版本
                // api作者信息
                .contact(new Contact(
                    swaggerConfigProperties.getContactName(),
                    swaggerConfigProperties.getContactUrl(),
                    swaggerConfigProperties.getContactEmail()))
                .build());
    }

    /**
     * 增加如下配置可解决Spring Boot 6.x 与Swagger 3.0.0 不兼容问题
     **/
    @Bean
    public WebMvcEndpointHandlerMapping webEndpointServletHandlerMapping(WebEndpointsSupplier webEndpointsSupplier,
                                                                         ServletEndpointsSupplier servletEndpointsSupplier,
                                                                         ControllerEndpointsSupplier controllerEndpointsSupplier,
                                                                         EndpointMediaTypes endpointMediaTypes,
                                                                         CorsEndpointProperties corsProperties,
                                                                         WebEndpointProperties webEndpointProperties,
                                                                         Environment environment) {
        List<ExposableEndpoint<?>> allEndpoints = new ArrayList();
        Collection<ExposableWebEndpoint> webEndpoints = webEndpointsSupplier.getEndpoints();
        allEndpoints.addAll(webEndpoints);
        allEndpoints.addAll(servletEndpointsSupplier.getEndpoints());
        allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
        String basePath = webEndpointProperties.getBasePath();
        EndpointMapping endpointMapping = new EndpointMapping(basePath);
        boolean shouldRegisterLinksMapping = this.shouldRegisterLinksMapping(webEndpointProperties, environment, basePath);
        return new WebMvcEndpointHandlerMapping(endpointMapping, webEndpoints, endpointMediaTypes, corsProperties.toCorsConfiguration(),
                new EndpointLinksResolver(allEndpoints, basePath), shouldRegisterLinksMapping, null);
    }
    private boolean shouldRegisterLinksMapping(WebEndpointProperties webEndpointProperties, Environment environment, String basePath) {
        return webEndpointProperties.getDiscovery().isEnabled() && (StringUtils.hasText(basePath) || ManagementPortType.get(environment).equals(ManagementPortType.DIFFERENT));
    }
}

2.3、配置类为:WebMvcConfig

设置静态资源映射,否则接口文档页面无法访问,配置类为:WebMvcConfig

java 复制代码
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    //支持webjars
    registry.addResourceHandler("/webjars/**")
            .addResourceLocations("classpath:/META-INF/resources/webjars/");
    //支持swagger
    registry.addResourceHandler("swagger-ui.html")
            .addResourceLocations("classpath:/META-INF/resources/");
    //支持小刀
    registry.addResourceHandler("doc.html")
            .addResourceLocations("classpath:/META-INF/resources/");
}

3、常用注解

通过注解可以控制生成的接口文档,使接口文档拥有更好的可读性,常用注解如下:

注解 说明
@Api 用在类上,描述Controller的作用
@ApiOperation 用在方法上,说明方法的用途、作用
@ApiParam 用在方法的参数上,描述单个形参的含义
@ApiImplicitParam 用在方法上,描述单个形参的含义,与上面相比使用范围更广
@ApiModel 用在类上,用对象来接收参数或者返回参数,描述类的含义
@ApiModelProperty 用在类的属性上,用对象来接收参数或者返回参数,描述字段的含义

4、代码改造

4.1、NursingProjectController

java 复制代码
package com.zzyl.controller;

import com.zzyl.base.PageResponse;
import com.zzyl.base.ResponseResult;
import com.zzyl.dto.NursingProjectDto;
import com.zzyl.service.NursingProjectService;
import com.zzyl.vo.NursingProjectVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * 护理项目Controller类
 */
@RestController
@RequestMapping("/nursing_project")
@Api(tags = "护理项目管理")
public class NursingProjectController {

    @Autowired
    private NursingProjectService nursingProjectService;

    /**
     * 新增护理项目
     *
     * @param nursingProjectDTO 护理项目数据传输对象
     * @return 操作结果
     */
    @PostMapping
    @ApiOperation("新增护理项目")
    public ResponseResult add(
            @ApiParam(value = "护理项目数据传输对象", required = true)
            @RequestBody NursingProjectDto nursingProjectDTO) {
        nursingProjectService.add(nursingProjectDTO);
        return ResponseResult.success();
    }

    /**
     * 根据编号查询护理项目信息
     *
     * @param id 护理项目编号
     * @return 护理项目信息
     */
    @GetMapping("/{id}")
    @ApiOperation("根据编号查询护理项目信息")
    public ResponseResult<NursingProjectVo> getById(
            @ApiParam(value = "护理项目编号", required = true)
            @PathVariable("id") Long id) {
        NursingProjectVo nursingProjectVO = nursingProjectService.getById(id);
        return ResponseResult.success(nursingProjectVO);
    }

    /**
     * 分页查询护理项目列表
     *
     * @param name     护理项目名称
     * @param status   状态:0-禁用,1-启用
     * @param pageNum  当前页码
     * @param pageSize 每页显示数量
     * @return 护理项目列表
     */
    @GetMapping
    @ApiOperation("分页查询护理项目列表")
    public ResponseResult<PageResponse<NursingProjectVo>> getByPage(
            @ApiParam(value = "护理项目名称")
            @RequestParam(value = "name", required = false) String name,
            @ApiParam(value = "状态:0-禁用,1-启用")
            @RequestParam(value = "status", required = false) Integer status,
            @ApiParam(value = "当前页码")
            @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
            @ApiParam(value = "每页显示数量")
            @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) {
        PageResponse<NursingProjectVo> nursingProjectPageInfo = nursingProjectService.getByPage(name, status, pageNum, pageSize);
        return ResponseResult.success(nursingProjectPageInfo);
    }

    /**
     * 更新护理项目信息
     *
     * @param nursingProjectDTO 护理项目数据传输对象
     * @return 操作结果
     */
    @PutMapping
    @ApiOperation("更新护理项目信息")
    public ResponseResult update(
            @ApiParam(value = "护理项目数据传输对象", required = true)
            @RequestBody NursingProjectDto nursingProjectDTO) {
        nursingProjectService.update(nursingProjectDTO);
        return ResponseResult.success();
    }

    /**
     * 删除护理项目信息
     *
     * @param id 护理项目编号
     * @return 操作结果
     */
    @DeleteMapping("/{id}")
    @ApiOperation("删除护理项目信息")
    public ResponseResult deleteById(
            @ApiParam(value = "护理项目编号", required = true)
            @PathVariable("id") Long id) {
        NursingProjectVo nursingProjectVO = nursingProjectService.getById(id);
        if (nursingProjectVO == null) {
            return ResponseResult.error();
        }
        nursingProjectService.deleteById(id);
        return ResponseResult.success();
    }

    @PutMapping("/{id}/status/{status}")
    @ApiOperation("启用/禁用护理项目")
    public ResponseResult enableOrDisable(
            @ApiParam(value = "护理项目编号", required = true)
            @PathVariable Long id,
            @ApiParam(value = "状态:0-禁用,1-启用", required = true)
            @PathVariable Integer status) {
        nursingProjectService.enableOrDisable(id, status);
        return ResponseResult.success();
    }

    @ApiOperation("查询所有护理项目")
    @GetMapping("/all")
    public ResponseResult<List<NursingProjectVo>> getAllNursingProject() {
        return ResponseResult.success(nursingProjectService.listAll());
    }
}

4.2、NursingProjectDto

java 复制代码
@Data
@ApiModel(value = "护理项目参数接收实体")
public class NursingProjectDto extends BaseDto {

    @ApiModelProperty(value = "护理名称")
    private String name;

    @ApiModelProperty(value = "排序字段")
    private Integer orderNo;

    @ApiModelProperty(value = "单位")
    private String unit;

    @ApiModelProperty(value = "价格")
    private BigDecimal price;

    @ApiModelProperty(value = "图片")
    private String image;

    @ApiModelProperty(value = "护理要求")
    private String nursingRequirement;

    @ApiModelProperty(value = "状态(0:禁用,1:启用)")
    private Integer status;
}

4.3、BaseDto

java 复制代码
package com.zzyl.base;

import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

/**
 * Entity基类
 *
 *
 */
@Data
public class BaseDto implements Serializable
{
    private static final long serialVersionUID = 1L;

    /**
     * 主键
     */
    @ApiModelProperty(value = "主键")
    private Long id;

    /** 搜索值 */
    @JsonIgnore
    private String searchValue;

    /** 备注 */
    @ApiModelProperty(value = "备注")
    private String remark;

    /** 请求参数 */
    @JsonIgnore
    private Map<String, Object> params;

    public Map<String, Object> getParams()
    {
        if (params == null)
        {
            params = new HashMap<>();
        }
        return params;
    }

    public void setParams(Map<String, Object> params)
    {
        this.params = params;
    }
}

4.4、NursingProject

java 复制代码
/**
 * 护理项目实体类
 */
@Data
@ApiModel(description = "护理项目实体类")
public class NursingProject extends BaseEntity {

    /**
     * 护理名称
     */
    @ApiModelProperty(value = "护理名称")
    private String name;

    /**
     * 排序
     */
    @ApiModelProperty(value = "排序")
    private Integer orderNo;

    /**
     * 单位
     */
    @ApiModelProperty(value = "单位")
    private String unit;

    /**
     * 价格
     */
    @ApiModelProperty(value = "价格")
    private BigDecimal price;

    /**
     * 图片路径
     */
    @ApiModelProperty(value = "图片路径")
    private String image;

    /**
     * 护理要求
     */
    @ApiModelProperty(value = "护理要求")
    private String nursingRequirement;

    /**
     * 状态 (0:禁用,1:启用)
     */
    @ApiModelProperty(value = "状态 (0:禁用,1:启用)")
    private Integer status;
}

4.5、在线文档测试

启动本地服务后,访问地址:http://ip:port/doc.html--->http://localhost:9995/doc.html

在这里即可对接口的描述信息(路径、请求方式、出参、入参)进行查看,也可以对接口进行调试

相关推荐
驭渊的小故事18 分钟前
Spring AI Alibaba 实战:从maven依赖治理到声明式工具调用
java·人工智能·spring
Elastic 中国社区官方博客42 分钟前
我们如何通过 70 多个拉取请求,将 OpenTelemetry Java agent 迁移到 invokedynamic
java·大数据·开发语言·elasticsearch·搜索引擎·全文检索·es
tyn1881 小时前
记录本地安装nacos服务的方法及异常
java·开发语言
步行cgn1 小时前
Spring MVC 视图机制的核心接口与类
java·开发语言·后端·spring·mvc
y1su2 小时前
Leetcode 字符串模板
java·数据结构·算法·leetcode·职场和发展·动态规划
我命由我123453 小时前
Python 开发 - Python 的 pathlib
java·开发语言·后端·python·学习·java-ee·学习方法
苜蓿muxu3 小时前
Java 字符串拼接:+、StringBuilder、StringBuffer的区别
java
摇滚侠3 小时前
《Java并发编程之美》第 4 章 Java 并发包中原子操作类原理剖析 阅读笔记 7
java·笔记·python
旋律4144 小时前
同义方法区别(增加类与删除类)
java·后端