SpringBoot集成接口文档
在生成文档前,你需要了解下OpenAPI规范,Swagger,SpringFox,Knife4J,Swagger UI等之间的关系。
实现案例之Swagger3
我们先看下最新Swagger3 如何配置和实现接口。
Swagger3 Maven依赖
根据上文介绍,我们引入springfox依赖包,最新的是3.x.x版本。和之前的版本比,只需要引入如下的starter包即可。
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
Swagger Config
我们在配置中还增加了一些全局的配置,比如全局参数等
import io.swagger.annotations.ApiOperation;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import springfox.documentation.builders.*;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.schema.ScalarType;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import com.demo.springboot.swagger.constant.ResponseStatus;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* swagger config for open api.
*
* @author yangjingjing
*/
@Configuration
@EnableOpenApi
public class SwaggerConfig {
/**
* @return swagger config
*/
@Bean
public Docket openApi() {
return new Docket(DocumentationType.OAS_30)
.groupName("Test group")
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.paths(PathSelectors.any())
.build()
.globalRequestParameters(getGlobalRequestParameters())
.globalResponses(HttpMethod.GET, getGlobalResponse());
}
/**
* @return global response code->description
*/
private List<Response> getGlobalResponse() {
return ResponseStatus.HTTP_STATUS_ALL.stream().map(
a -> new ResponseBuilder().code(a.getResponseCode()).description(a.getDescription()).build())
.collect(Collectors.toList());
}
/**
* @return global request parameters
*/
private List<RequestParameter> getGlobalRequestParameters() {
List<RequestParameter> parameters = new ArrayList<>();
parameters.add(new RequestParameterBuilder()
.name("AppKey")
.description("App Key")
.required(false)
.in(ParameterType.QUERY)
.query(q -> q.model(m -> m.scalarModel(ScalarType.STRING)))
.required(false)
.build());
return parameters;
}
/**
* @return api info
*/
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Swagger API")
.description("test api")
.contact(new Contact("yangjingjing", "http://yangjingjing", "yangjingjing@gmail.com"))
.termsOfServiceUrl("http://xxxxxx.com/")
.version("1.0")
.build();
}
}
controller接口
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import com.demo.springboot.swagger.entity.param.UserParam;
import com.demo.springboot.swagger.entity.vo.AddressVo;
import com.demo.springboot.swagger.entity.vo.UserVo;
import java.util.Collections;
import java.util.List;
/**
* @author pdai
*/
@Api
@RestController
@RequestMapping("/user")
public class UserController {
/**
* http://localhost:8080/user/add .
*
* @param userParam user param
* @return user
*/
@ApiOperation("Add User")
@PostMapping("add")
@ApiImplicitParam(name = "userParam", type = "body", dataTypeClass = UserParam.class, required = true)
public ResponseEntity<String> add(@RequestBody UserParam userParam) {
return ResponseEntity.ok("success");
}
/**
* http://localhost:8080/user/list .
*
* @return user list
*/
@ApiOperation("Query User List")
@GetMapping("list")
public ResponseEntity<List<UserVo>> list() {
List<UserVo> userVoList = Collections.singletonList(UserVo.builder().name("dai").age(18)
.address(AddressVo.builder().city("SZ").zipcode("10001").build()).build());
return ResponseEntity.ok(userVoList);
}
}
Knife4J
目前使用Java生成接口文档的最佳实现: SwaggerV3(OpenAPI)+ Knife4J。
Knife4J Maven依赖
<!-- https://mvnrepository.com/artifact/com.github.xiaoymin/knife4j-spring-boot-starter -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
yml配置
server:
port: 8080
knife4j:
enable: true
documents:
- group: Test Group
name: My Documents
locations: classpath:wiki/*
setting:
# default lang
language: en-US
# footer
enableFooter: false
enableFooterCustom: true
footerCustomContent: MIT | [Java 全栈]()
# header
enableHomeCustom: true
homeCustomLocation: classpath:wiki/README.md
# models
enableSwaggerModels: true
swaggerModelName: My Models
注入配置
import com.github.xiaoymin.knife4j.spring.extension.OpenApiExtensionResolver;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import springfox.documentation.builders.*;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.schema.ScalarType;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import tech.pdai.springboot.knife4j.constant.ResponseStatus;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* swagger config for open api.
*
* @author pdai
*/
@Configuration
@EnableOpenApi
public class OpenApiConfig {
/**
* open api extension by knife4j.
*/
private final OpenApiExtensionResolver openApiExtensionResolver;
@Autowired
public OpenApiConfig(OpenApiExtensionResolver openApiExtensionResolver) {
this.openApiExtensionResolver = openApiExtensionResolver;
}
/**
* @return swagger config
*/
@Bean
public Docket openApi() {
String groupName = "Test Group";
return new Docket(DocumentationType.OAS_30)
.groupName(groupName)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.paths(PathSelectors.any())
.build()
.globalRequestParameters(getGlobalRequestParameters())
.globalResponses(HttpMethod.GET, getGlobalResponse())
.extensions(openApiExtensionResolver.buildExtensions(groupName))
.extensions(openApiExtensionResolver.buildSettingExtensions());
}
/**
* @return global response code->description
*/
private List<Response> getGlobalResponse() {
return ResponseStatus.HTTP_STATUS_ALL.stream().map(
a -> new ResponseBuilder().code(a.getResponseCode()).description(a.getDescription()).build())
.collect(Collectors.toList());
}
/**
* @return global request parameters
*/
private List<RequestParameter> getGlobalRequestParameters() {
List<RequestParameter> parameters = new ArrayList<>();
parameters.add(new RequestParameterBuilder()
.name("AppKey")
.description("App Key")
.required(false)
.in(ParameterType.QUERY)
.query(q -> q.model(m -> m.scalarModel(ScalarType.STRING)))
.required(false)
.build());
return parameters;
}
/**
* @return api info
*/
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("My API")
.description("test api")
.contact(new Contact("pdai", "http://pdai.tech", "suzhou.daipeng@gmail.com"))
.termsOfServiceUrl("http://xxxxxx.com/")
.version("1.0")
.build();
}
}
其中ResponseStatus封装
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* @author pdai
*/
@Getter
@AllArgsConstructor
public enum ResponseStatus {
SUCCESS("200", "success"),
FAIL("500", "failed"),
HTTP_STATUS_200("200", "ok"),
HTTP_STATUS_400("400", "request error"),
HTTP_STATUS_401("401", "no authentication"),
HTTP_STATUS_403("403", "no authorities"),
HTTP_STATUS_500("500", "server error");
public static final List<ResponseStatus> HTTP_STATUS_ALL = Collections.unmodifiableList(
Arrays.asList(HTTP_STATUS_200, HTTP_STATUS_400, HTTP_STATUS_401, HTTP_STATUS_403, HTTP_STATUS_500
));
/**
* response code
*/
private final String responseCode;
/**
* description.
*/
private final String description;
}
Controller接口
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import tech.pdai.springboot.knife4j.entity.param.AddressParam;
/**
* Address controller test demo.
*
* @author yangjingjing
*/
@Api(value = "Address Interfaces", tags = "Address Interfaces")
@RestController
@RequestMapping("/address")
public class AddressController {
/**
* http://localhost:8080/address/add .
*
* @param addressParam param
* @return address
*/
@ApiOperation("Add Address")
@PostMapping("add")
@ApiImplicitParams({
@ApiImplicitParam(name = "city", type = "query", dataTypeClass = String.class, required = true),
@ApiImplicitParam(name = "zipcode", type = "query", dataTypeClass = String.class, required = true)
})
public ResponseEntity<String> add(AddressParam addressParam) {
return ResponseEntity.ok("success");
}
}
参考资料
官方GitHub地址:https://github.com/OAI/OpenAPI-Specification
Swagger 官网地址:https://swagger.io/
Knife4j 快速开始https://doc.xiaominfo.com/docs/quick-start