当前位置: 当前位置:首页 > 娱乐 > 入门级swagger2和knife4j的详细使用 正文

入门级swagger2和knife4j的详细使用

2024-04-29 00:56:37 来源:口口声声网 作者:休闲 点击:832次

入门级swagger2和knife4j的详细使用

入门级swagger2和knife4j的入门详细使用

重要的使事情说三遍
重要的使事情说三遍
重要的使事情说三遍
使用swagge或knife4j都有与springboot的版本兼容问题,该文章使用的详细springboot版本是2.2.2.RELEASE版本,如果高版本可能会出现启动报错

1、使用swagger介绍

相信无论是入门前端还是后端开发,都或多或少地被接口文档折磨过。详细前端经常抱怨后端给的使用接口文档与实际情况不一致。后端又觉得编写及维护接口文档会耗费不少精力,入门经常来不及更新。详细其实无论是使用前端调用后端,还是入门后端调用后端,都期望有一个好的详细接口文档。但是使用这个接口文档对于程序员来说,就跟注释一样,入门经常会抱怨别人写的详细代码没有写注释,然而自己写起代码起来,使用最讨厌的,也是写注释。所以仅仅只通过强制来规范大家是不够的,随着时间推移,版本迭代,接口文档往往很容易就跟不上代码了。

使用Swagger你只需要按照它的规范去定义接口及接口相关的信息。再通过Swagger衍生出来的一系列项目和工具,就可以做到生成各种格式的接口文档,生成多种语言的客户端和服务端的代码,以及在线接口调试页面等等。这样,如果按照新的开发模式,在开发新版本或者迭代版本的时候,只需要更新Swagger描述文件,就可以自动生成接口文档和客户端服务端代码,做到调用端代码、服务端代码以及接口文档的一致性。

为了简化swagger的使用,Spring框架对swagger进行了整合,建立了Spring-swagger项目,后面改成了现在的Springfox。通过在项目中引入Springfox,可以扫描相关的代码,生成描述文件,进而生成与代码一致的接口文档和客户端代码。

Springfox对应的maven坐标如下:

注意:swagger与springBoot的版本是有兼用性的,需要对应的版本号

io.springfoxspringfox-swagger-ui    2.9.2io.springfoxspringfox-swagger2    2.9.2

2、swagger常用注解

注解说明
@Api用在请求的类上,例如Controller,表示对类的说明
@ApiModel用在类上,通常是实体类,表示一个返回响应数据的信息
@ApiModelProperty用在属性上,描述响应类的属性
@ApiOperation用在请求的方法上,说明方法的用途、作用
@ApiImplicitParams用在请求的方法上,表示一组参数说明
@ApiImplicitParam用在@ApiImplicitParams注解中,指定一个请求参数的各个方面

3、 swagger入门案例

3.1、第一步:创建maven工程swagger_demo并配置pom.xml文件

4.0.0org.springframework.bootspring-boot-starter-parent        2.2.2.RELEASEorg.exampleswagger_demo    1.0-SNAPSHOT88org.springframework.bootspring-boot-starter-web        io.springfoxspringfox-swagger-ui            2.9.2io.springfoxspringfox-swagger2            2.9.2org.projectlomboklombok        

3.2、创建application.yml文件

server:  port: 9000

3.3、第三步: 创建实体类User和Menu

package com.zcl.entity;import io.swagger.annotations.ApiModel;import io.swagger.annotations.ApiModelProperty;import lombok.Data;/** * 项目名称:swagger_demo * 描述:用户实体类 * * @author zhong * @date 2022-08-29 6:50 */@Data@ApiModel(value = "用户实体",description = "用户响应实体")public class User {    @ApiModelProperty(value = "主键")    private int id;    @ApiModelProperty(value = "姓名")    private String name;    @ApiModelProperty(value = "年龄")    private int age;    @ApiModelProperty(value = "地址")    private String address;}
package com.zcl.entity;import io.swagger.annotations.ApiModel;import io.swagger.annotations.ApiModelProperty;import lombok.Data;/** * 项目名称:swagger_demo * 描述:菜单实体类 * * @author zhong * @date 2022-08-29 6:49 */@Data@ApiModel(value = "菜单实体",discriminator = "菜单实体描述")public class Menu {    @ApiModelProperty(value = "主键")    private int id;    @ApiModelProperty(value = "菜单名称")    private String name;}

3.4、第四步:创建UserController和MenuController

package com.zcl.controller.user;import com.zcl.entity.User;import io.swagger.annotations.Api;import io.swagger.annotations.ApiImplicitParam;import io.swagger.annotations.ApiImplicitParams;import io.swagger.annotations.ApiOperation;import org.springframework.web.bind.annotation.*;import java.util.ArrayList;import java.util.List;/** * 项目名称:swagger_demo * 描述:用户控制器 * * @author zhong * @date 2022-08-29 6:55 */@Api(value = "用户控制器")@RestController@RequestMapping("/user")public class UserController {    @GetMapping("/getUsers")    @ApiOperation(value = "查询所有用户", notes = "查询所有用户信息")    public ListgetAllUsers(){        User user = new User();        user.setId(100);        user.setName("itcast");        user.setAge(20);        user.setAddress("bj");        Listlist = new ArrayList<>();        list.add(user);        return list;    }    @PostMapping("/save")    @ApiOperation(value = "新增用户", notes = "新增用户信息")    public String save(@RequestBody User user){        return "OK";    }    @PutMapping("/update")    @ApiOperation(value = "修改用户", notes = "修改用户信息")    public String update(@RequestBody User user){        return "OK";    }    @DeleteMapping("/delete")    @ApiOperation(value = "删除用户", notes = "删除用户信息")    public String delete(int id){        return "OK";    }    @ApiImplicitParams({            @ApiImplicitParam(name = "pageNum", value = "页码",                    required = true, type = "Integer"),            @ApiImplicitParam(name = "pageSize", value = "每页条数",                    required = true, type = "Integer"),    })    @ApiOperation(value = "分页查询用户信息")    @GetMapping(value = "page/{pageNum}/{pageSize}")    public String findByPage(@PathVariable Integer pageNum,                             @PathVariable Integer pageSize) {        return "OK";    }}
package com.zcl.controller.menu;import com.zcl.entity.Menu;import io.swagger.annotations.Api;import io.swagger.annotations.ApiImplicitParam;import io.swagger.annotations.ApiImplicitParams;import io.swagger.annotations.ApiOperation;import org.springframework.web.bind.annotation.*;import java.util.ArrayList;import java.util.List;/** * 项目名称:swagger_demo * 描述:菜单控制器 * * @author zhong * @date 2022-08-29 7:00 */@Api(tags = "菜单控制器")@RestController@RequestMapping("/menu")public class MenuController {    @GetMapping("/getMenus")    @ApiOperation(value = "查询所有菜单", notes = "查询所有菜单信息")    public ListgetMenus(){        Menu menu = new Menu();        menu.setId(100);        menu.setName("itcast");        Listlist = new ArrayList<>();        list.add(menu);        return list;    }    @PostMapping("/save")    @ApiOperation(value = "新增菜单", notes = "新增菜单信息")    public String save(@RequestBody Menu menu){        return "OK";    }    @PutMapping("/update")    @ApiOperation(value = "修改菜单", notes = "修改菜单信息")    public String update(@RequestBody Menu menu){        return "OK";    }    @DeleteMapping("/delete")    @ApiOperation(value = "删除菜单", notes = "删除菜单信息")    public String delete(int id){        return "OK";    }    @ApiImplicitParams({            @ApiImplicitParam(name = "pageNum", value = "页码",                    required = true, type = "Integer"),            @ApiImplicitParam(name = "pageSize", value = "每页条数",                    required = true, type = "Integer"),    })    @ApiOperation(value = "分页查询菜单信息")    @GetMapping(value = "page/{pageNum}/{pageSize}")    public String findByPage(@PathVariable Integer pageNum,                             @PathVariable Integer pageSize) {        return "OK";    }}

3.5、第五步:创建配置类SwaggerAutoConfiguration

package com.zcl.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.service.Contact;import springfox.documentation.spi.DocumentationType;import springfox.documentation.spring.web.plugins.Docket;import springfox.documentation.swagger2.annotations.EnableSwagger2;/** * 项目名称:swagger_demo * 描述:swagger自动配置类 * * @author zhong * @date 2022-08-29 7:04 */@Configuration@EnableSwagger2public class SwaggerAutoConfiguration {    @Bean    public Docket createRestApi1() {        Docket docket = new Docket(DocumentationType.SWAGGER_2)                .apiInfo(apiInfo()).groupName("用户接口组")                .select()                //为当前包路径                .apis(RequestHandlerSelectors.basePackage("com.zcl.controller.user"))                .build();        return docket;    }    @Bean    public Docket createRestApi2() {        Docket docket = new Docket(DocumentationType.SWAGGER_2)                .apiInfo(apiInfo()).groupName("菜单接口组")                .select()                //为当前包路径                .apis(RequestHandlerSelectors.basePackage("com.zcl.controller.menu"))                .build();        return docket;    }    //构建 api文档的详细信息    private ApiInfo apiInfo() {        return new ApiInfoBuilder()                //页面标题                .title("API接口文档")                //创建人                .contact(new Contact("雕刻笔记", "http://xiaozhong01.top", ""))                //版本号                .version("1.0")                //描述                .description("API 描述")                .build();    }}

注意:如果不需要进行分组,可以将后面的createRestApi2()进行删除就剩余一个组了,并将.groupName("用户接口组")分组描述去掉以及将扫描控制器包修改即可

3.6、第六步:创建启动类SwaggerApplication

package com.zcl;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;/** * 项目名称:swagger_demo * 描述:swagger项目启动类 * * @author zhong * @date 2022-08-29 7:13 */@SpringBootApplicationpublic class SwaggerApplication {    public static void main(String[] args) {        SpringApplication.run(SwaggerApplication.class,args);    }}

3.7、项目启动

执行启动类main方法启动项目,访问地址:http://localhost:9000/swagger-ui.html
在这里插入图片描述

4、knife4j介绍

knife4j是为Java MVC框架集成Swagger生成Api文档的增强解决方案,前身是swagger-bootstrap-ui,取名knife4j是希望它能像一把匕首一样小巧,轻量,并且功能强悍!其底层是对Springfox的封装,使用方式也和Springfox一致,只是对接口文档UI进行了优化。

核心功能

  • 文档说明:根据Swagger的规范说明,详细列出接口文档的说明,包括接口地址、类型、请求示例、请求参数、响应示例、响应参数、响应码等信息,对该接口的使用情况一目了然。

  • 在线调试:提供在线接口联调的强大功能,自动解析当前接口参数,同时包含表单验证,调用参数可返回接口响应内容、headers、响应时间、响应状态码等信息,帮助开发者在线调试。

5、knife4j入门案例

第一步:创建maven工程knife4j_demo并配置pom.xml文件

4.0.0org.springframework.bootspring-boot-starter-parent        2.2.2.RELEASEorg.exampleknife4j    1.0-SNAPSHOT88org.springframework.bootspring-boot-starter-web        com.github.xiaoyminknife4j-spring-boot-starter            2.0.1org.projectlomboklombok        

第二步: 创建实体类User和Menu

package com.zcl.entity;import io.swagger.annotations.ApiModel;import io.swagger.annotations.ApiModelProperty;import lombok.Data;/** * 项目名称:swagger_demo * 描述:菜单实体类 * * @author zhong * @date 2022-08-29 6:49 */@Data@ApiModel(value = "菜单实体",discriminator = "菜单实体描述")public class Menu {    @ApiModelProperty(value = "主键")    private int id;    @ApiModelProperty(value = "菜单名称")    private String name;}
package com.zcl.entity;import io.swagger.annotations.ApiModel;import io.swagger.annotations.ApiModelProperty;import lombok.Data;/** * 项目名称:swagger_demo * 描述:用户实体类 * * @author zhong * @date 2022-08-29 6:50 */@Data@ApiModel(value = "用户实体",description = "用户响应实体")public class User {    @ApiModelProperty(value = "主键")    private int id;    @ApiModelProperty(value = "姓名")    private String name;    @ApiModelProperty(value = "年龄")    private int age;    @ApiModelProperty(value = "地址")    private String address;}

第三步:创建UserController和MenuController

控制器与入门的swagger2是一样的,直接复制下来

第四步:创建接口文档配置属性类SwaggerProperties

由于上一个swagger_demo的接口文档配置文件是写死在项目代码中的,不利于后面的开发与维护,使用knife4j时并将相关的属性配置以yml全局的方式灵活的进行配置,方便进行修改

package com.zcl.config;import lombok.Data;import org.springframework.boot.context.properties.ConfigurationProperties;import java.util.ArrayList;import java.util.LinkedHashMap;import java.util.List;import java.util.Map;/** * 项目名称:knife4j * 描述:配置属性类,用于封装yml配置文件中关于接口相关的配置文件 * * @author zhong * @date 2022-08-29 7:58 */@Data@ConfigurationProperties(prefix = "knife.swagger")public class SwaggerProperties {    /**标题*/    private String title = "在线文档";    /**自定义组名*/    private String group = "";    /**描述*/    private String description = "在线文档";    /**版本*/    private String version = "1.0";    /**联系人*/    private Contact contact = new Contact();    /**swagger会解析的包路径*/    private String basePackage = "com.zcl";    /**swagger会解析的url规则*/    private ListbasePath = new ArrayList<>();    /**在basePath基础上需要排除的url规则*/    private ListexcludePath = new ArrayList<>();    /**分组文档*/    private Mapdocket = new LinkedHashMap<>();    public String getGroup() {        if (group == null || "".equals(group)) {            return title;        }        return group;    }    @Data    public static class DocketInfo {        /**标题*/        private String title = "在线文档";        /**自定义组名*/        private String group = "";        /**描述*/        private String description = "在线文档";        /**版本*/        private String version = "1.0";        /**联系人*/        private Contact contact = new Contact();        /**swagger会解析的包路径*/        private String basePackage = "com.zcl";        /**swagger会解析的url规则*/        private ListbasePath = new ArrayList<>();        /**在basePath基础上需要排除的url规则*/        private ListexcludePath = new ArrayList<>();        /**分组文档*/        private Mapdocket = new LinkedHashMap<>();        public String getGroup() {            if (group == null || "".equals(group)) {                return title;            }            return group;        }    }    @Data    public static class Contact {        /**联系人*/        private String name = "pinda";        /**联系人url*/        private String url = "";        /**联系人email*/        private String email = "";    }}

第五步:创建application.yml文件

该配置文件的属性是对应上面的配置文件属性的如果不对上就不会被读取到
下面重点的是对【docket】进行map分组的属性配置
private Mapdocket = new LinkedHashMap<>();

不进行分组的配置

server:  port: 7788knife:  swagger:    enabled: true #是否启用swagger的开关    title: knife4j测试文档    description: knife4j测试文档描述    version: v1.0.0    basePackage: com.zcl.controller

进行分组的配置

server:  port: 7788knife:  swagger:    enabled: true #是否启用swagger的开关    title: knife4j测试文档    description: knife4j测试文档描述    version: v1.0.0    docket: # 进行分组      user: # key        # value        title: 用户模块        base-package: com.zcl.controller.user      menu:        title: 菜单模块        base-package: com.zcl.controller.menu

注意:上面配置文件中的enabled属性是对应着下面配置类中【@ConditionalOnProperty】通过注解判断是否符合条件才让配置类生效

第六步:创建配置类SwaggerAutoConfiguration

该配置类需要使到上面创建的SwaggerProperties生效以及需要启用swagger注解

package com.zcl.config;import com.google.common.base.Predicate;import com.google.common.base.Predicates;import org.springframework.beans.BeansException;import org.springframework.beans.factory.BeanFactory;import org.springframework.beans.factory.BeanFactoryAware;import org.springframework.beans.factory.config.ConfigurableBeanFactory;import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;import org.springframework.boot.context.properties.EnableConfigurationProperties;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.service.Contact;import springfox.documentation.spi.DocumentationType;import springfox.documentation.spring.web.plugins.Docket;import springfox.documentation.swagger2.annotations.EnableSwagger2;import javax.annotation.Resource;import java.util.ArrayList;import java.util.List;import java.util.Map;import java.util.Set;/** * 项目名称:knife4j * 描述:配置类 * * @author zhong * @date 2022-08-29 8:22 */@Configuration@EnableConfigurationProperties(SwaggerProperties.class)@EnableSwagger2@ConditionalOnProperty(name = "knife.swagger.enabled", havingValue = "true",        matchIfMissing = true)public class SwaggerAutoConfiguration implements BeanFactoryAware {    private BeanFactory beanFactory;    /**     * 通过类型注入去查找beanFactory     * @param beanFactory     * @throws BeansException     */    @Override    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {        this.beanFactory = beanFactory;    }    /**     * 注入自动配置属性类     */    @Resource    private SwaggerProperties swaggerProperties;    /**     * 遍历swaggerProperties属性配置的内容,转换成List集合【方便判断有没有进行分组,没有分组就一个list,分组就有多个】     * 使用@ConditionalOnProperty条件注入,bean工程有就不创建     * @return     */    @Bean    @ConditionalOnMissingBean    public ListcreateRestApi() {        // 强转beanFactory为可配置的bean工厂        ConfigurableBeanFactory configurableBeanFactory =                (ConfigurableBeanFactory) beanFactory;        // 创建返回的list集合        ListdocketList = new ArrayList<>();        // 获取到分组的对象如果为空就是不分组        if(swaggerProperties.getDocket().isEmpty()){            Docket docket = createDocket(swaggerProperties);            docketList.add(docket);        }else{            // 存在分组对象            // 获取到key【user\menu】            SetkeySet = swaggerProperties.getDocket().keySet();            // 遍历key获取到对应的value            for (String key : keySet) {                // 获取到info                SwaggerProperties.DocketInfo docketInfo = swaggerProperties.getDocket().get(key);                ApiInfo apiInfo = new ApiInfoBuilder()                        //页面标题                        .title(docketInfo.getTitle())                        //创建人                        .contact(new Contact(docketInfo.getContact().getName(),                                docketInfo.getContact().getUrl(),                                docketInfo.getContact().getEmail()))                        //版本号                        .version(docketInfo.getVersion())                        //描述                        .description(docketInfo.getDescription())                        .build();                // base-path处理                // 当没有配置任何path的时候,解析/**                if (docketInfo.getBasePath().isEmpty()) {                    docketInfo.getBasePath().add("/**");                }                List>basePath = new ArrayList<>();                for (String path : docketInfo.getBasePath()) {                    basePath.add(PathSelectors.ant(path));                }                // exclude-path处理                List>excludePath = new ArrayList<>();                for (String path : docketInfo.getExcludePath()) {                    excludePath.add(PathSelectors.ant(path));                }                Docket docket = new Docket(DocumentationType.SWAGGER_2)                        .apiInfo(apiInfo)                        .groupName(docketInfo.getGroup())                        .select()                        //为当前包路径                        .apis(RequestHandlerSelectors.basePackage(docketInfo.getBasePackage()))                        .paths(Predicates.and(Predicates.not(Predicates.or(excludePath)),Predicates.or(basePath)))                        .build();                configurableBeanFactory.registerSingleton(key, docket);                docketList.add(docket);            }        }        return docketList;    }    /**     * 构建 api文档的详细信息     * @param swaggerProperties     * @return     */    private ApiInfo apiInfo(SwaggerProperties swaggerProperties) {        return new ApiInfoBuilder()                //页面标题                .title(swaggerProperties.getTitle())                //创建人                .contact(new Contact(swaggerProperties.getContact().getName(),                        swaggerProperties.getContact().getUrl(),                        swaggerProperties.getContact().getEmail()))                //版本号                .version(swaggerProperties.getVersion())                //描述                .description(swaggerProperties.getDescription())                .build();    }    /**     * 创建接口文档对象     * @param swaggerProperties 属性配置     * @return     */    private Docket createDocket(SwaggerProperties swaggerProperties) {        //API 基础信息        ApiInfo apiInfo = apiInfo(swaggerProperties);        // base-path处理        // 当没有配置任何path的时候,解析/**        if (swaggerProperties.getBasePath().isEmpty()) {            swaggerProperties.getBasePath().add("/**");        }        List>basePath = new ArrayList<>();        for (String path : swaggerProperties.getBasePath()) {            basePath.add(PathSelectors.ant(path));        }        // exclude-path排除处理        List>excludePath = new ArrayList<>();        for (String path : swaggerProperties.getExcludePath()) {            excludePath.add(PathSelectors.ant(path));        }        return new Docket(DocumentationType.SWAGGER_2)                .apiInfo(apiInfo)                .groupName(swaggerProperties.getGroup())                .select()                .apis(RequestHandlerSelectors.basePackage(swaggerProperties.getBasePackage()))                .paths(Predicates.and(Predicates.not(Predicates.or(excludePath)),Predicates.or(basePath)))                .build();    }}

第七步:创建启动类knife4jApplication

package com.zcl;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;/** * 项目名称:knife4j * 描述:knife4j项目启动类 * * @author zhong * @date 2022-08-29 8:09 */@SpringBootApplicationpublic class knife4jApplication {    public static void main(String[] args) {        SpringApplication.run(knife4jApplication.class, args);    }}

执行启动类main方法启动项目,访问地址:http://localhost:7788/doc.html

在这里插入图片描述

作者:探索
------分隔线----------------------------
头条新闻
图片新闻
新闻排行榜