Knife4j -- 在线API文档框架

Posted ^吃酒和尚*

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Knife4j -- 在线API文档框架相关的知识,希望对你有一定的参考价值。

6.5. Knife4j – 在线API文档框架

Knife4j是国人开发一个基于Swagger2的在线API文档的框架,它可以扫描控制器所在的包,并解析每一个控制器及其内部的处理请求的方法,生成在线API文档,为前后端的开发人员的沟通提供便利。

pom.xml中添加依赖:

<!-- https://mvnrepository.com/artifact/com.github.xiaoymin/knife4j-spring-boot-starter -->
<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>knife4j-spring-boot-starter</artifactId>
    <version>2.0.9</version>
</dependency>

然后,需要在application.properties中添加配置:

knife4j.enable=true

并且,需要在cn.tedu.boot.demo.config下创建Knife4jConfiguration配置类:

/**
 * Knife4j(Swagger2)的配置
 */
@Configuration
@EnableSwagger2WebMvc
public class Knife4jConfiguration 

    /**
     * 【重要】指定Controller包路径
     */
    private String basePackage = "cn.tedu.boot.demo.controller";
    /**
     * 分组名称
     */
    private String groupName = "xxx";
    /**
     * 主机名
     */
    private String host = "xxx";
    /**
     * 标题
     */
    private String title = "xxx";
    /**
     * 简介
     */
    private String description = "xxx";
    /**
     * 服务条款URL
     */
    private String termsOfServiceUrl = "http://www.apache.org/licenses/LICENSE-2.0";
    /**
     * 联系人
     */
    private String contactName = "xxx";
    /**
     * 联系网址
     */
    private String contactUrl = "xxx";
    /**
     * 联系邮箱
     */
    private String contactEmail = "xxx";
    /**
     * 版本号
     */
    private String version = "1.0.0";

    @Autowired
    private OpenApiExtensionResolver openApiExtensionResolver;

    @Bean
    public Docket docket() 
        String groupName = "1.0.0";
        Docket docket = new Docket(DocumentationType.SWAGGER_2)
                .host(host)
                .apiInfo(apiInfo())
                .groupName(groupName)
                .select()
                .apis(RequestHandlerSelectors.basePackage(basePackage))
                .paths(PathSelectors.any())
                .build()
                .extensions(openApiExtensionResolver.buildExtensions(groupName));
        return docket;
    

    private ApiInfo apiInfo() 
        return new ApiInfoBuilder()
                .title(title)
                .description(description)
                .termsOfServiceUrl(termsOfServiceUrl)
                .contact(new Contact(contactName, contactUrl, contactEmail))
                .version(version)
                .build();
    


完成后,启动项目,通过 http://localhost:8080/doc.html 即可访问在线API文档。

在开发实践中,每个处理请求的方法应该限定为某1种请求方式,如果允许多种请求方式,则在API文档的菜单中会有多项。

在API文档中,菜单中的各名称默认是根据控制器类名、方法名转换得到的,通常,应该通过配置改为更加易于阅读理解的名称:

  • @Api:是添加在控制器类上的注解,通过此注解的tags属性可以修改原本显示控制器类名称的位置的文本,通常,建议在配置的tags值上添加序号,例如:"1. 管理员模块""2. 商品模块",则框架会根据值进行排序
  • @ApiOperation:是添加在控制器类中处理请求的方法上的注解,用于配置此方法处理的请求在API文档中显示的文本
  • @ApiOperationSupport:是添加在控制器类中处理请求的方法上的注解,通过配置其order属性可以指定各方法在API文档中的显示顺序
  • @ApiModelProperty:是添加在POJO类的属性上的注解,用于对请求参数或响应结果中的某个属性进行说明,主要通过其value属性配置描述文本,并可通过example属性配置示例值,还可在响应结果时通过position属性指定顺序
  • @ApiImplicitParam:是添加在控制器类中处理请求的方法上的注解,也可以作为@ApiImplicitParams注解的参数值,主要用于配置非封装的参数,主要配置namevalueexamplerequireddataType属性
  • @ApiImplicitParams:是添加在控制器类中处理请求的方法上的注解,当方法有多个非封装的参数时,在方法上添加此注解,并在注解内部通过@ApiImplicitParam数组配置多个参数

提示:以上@ApiImplicitParams@ApiImplicitParam@ApiModelProperty可以组合使用。

配置示例–控制器类:

@Api(tags = "1. 管理员模块")
@Slf4j
@RestController
@RequestMapping("/admin")
public class AdminController 

    @ApiOperationSupport(order = 10)
    @ApiOperation("增加管理员")
    @PostMapping("/add-new")
    public JsonResult<Void> addNew(AdminAddNewDTO adminAddNewDTO) 
        throw new RuntimeException("此功能尚未实现");
    

    @ApiOperationSupport(order = 40)
    @ApiOperation("根据id查询管理员详情")
    @ApiImplicitParam(name = "id", value = "管理员id", example = "1",
            required = true, dataType = "long")
    @GetMapping("/id:[0-9]+")
    public JsonResult<Admin> getById(@PathVariable Long id) 
        throw new RuntimeException("此功能尚未实现");
    

    @ApiOperationSupport(order = 41)
    @ApiOperation("根据角色类型查询管理员列表")
    @ApiImplicitParams(
            @ApiImplicitParam(name = "roleId", value = "角色id", example = "1",
                required = true, dataType = "long"),
            @ApiImplicitParam(name = "page", value = "页码", example = "1",
                dataType = "int")
    )
    @GetMapping("/list-by-role")
    public JsonResult<Admin> listByRole(Long roleId, Integer page) 
        throw new RuntimeException("此功能尚未实现");
    


配置示例–封装的POJO类:

@Data
@Accessors(chain = true)
public class AdminAddNewDTO implements Serializable 

    @ApiModelProperty(value = "用户名", example = "admin001")
    private String username;

    @ApiModelProperty(value = "密码", example = "123456")
    private String password;

    @ApiModelProperty(value = "昵称", example = "管理员1号")
    private String nickname;


6.6. 检查参数的基本格式

使用spring-boot-starter-validation即可检查请求参数的有效性,需要在pom.xml中添加此依赖项:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

然后,在封装的POJO类的属性上配置检查相关注解,例如:

@Data
@Accessors(chain = true)
public class AdminAddNewDTO implements Serializable 

    @NotNull(message = "增加管理员失败,必须提交用户名!")
    private String username;

    @NotNull(message = "增加管理员失败,必须提交密码!")
    private String password;

    @NotNull(message = "增加管理员失败,必须提交昵称!")
    private String nickname;


然后,在处理请求的方法中,对需要检查的参数添加@Valid@Validated注解,例如:

@PostMapping("/add-new")
public JsonResult<Void> addNew(@Valid AdminAddNewDTO adminAddNewDTO) 
    adminService.addNew(adminAddNewDTO);
    return JsonResult.ok();

至此,Validation框架已经生效,可以对以上请求的参数进行检查!

启动项目后,如果故意没有提交以上必要的参数,则会出现400错误,并且在IntelliJ IDEA控制台可以看到以下信息:

Resolved [org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 3 errors<LF>Field error in object 'adminAddNewDTO' on field 'password': rejected value [null]; codes [NotNull.adminAddNewDTO.password,NotNull.password,NotNull.java.lang.String,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [adminAddNewDTO.password,password]; arguments []; default message [password]]; default message [增加管理员失败,必须提交密码!]<LF>Field error in object 'adminAddNewDTO' on field 'username': rejected value [null]; codes [NotNull.adminAddNewDTO.username,NotNull.username,NotNull.java.lang.String,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [adminAddNewDTO.username,username]; arguments []; default message [username]]; default message [增加管理员失败,必须提交用户名!]<LF>Field error in object 'adminAddNewDTO' on field 'nickname': rejected value [null]; codes [NotNull.adminAddNewDTO.nickname,NotNull.nickname,NotNull.java.lang.String,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [adminAddNewDTO.nickname,nickname]; arguments []; default message [nickname]]; default message [增加管理员失败,必须提交昵称!]]

由于Validation框架在验证不通过时会抛出BindException,则可以使用Spring MVC统一处理异常的机制进行处理!

首先,在State枚举中添加新的枚举值:

public enum State 
	OK(20000),
	ERR_BAD_REQUEST(40000),
	ERR_CONFLICT(40900),
	ERR_INTERNAL_ERROR(50000);

	// 原有其它代码……

然后在GlobalExceptionHandler中添加新的处理异常的方法:

@ExceptionHandler(BindException.class)
public JsonResult<Void> handleBindException(BindException e) 
    String message = e.getBindingResult().getFieldError().getDefaultMessage();
    return JsonResult.fail(JsonResult.State.ERR_BAD_REQUEST, message);

重启项目后,再次故意不提交某些请求参数,将响应类似以下结果:


  "state": 40000,
  "message": "增加管理员失败,必须提交用户名!"

提示:当验证请求参数出现多种错误时,以上语句仅会随机的显示其中1个错误的描述文本。

SpringBoot2.0系列教程Springboot框架添加Swagger2来在线自动生成接口的文档+测试功能

Hello大家好,本章我们添加Swagger2来在线自动生成接口的文档+测试功能。有问题可以联系我[email protected]。另求各路大神指点,感谢

一:什么是Swagger

Swagger是一款通过我们添加的注解来对方法进行说明,来自动生成项目的在线api接口文档的web服务。

二:添加Swagger2依赖

<dependency>
   <groupId>io.springfox</groupId>
   <artifactId>springfox-swagger2</artifactId>
   <version>2.4.0</version>
</dependency>
<dependency>
   <groupId>io.springfox</groupId>
   <artifactId>springfox-swagger-ui</artifactId>
   <version>2.4.0</version>
</dependency>
技术图片

然后鼠标右键选择Maven→Reimport进行依赖下载

三:创建Swagger2配置文件

在文件夹configurer中创建SwaggerConfigurer

package com.example.demo.core.configurer;

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;

/**
 * @author 张瑶
 * @Description:Swagger2 配置文件
 * @time 2018/4/20 22:42
 */
@Configuration
@EnableSwagger2
public class SwaggerConfigurer {

    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.example.demo.controller"))
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("mySpringBoot 使用Swagger2构建RESTful APIs")
                .description("更多Spring Boot相关文章请关注:https://juejin.im/user/59e7fb9451882578e1406a51/posts")
                .termsOfServiceUrl("https://juejin.im/user/59e7fb9451882578e1406a51/posts")
                .contact(new Contact("Mr_初晨", "https://gitee.com/beany/mySpringBoot", null))
                .version("1.0")
                .build();
    }
}
技术图片

四:修改Controller,添加API注解

package com.example.demo.controller;

@RestController
@RequestMapping("userInfo")
@Api(tags = {"用户操作接口"}, description = "userInfoControler")
public class UserInfoController {

    @Resource
    private UserInfoService userInfoService;

    @PostMapping("/hello")
    public String hello() {
        return "hello SpringBoot";
    }

    @ApiOperation(value = "查询用户", notes = "根据用户ID查询用户")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "用户ID", required = true,
                    dataType = "Integer", paramType = "query")
    })
    @PostMapping("/selectById")
    public RetResult<UserInfo> selectById(@RequestParam Integer id) {
        UserInfo userInfo = userInfoService.selectById(id);
        return RetResponse.makeOKRsp(userInfo);
    }

    @PostMapping("/testException")
    public RetResult<UserInfo> testException(Integer id) {
        List a = null;
        a.size();
        UserInfo userInfo = userInfoService.selectById(id);
        return RetResponse.makeOKRsp(userInfo);
    }


}
技术图片

注意参数前需加上@RequestParam

以上注解大家可以查看参考swagger官方注解文档进行自定义添加

五:接口测试

浏览器输入localhost:8080/swagger-ui.html我们可以看到。。哎呀我曹,页面呢??

技术图片技术图片?

六:解决问题

继承WebMvcConfigurationSupport之后,静态文件映射会出现问题,需要重新指定静态资源

WebConfigurer 中添加如下代码

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("swagger-ui.html")
            .addResourceLocations("classpath:/META-INF/resources/");
    registry.addResourceHandler("/webjars/**")
            .addResourceLocations("classpath:/META-INF/resources/webjars/");
    registry.addResourceHandler("/favicon.ico")
            .addResourceLocations("classpath:/META-INF/resources/favicon.ico");
    super.addResourceHandlers(registry);
}
技术图片

七:接口测试

浏览器输入localhost:8080/swagger-ui.html我们可以看到如下页面

技术图片技术图片?

打开POST /userInfo/selectById

技术图片技术图片?

请求结果

技术图片技术图片?

 

八:英语看着不爽,怎么办?

根据swagger官方使用手册 找到关于本地化和翻译的说明:

技术图片技术图片?

九:添加翻译文件

resourece目录下创建\META-INF\resourece目录,创建swagger-ui.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Swagger UI</title>
    <link rel="icon" type="image/png" href="webjars/springfox-swagger-ui/images/favicon-32x32.png" sizes="32x32"/>
    <link rel="icon" type="image/png" href="webjars/springfox-swagger-ui/images/favicon-16x16.png" sizes="16x16"/>
    <link href=‘webjars/springfox-swagger-ui/css/typography.css‘ media=‘screen‘ rel=‘stylesheet‘ type=‘text/css‘/>
    <link href=‘webjars/springfox-swagger-ui/css/reset.css‘ media=‘screen‘ rel=‘stylesheet‘ type=‘text/css‘/>
    <link href=‘webjars/springfox-swagger-ui/css/screen.css‘ media=‘screen‘ rel=‘stylesheet‘ type=‘text/css‘/>
    <link href=‘webjars/springfox-swagger-ui/css/reset.css‘ media=‘print‘ rel=‘stylesheet‘ type=‘text/css‘/>
    <link href=‘webjars/springfox-swagger-ui/css/print.css‘ media=‘print‘ rel=‘stylesheet‘ type=‘text/css‘/>
    <script src=‘webjars/springfox-swagger-ui/lib/jquery-1.8.0.min.js‘ type=‘text/javascript‘></script>
    <script src=‘webjars/springfox-swagger-ui/lib/jquery.slideto.min.js‘ type=‘text/javascript‘></script>
    <script src=‘webjars/springfox-swagger-ui/lib/jquery.wiggle.min.js‘ type=‘text/javascript‘></script>
    <script src=‘webjars/springfox-swagger-ui/lib/jquery.ba-bbq.min.js‘ type=‘text/javascript‘></script>
    <script src=‘webjars/springfox-swagger-ui/lib/handlebars-2.0.0.js‘ type=‘text/javascript‘></script>
    <script src=‘webjars/springfox-swagger-ui/lib/underscore-min.js‘ type=‘text/javascript‘></script>
    <script src=‘webjars/springfox-swagger-ui/lib/backbone-min.js‘ type=‘text/javascript‘></script>
    <script src=‘webjars/springfox-swagger-ui/swagger-ui.min.js‘ type=‘text/javascript‘></script>
    <script src=‘webjars/springfox-swagger-ui/lib/highlight.7.3.pack.js‘ type=‘text/javascript‘></script>
    <script src=‘webjars/springfox-swagger-ui/lib/jsoneditor.min.js‘ type=‘text/javascript‘></script>
    <script src=‘webjars/springfox-swagger-ui/lib/marked.js‘ type=‘text/javascript‘></script>
    <script src=‘webjars/springfox-swagger-ui/lib/swagger-oauth.js‘ type=‘text/javascript‘></script>

    <script src=‘webjars/springfox-swagger-ui/springfox.js‘ type=‘text/javascript‘></script>
    <!--国际化操作:选择中文版 -->
    <script src=‘webjars/springfox-swagger-ui/lang/translator.js‘ type=‘text/javascript‘></script>
    <script src=‘webjars/springfox-swagger-ui/lang/zh-cn.js‘ type=‘text/javascript‘></script>
</head>

<body class="swagger-section">
<div id=‘header‘>
    <div class="swagger-ui-wrap">
        <a id="logo" href="http://swagger.io">swagger</a>

        <form id=‘api_selector‘>
            <div class=‘input‘>
                <select id="select_baseUrl" name="select_baseUrl"/>
            </div>
            <div class=‘input‘><input placeholder="http://example.com/api" id="input_baseUrl" name="baseUrl" type="text"/>
            </div>
            <div class=‘input‘><input placeholder="api_key" id="input_apiKey" name="apiKey" type="text"/></div>
            <div class=‘input‘><a id="explore" href="#" data-sw-translate>Explore</a></div>
        </form>
    </div>
</div>

<div id="message-bar" class="swagger-ui-wrap" data-sw-translate>&nbsp;</div>
<div id="swagger-ui-container" class="swagger-ui-wrap"></div>
</body>
</html>

 

技术图片

重点为<!--国际化操作:选择中文版 -->下两个js文件

translator.js为翻译器    zh-cn.js为中文脚本语言

十:测试

浏览器输入localhost:8080/swagger-ui.html我们可以看到如下页面

技术图片技术图片?

十一:样式丑?更换ui

swagger-bootstrap-ui

技术图片技术图片?

swagger-ui-layer

技术图片技术图片?

项目地址

码云地址: https://gitee.com/beany/mySpringBoot

GitHub地址: https://github.com/MyBeany/mySpringBoot

写文章不易,如对您有帮助,请帮忙点下star

技术图片技术图片?

结尾

springboot添加Swagger2来在线自动生成接口的文档+测试功能已完成,后续功能接下来陆续更新。另求各路大神指点,感谢大家。

以上是关于Knife4j -- 在线API文档框架的主要内容,如果未能解决你的问题,请参考以下文章

再见 Swagger UI!国人开源了一款超好用的 API 文档生成框架,Star 4.7K+,真香!!

springboot整合swagger2+knife4j

(二十五)ATP应用测试平台——springboot集成knife4j实现API接口文档说明

还在使用Swagger吗,快来试试这款强大的在线API工具

SpringBoot2.x集成knife4j

教程使用 Swagger2 自动生成API接口文档 knife4j