swagger+swagger-maven-plugin+Resteasy
一、swagger
参考文章:
swagger使用教程(强烈推荐,强忍住复制过来的冲动)
Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。总体目标是使客户端和文件系统作为服务器以同样的速度来更新。文件的方法、参数和模型紧密集成到服务器端的代码,允许 API 来始终保持同步。主要两件事:
-
接口的文档在线自动生成
-
功能测试
主要解决问题:
接口提供者与接口使用者之间,接口信息同步不及时问题
二、springfox-swagger2
参考文章:
a. 引入依赖
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency>
b. 将swagger交给spring管理
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; /** * Swagger相关的配置 * @author: 2020/4/13 10:09 * @since: 0.0.1-SNAPSHOT * @modified By: */ @Configuration @EnableSwagger2 // 启用swagger,在这里指定即可,web应用入口函数(WebApplication)就不用重复指定了 public class SwaggerConfig { @Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() /* * 指定接口包 * 不能使用通配符,像‘com.abc.*.api’; * 不能多次调用apis()方法,否则只有最后一次有效 * 如果需要指定多个包下的接口类,有以下两种方法可以使用: * 1. 指定多个类的公共父包,使用【.apis(RequestHandlerSelectors.basePackage("com.abc.efg.api"))】,会扫描api包下的所有类 * 2. 指定这些类都有的注解,一般使用swagger的标准注解,使用【.apis(RequestHandlerSelectors.withClassAnnotation(ApiOperation.class))】即可 * */ // .apis(RequestHandlerSelectors.withClassAnnotation(ApiOperation.class)) .apis(RequestHandlerSelectors.basePackage("com.abc.efg.api")) .paths(PathSelectors.any()) .build(); } private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("LLCAS") .description("LLCAS API") .termsOfServiceUrl("。。。。。。。。。") .version("1.0") .build(); } }
c. 修改接口
@Api(description = "平台操作员接口") @RequestMapping("api/adminUsers") @RestController public class AdminUserController { @Resource private AdminUserService adminUserService; @ApiOperation(value = "创建平台操作员", produces = "application/json") @RequestMapping(value = {"", "/"}, method = RequestMethod.POST) public WebResult createAdminUser(@ApiIgnore @ModelAttribute Session session, @ApiParam("平台操作员") @RequestBody AdminUser adminUser) { return WebResult.SUCCESS; } }
备注:接口函数必须指定method,否则swagger会认为这个函数支持所有http请求方式,会生成多个重复接口说明
d. 访问接口说明信息
完成以上步骤后,启动项目后可以在浏览器中打开连接http://ip:port/swagger-ui.html,则可以看到接口文档,并且可以直接测试接口
三、springfox-swagger2无法生成JAX-RS接口文档
在第三章中,指定的接口都是标准的springMVC接口,就是controller中函数加上swagger注解。经常的,我们需要开发JAX-RS接口给第三方或其他组件,JAX-RS 接口实现结构可以视作下面这样的:
import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import javax.validation.constraints.Size; import javax.ws.rs.*; /** * @author: 2020/4/21 11:08 * @since: 0.0.1-SNAPSHOT * @modified By: */ @Path("/test") @RestController @Api(tags = "test") public class ApiTestController{ @GET @Path(value = "/hello") // @GetMapping("/hello") @Consumes(value = {"text/html", "application/xhtml+xml" }) @Produces(value = { "application/json" }) @ApiOperation(value = "测试接口", notes = "这是notes") public ApiResponse<String> test(//字符串长度需要使用该注解定义 //定义参数详细新 @ApiParam(name = "name", value = "姓名:需要设置字符串长度", required = true, defaultValue = "张三", type = "string") @Size(max = 5) //定义Get请求参数位置 @QueryParam("name") String name, //数值型参数可以使用@ApiParam中的allowableValues属性进行描述数值的最大最小值 @ApiParam(name = "age", value = "年龄", required = true, defaultValue = "32", type = "int", allowableValues = "range[1,100]") @QueryParam("age") Integer age){ ApiResponse<String> res = new ApiResponse<>(); res.setCode("0"); res.setMsg("ok"); res.setData("hello world"); return res; } }
这种接口函数是不能被springfox-swagger2识别的,但是如果在这个函数上添加‘@GetMapping("/hello")’, 就可以被识别到了。可见,springfox-swagger2只能识别spring mvc接口,不能失败JAX-RS接口。
四、swagger-maven-plugin
这个插件的功能介绍,网上文章都没有多说,它的GitHub上说的很清楚 :
This plugin enables your Swagger-annotated project to generate Swagger specs and customizable, templated static documents during the maven build phase.
Unlike swagger-core, swagger-maven-plugin does not actively serve the spec with the rest of the application; it generates the spec as a build artifact
to be used in downstream Swagger tooling.
将项目中swagger注解的信息在maven编译时,制作成文档或json文件,它不能提供swagger那样的在线查看接口的功能,只是个接口信息转换为自定义的、模板化的文档的工具。
我在应用中没有“下游swagger”,我使用了它“生成自定义、模板化文档”的功能,将接口信息制作成html文件,发给别人用了。制作HTML的方法下一章介绍。更多关于这个插件的内容,直接参考它的GitHub就可以了。
有的人将json文件生成地址指定为swagger-ui的目录下,可以在编译后,让其他人直接访问swagger-ui获取接口信息,我没有这样用。可以参考swagger接入了解如何操作。
五、swagger-maven-plugin+resteasy
(1)swagger-maven-plugin的使用方法
这个插件的使用方法,官方给了个demo,这里对demo的配置进行说明,方便理解:
<build> <plugins> <plugin> <!-- 引入插件 --> <groupId>com.github.kongchen</groupId> <artifactId>swagger-maven-plugin</artifactId> <version>3.1.1</version> <configuration> <apiSources> <apiSource> <!-- 如果接口是SpringMVC接口还是JAX-RS接口 --> <springmvc>false</springmvc> <!-- 接口函数类所在的包 --> <locations>com.github.kongchen.swagger.sample.wordnik.resource</locations> <!-- 接口使用的通信协议,["http", "https", "ws", "wss"] --> <schemes>http,https</schemes> <!-- 接口服务地址,可以带端口。(localhost:8080) --> <host>petstore.swagger.wordnik.com</host> <!-- 接口跟路由 --> <basePath>/api</basePath> <!-- 接口的一些基础信息 --> <info> <title>Swagger Maven Plugin Sample</title> <version>v1</version> <description>This is a sample for swagger-maven-plugin</description> <termsOfService> http://www.github.com/kongchen/swagger-maven-plugin </termsOfService> <contact> <email>kongchen@gmail.com</email> <name>Kong Chen</name> <url>http://kongch.com</url> </contact> <license> <url>http://www.apache.org/licenses/LICENSE-2.0.html</url> <name>Apache 2.0</name> </license> </info> <!-- Support classpath or file absolute path here. 1) classpath e.g: "classpath:/markdown.hbs", "classpath:/templates/hello.html" 2) file e.g: "${basedir}/src/main/resources/markdown.hbs", "${basedir}/src/main/resources/template/hello.html" --> <!-- 模板文档路径,strapdown.html.hbs可以从官网下载 --> <templatePath>${basedir}/templates/strapdown.html.hbs</templatePath> <!-- 根据模板输出的文档,可以脱离swagger使用,生成的swagger.json文档,需要配合swagger-ui使用 --> <!-- 输出文档地址及名称 --> <outputPath>${basedir}/generated/document.html</outputPath> <!-- json文件输出地址,文件名称可以使用‘swaggerFileName’标签 --> <swaggerDirectory>generated/swagger-ui</swaggerDirectory> <!-- 权限控制相关的声明 --> <securityDefinitions> <securityDefinition> <!-- 绝对路径 --> <!--<jsonPath>${basedir}/securityDefinition.json</jsonPath> --> <!-- 相对路径,寻址起始路径为项目根目录 --> <json>/securityDefinitions.json</json> </securityDefinition> </securityDefinitions> </apiSource> </apiSources> </configuration> <executions> <execution> <phase>compile</phase> <goals> <goal>generate</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.1.1</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.6</source> <target>1.6</target> </configuration> </plugin> </plugins> </build>
(2)resteasy接口开发
编写一个Rest接口,并使用Swagger注解对接口类、接口函数、入参、返回值等信息进行说明,类似代码如下:
import io.swagger.annotations.*; import org.springframework.web.bind.annotation.RestController; import javax.ws.rs.*; import java.util.ArrayList; /** * 接口 * @author: 2020/4/22 15:28 * @since: 0.0.1-SNAPSHOT * @modified By: */ @Path("/v1") @RestController @Api(tags = "测试个大苹果") public interface ApiSyslogService { /** * 分页查询 * @param testApple 查询条件 * @return 返回值 */ @POST @Path(value = "/apple") @Consumes(value = {"text/html", "application/xhtml+xml", "application/json" }) @Produces(value = { "application/json;charset=UTF-8" }) @ApiOperation(value = "测试接口", notes = "这是个测试接口") @ApiResponses({ @ApiResponse(code=200,message="成功"), @ApiResponse(code=403,message="没有访问该接口的权限"), @ApiResponse(code=500,message="后台服务异常,响应请求失败"), }) ApiResponseDTO findLog( @ApiParam(name = "testApple", value = "测试数据", required = true, type = "Apple") Apple testApple ); }
(3)使用模板,生成HTML文件
模板可以从swagger-maven-plugin提供的地址下载,模块文件有如下几个:
![](https://img2020.cnblogs.com/blog/1156834/202004/1156834-20200423231152590-1632331563.png)
其中strapdown.html.hbs是模板的入口文件,上面提到的swagger-maven-plugin配置里,需要指定这个文件为模板文件。swagger-maven-plugin根据这个文件会生成一个后缀为html的文件,这个放到浏览器有可能不被解析,下面对这个原因进行说明:
strapdown.html.hbs文件的内容如下:
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="application/json; charset=utf-8" /> </head> <title>API Document</title> <xmp theme="united" style="display:none;"> {{>markdown}} </xmp> <script src="http://strapdownjs.com/v/0.2/strapdown.js"></script> </html>
注意到 “<script src="http://strapdownjs.com/v/0.2/strapdown.js"></script>”用于解析markdown文档,但是多数情况下,我无法下载这个strapdown.js文件,导致无法让浏览器解析出Markdown的html格式的文档。
所以我下载了strapdown.js相关的文件,放到本地,修改模板文档,就可以离线浏览生成的html文档了。具体操作如下:
a) 下载strapdown.js相关的文件
下载后的文件列表如下,文末有下载地址
![](https://img2020.cnblogs.com/blog/1156834/202004/1156834-20200423231243531-212880946.png)
b) 修改strapdown.html.hbs内容
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="application/json; charset=utf-8" /> <!-- 下面是新增的部分,引入关键文件,方便浏览器解析 --> <script src="vendor/jquery.min.js"></script> <script src="vendor/marked.min.js"></script> <script src="vendor/prettify.min.js"></script> <link href="vendor/strapdown.css" rel="stylesheet"></link> <!-- 此处指定了主题,可以按照喜好修改 --> <link href="vendor/themes/cerulean.min.css" rel="stylesheet"></link> </head> <title>API Document</title> <xmp theme="cerulean" style="display:none;"> {{>markdown}} </xmp> <!-- 指定strapdown.js在本地的路径 --> <script src="vendor/strapdown.js"></script> </html>
编译后,生成了api.html文档到outdoc文件夹下(参考上面的截图),将outdoc打包给别人,浏览器打开api.html,就可以查看接口数据了。