文章目录
Swagger定义及为何使用
定义
Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务
目标
总体目标是使客户端和文件系统作为服务器以同样的速度来更新。
文件的方法,参数和模型紧密集成到服务器端的代码,允许API来始终保持同步。 Swagger 让部署管理和使用功能强大的API从未如此简单。
好处
-
Swagger 可以生成一个具有互动性的API控制台,开发者可以用来快速学习和尝试API。
-
Swagger 可以生成客户端SDK代码用于各种不同的平台上的实现。
-
Swagger 文件可以在许多不同的平台上从代码注释中自动生成。
-
Swagger 有一个强大的社区,里面有许多强悍的贡献者。
Swagger与Easy Mock
Easy Mock作用
主要为前端测试提供模拟数据,更好地帮助前后端分离,同步开发,也可用于微服务间调用的模拟数据
Swagger 与 Easy Mock的对接
- 将生成的swagger.json上传至 Easy Mock 服务
- 在Easy Mock上配置同步的swagger地址
Swagger 与 Restful
Restful规范
- 请求方式代表动词,为以下五种
- GET:读取(Read)
- POST:新建(Create)
- PUT:更新(Update)
- PATCH:更新(Update),通常是部分更新
- DELETE:删除(Delete)
- URL 代表宾语,且需要是名词,操作是集合时,需要是复数
- 请求和相应参数都为JSON对象,故HTTP头的Content-Type属性应为application/json
- 状态码需要精确
- 提供服务链接
参考:http://www.ruanyifeng.com/blog/2018/10/restful-api-best-practices.html
Swagger Tools
- Swagger UI: 一个无依赖的HTML、JS和CSS集合,可以为Swagger兼容API动态生成优雅文档。
- Swagger Editor: 可浏览编辑swagger.json显示的API接口
- Swagger Generators: 可以生成客户端SDK代码用于各种不同的平台上的实现
Swagger.json
swagger.json相当于跨工具API接口的序列化数据
Java生成Swagger.json、html和pdf
- 引入swagger的maven包
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
<version>1.5.20</version>
</dependency>
- 在接口和参数和返回值上加入swagger注解
@Api(value = "/api/item", description = "条目", tags = {"[条目]"})
@RestController
public class SwaggerController {
@Autowired
private ItemService itemService;
@ApiOperation(value = "查询条目", notes = "调用方:", produces = MimeTypeUtils.APPLICATION_JSON_VALUE, httpMethod = "POST")
@ApiImplicitParams({
@ApiImplicitParam(value = "标签", name = "id", required = true, paramType = "query", dataType = "string")})
@RequestMapping(value = "/items/{id}",method = RequestMethod.GET)
@ResponseBody
public Item getItems(@PathVariable("id") Long id){
return itemService.queryItem(id);
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "条目详细信息")
public class Item {
@ApiModelProperty(value = "条目ID")
private Long id;
@ApiModelProperty(value = "条目标题")
private String title;
@ApiModelProperty(value = "条目图片URL")
private String pic;
@ApiModelProperty(value = "条目描述")
private String desc;
@ApiModelProperty(value = "条目价格")
private Long price;
}
- 通过maven-surefire-plugin插件执行单元测试输出swagger.json
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = {"classpath:spring-mvc.xml"})
public class Swagger2MackupTest {
@Autowired
private WebApplicationContext webApplicationContext;
private MockMvc mockMvc;
@Before
public void init(){
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.webApplicationContext).build();
}
@Test
public void getJson() throws Exception {
String outputDir = "target/swagger";
MvcResult mvcResult = this.mockMvc.perform(get("/v2/api-docs").accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk()).andReturn();
String json = mvcResult.getResponse().getContentAsString();
File outputFile = Paths.get(outputDir).toFile();
if (!outputFile.exists()){
outputFile.mkdirs();
}
FileUtils.writeStringToFile(new File(outputFile,"swagger.json"),json, StandardCharsets.UTF_8);
}
}
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<includes>
<include>**/Swagger2MarkupTest.java</include>
</includes>
</configuration>
</plugin>
- 通过swagger2markup-maven-plugin插件,将swagger.json转化为asciidoc
<!-- properties的配置 -->
<properties>
<asciidoctor.input.directory>${project.basedir}/src/docs/json</asciidoctor.input.directory>
<swagger2markup.version>1.2.0</swagger2markup.version>
<asciidoctor.input.directory>${project.basedir}/src/docs/asciidoc</asciidoctor.input.directory>
<swagger.output.dir>${project.build.directory}/swagger</swagger.output.dir>
<swagger.snippetOutput.dir>${project.build.directory}/asciidoc/snippets</swagger.snippetOutput.dir>
<generated.asciidoc.directory>${project.build.directory}/asciidoc/generated</generated.asciidoc.directory>
<asciidoctor.html.output.directory>${project.build.directory}/asciidoc/html</asciidoctor.html.output.directory>
<asciidoctor.pdf.output.directory>${project.build.directory}/asciidoc/pdf</asciidoctor.pdf.output.directory>
<swagger.input>${swagger.output.dir}/swagger.json</swagger.input>
</properties>
<!-- First, use the swagger2markup plugin to generate asciidoc -->
<plugin>
<groupId>io.github.swagger2markup</groupId>
<artifactId>swagger2markup-maven-plugin</artifactId>
<version>${swagger2markup.version}</version>
<dependencies>
<dependency>
<groupId>io.github.swagger2markup</groupId>
<artifactId>swagger2markup-import-files-ext</artifactId>
<version>${swagger2markup.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>
- 从asciidoc2html-demo获取 src/docs/asciidoc下编写的index.adoc,可引入自定义的adoc文件(若不引入自定义文件,可从target获取adoc文件)
include::{generated}/overview.adoc[]
include::starting.adoc[]
include::{generated}/paths.adoc[]
include::{generated}/security.adoc[]
include::ending.adoc[]
include::{generated}/definitions.adoc[]
- 通过asciidoctor-maven-plugin将asciidoc转换为html/pdf
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</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.10.1</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>1.7.21</version>
</dependency>
</dependencies>
<!-- Configure generic document generation settings -->
<configuration>
<!--默认指向 ${basedir}/src/main/asciidoc-->
<sourceDirectory>${asciidoctor.input.directory}</sourceDirectory>
<!--an override to process a single source file; 默认指向 ${sourceDirectory} 中的所有文件-->
<!--<sourceDocumentName>index.adoc</sourceDocumentName>-->
<attributes>
<doctype>book</doctype>
<toc>left</toc>
<toclevels>3</toclevels>
<numbered></numbered>
<hardbreaks></hardbreaks>
<sectlinks></sectlinks>
<sectanchors></sectanchors>
<generated>${generated.asciidoc.directory}</generated>
</attributes>
</configuration>
<!-- Since each execution can only handle one backend, run
separate executions for each desired output type -->
<executions>
<execution>
<id>output-html</id>
<phase>generate-resources</phase>
<goals>
<goal>process-asciidoc</goal>
</goals>
<configuration>
<backend>html5</backend>
<outputDirectory>${asciidoctor.html.output.directory}</outputDirectory>
</configuration>
</execution>
<!-- 生成PDF -->
<execution>
<id>output-pdf</id>
<phase>generate-resources</phase>
<goals>
<goal>process-asciidoc</goal>
</goals>
<configuration>
<backend>pdf</backend>
<outputDirectory>${asciidoctor.pdf.output.directory}</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>