频道
bg

使用springfox生成springmvc项目的swagger的文档

coding七月 07, 20151mins
Spring Framework API Swagger

介绍H1

SwaggerH2

Swagger是用来描述和文档化RESTful API的一个项目。Swagger Spec是一套规范,定义了该如何去描述一个RESTful API。类似的项目还有RAMLAPI Blueprint。 根据Swagger Spec来描述RESTful API的文件称之为Swagger specification file,它使用JSON来表述,也支持作为JSON支持的YAML。

Swagger specification file可以用来给swagger-ui生成一个Web的可交互的文档页面,以可以用swagger2markup生成静态文档,也可用使用swagger-codegen生成客户端代码。总之有了有个描述API的JSON文档之后,可以做各种扩展。

Swagger specification file可以手动编写,swagger-editor为了手动编写的工具提供了预览的功能。但是实际写起来也是非常麻烦的,同时还得保持代码和文档的两边同步。于是针对各种语言的各种框架都有一些开源的实现来辅助自动生成这个`Swagger specification file

swagger-core是一个Java的实现,现在支持JAX-RSswagger-annotation定义了一套注解给用户用来描述API。 spring-fox也是一个Java的实现,它支持Spring MVC, 它也支持swagger-annotation定义的部分注解。

使用SpringfoxH1

DocketH2

Springfox通过定义Docket对象来全局的定义API的一些属性。同时支持swagger-annotation的部分注解来定义各个API方法一些参数等。 看一个定义的例子

bash

@SpringBootApplication
@EnableSwagger2
@ComponentScan(basePackageClasses = {
PetController.class
})
public class Swagger2SpringBoot {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(Swagger2SpringBoot.class, args);
}
@Bean
public Docket petApi() {
return new Docket(DocumentationType.SWAGGER_2)
.select() //1
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build()
.pathMapping("/") //2
.directModelSubstitute(LocalDate.class, //3
String.class)
.genericModelSubstitutes(ResponseEntity.class) //4
.alternateTypeRules( //5
newRule(typeResolver.resolve(DeferredResult.class,
typeResolver.resolve(ResponseEntity.class, WildcardType.class)),
typeResolver.resolve(WildcardType.class)))
.useDefaultResponseMessages(false) //6
.globalResponseMessage(RequestMethod.GET, //7
newArrayList(new ResponseMessageBuilder()
.code(500)
.message("500 message")
.responseModel(new ModelRef("Error"))
.build()))
.securitySchemes(newArrayList(apiKey())) //8
.securityContexts(newArrayList(securityContext())) //9
;
}
@Autowired
private TypeResolver typeResolver;
private ApiKey apiKey() {
return new ApiKey("mykey", "api_key", "header");
}
private SecurityContext securityContext() {
return SecurityContext.builder()
.securityReferences(defaultAuth())
.forPaths(PathSelectors.regex("/anyPath.*"))
.build();
}
List<SecurityReference> defaultAuth() {
AuthorizationScope authorizationScope
= new AuthorizationScope("global", "accessEverything");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
return newArrayList(
new SecurityReference("mykey", authorizationScopes));
}
@Bean
SecurityConfiguration security() {
return new SecurityConfiguration(
"test-app-client-id",
"test-app-realm",
"test-app",
"apiKey");
}
@Bean
UiConfiguration uiConfig() {
return new UiConfiguration(
"validatorUrl");
}
}
  1. 定义了需要生成API文档的endpoint,api()方法可以通过RequestHandlerSelectors的各种选择器来选择,比如说选择所有注解了@RsestController的类中的所有API e.g. .apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))。path()方法可以通过PathSelectors的来匹配路径,提供了regex匹配或者ant匹配
  2. 定义了API的根路径
  3. 输出模型定义时的替换,比如遇到所有LocalDate的字段时,输出成String
  4. 遇到对应泛型类型的外围类,直接解析成泛型类型,比如说ResponseEntity<T>,应该直接输出成类型T
  5. 提供了自定义性更强的针对泛型的处理,示例中的代码的意思是将类型DeferredResult<ResponseEntity<T>>直接解析成类型T
  6. 是否使用默认的ResponseMessage, 框架默认定义了一些针对各个HTTP方法时各种不同响应值对应的message
  7. 全局的定义ResponseMessage,示例代码定义GET方法的500错误的消息以及错误模型。注意这里GET方法的所有ResponseMessage都会被这里的定义覆盖
  8. 定义API支持的SecurityScheme,指的是认证方式,支持OAuth、APIkey。 P.S. 要让swagger-ui的oauth正常工作,需要定义个SecurityConfiguration的Bean
  9. 定义具体上下文路径对应的认证方式
  10. 还有一些接口可以定义API的名称等一些基本信息,定义API支持的数据格式等等。

注解H2

还有一些swagger-annotation的注解可以帮助我们针对各个API生成更为详细的文档

  • @ApiOperation 描述方法名称,描述
  • @ApiResponses 描述方法发生异常时返回的code以及message
  • @ApiImplicitParams 显示的描述方法的参数,默认情况下springfox会根据参数的@RequestParam@PathParam等注解来自动获取参数。 但是如果没有注解则会识别为request body。 方法的一些参数是由容器注入的,并不是客户端的参数。使用 @ApiIgnore来忽略。

一些坑H2

swagger-ui的o2c.hmtl找不到H3

2.0.4版本之前,Oauth2认证返回的redirectUri为/o2c.html,但是o2c.html在webjar里面,实际路径是/webjars/springfox-swagger-ui/o2c.html,具体参考

swagger-ui的oauth认证弹出框失效H3

2.0.4版本之前存在的问题,之前提到了需要在容易中定义一个SecurityConfiguration的Bean,因为swagger-ui.html会在初始化的时候请求这个Bean,访问返回对象中的几个属性,然后初始Oauth的一些JS代码。如果后台返回的JSON的property名不是驼峰式命名的,那这几个属性就不能正确获取到,导出初始化失败,具体参考

静态文档H1

静态文档可以通过Swagger2MarkupResultHandler执行生成asciidoc或者SwaggerResultHandler生成swagger.json,再使用swagger2markup-gradle-plugin根据swagger.json生成asciidoc,ResultHandler的使用要配合Spring Test Framework

最后使用asciidoctor-gradle-plugin合并asciidoc并生成html

评论


新的评论

匹配您的Gravatar头像

Joen Yu

@2022 JoenYu, all rights reserved. Made with love.