springboot整合swagger2(升级版)

springboot整合swagger2(升级版)


简述

为了项目的方便,整合一个接口文档,swagger2的升级版knife4j,页面跟简单方便,功能也增强了不少,废话不多说。


knife4j简介


Swagger是一个API接口管理工具,支持在线测试接口数据,根据配置自动生成API文档,结合spring mvc而提供界面化方法文档的一个开源框架。

knife4j特点

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

在线调试:提供在线接口联调的强大功能,自动解析当前接口参数,同时包含表单验证,调用参数可返回接口响应内容、headers、Curl请求命令实例、响应时间、响应状态码等信息,帮助开发者在线调试,而不必通过其他测试工具测试接口是否正确,简介、强大。


knife4j整合到项目


Maven依赖

  • springboot项目导入
      <!--swagger2  增强版接口文档-->
      <dependency>
        <groupId>com.github.xiaoymin</groupId>
        <artifactId>knife4j-spring-boot-starter</artifactId>
        <version>2.0.1</version>
      </dependency>

SwaggerConfig配置类

  • 小编在配置类中添加了两个模块(即为两个分组)
@Configuration//配置类注解
@EnableSwagger2
@EnableKnife4j //第三方swagger增强API注解
public class SwaggerConfig {

    public static final String BASE_PACKAGE = "com.vx.music";//需要扫描的包

    @Value("${swagger.enableSwagger}")
    private Boolean enableSwagger ;

    @Bean
    public Docket createRestApi() {
        //添加head参数start
        ParameterBuilder tokenPar = new ParameterBuilder();
        List<Parameter> operationParameters = new ArrayList<Parameter>();
        tokenPar.name("Authorization").description("JWT").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
        operationParameters.add(tokenPar.build());
        //添加head参数end
        return new Docket(DocumentationType.SWAGGER_2)
                //将Timestamp类型全部转为Long类型
                .directModelSubstitute(Timestamp.class, Long.class)
                //分分组名称
                .groupName("首页模块")
                //将Date类型全部转为Long类型
                .directModelSubstitute(Date.class, Long.class)
                .globalOperationParameters(operationParameters)
                .apiInfo(apiInfo())
                // 生产环境的时候关闭 swagger 比较安全
                .enable(enableSwagger)
                .select()
                // 扫描接口的包路径,不要忘记改成自己的
                .apis(RequestHandlerSelectors.basePackage(BASE_PACKAGE+".controller"))//拼接该模块最后一级目录
                .paths(PathSelectors.any())
                .build();
    }
    @Bean
    public Docket createRestApi2() {
        //添加head参数start
        ParameterBuilder tokenPar = new ParameterBuilder();
        List<Parameter> operationParameters = new ArrayList<Parameter>();
        tokenPar.name("Authorization").description("JWT").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
        operationParameters.add(tokenPar.build());
        //添加head参数end
        return new Docket(DocumentationType.SWAGGER_2)
                //将Timestamp类型全部转为Long类型
                .directModelSubstitute(Timestamp.class, Long.class)
                //分分组名称
                .groupName("用户模块")
                //将Date类型全部转为Long类型
                .directModelSubstitute(Date.class, Long.class)
                .globalOperationParameters(operationParameters)
                .apiInfo(apiInfo2())
                // 生产环境的时候关闭 swagger 比较安全
                .enable(enableSwagger)
                .select()
                // 扫描接口的包路径,不要忘记改成自己的
                .apis(RequestHandlerSelectors.basePackage(BASE_PACKAGE+".LoginController"))
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("小程序接口文档")
                .description("首页模块API")
                .termsOfServiceUrl("http://swagger.io/")
                .contact(new Contact("ZHANGYU", "8.131.58.227:80/MusicVX/index.html", "2470838639@qq.com"))
                .version("1.0")
                .build();
    }

    private ApiInfo apiInfo2() {
        return new ApiInfoBuilder()
                .title("小程序接口文档")//
                .description("用户模块API")
                .termsOfServiceUrl("http://8.131.58.227:80/MusicVX/index.html")
                .contact(new Contact("ZHANGYU", "8.131.58.227:80/MusicVX/index.html", "2470838639@qq.com"))
                .version("1.0")
                .build();
    }

注解说明
@EnableSwagger2该注解是Springfox-swagger框架提供的使用Swagger注解,该注解必须加

@EnableKnife4j该注解是knife4j提供的增强注解,Ui提供了例如动态参数、参数过滤、接口排序等增强功能,如果你想使用这些增强功能就必须加该注解,否则可以不用加

配置项目拦截器

/**
 *拦截器
 */
@SpringBootApplication
@ConditionalOnClass(SpringfoxWebMvcConfiguration.class)
public class WebMvcConfig  implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
    }
}

Springboot项目配置文件

  • application.properties配置文件,配置knife4j相关内容
#Swagger开关
swagger.enableSwagger=true
#配置swagger配置
knife4j.basic.username=admin
knife4j.basic.password=123
#开启认证
knife4j.basic.enable=true
#默认是false ,屏蔽所有Swagger的相关资源 生产环境关闭
knife4j.production=false

修改启动类

  • 由于小编是一个多模块的父子项目,所有需要修改启动类,使web项目打war包
@SpringBootApplication
@MapperScan(value = "com.vx.music.dao")//扫描mapper接口
@ServletComponentScan//springboot打war注解
public class AppStartup extends SpringBootServletInitializer {//继承SpringBootServletInitializer
   
    @Override//重写configure方法
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(AppStartup.class);
    }

    public static void main(String[] args) {
        SpringApplication.run(AppStartup.class, args);
        System.out.println("Application is Started !!! ");
        logger.info("Application is Started !!! ");
    }
}

使用注解生成接口文档

实体类

@Data
@Builder
@ToString
@ApiModel(value = "MusicAdmin",description ="用户实体类" )
public class MusicAdmin implements Serializable {

    private Integer id;

    @ApiModelProperty(value = "微信用户唯一标识")
    private String openid;

    private String qq;

    private String email;

    private String majorid;

    private String majorname;

}

接口类

  • 接口上有比较多的注解,下面会在详细讲解,这里先把环境项目搭建,跑起来。
/**
 * 测试
 */
@RestController
@RequestMapping("/test")
@Api(value="Hello  Controller",tags={"测试接口类"})
public class HelloController {

    @Autowired
    private MusicAdminService musicAdminService;

    @ApiOperation(value = "测试用户列表", notes = "测试查询单表",response =List.class )
    @PostMapping("/selectAll")
    public List<MusicAdmin> indexApp() {
       List<MusicAdmin>  musicAdminlist = musicAdminService.getAll();//可以换成自己的,或者输出一句话
        return musicAdminlist;
    }
}

至此,我们是简单整合好了,springboot+knife4j接口文档,登录测试,
访问:

http://localhost:host/doc.html



knife4j相关注解详解


Controller层添加注解

  • @Api:用于类;表示标识这个类是swagger的资源

    属性名称 数据类型 默认值 说明
    value String "" 字段说明
    tags String[] "" 标签说明
    description String "" 详情描述
    basePath String "" 基本路径可以不配置
    position int "" 如果配置多个Api 想改变显示的顺序位置
    produces String "" 提供者 (For example, "application/json, application/xml")
    consumes String "" 消费者(For example, "application/json, application/xml")
    protocols String "" 协议(Possible values: http, https, ws, wss.)
    authorizations Authorization[] "" 高级特性认证时配置
    hidden boolean "" 配置为true 将在文档中隐藏

使用示例

@Api(tags = "HELLO CONTROLLER 测试功能接口")//注解加载在controller类上
@RestController
public class HelloController {
}
  • @ApiResponses:在 Rest 接口上使用,用作返回值的描述
    参数:

    属性名称 数据类型 默认值 说明
    value ApiResponse[] "" 访问对象
    ApiResponse参数:
    属性名称 数据类型 默认值 说明
    ----------------- ---------------- ---- ----------------------------------------
    code String "" 响应的HTTP状态码
    message String "" 响应的信息内容
    response Class<?> "" 用于描述消息有效负载的可选响应类,对应于响应消息对象的 schema 字段
    reference String "" 指定对响应类型的引用,指定的应用可以使本地引用,也可以是远程引用,将按原样使用,并将覆盖任何指定的response()类
    responseHeaders ResponseHeader[] "" 声明包装响应的容器,有效值为List或Set,任何其他值都将被覆盖
    responseContainer String "" 声明响应的容器,有效值为List,Set,Map,任何其他值都将被忽略
    examples Example "" 例子

使用实例:

@ApiResponses(value = {
            @ApiResponse(code = 200, message = "接口返回成功状态"),
            @ApiResponse(code = 500, message = "接口返回未知错误,请联系开发人员调试")
    })
    @PostMapping("hello")
    public Results<UserVO> hello(@RequestBody UserVO userVO){

        Results<UserVO> results = new Results<>(200,"SUCCESS", userVO);
        return results;
    }
  • @ApiOperation:用在方法上,说明方法的作用,每一个url资源的定义

参数

属性名称 数据类型 默认值 说明
value String "" url的路径值
notes String "" 文本说明
tags String[] "" 如果设置这个值、value的值会被覆盖
response Class<?> "" 返回的对象
responseContainer String "" 声明响应的容器,有效值为List,Set,Map,任何其他值都将被忽略
responseReference String "" 声明包装响应的容器,有效值为List或Set,任何其他值都将被覆盖
httpMethod String "" "GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS" and "PATCH"
position int "" 如果配置多个Api 想改变显示的顺序位置
nickname String "" 昵称
produces String "" 提供者 (For example, "application/json, application/xml")
consumes String "" 消费者(For example, "application/json, application/xml")
protocols String "" 协议(Possible values: http, https, ws, wss.)
authorizations Authorization[] "" 高级特性认证时配置
hidden boolean "" 隐藏
responseHeaders ResponseHeader[] "" 声明包装响应的容器,有效值为List或Set,任何其他值都将被覆盖
code String "" http的状态码 默认 200
extensions Extension[] "" 扩展属性
ignoreJsonView boolean "" 是否忽略显示

使用实例:

@ApiOperation(value = "Hello 测试接口", notes = "访问此接口,返回hello语句,测试接口")
    @PostMapping("hello")
    public Results<UserVO> hello(@RequestBody UserVO userVO){

        Results<UserVO> results = new Results<>(200,"SUCCESS", userVO);
        return results;
    }
  • @PathVariable:是获取get方式,url后面参数,进行参数绑定(单个参数或两个以内参数使用)
    参数
属性名称 数据类型 默认值 说明
value String "" url的路径值
name String "" 重写属性名字
required String "" 是否必填

使用实例:

@ApiResponses(value = {
            @ApiResponse(code = 200, message = "接口返回成功状态"),
            @ApiResponse(code = 500, message = "接口返回未知错误,请联系开发人员调试")
    })
    @ApiOperation(value = "获取用户信息", notes = "访问此接口,返回用户信息")
    @PostMapping("/getUser/{id}")
    public String getUser(@PathVariable String id) throws InterruptedException {
        // 业务...
        return "";
    }
  • @RequestBody :在当前对象获取整个http请求的body里面的所有数据(两个以上参数封装成对象使用)
    参数
属性名称 数据类型 默认值 说明
required String "" 是否必填

使用实例:

@ApiResponses(value = {
            @ApiResponse(code = 200, message = "接口返回成功状态"),
            @ApiResponse(code = 500, message = "接口返回未知错误,请联系开发人员调试")
    })
    @ApiOperation(value = "Hello 测试接口", notes = "访问此接口,返回hello语句,测试接口")
    @PostMapping("hello")
    public Results<UserVO> hello(@RequestBody UserVO userVO){
        Results<UserVO> results = new Results<>(200,"SUCCESS", userVO);
        return results;
    }

相关问题

处理接口接收JSON数据的问题

  • 当我们用老版本的swagger生成接口文档时,它是不支持接口json数据的,只能传java实体bean
  • 在升级版中我们使用@ApiOperationSupport注解和@DynamicParameter即可自动处理json数据

    //首页排行榜
    @ApiOperation(value = "首页排行榜 songList", notes = "首页排行榜")
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "接口返回成功状态"),
            @ApiResponse(code = 500, message = "接口返回未知错误,请联系开发人员调试")
    })
    @ApiOperationSupport(params = @DynamicParameters(name = "obj",properties = {
            @DynamicParameter(name = "pageNum",value = "当前页数",example = "1",required = true,dataTypeClass = Integer.class),
            @DynamicParameter(name = "pageSize",value = "每页条数",example = "10",required = true,dataTypeClass = Integer.class),
            @DynamicParameter(name = "Leaderboard_flag",value = "加载标识",example = "0",required = true,dataTypeClass = Integer.class)
    }))
    @PostMapping("/songList")
    public ApiReturn  selectSongList(@RequestBody  JSONObject obj){
        logger.info("查询首页排行榜歌曲分页列表,obj={}",obj);
        ApiReturn apiReturn = new ApiReturn();
        PageVO page = new PageVO();
        if ( obj != null && obj.getInteger(Constants.PAGE_NUM)!=null && obj.getInteger(Constants.PAGE_SIZE)!=null) {
            page.setPageNum(obj.getInteger(Constants.PAGE_NUM));
            page.setPageSize(obj.getInteger(Constants.PAGE_SIZE));
            obj.remove(Constants.PAGE_NUM);
            obj.remove(Constants.PAGE_SIZE);
        }
        HashMap<String,Object> songMap =songListService.selectSongList(page,obj);

        apiReturn.setData(songMap);
        apiReturn.isSuccess();
        return apiReturn;
    }

原文地址:https://www.cnblogs.com/MrYuChen-Blog/p/14185561.html