前言 相信很多后端开发在项目中都会碰到要写api文档,不管是给前端、移动端等提供更好的对接,还是以后为了以后交接方便,都会要求写api文档。 而手写api文档的话有诸多痛点:文档更新的时候,需要再次发送给对接人接口太多,手写文档很难管理接口返回的结果不明确不能直接在线测试接口,通常需要使用工具,如postman等 Swagger就很好地解决了这个问题。Swagger简介 Swagger是一个规范和完整的框架,用于生成、描述、调用和可视化RESTful风格的Web服务。总体目标是使客户端和文件系统作为服务器以同样的速度来更新。文件的方法,参数和模型紧密集成到服务器端的代码,允许API来始终保持同步。Swagger使用1。相关依赖!swagger2dependencygroupIdio。springfoxgroupIdspringfoxswagger2artifactIdversion2。9。2versiondependencydependencygroupIdio。springfoxgroupIdspringfoxswaggeruiartifactIdversion2。9。2versiondependency2。Swagger配置类ConfigurationEnableSwagger2publicclassSwaggerConfig{BeanpublicDocketbuildDocket(){returnnewDocket(DocumentationType。SWAGGER2)。apiInfo(buildApiInf())将api的元信息设置为包含在jsonresourcelisting响应中。host(127。0。0。1:8080)设置ip和端口,或者域名。select()启动用于api选择的生成器。apis(RequestHandlerSelectors。any())。apis(RequestHandlerSelectors。basePackage(cn。zwqh。springboot。controller))指定controller路径。paths(PathSelectors。any())。build();}privateApiInfobuildApiInf(){ContactcontactnewContact(朝雾轻寒,https:www。zwqh。top,zwqhclover1314。com);returnnewApiInfoBuilder()。title(SwaggerDemoRestfulAPIDocs)文档标题。description(Swagger示例RestfulApi文档)文档描述。contact(contact)联系人。version(1。0)版本号。license()更新此API的许可证信息。licenseUrl()更新此API的许可证Url。termsOfServiceUrl()更新服务条款URL。build();}}3。SpringMVC相关配置ConfigurationpublicclassWebMvcConfigextendsWebMvcConfigurationSupport{静态资源配置(默认)OverridepublicvoidaddResourceHandlers(ResourceHandlerRegistryregistry){registry。addResourceHandler()。addResourceLocations(classpath:static);静态资源路径registry。addResourceHandler(swaggerui。html)。addResourceLocations(classpath:METAINFresources);registry。addResourceHandler(webjars)。addResourceLocations(classpath:METAINFresourceswebjars);super。addResourceHandlers(registry);}} 如果不添加此静态资源配置会报错,找不到相关路径4。Model中使用Swagger注解ApiModel(valueUserEntity,description用户对象)publicclassUserEntityimplementsSerializable{privatestaticfinallongserialVersionUID5237730257103305078L;ApiModelProperty(value用户id,nameid,dataTypeLong,requiredfalse,example1,hiddenfalse)privateLongid;ApiModelProperty(value用户名,nameuserName,dataTypeString,requiredfalse,example关羽)privateStringuserName;ApiModelProperty(value用户性别,nameuserSex,dataTypeString,requiredfalse,example男)privateStringuserSex;publicLonggetId(){returnid;}publicvoidsetId(Longid){this。idid;}publicStringgetUserName(){returnuserName;}publicvoidsetUserName(StringuserName){this。userNameuserName;}publicStringgetUserSex(){returnuserSex;}publicvoidsetUserSex(StringuserSex){this。userSexuserSex;}}5。Controller中使用Swagger注解RestControllerRequestMapping(api)Api(tags{接口分组1,接口分组2})publicclassApiController{AutowiredprivateUserDaouserDao;GetMapping(getAllUser)ApiOperation(value获取所有用户,notes,httpMethodGET,tags接口分组3)publicListUserEntitygetAll(){returnuserDao。getAll();}GetMapping(getUserById)ApiOperation(value根据id获取用户,notesid必传,httpMethodGET)ApiImplicitParam(nameid,value用户id,example1,requiredtrue,dataTypelong,paramTypequery)publicUserEntitygetOne(Longid){returnuserDao。getOne(id);}PostMapping(getUserByNameAndSex)ApiOperation(value根据name和sex获取用户,notes,httpMethodPOST)ApiImplicitParams({ApiImplicitParam(nameuserName,value用户名,example关羽,requiredtrue,dataTypestring,paramTypequery),ApiImplicitParam(nameuserSex,value用户性别,example男,requiredtrue,dataTypestring,paramTypequery)})publicUserEntitygetUserByNameAndSex(StringuserName,StringuserSex){returnuserDao。getUserByNameAndSex(userName,userSex);}PostMapping(insertUser)ApiOperation(value新增用户,notes传json,数据放body,httpMethodPOST)ApiImplicitParams({ApiImplicitParam(namebody,value用户对象json,example{userName:朝雾轻寒,userSex:男},requiredtrue)})publicStringinsertUser(RequestBodyStringbody){System。out。println(body);UserEntityuserJSON。parseObject(body,UserEntity。class);userDao。insertUser(user);return{code:0,msg:success};}PostMapping(updateUser)ApiOperation(value修改用户,notes传json,数据放body,httpMethodPOST)ApiImplicitParams({ApiImplicitParam(namebody,value用户对象json,example{id:23,userName:朝雾轻寒,userSex:女},requiredtrue)})publicStringupdateUser(RequestBodyStringbody){System。out。println(body);UserEntityuserJSON。parseObject(body,UserEntity。class);userDao。updateUser(user);return{code:0,msg:success};}PostMapping(deleteUser)ApiOperation(value删除用户,notesid必传,httpMethodPOST)publicStringdeleteUser(ApiParam(nameid,value用户id,requiredtrue)Longid){userDao。deleteUser(id);return{code:0,msg:success};}}5。测试 访问http:127。0。0。1:8080swaggerui。html进行接口在线测试Swagger常用注解1。Api 用于类,表示表示这个类是swagger的资源。属性如下:tags表示说明,tags如果有多个值,会生成多个列表value表示说明,可以使用tags替代2。ApiOperation 用于方法,表示一个http请求的操作。属性如下:value用于方法描述notes用于提示内容tags用于API文档控制的标记列表,视情况而用,可以进行独立分组3。ApiParam 用于方法、参数、字段说明;表示对参数的添加元数据。name参数名value参数说明required是否必填4。ApiModel 用于类,表示对类进行说明,用于参数用实体类接受。value对象名description描述5。ApiModelProperty 用于方法、字段,表示对model属性的说明或者数据操作更改。value字段说明name重写属性名dataType重写属性数据类型required是否必填example举例说明hidden隐藏6。ApiIgnore 用于类、方法、方法参数,表示这个方法或者类被忽略,不在swaggerui。html上显示。7。ApiImplicitParam 用于方法,表示单独的请求参数。name参数名value参数说明dataType数据类型paramType参数类型example举例说明8。ApiImplicitParams 用于方法,包含多个ApiImplicitParam。9。ApiResponsesApiResponse 用于类或者方法,描述操作的可能响应。code响应的HTTP状态代码message响应附带的可读消息10。ResponseHeader 用于方法,响应头设置。name响应头名称description头描述response默认响应类voidresponseContainer参考ApiOperation中配置Swagger导出离线api文档1。导出AsciiDocs、Markdown、Confluence格式文档 添加依赖!swagger2markup相关依赖dependencygroupIdio。github。swagger2markupgroupIdswagger2markupartifactIdversion1。3。3versiondependency 转换工具类publicclassSwaggerUtils{privatestaticfinalStringurlhttp:127。0。0。1:8080v2apidocs;生成AsciiDocs格式文档throwsMalformedURLExceptionpublicstaticvoidgenerateAsciiDocs()throwsMalformedURLException{Swagger2MarkupConfigconfignewSwagger2MarkupConfigBuilder()。withMarkupLanguage(MarkupLanguage。ASCIIDOC)。withOutputLanguage(Language。ZH)。withPathsGroupedBy(GroupBy。TAGS)。withGeneratedExamples()。withoutInlineSchema()。build();Swagger2MarkupConverter。from(newURL(url))。withConfig(config)。build()。toFolder(Paths。get(。docsasciidocgenerated));}生成AsciiDocs格式文档,并汇总成一个文件throwsMalformedURLExceptionpublicstaticvoidgenerateAsciiDocsToFile()throwsMalformedURLException{Swagger2MarkupConfigconfignewSwagger2MarkupConfigBuilder()。withMarkupLanguage(MarkupLanguage。ASCIIDOC)。withOutputLanguage(Language。ZH)。withPathsGroupedBy(GroupBy。TAGS)。withGeneratedExamples()。withoutInlineSchema()。build();Swagger2MarkupConverter。from(newURL(url))。withConfig(config)。build()。toFile(Paths。get(。docsasciidocgeneratedall));}生成Markdown格式文档throwsMalformedURLExceptionpublicstaticvoidgenerateMarkdownDocs()throwsMalformedURLException{Swagger2MarkupConfigconfignewSwagger2MarkupConfigBuilder()。withMarkupLanguage(MarkupLanguage。MARKDOWN)。withOutputLanguage(Language。ZH)。withPathsGroupedBy(GroupBy。TAGS)。withGeneratedExamples()。withoutInlineSchema()。build();Swagger2MarkupConverter。from(newURL(url))。withConfig(config)。build()。toFolder(Paths。get(。docsmarkdowngenerated));}生成Markdown格式文档,并汇总成一个文件throwsMalformedURLExceptionpublicstaticvoidgenerateMarkdownDocsToFile()throwsMalformedURLException{Swagger2MarkupConfigconfignewSwagger2MarkupConfigBuilder()。withMarkupLanguage(MarkupLanguage。MARKDOWN)。withOutputLanguage(Language。ZH)。withPathsGroupedBy(GroupBy。TAGS)。withGeneratedExamples()。withoutInlineSchema()。build();Swagger2MarkupConverter。from(newURL(url))。withConfig(config)。build()。toFile(Paths。get(。docsmarkdowngeneratedall));}生成Confluence格式文档throwsMalformedURLExceptionpublicstaticvoidgenerateConfluenceDocs()throwsMalformedURLException{Swagger2MarkupConfigconfignewSwagger2MarkupConfigBuilder()。withMarkupLanguage(MarkupLanguage。CONFLUENCEMARKUP)。withOutputLanguage(Language。ZH)。withPathsGroupedBy(GroupBy。TAGS)。withGeneratedExamples()。withoutInlineSchema()。build();Swagger2MarkupConverter。from(newURL(url))。withConfig(config)。build()。toFolder(Paths。get(。docsconfluencegenerated));}生成Confluence格式文档,并汇总成一个文件throwsMalformedURLExceptionpublicstaticvoidgenerateConfluenceDocsToFile()throwsMalformedURLException{Swagger2MarkupConfigconfignewSwagger2MarkupConfigBuilder()。withMarkupLanguage(MarkupLanguage。CONFLUENCEMARKUP)。withOutputLanguage(Language。ZH)。withPathsGroupedBy(GroupBy。TAGS)。withGeneratedExamples()。withoutInlineSchema()。build();Swagger2MarkupConverter。from(newURL(url))。withConfig(config)。build()。toFile(Paths。get(。docsconfluencegeneratedall));}} 使用测试ControllerRestControllerRequestMapping(export)ApiIgnorepublicclassExportController{RequestMapping(ascii)publicStringexportAscii()throwsMalformedURLException{SwaggerUtils。generateAsciiDocs();returnsuccess;}RequestMapping(asciiToFile)publicStringasciiToFile()throwsMalformedURLException{SwaggerUtils。generateAsciiDocsToFile();returnsuccess;}RequestMapping(markdown)publicStringexportMarkdown()throwsMalformedURLException{SwaggerUtils。generateMarkdownDocs();returnsuccess;}RequestMapping(markdownToFile)publicStringexportMarkdownToFile()throwsMalformedURLException{SwaggerUtils。generateMarkdownDocsToFile();returnsuccess;}RequestMapping(confluence)publicStringconfluence()throwsMalformedURLException{SwaggerUtils。generateConfluenceDocs();returnsuccess;}RequestMapping(confluenceToFile)publicStringconfluenceToFile()throwsMalformedURLException{SwaggerUtils。generateConfluenceDocsToFile();returnsuccess;}}2。导出html、pdf、xml格式 添加依赖!离线文档dependencygroupIdorg。springframework。restdocsgroupIdspringrestdocsmockmvcartifactIdscopetestscopedependency!springfoxstaticdocs生成静态文档dependencygroupIdio。springfoxgroupIdspringfoxstaticdocsartifactIdversion2。6。1versiondependencybuildpluginManagementpluginsplugingroupIdorg。springframework。bootgroupIdspringbootmavenpluginartifactIdpluginplugingroupIdio。github。swagger2markupgroupIdswagger2markupmavenpluginartifactIdversion1。3。1versionconfigurationswaggerInputhttp:127。0。0。1:8080v2apidocsswaggerInputoutputDir。docsasciidocgeneratedoutputDirconfigswagger2markup。markupLanguageASCIIDOCswagger2markup。markupLanguageconfigconfigurationpluginplugingroupIdorg。asciidoctorgroupIdasciidoctormavenpluginartifactIdversion1。5。3version!version2。0。0RC。1version!IncludeAsciidoctorPDFforpdfgenerationdependenciesdependencygroupIdorg。asciidoctorgroupIdasciidoctorjpdfartifactIdversion1。5。0alpha。10。1versiondependencydependencygroupIdorg。jrubygroupIdjrubycompleteartifactIdversion1。7。21versiondependencydependenciesconfigurationsourceDirectory。docsasciidocgeneratedsourceDirectoryoutputDirectory。docsasciidochtmloutputDirectorybackendhtmlbackend!outputDirectory。docsasciidocpdfoutputDirectorybackendpdfbackendheaderFootertrueheaderFooterdoctypebookdoctypesourceHighlightercoderaysourceHighlighter!菜单栏在左边toclefttoc!多标题排列toclevels3toclevels!自动打数字序号sectnumstruesectnumsattributesconfigurationpluginpluginspluginManagementbuild 可以修改此处html和pdf,通过mvnasciidoctor:processasciidoc可以导出相应格式文件outputDirectory。docsasciidochtmloutputDirectorybackendhtmlbackend 执行mvnasciidoctor:processasciidoc后再执行mvngenerateresources,可在targtgenerateddocs目录下生成xml格式文件