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;
}