随着前后端的分离,作为后端的开发多以接口的方式暴露给前端使用,一方面需要对接口进行版本管理,另一方面需要对接口进行文档说明的管理,这里对knife4j进行了简单的使用,借以说明如何通过knife4j在springboot项目中自动生成接口说明文档以及进行接口版本管理。

knife4j需要引入的包

对于新的knife4j使用比较简单,需要在springboot项目引入以下两个包即可,如下

com.github.xiaoymin     knife4j-spring-boot-starter     2.0.2javax.validation     validation-api     2.0.1.Final

然后就是对接口自动生成的相关配置,这里对一个接口做了两个版本,分别进行配置,对于相同接口的不同版本配置也可以放在一个配置类中,这个看个人喜好,这里假定有一个关于用户的接口,一共有两个版本,分别配置如下

接口版本V1.0.0配置

package or.noka.nokabar.config;import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Import;import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;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;/** ---------------------------------------------------------- * 接口文档生成配置 * 接口版本 V 1.0.0 * @author xiefangjian@163.com * @version 1.0.0 **--------------------------------------------------------**/@Configuration@EnableSwagger2@EnableKnife4j@Import(BeanValidatorPluginsConfiguration.class)public class SwaggerConfigV1_0_0 {    /** ---------------------------------------------------     * 接口版本 API_VERSIONS_V_1_0_0     * @return 接口配置信息     ** ------------------------------------------------**/    @Bean(ConstVarConfig.API_VERSIONS_V_1_0_0)    public Docket docket() {        Docket docket=new Docket(DocumentationType.SWAGGER_2)                .apiInfo(appinfo())//接说明信息                .groupName(ConstVarConfig.API_VERSIONS_V_1_0_0)//接口版本号                .select()                .apis(RequestHandlerSelectors.basePackage("or.noka.nokabar.controller"))//这里指定Controller扫描包路径                .paths((s) -> {                    if(s.indexOf("/"+ConstVarConfig.API_VERSIONS_V_1_0_0)!=-1) {//只显示对应版本的接口                        return true;                    }                    return false;                })                .build();        return docket;    }    /** ----------------------------------------------     * 接口说明信息     * @return 接口说明信息     ** -------------------------------------------**/    private ApiInfo appinfo(){        return new ApiInfoBuilder()                .title("接口服务")//设置文档的标题                .description("

API 接口文档


" + "
这里存放接口说明" + "
接口说明") // 设置文档的描述 .version(ConstVarConfig.API_VERSIONS_V_1_0_0) //设置文档的版本信息-> 1.0.0 .build(); }}


接口版本V1.0.01配置

package or.noka.nokabar.config;import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Import;import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;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;/** ---------------------------------------------------------- * 接口文档生成配置 * 接口版本 V 1.0.1 * @author xiefangjian@163.com * @version 1.0.0 **--------------------------------------------------------**/@Configuration@EnableSwagger2@EnableKnife4j@Import(BeanValidatorPluginsConfiguration.class)public class SwaggerConfigV1_0_1 {    /** ----------------------------------------------------     * 接口版本 API_VERSIONS_V_1_0_1     * @return 接口配置信息     ** -------------------------------------------------**/    @Bean(ConstVarConfig.API_VERSIONS_V_1_0_1)    public Docket docket() {        Docket docket=new Docket(DocumentationType.SWAGGER_2)                .apiInfo(appinfo())//接说明                .groupName(ConstVarConfig.API_VERSIONS_V_1_0_1)//接口版本                .select()                .apis(RequestHandlerSelectors.basePackage("or.noka.nokabar.controller"))//这里指定Controller扫描包路径                .paths((s) -> {                    if(s.indexOf("/"+ConstVarConfig.API_VERSIONS_V_1_0_1)!=-1) {//只显示对应版本的接口                        return true;                    }                    return false;                })                .build();        return docket;    }    /** ---------------------------------------------------     * 接口说明信息     * @return 接口说明信息     ** ------------------------------------------------**/    private ApiInfo appinfo(){        return new ApiInfoBuilder()                .title("接口服务")//设置文档的标题                .description("

API 接口文档


" + "
这里存放接口说明" + "
接口说明") // 设置文档的描述 .version(ConstVarConfig.API_VERSIONS_V_1_0_1) //设置文档的版本信息-> 1.0.1 .build(); }}


以上配置了两个版本的接口分别为V1.0.0和V1.0.0.1,这两个版本的定义放在了ConstVarConfig类中,该类中只是对这两个版本做了常量定义,以便在接口实现中使用该版本定义,实现如下

package or.noka.nokabar.config;/** ----------------------------------------------- * 配置常量 * @author xiefangjian@163.com * @version 1.0.0 ** --------------------------------------------**/public class ConstVarConfig {    public static final  String API_VERSIONS_V_1_0_0 = "V1.0.0";//接口版本号    public static final  String API_VERSIONS_V_1_0_1 = "V1.0.1";//接口版本号}

接口实现及接口说明文档编写

接口实现和普通的springboot中的Controller实现完全相同,只需要加上接口说明自动生成需要的一些说明即可

package or.noka.nokabar.controller;import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;import com.github.xiaoymin.knife4j.annotations.ApiSort;import io.swagger.annotations.Api;import io.swagger.annotations.ApiImplicitParam;import io.swagger.annotations.ApiImplicitParams;import io.swagger.annotations.ApiOperation;import or.noka.nokabar.config.ConstVarConfig;import or.noka.nokabar.vo.UserApiVo;import org.springframework.stereotype.Component;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.ResponseBody;/** -------------------------------------------------------------- * 用户相关接口 * @author  xiefangjian@163.com * @version 1.0.0 ** -----------------------------------------------------------**/@Controller@Component@Api(tags = "1 用户接口") //接口名称,该内容将做为接口说明界面中的第一级菜单名称@ApiSort(1) //该接口文档在接口界面中菜单的排序,该排序只针对第一级菜单的顺序@RequestMapping("/user")//接口根地址,该地址与后面的方法访问地址共同组成接口访问的完整地址public class UserAPIController {    /**----------------------------------------------------------     * 用户登陆接口     * 接口版本 API_VERSIONS_V_1_0_0     * @param id 传入参数 id     **------------------------------------------------------**/    @GetMapping({"/login/"+ConstVarConfig.API_VERSIONS_V_1_0_0+"/{id}"})//接口调用地址    @ApiOperationSupport(order = 1)//接口排序,只针对二级菜单的顺序,序号越小,排序越靠前    @ResponseBody //返回JSON    @ApiOperation(value = "1.1 用户登陆接口",notes = "用户登陆接口",produces = "application/json")    @ApiImplicitParam(name = "id",value = "用户id",dataType = "Long",paramType = "Long",required = true)    public UserApiVo loginV1_0_0(@PathVariable("id") String id){       return  new UserApiVo("SUCCESS","login success");    }    /**----------------------------------------------------------     * 用户登陆接口     * 接口版本 API_VERSIONS_V_1_0_1     * @param id 传入参数 id     * @param password 传入参数 密码     **------------------------------------------------------**/    @GetMapping({"/login/"+ConstVarConfig.API_VERSIONS_V_1_0_1+"/{id}/{password}"})//接口调用地址    @ApiOperationSupport(order = 1)//接口排序,只针对二级菜单的顺序,序号越小,排序越靠前    @ResponseBody //返回JSON    @ApiOperation(value = "1.1 用户登陆接口",notes = "用户登陆接口",produces = "application/json") //接口名称以及接口说明    @ApiImplicitParam(name = "id",value = "用户id",dataType = "Long",paramType = "Long",required = true)    @ApiImplicitParams({            @ApiImplicitParam(name = "id",value = "用户id",dataType = "Long",paramType = "Long",required = true),            @ApiImplicitParam(name = "password",value = "用户密码",dataType = "String",paramType = "Long",required = true)    })    public UserApiVo loginV1_0_1(@PathVariable("id") String id,@PathVariable("password") String password){        return  new UserApiVo("SUCCESS","login success");    }}

以上配置中,分别对接口的名称,参数类型,参数是否为必须的进行了说明,具体参数含义如下

  • ApiOperationSupport

order:接口排序,序号越小,排序越靠前,该功能需要在接口界面中开启增强功能才会有效果

  • ApiOperation

value:接口名称,显示在二级菜单中的名称

notes:接口描述,显示在接口描述信息中的内容

produces:接口返回的数据类型,这里返回的是JSON字符串

  • ApiImplicitParam

name:参数名字,与方法里的参数同名

value:参数描述

dataType:参数的数据类型

required:该参数是否为必须项

如上所示,多个参数需要用ApiImplicitParams进行配置

配置完成以后,在接口中可以看到该接口说明,并且可以直接进行接口测试




Java wsdl 生成接口 java接口生成工具_API

接口说明界面




Java wsdl 生成接口 java接口生成工具_API_02

接口在线测试界面



以上接口返回的是一个名为UserApiVo的对象,该对象被定义成了一个消息的实体对象,可以在该消息实体对象中对参数进行说明,如下

package or.noka.nokabar.vo;import io.swagger.annotations.ApiModel;import io.swagger.annotations.ApiModelProperty;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;import java.io.Serializable;/** ------------------------------------------------- * 用户接口返回对象 * @author xiefangjian@163.com * @version V1.0.0 */@Data //这里使用了lombok封装实体类@AllArgsConstructor //全参数构造方法@NoArgsConstructor //无参数构造方法@ApiModel("用户操作返回信息")//定义用户操作接口返回对象说明public class UserApiVo implements Serializable {    @ApiModelProperty(value = "返回代码,{SUCCESS|操作成功,FAIL|操作失败}",required = true)    private String code=null;    @ApiModelProperty(value = "返回信息",required = true)    private String msg=null;}

以上配置完成以后,就可以启动项目访问接口说明文档了,接口说明文档的访问路径为/doc.html,默认是没有密码的,可以直接访问,为了安全可以配置一个访问账户和密码

knife4j访问参数配置

## 是否关闭接口文档,默认是false,在生产环境中可以设为true,以关闭接口说明#knife4j.production=true## 开启Swagger的Basic认证功能,默认是falseknife4j.basic.enable=true## Basic认证用户名knife4j.basic.username=admin## Basic认证密码knife4j.basic.password=admin123

至此,knife4j所有配置完成,这里的版本控制被放置在了接口访问路径里的最后一级,这只是个人喜好,没有特别意义,版本号的标识可以放在访问路径中的任何地方,另外如果接口需要做版本控制,那么最好从一开始就要规划好多版本共存的问题,以及是否需要不同版本接口向下兼容等问题。