微服務之Swagger
Swagger使用
1. Swagger UI
按以下步驟配置,項目啟動後訪問:
http://localhost:8080/swagger-ui.html
1.1 添加依賴
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.2.2</version>
</dependency>
1.2 配置類
@Configuration
@EnableSwagger2
public class Swagger2 {
public static final String SWAGGER_SCAN_BASE_PACKAGE = "abc.boot.examples.web";
public static final String VERSION = "1.0.0";
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage(SWAGGER_SCAN_BASE_PACKAGE))//api接口包掃描路徑
.paths(PathSelectors.any())//可以根據url路徑設置哪些請求加入文檔,忽略哪些請求
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Swagger2 接口文檔示例")//設置文檔的標題
.description("更多內容請關註:http://www.abc.com")//設置文檔的描述->1.Overview
.version(VERSION)//設置文檔的版本信息-> 1.1 Version information
.contact(new Contact("ABC Boot", "http://www.abc.comt", ""))//設置文檔的聯系方式->1.2 Contact information
.termsOfServiceUrl("www.abc.com")//設置文檔的License信息->1.3 License information
.build();
}
}
1.3 註解使用
@ApiOperation
@ApiOperation(value="獲取用戶列表", notes="獲取所有用戶列表",produces = "application/json")
@RequestMapping(value="/users", method= RequestMethod.GET)
public List<User> getUserList() {
List<User> r = new ArrayList<User>(users.values());
return r;
}
@ApiResponses
@ApiOperation(value="獲取用戶詳細信息", notes="根據url的id來獲取用戶詳細信息",produces = "application/json")
// ApiResponses 增加返回結果的描述
@ApiResponses(value = {@ApiResponse(code = 405,message = "Invalid input",response = Integer.class)}) (1)
@ApiImplicitParam(name = "id",value = "用戶ID",dataType = "int",paramType = "path") (2)
@RequestMapping(value="/users/{id}", method= RequestMethod.GET)
public User getUser(@PathVariable Integer id) {
return users.get(id);
}
(1) 在默認Response的基礎上增加新的Response說明
(2) 使用ApiImplicitParam描述接口參數
@ApiImplicitParams
@ApiOperation(value="更新用戶名稱", notes="更新指定用戶的名稱")
@RequestMapping(value="/users/{id}", method= RequestMethod.POST)
@ApiImplicitParams({ (1)
@ApiImplicitParam(name = "id",value = "用戶ID",paramType = "path",dataType = "int"), (2)
@ApiImplicitParam(name = "userName",value = "用戶名稱",paramType = "form",dataType = "string")
})
public void updateUserName(@PathVariable Integer id,@RequestParam String userName){
User u = users.get(id);
u.setName(userName);
}
(1) 使用ApiImplicitParams描述多個參數
(2) 使用ApiImplicitParam時,需要指定paramType,這樣也便於swagger ui 生成參數的輸入格式。
paramType 有五個可選值 : path, query, body, header, form
@ApiParam
@ApiOperation(value="創建用戶-傳遞簡單對象", notes="傳遞簡單對象",produces = "application/json")
@RequestMapping(value="/users-1", method= RequestMethod.POST)
//可以不加ApiParam註解,需要給參數添加描述時可以使用這個註解,或者使用ApiImplicitParams註解 (1)
public Map postUser(@RequestParam String userName,@ApiParam("地址") @RequestParam(required = false) String address) {
User user = new User();
user.setId(Math.round(10));
user.setName(userName);
user.setAddress(address);
users.put(user.getId(), user);
return ImmutableMap.of("user",user);
}
(1) 使用ApiParam描述接口參數
ApiImplicitParam 與 ApiParam 的區別
ApiImplicitParam: This is the only way to define parameters when using Servlets or other non-JAX-RS environments.
- 對Servlets或者非 JAX-RS的環境,只能使用 ApiImplicitParam。
- 在使用上,ApiImplicitParam比ApiParam具有更少的代碼侵入性,只要寫在方法上就可以了,但是需要提供具體的屬性才能配合swagger ui解析使用。
- ApiParam只需要較少的屬性,與swagger ui配合更好。
傳遞復雜對象 By ModelAttribute
@ApiOperation(value="創建用戶-傳遞復雜對象", notes="傳遞復雜對象DTO, url參數拼接",produces = "application/json")
@RequestMapping(value="/users-2", method= RequestMethod.POST)
//傳遞對象推薦使用ModelAttribute註解
public Map postUser2(@ModelAttribute User user) { (1)
users.put(user.getId(),user);
return ImmutableMap.of("user",user);
}
(1) ModelAttribute 是Spring mvc的註解,這裏Swagger可以解析這個註解,獲得User的屬性描述
@ApiModel
@ApiModel(value = "User", description = "用戶對象")
public class User {
@ApiModelProperty(value = "ID")
private Integer id;
@ApiModelProperty(value = "姓名")
private String name;
@ApiModelProperty(value = "地址")
private String address;
@ApiModelProperty(value = "年齡",access = "hidden")
private int age;
@ApiModelProperty(value = "性別")
private int sex;
.......
}
傳遞復雜對象 By RequestBody
@ApiOperation(value="創建用戶-傳遞復雜對象", notes="傳遞復雜對象DTO,json格式傳遞數據",produces = "application/json")
@RequestMapping(value="/users-3", method= RequestMethod.POST)
//json格式傳遞對象使用RequestBody註解
public User postUser3(@RequestBody User user) {
users.put(user.getId(),user);
return user;
}
PathVariable
@ApiOperation(value="刪除用戶- PathVariable", notes="根據url的id來指定刪除對象")
@RequestMapping(value="/users/{id}", method = RequestMethod.DELETE)
public void deleteUser(@PathVariable Integer id) { (1)
users.remove(id);
}
(1) PathVariable是Spring 的註解,對於這種簡單的參數,就可以不用寫ApiParam來描述接口參數。
數組的描述
@ApiOperation(value="刪除用戶-傳遞數組", notes="刪除對象,傳遞數組")
@RequestMapping(value="/users/deleteByIds", method = RequestMethod.DELETE)
public void deleteUser(@ApiParam("用戶ID數組") @RequestParam Integer[] ids) { (1)
for (int id:ids){
users.remove(id);
}
}
(1) 這裏用ApiParam為數組參數添加描述
1.4 可選配置
在application.properties中加入以下配置,用於設置測試請求的host,默認在swagger ui上做請求測試時都是以/users/1為路徑發送請求。
如果需要改變請求的根路徑,就需要配置這個參數:
springfox.documentation.swagger.v2.host = yourapp.abc.com
配置獲取api docs json數據的請求路徑 ,默認為/v2/api-docs:
springfox.documentation.swagger.v2.path = /api
2. springfox-staticdocs 生成靜態文檔
springfox
2.1 Maven 配置
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-staticdocs</artifactId>
<version>2.2.2</version>
<scope>test</scope>
</dependency>
2.2 生成json文件
編寫Junit測試,這樣在測試環節就可以將api-docs的json數據寫入文檔,便於下一步生成asciidoc文件。
@WebAppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = DemoBootApplication.class)
public class Swagger2MarkupTest {
@Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
@Before
public void setUp() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build();
}
@Test
public void createSpringfoxSwaggerJson() throws Exception {
String outputDir = "src/docs/json"; //將api-docs的json數據寫入文件
MvcResult mvcResult = this.mockMvc.perform(get("/v2/api-docs")
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andReturn();
MockHttpServletResponse response = mvcResult.getResponse();
String swaggerJson = response.getContentAsString();
Files.createDirectories(Paths.get(outputDir));
try (BufferedWriter writer = Files.newBufferedWriter(Paths.get(outputDir, "swagger.json"), StandardCharsets.UTF_8)) {
writer.write(swaggerJson);
}
}
}
2.3 配置Maven Plugin
配置以下兩個插件:
swagger2markup-maven-plugin,該插件將json文件轉為asciidoc
asciidoctor-maven-plugin, 該插件將asciidoc轉為html/pdf
執行Maven命令 : mvn swagger2markup:convertSwagger2markup process-resources
生成的html文檔存儲在src\main\resources\META-INF\resources\docs目錄下。
啟動DemoBootApplication,直接訪問http://localhost:8080/docs/index.html。
<pluginRepositories>
<pluginRepository>
<id>jcenter-snapshots</id>
<name>jcenter</name>
<url>http://oss.jfrog.org/artifactory/oss-snapshot-local/</url>
</pluginRepository>
<pluginRepository>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>jcenter-releases</id>
<name>jcenter</name>
<url>http://jcenter.bintray.com</url>
</pluginRepository>
</pluginRepositories>
<build>
<plugins>
<!-- First, use the swagger2markup plugin to generate asciidoc -->
<plugin>
<groupId>io.github.swagger2markup</groupId>
<artifactId>swagger2markup-maven-plugin</artifactId>
<version>${swagger2markup.plugin.version}</version>
<dependencies>
<dependency>
<groupId>io.github.swagger2markup</groupId>
<artifactId>swagger2markup-import-files-ext</artifactId>
<version>${swagger2markup.extension.version}</version>
</dependency>
<dependency>
<groupId>io.github.swagger2markup</groupId>
<artifactId>swagger2markup</artifactId>
<version>${swagger2markup.version}</version>
</dependency>
</dependencies>
<configuration>
<!--The URL or file path to the Swagger specification-->
<swaggerInput>${swagger.input}</swaggerInput>
<outputDir>${generated.asciidoc.directory}</outputDir>
<config>
<!--設置輸出文件的語言:ASCIIDOC, MARKDOWN, CONFLUENCE_MARKUP-->
<swagger2markup.markupLanguage>ASCIIDOC</swagger2markup.markupLanguage>
<!--設置目錄的展現方式-->
<swagger2markup.pathsGroupedBy>TAGS</swagger2markup.pathsGroupedBy>
<!--擴展Overview的內容,可以增加一些自定義的內容-->
<!--<swagger2markup.extensions.dynamicOverview.contentPath>${project.basedir}/src/docs/asciidoc/extensions/overview</swagger2markup.extensions.dynamicOverview.contentPath>
<swagger2markup.extensions.dynamicDefinitions.contentPath>${project.basedir}/src/docs/asciidoc/extensions/definitions</swagger2markup.extensions.dynamicDefinitions.contentPath>
<swagger2markup.extensions.dynamicPaths.contentPath>${project.basedir}/src/docs/asciidoc/extensions/paths</swagger2markup.extensions.dynamicPaths.contentPath>
<swagger2markup.extensions.dynamicSecurity.contentPath>${project.basedir}src/docs/asciidoc/extensions/security</swagger2markup.extensions.dynamicSecurity.contentPath>-->
</config>
</configuration>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>convertSwagger2markup</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Run the generated asciidoc through Asciidoctor to generate
other documentation types, such as PDFs or HTML5 -->
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<version>1.5.3</version>
<!-- Include Asciidoctor PDF for pdf generation -->
<dependencies>
<dependency>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj-pdf</artifactId>
<version>1.5.0-alpha.11</version>
</dependency>
<!-- Comment this section to use the default jruby artifact provided by the plugin -->
<dependency>
<groupId>org.jruby</groupId>
<artifactId>jruby-complete</artifactId>
<version>${jruby.version}</version>
</dependency>
<!-- Comment this section to use the default AsciidoctorJ artifact provided by the plugin -->
<dependency>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj</artifactId>
<version>${asciidoctorj.version}</version>
</dependency>