{"id":322785,"date":"2021-05-08T15:00:59","date_gmt":"2021-05-08T15:00:59","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=322785"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=322785","title":{"rendered":"\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u0439 \u044d\u0442\u043e"},"content":{"rendered":"\n<div class=\"post__text post__text_v2\" id=\"post-content-body\">\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/358\/89a\/06b\/35889a06bad78ecd59dd1867eab3a399.png\" width=\"480\" height=\"424\"><figcaption><\/figcaption><\/figure>\n<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442! \u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0445\u043e\u0442\u0435\u043b \u0431\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0438\u0430\u043b\u044c\u043d\u043e \u0440\u0430\u0437\u043d\u044b\u0445 \u043f\u043e\u0434\u0445\u043e\u0434\u0430\u0445 \u0432 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 REST API, \u0430 \u0438\u043c\u0435\u043d\u043d\u043e \u0434\u043b\u044f CodeFirst &#8212; \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b SpringRestDocs (\u0430 \u0442\u0430\u043a\u0436\u0435 \u0435\u0433\u043e \u043d\u0430\u0434\u0441\u0442\u0440\u043e\u0439\u043a\u0443 SpringAutoRestDocs) \u0438 \u0434\u043b\u044f ApiFirst &#8212; \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u044d\u043a\u043e\u0441\u0438\u0441\u0442\u0435\u043c\u044b Swagger(Open-Api).<\/p>\n<p><em>\u0414\u0438\u0441\u043a\u043b\u0435\u0439\u043c\u0435\u0440: \u0412 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u0445\u043e\u043b\u0438\u0432\u0430\u0440\u0430 \u043d\u0430 \u0442\u0435\u043c\u0443 \u0447\u0442\u043e \u0436\u0435 \u043b\u0443\u0447\u0448\u0435 CodeFirst \u0438\u043b\u0438 ApiFirst \u044f \u0432\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0435 \u0431\u0443\u0434\u0443\u0442, \u0430 \u043f\u043e\u0441\u0442\u0430\u0440\u0430\u044e\u0441\u044c \u043f\u0440\u043e\u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u0443\u044e \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0443 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0432 \u043e\u0431\u043e\u0438\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430\u0445.<\/em><\/p>\n<h2>CodeFirst \u043f\u043b\u044e\u0441 SpringAutoRestDocs<\/h2>\n<p>\u041a\u0430\u043a \u0443\u0436\u0435 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u043b\u0438 \u0432 <a href=\"https:\/\/habr.com\/ru\/post\/341636\/\" rel=\"noopener noreferrer nofollow\">\u0441\u0442\u0430\u0442\u044c\u0435 \u043f\u0440\u043e SpringRestDocs<\/a> \u044d\u0442\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0448\u0438\u0440\u043e\u043a\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u0439 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u0443\u044e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e (\u0430\u0441\u043a\u0435\u0434\u043e\u043a, \u0445\u0442\u043c\u043b \u0438 \u0442.\u0434.) \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0442\u0435\u0441\u0442\u043e\u0432. \u041f\u043e\u0436\u0430\u043b\u0443\u0439 \u043e\u0434\u0438\u043d \u0438\u0437 \u043d\u0435\u043c\u043d\u043e\u0433\u0438\u0445 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u043e\u0432 \u044d\u0442\u043e\u0433\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0435\u0433\u043e \u043c\u043d\u043e\u0433\u043e\u0441\u043b\u043e\u0432\u043d\u043e\u0441\u0442\u044c \u0432 \u0442\u0435\u0441\u0442\u0430\u0445, \u0430 \u0438\u043c\u0435\u043d\u043d\u043e &#8212; \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043a\u0430\u0436\u0434\u044b\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440, \u043a\u0430\u0436\u0434\u043e\u0435 \u043f\u043e\u043b\u0435 \u0438 \u0442.\u0434. \u0412 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0442\u0435\u0441\u044b \u0432 SpringAutoRestDocs, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f JSR \u0438 Spring \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438, \u0430 \u0442\u0430\u043a\u0436\u0435 Javadoc, \u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0442\u0441\u044f \u0431\u043e\u043b\u0435\u0435 \u043a\u043e\u0440\u043e\u0442\u043a\u0438\u043c \u0438 \u043d\u0435\u043c\u043d\u043e\u0433\u043e\u0441\u043b\u043e\u0432\u043d\u044b\u043c\u0438.<\/p>\n<details class=\"spoiler\">\n<summary>\u0427\u0443\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043f\u0440\u043e SpringAutoRestDocs<\/summary>\n<div class=\"spoiler__content\">\n<p>SpringAutoRestDocs \u044d\u0442\u043e \u043d\u0430\u0434\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043d\u0430\u0434 SpringRestDocs, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u0442\u0430\u0432\u0438\u0442 \u0441\u0432\u043e\u0435\u0439 \u0446\u0435\u043b\u044c\u044e \u0443\u043c\u0435\u043d\u044c\u0448\u0435\u043d\u0438\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043a\u043e\u0434\u0430 \u0438 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438. \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u043e \u044d\u0442\u043e\u0433\u043e \u0438\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430 &#8212; \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043c\u0435\u043d\u044c\u0448\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0438 \u0431\u043e\u043b\u044c\u0448\u0430\u044f \u0441\u0432\u044f\u0437\u0430\u043d\u043e\u0441\u0442\u044c \u0441 \u0440\u0430\u0431\u043e\u0447\u0438\u043c \u043a\u043e\u0434\u043e\u043c.<\/p>\n<p>\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0437 \u0444\u0438\u0447\u0435\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430:<\/p>\n<ul>\n<li>\n<p>\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u043e\u043b\u0435\u0439 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438 \u043e\u0442\u0432\u0435\u0442\u0430, \u0445\u0435\u0434\u0435\u0440\u043e\u0432 \u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Jackson, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043e\u043f\u0438\u0441\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 Javadocs<\/p>\n<\/li>\n<li>\n<p>\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u0435\u0439 \u043f\u043e \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 JSR-303<\/p>\n<\/li>\n<li>\n<p>\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u0442\u043e\u0433\u043e\u0432\u044b\u0445 \u0441\u043d\u0438\u043f\u0435\u0442\u0442\u043e\u0432<\/p>\n<\/li>\n<\/ul>\n<p><em>\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0432 <\/em><a href=\"https:\/\/scacap.github.io\/spring-auto-restdocs\/\" rel=\"noopener noreferrer nofollow\"><em>\u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/em><\/a><em>.<\/em><\/p>\n<\/div>\n<\/details>\n<p>\u0414\u043b\u044f \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0432\u043e\u0437\u044c\u043c\u0435\u043c \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0439 <a href=\"https:\/\/petstore.swagger.io\/\" rel=\"noopener noreferrer nofollow\">Swagger PetStore<\/a> (\u0441 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043c\u043e\u0434\u0435\u0440\u043d\u0438\u0437\u0430\u0446\u0438\u0435\u0439, \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c <a href=\"https:\/\/github.com\/GrinRus\/rest-docs-demo\/blob\/master\/swagger-library\/specs\/some_swagger.yaml\" rel=\"noopener noreferrer nofollow\">\u0441\u043f\u0435\u043a\u0443 \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438<\/a>) \u0438 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u0435\u043c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 (<code>addPet<\/code>, <code>deletePet<\/code>, <code>getPetById<\/code>). \u0412 \u0441\u0442\u0430\u0442\u044c\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d \u043f\u0440\u0438\u043c\u0435\u0440 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043e\u0434\u043d\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 <code>getPetById<\/code><\/p>\n<p><strong>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440:<\/strong><\/p>\n<pre><code class=\"java\">@RestController @RequiredArgsConstructor public class PetController implements PetApi {      private final PetRepository petRepository;          @Override     public ResponseEntity&lt;Pet&gt; getPetById(Long petId) {         return new ResponseEntity&lt;&gt;(petRepository.getPetById(petId), HttpStatus.OK);     }   \/\/\u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b }<\/code><\/pre>\n<p>\u0420\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0431\u044b\u0447\u043d\u044b\u043c \u043b\u0438\u0441\u0442\u043e\u043c \u0441 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u0430.<\/p>\n<p><strong>\u0411\u0430\u0437\u043e\u0432\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0439 \u0430\u0432\u0442\u043e\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438:<\/strong><\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0442\u0435\u0441\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u043f\u0438\u0448\u0435\u0442 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043d\u0430\u0448\u0435\u0439 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438. \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u0447\u0442\u043e \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f, \u044d\u0442\u043e \u0441\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 <code>MockMvc<\/code> (\u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c <a href=\"https:\/\/github.com\/GrinRus\/rest-docs-demo\/blob\/master\/spring-auto-rest-docs\/src\/test\/groovy\/ru\/spring\/auto\/rest\/docs\/demo\/controllers\/MockMvcDocumentSpec.groovy#L37\" rel=\"noopener noreferrer nofollow\">\u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438<\/a>):<\/p>\n<pre><code class=\"java\">@Before void setUp() throws Exception {   this.mockMvc = MockMvcBuilders     .webAppContextSetup(context)     .alwaysDo(prepareJackson(objectMapper, new TypeMapping()))     .alwaysDo(commonDocumentation())     .apply(documentationConfiguration(restDocumentation)            .uris().withScheme(\"http\").withHost(\"localhost\").withPort(8080)            .and()            .snippets().withTemplateFormat(TemplateFormats.asciidoctor())            .withDefaults(curlRequest(), httpRequest(), httpResponse(),                          requestFields(), responseFields(), pathParameters(),                          requestParameters(), description(), methodAndPath(),                          section(), links(), embedded(), authorization(DEFAULT_AUTHORIZATION),                          modelAttribute(requestMappingHandlerAdapter.getArgumentResolvers())))     .build()   }  protected RestDocumentationResultHandler commonDocumentation(Snippet... snippets) {   return document(\"rest-auto-documentation\/{class-name}\/{method-name}\", commonResponsePreprocessor(), snippets)   }  protected OperationResponsePreprocessor commonResponsePreprocessor() {   return preprocessResponse(replaceBinaryContent(), limitJsonArrayLength(objectMapper), prettyPrint())   }<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u0427\u0443\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043f\u0440\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 MockMVC<\/summary>\n<div class=\"spoiler__content\">\n<p><code>WebApplicationContext<\/code> \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043e\u0442 <code><a class=\"mention\" href=\"\/users\/springboottest\">@SpringBootTest<\/a><\/code><\/p>\n<p><code>prepareJackson(objectMapper, new TypeMapping())<\/code> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c <code>ResultHandler<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u0442 \u043d\u0430\u0448\u0438 pojo \u0434\u043b\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f<\/p>\n<p><code>withDefaults(curlRequest(), httpRequest(), \u0438 \u0442.\u0434.)<\/code> \u043d\u0430\u0431\u043e\u0440 \u0441\u043d\u0438\u043f\u043f\u0435\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u044b<\/p>\n<p><code>commonDocumentation()<\/code> \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e, \u043a\u0443\u0434\u0430 \u0432 build \u043f\u0430\u043f\u043a\u0435 \u0440\u0430\u0437\u043c\u0435\u0441\u0442\u044f\u0442\u0441\u044f \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0441\u043d\u0438\u043f\u043f\u0435\u0442\u044b, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u0435\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0438\u043d\u0433 \u043e\u0442\u0432\u0435\u0442\u0430 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430.<\/p>\n<\/div>\n<\/details>\n<p><strong>\u041d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0441\u0430\u043c \u0442\u0435\u0441\u0442:<\/strong><\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0442\u0435\u0441\u0442\u0430 \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c <a href=\"https:\/\/github.com\/GrinRus\/rest-docs-demo\/blob\/master\/spring-auto-rest-docs\/src\/test\/groovy\/ru\/spring\/auto\/rest\/docs\/demo\/controllers\/PetControllerAutoTest.groovy\" rel=\"noopener noreferrer nofollow\">\u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438<\/a>.<\/p>\n<pre><code>@Test void getPetTest() { \/\/given def petId = 1L \/\/when def resultActions = mockMvc \t.perform(RestDocumentationRequestBuilders \t\t.get(\"\/pet\/{petId}\", petId) \t\t.header(\"Accept\", \"application\/json\")) \/\/then resultActions \t.andExpect(status().isOk()) \t.andExpect(content().string(objectMapper.writeValueAsString(buildReturnPet()))) }<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 <code>MockMvc<\/code> \u0442\u0435\u0441\u0442, \u0441 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u043c \u0441\u0442\u0430\u0442\u0443\u0441\u043e\u043c \u0438 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u043c \u0442\u0435\u043b\u043e\u043c \u043e\u0442\u0432\u0435\u0442\u0430.<\/p>\n<p><strong>\u0418\u0442\u043e\u0433\u043e \u043d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435:<\/strong><\/p>\n<p>\u041d\u0430\u0431\u043e\u0440 \u0441\u043d\u0438\u043f\u0435\u0442\u0442\u043e\u0432 \u0441 &#171;\u0433\u043b\u0430\u0432\u043d\u044b\u043c&#187; \u0441\u043d\u0438\u043f\u043f\u0435\u0442\u043e\u043c \u043f\u043e\u0434 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c <code>auto-section.adoc<\/code> (\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0438\u0437 \u0432\u0441\u0435\u0445 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445, \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0445 \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 <code>MockMVC<\/code>) \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043f\u043e\u0437\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u043e\u0431\u0449\u0438\u0439 <code>index.adoc<\/code> \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 API. \u0413\u043e\u0442\u043e\u0432\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0441\u043d\u0438\u043f\u043f\u0435\u0442\u043e\u0432:<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/1c3\/281\/76b\/1c328176b3d494b36eca277321cf57d2.png\" width=\"420\" height=\"634\"><figcaption><\/figcaption><\/figure>\n<p>\u0413\u043e\u0442\u043e\u0432\u044b\u0435 \u0441\u043d\u0438\u043f\u043f\u0435\u0442\u044b \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u044b \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438: <a href=\"https:\/\/github.com\/GrinRus\/rest-docs-demo\/tree\/master\/generated\/spring-auto-rest-docs\/generated-snippets\/rest-auto-documentation\/pet-controller-auto-test\" rel=\"noopener noreferrer nofollow\">\u0441\u043d\u0438\u043f\u043f\u0435\u0442\u044b, <\/a><a href=\"https:\/\/htmlpreview.github.io\/?https:\/\/github.com\/GrinRus\/rest-docs-demo\/blob\/master\/generated\/spring-auto-rest-docs\/generated-snippets\/asciidoc\/index.html\" rel=\"noopener noreferrer nofollow\">html \u0441\u0433\u0435\u043d\u0435\u0440\u0435\u043d\u043d\u044b\u0439 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0441\u043d\u0438\u043f\u043f\u0435\u0442\u043e\u0432<\/a>.<\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043f\u0440\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c \u0448\u0430\u0431\u043b\u043e\u043d\u044b \u043b\u0438\u0431\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u0432\u043e\u0438 \u0441\u043d\u0438\u043f\u043f\u0435\u0442\u044b \u0438 SprinAutoRestDocs \u0438\u0445 \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u0435\u0442 \u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u0442 \u0442\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c, \u0447\u0442\u043e \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u0430. \u0414\u043e\u043a\u0430 \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u0438 <a href=\"https:\/\/scacap.github.io\/spring-auto-restdocs\/#snippets-customization\" rel=\"noopener noreferrer nofollow\">\u0441\u043d\u0438\u043f\u043f\u0435\u0442\u043e\u0432<\/a>, <a href=\"https:\/\/scacap.github.io\/spring-auto-restdocs\/#constraints-custom\" rel=\"noopener noreferrer nofollow\">\u043a\u043e\u043d\u0441\u0442\u0440\u0435\u0439\u043d\u0442\u043e\u0432<\/a>.<\/p>\n<details class=\"spoiler\">\n<summary>\u0427\u0443\u0442\u044c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u0440\u043e \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u044e \u0441\u043d\u0438\u043f\u043f\u0435\u0442\u043e\u0432 \u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439<\/summary>\n<div class=\"spoiler__content\">\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0432 SpringAutoRestDocs \u0431\u0430\u0437\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043d\u0430 \u0442\u0430\u043a\u043e\u0432\u043e\u043c \u0436\u0435 \u0432 SpringRestDocs.<\/p>\n<ul>\n<li>\n<p>\u041d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0430\u0441\u043a\u0435\u0434\u043e\u043a \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432 &#8212; \u0432 \u0440\u0435\u0441\u0443\u0440\u0441\u044b \u0432\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0432 \u043f\u0430\u043f\u043a\u0443 org\/springframework\/restdocs\/templates\/asciidoctor \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u0443\u0436\u043d\u044b\u0439 \u0432\u0430\u043c \u0441\u043d\u0438\u043f\u043f\u0435\u0442 \u0431\u0435\u0437 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438 <code>default-<\/code><a href=\"https:\/\/github.com\/ScaCap\/spring-auto-restdocs\/tree\/master\/spring-auto-restdocs-core\/src\/main\/resources\/org\/springframework\/restdocs\/templates\/asciidoctor\" rel=\"noopener noreferrer nofollow\">\u0421\u043f\u0438\u0441\u043e\u043a \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0445 \u0430\u0441\u043a\u0435\u0434\u043e\u043a \u0441\u043d\u0438\u043f\u043f\u0435\u0442\u043e\u0432.<\/a><\/p>\n<\/li>\n<li>\n<p>\u041d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439 &#8212; \u0432 \u0440\u0435\u0441\u0443\u0440\u0441\u044b \u0432\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0432 \u043f\u0430\u043f\u043a\u0443 org\/springframework\/restdocs\/constraints \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0444\u0430\u0439\u043b <code>DefaultConstraintDescriptions.properties<\/code> \u0441 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c \u0441\u043f\u0438\u0441\u043a\u043e\u043c \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439 <a href=\"https:\/\/github.com\/spring-projects\/spring-restdocs\/blob\/main\/spring-restdocs-core\/src\/main\/resources\/org\/springframework\/restdocs\/constraints\/DefaultConstraintDescriptions.properties\" rel=\"noopener noreferrer nofollow\">\u0421\u043f\u0438\u0441\u043e\u043a \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0445 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439 \u0438 \u0438\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f<\/a>.<\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/details>\n<p>\u041a \u043f\u0440\u0438\u043c\u0435\u0440\u0443 <a href=\"https:\/\/github.com\/GrinRus\/rest-docs-demo\/tree\/master\/spring-auto-rest-docs\/src\/test\/resources\/org\/springframework\/restdocs\" rel=\"noopener noreferrer nofollow\">\u0440\u0443\u0441\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u0448\u0430\u043f\u043e\u043a \u0441\u043d\u0438\u043f\u043f\u0435\u0442\u043e\u0432 \u0438 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439:<\/a><\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/9ca\/f54\/2f5\/9caf542f566255273c5b396e78e2c10e.png\" width=\"964\" height=\"532\"><figcaption><\/figcaption><\/figure>\n<h2>ApiFirst \u043f\u043b\u044e\u0441 Swagger<\/h2>\n<p>\u041a\u0430\u043a \u0443\u0436\u0435 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u043b\u043e\u0441\u044c \u0432\u043e \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0435 \u0441\u0442\u0430\u0442\u0435\u0439 (<a href=\"https:\/\/habr.com\/ru\/post\/434798\/\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u0438\u043c\u0435\u04401<\/a>, <a href=\"https:\/\/habr.com\/ru\/post\/541592\/\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u0438\u043c\u0435\u04402<\/a>) swagger &#8212; \u044d\u0442\u043e open-source \u043f\u0440\u043e\u0435\u043a\u0442, \u0432\u043a\u043b\u044e\u0447\u0430\u044e\u0449\u0438\u0439 OpenApi Specification \u0438 \u0448\u0438\u0440\u043e\u043a\u0438\u0439 \u043d\u0430\u0431\u043e\u0440 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f, \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f REST api.<\/p>\n<details class=\"spoiler\">\n<summary>\u0427\u0443\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043f\u0440\u043e Swagger<\/summary>\n<div class=\"spoiler__content\">\n<p>Swagger \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0434\u0432\u0443\u0445 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u0447\u0430\u0441\u0442\u0435\u0439 &#8212; \u044d\u0442\u043e OpenApi Specification \u0438 Swagger Tools.<\/p>\n<ul>\n<li>\n<p>OpenApi Specification &#8212; \u044d\u0442\u043e \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0449\u0430\u044f \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f REST \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u0430 \u0434\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u044f API. \u0421\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u043f\u0438\u0441\u0430\u043d\u0430 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 YAML \u0438 JSON. \u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u0430, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043c\u043e\u0436\u043d\u043e \u0438\u0437\u0443\u0447\u0438\u0442\u044c \u043f\u043e <a href=\"https:\/\/swagger.io\/docs\/specification\/basic-structure\/\" rel=\"noopener noreferrer nofollow\">\u0441\u0441\u044b\u043b\u043a\u0435<\/a>.<\/p>\n<\/li>\n<li>\n<p>Swagger Tools &#8212; \u044d\u0442\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0438 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u043d\u043e-\u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 REST api. \u0421\u043e\u0441\u0442\u043e\u044f\u0442 \u0438\u0437 \u0442\u0440\u0435\u0445 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u0431\u043b\u043e\u043a\u043e\u0432: <a href=\"http:\/\/editor.swagger.io\/\" rel=\"noopener noreferrer nofollow\">Swagger Editor<\/a>(\u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043d\u044b\u0439 \u044d\u0434\u0438\u0442\u043e\u0440, \u0434\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u0443\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u0430 \u0441 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u043e\u0439 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u0441\u0438\u0442\u0430\u043a\u0441\u0438\u0441\u0430),  <a href=\"https:\/\/swagger.io\/swagger-ui\/\" rel=\"noopener noreferrer nofollow\">Swagger UI<\/a>(\u0440\u0435\u043d\u0434\u0435\u0440 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 API), <a href=\"https:\/\/github.com\/swagger-api\/swagger-codegen\" rel=\"noopener noreferrer nofollow\">Swagger Codegen<\/a>(\u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e-\u043a\u043b\u0438\u0435\u043d\u0442\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0442\u0438\u043f\u043e\u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0439)<\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/details>\n<p>\u041d\u0438\u0436\u0435 \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043c\u0443\u043b\u044c\u0442\u0438-\u043c\u043e\u0434\u0443\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0441\u043e \u0441\u043b\u0435\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043e\u0439: \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0441\u043e \u0441\u0432\u0430\u0433\u0435\u0440 \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u043c (<a href=\"https:\/\/github.com\/GrinRus\/rest-docs-demo\/tree\/master\/swagger-library\" rel=\"noopener noreferrer nofollow\">swagger-library<\/a>), \u0441\u0442\u0430\u0440\u0442\u0435\u0440 \u0441 swagger-ui(<a href=\"https:\/\/github.com\/GrinRus\/rest-docs-demo\/tree\/master\/swagger-webjar-ui-starter\" rel=\"noopener noreferrer nofollow\">swagger-webjar-ui-starter<\/a>), \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u0435\u0442 \u043a\u043b\u0430\u0441\u0441\u044b \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438(<a href=\"https:\/\/github.com\/GrinRus\/rest-docs-demo\/tree\/master\/spring-auto-rest-docs\" rel=\"noopener noreferrer nofollow\">spring-auto-rest-docs<\/a>).<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/eee\/029\/e38\/eee029e38f73aaaa03f35bd092839225.png\" width=\"323\" height=\"569\"><figcaption><\/figcaption><\/figure>\n<p>\u0414\u043b\u044f \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 Swagger \u0432\u043e\u0437\u044c\u043c\u0435\u043c \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0439 <a href=\"https:\/\/petstore.swagger.io\/\" rel=\"noopener noreferrer nofollow\">Swagger PetStore<\/a> \u0438\u0437 \u043f\u0440\u0438\u043c\u0435\u0440\u0430 SpringAutoRestDocs \u0432\u044b\u0448\u0435.<\/p>\n<p><strong>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 build.gradle \u0434\u043b\u044f \u043c\u043e\u0434\u0443\u043b\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438:<\/strong><\/p>\n<p>\u0414\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 server stub \u0438 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 Swagger \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <a href=\"https:\/\/github.com\/OpenAPITools\/openapi-generator\" rel=\"noopener noreferrer nofollow\">OpenApi Generator<\/a>.<\/p>\n<details class=\"spoiler\">\n<summary>\u0427\u0443\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043f\u0440\u043e OpenApi Generator<\/summary>\n<div class=\"spoiler__content\">\n<p>\u0412 \u043c\u043e\u0434\u0443\u043b\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f gradle \u043f\u043b\u044e\u0441 <a href=\"https:\/\/github.com\/OpenAPITools\/openapi-generator\/tree\/master\/modules\/openapi-generator-gradle-plugin\" rel=\"noopener noreferrer nofollow\">gradle plugin OpenApi Generator<\/a>.<\/p>\n<p>\u0421\u0430\u043c \u043f\u043b\u0430\u0433\u0438\u043d \u0434\u0430\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0433\u0435\u043d\u0435\u0440\u0438\u0442\u044c \u043a\u0430\u043a \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e-\u043a\u043b\u0438\u0435\u043d\u0442\u043d\u0443\u044e \u0447\u0430\u0441\u0442\u044c, \u0442\u0430\u043a \u0438 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u044b \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438. \u0411\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 <a href=\"https:\/\/github.com\/OpenAPITools\/openapi-generator\" rel=\"noopener noreferrer nofollow\">\u0441\u0441\u044b\u043b\u043a\u0435 \u043d\u0430 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439<\/a>.<\/p>\n<\/div>\n<\/details>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0442\u0430\u0441\u043a\u0430 \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438 \u0435\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438:<\/p>\n<pre><code>openApiGenerate {     generatorName = 'spring'     inputSpec = specFile     outputDir = \"${project.projectDir}\/\"     id = \"${artifactId}\"     groupId = projectPackage     ignoreFileOverride = ignoreFile     apiPackage = \"${projectPackage}.rest.api\"     invokerPackage = \"${projectPackage}.rest.invoker\"     modelPackage = \"${projectPackage}.rest.model\"     configOptions = [             dateLibrary            : 'java8',             hideGenerationTimestamp: 'true',             interfaceOnly          : 'true',             delegatePattern        : 'false',             configPackage          : \"${projectPackage}.configuration\"     ] }<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u0427\u0443\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043f\u0440\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0442\u0430\u0441\u043a\u0438 openApiGenerate<\/summary>\n<div class=\"spoiler__content\">\n<ul>\n<li>\n<p>generatorName &#8212; \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043e\u0441\u043d\u043e\u0432\u044b \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <\/p>\n<\/li>\n<li>\n<p>Spring (<a href=\"https:\/\/github.com\/OpenAPITools\/openapi-generator\/blob\/master\/docs\/generators\/spring.md\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u043e\u043f\u0435\u0440\u0442\u0438 \u0434\u043b\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440\u0430 spring<\/a>)<\/p>\n<\/li>\n<li>\n<p>dateLibrary &#8212; \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0448\u0430\u0431\u043b\u043e\u043d \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 \u0432 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0434\u0430\u0442\u043e\u0439 (joda, JSR-310 \u0438 \u0442.\u0434.)<\/p>\n<\/li>\n<li>\n<p>\u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c <a href=\"https:\/\/github.com\/OpenAPITools\/openapi-generator\/blob\/master\/docs\/global-properties.md\" rel=\"noopener noreferrer nofollow\">\u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u043e\u043f\u0435\u0440\u0442\u0438 \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440\u0430<\/a>, \u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u044f\u0449\u0438\u0435 \u043e\u0442 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438<\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/details>\n<p>\u041d\u0435\u0437\u0430\u0431\u044b\u0432\u0430\u0435\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044e \u043a\u043e\u0434\u0430 \u0434\u043e \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430:<\/p>\n<pre><code>task codegen(dependsOn: ['openApiGenerate', 'copySpecs'])  compileJava.dependsOn(codegen) compileJava.mustRunAfter(codegen)<\/code><\/pre>\n<p>\u041a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u0441\u043f\u0435\u043a\u0438 \u0432 \u0440\u0435\u0441\u0443\u0440\u0441\u044b, \u0447\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u0430 \u043f\u043e\u0437\u0436\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u044c UI \u043f\u0440\u044f\u043c\u043e \u0438\u0437 \u0441\u043f\u0435\u043a:<\/p>\n<pre><code>task copySpecs(type: Copy) {     from(\"${project.projectDir}\/specs\")     into(\"${project.projectDir}\/src\/main\/resources\/META-INF\/specs\") }<\/code><\/pre>\n<p>\u041f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0442\u044c <a href=\"https:\/\/github.com\/GrinRus\/rest-docs-demo\/blob\/master\/swagger-library\/build.gradle#L51\" rel=\"noopener noreferrer nofollow\">Asciidoc<\/a> \u0438\u043b\u0438 <a href=\"https:\/\/github.com\/GrinRus\/rest-docs-demo\/blob\/master\/swagger-library\/build.gradle#L62\" rel=\"noopener noreferrer nofollow\">Html2<\/a>.<\/p>\n<p><strong>Swagger-ui \u0441\u0442\u0430\u0440\u0442\u0435\u0440:<\/strong><\/p>\n<p>\u0421\u0442\u0430\u0440\u0442\u0435\u0440 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u0432 \u0440\u0435\u0433\u0438\u0441\u0442\u0440 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u0441\u043f\u0435\u043a\u0438 \u0441 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c\u0438 \u0432 <a href=\"https:\/\/github.com\/GrinRus\/rest-docs-demo\/blob\/master\/swagger-webjar-ui-starter\/src\/main\/java\/ru\/ryabov\/swagger\/webjar\/ui\/autoconfiguration\/SwaggerProperties.java#L13\" rel=\"noopener noreferrer nofollow\">\u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u043c\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438 <\/a>\u0438 webjar swagger-ui \u0441 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u043d\u044b\u043c \u043f\u0443\u0442\u0435\u043c \u0434\u043e \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u0430.<\/p>\n<p><strong>Rest-docs API:<\/strong><\/p>\n<p>\u0412 \u0441\u0430\u043c\u043e\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e <a href=\"https:\/\/github.com\/GrinRus\/rest-docs-demo\/blob\/master\/spring-auto-rest-docs\/src\/main\/java\/ru\/spring\/auto\/rest\/docs\/demo\/controllers\/PetController.java\" rel=\"noopener noreferrer nofollow\">\u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441<\/a> \u0438 <a href=\"https:\/\/github.com\/GrinRus\/rest-docs-demo\/blob\/master\/spring-auto-rest-docs\/src\/main\/resources\/config\/application.yml#L3-L10\" rel=\"noopener noreferrer nofollow\">\u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 UI \u0441\u0442\u0430\u0440\u0442\u0435\u0440\u0430<\/a>:<\/p>\n<pre><code>@RestController @RestController @RequiredArgsConstructor public class PetController implements PetApi {      private final PetRepository petRepository;          @Override     public ResponseEntity&lt;Pet&gt; getPetById(Long petId) {         return new ResponseEntity&lt;&gt;(petRepository.getPetById(petId), HttpStatus.OK);     }   \/\/\u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b }<\/code><\/pre>\n<pre><code>swagger:   ui:     indexHandler:       enabled: true       resourceHandler: \"\/api\/**\"     apis:       - url: http:\/\/localhost:8080\/specs\/some_swagger.yaml         name: My api<\/code><\/pre>\n<p><strong>\u0418\u0442\u043e\u0433\u043e \u043d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435:<\/strong><\/p>\n<p>Server stub &#8212; \u0433\u043e\u0442\u043e\u0432\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0441 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u043c \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 API.<\/p>\n<p>Swagger UI &#8212; \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u0443\u044e \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e API \u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043f\u0440\u044f\u043c\u043e \u0438\u0437 UI:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/a35\/ba0\/48b\/a35ba048b0a47e10bad0172fd531852a.png\" width=\"1140\" height=\"613\"><figcaption><\/figcaption><\/figure>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b <a href=\"https:\/\/github.com\/GrinRus\/rest-docs-demo\/blob\/master\/generated\/swagger\/asciidoc\/index.adoc\" rel=\"noopener noreferrer nofollow\">Asciidoc<\/a> \u0438\u043b\u0438 <a href=\"https:\/\/htmlpreview.github.io\/?https:\/\/github.com\/GrinRus\/rest-docs-demo\/blob\/master\/generated\/swagger\/asciidoc\/index.html\" rel=\"noopener noreferrer nofollow\">Html2<\/a> \u0438\u0437 \u0441\u0430\u043c\u043e\u0433\u043e swagger \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u0430:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/950\/d3d\/51f\/950d3d51f7987f084cee36f39fbf5283.png\" width=\"1880\" height=\"865\"><figcaption><\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/65d\/473\/aba\/65d473abac30a341d38060bf6007aab7.png\" width=\"1881\" height=\"873\"><figcaption><\/figcaption><\/figure>\n<h2>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435:<\/h2>\n<p>\u0427\u0442\u043e \u0434\u0430\u0435\u0442 SpringAutoRestDocs:<\/p>\n<ul>\n<li>\n<p>\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e \u043a\u0430\u043a \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 (\u043a \u043f\u0440\u0438\u043c\u0435\u0440\u0443 \u0432 \u0444\u043e\u0440\u043c\u0435 \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u043e\u0433\u043e index.html \u0438\u0437 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0430 \u0441\u043d\u0438\u043f\u043f\u0435\u0442\u043e\u0432), \u0442\u0430\u043a \u0438 \u0432 \u043b\u044e\u0431\u043e\u043c \u0434\u0440\u0443\u0433\u043e\u043c \u0443\u0434\u043e\u0431\u043d\u043e\u043c \u043c\u0435\u0441\u0442\u0435.<\/p>\n<\/li>\n<li>\n<p>\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0438 \u043c\u043e\u0434\u0435\u043b\u044c \u0434\u0430\u043d\u043d\u044b\u0445 \u0432\u0441\u0435\u0433\u0434\u0430 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u0430 \u0441 \u043a\u043e\u0434\u043e\u043c, \u0442\u0430\u043a \u043a\u0430\u043a \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 &#171;\u0437\u0435\u043b\u0435\u043d\u044b\u0445&#187; \u0442\u0435\u0441\u0442\u043e\u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430.<\/p>\n<\/li>\n<li>\n<p>\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u043d\u0438\u043f\u043f\u0435\u0442\u043e\u0432 \u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439.<\/p>\n<\/li>\n<\/ul>\n<p>\u0427\u0442\u043e \u0434\u0430\u0435\u0442 Swagger:<\/p>\n<ul>\n<li>\n<p>\u0415\u0434\u0438\u043d\u044b\u0439 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442 \u043d\u0430 \u0432\u0441\u0435\u0445 \u044d\u0442\u0430\u043f\u0430\u0445 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438.<\/p>\n<\/li>\n<li>\n<p>\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0438 \u043c\u043e\u0434\u0435\u043b\u044c \u0434\u0430\u043d\u043d\u044b\u0445 \u0432\u0441\u0435\u0433\u0434\u0430 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u0430 \u0441 \u043a\u043e\u0434\u043e\u043c, \u0442\u0430\u043a \u043a\u0430\u043a \u043a\u043e\u0434 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u0430.<\/p>\n<\/li>\n<li>\n<p>\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c UI, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0431\u0443\u0434\u0435\u0442 \u0432\u0441\u044f \u0442\u0430 \u0436\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f, \u0447\u0442\u043e \u0432 \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u0435 \u0441 \u0432\u043e\u0437\u044c\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b.     <\/p>\n<\/li>\n<\/ul>\n<p>\u041a\u0430\u043a\u043e\u0439 \u0431\u044b \u0432\u044b \u043d\u0435 \u0432\u044b\u0431\u0440\u0430\u043b\u0438 \u043f\u0443\u0442\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0432\u044b\u0448\u0435 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0442 \u0432\u0430\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u0443\u044e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e, \u0442\u0435\u0441\u043d\u043e \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u0443\u044e \u0441 \u0440\u0430\u0431\u043e\u0447\u0438\u043c \u043a\u043e\u0434\u043e\u043c.<\/p>\n<\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/556400\/\"> https:\/\/habr.com\/ru\/post\/556400\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text_v2\" id=\"post-content-body\">\n<figure class=\"\"><figcaption><\/figcaption><\/figure>\n<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442! \u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0445\u043e\u0442\u0435\u043b \u0431\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0438\u0430\u043b\u044c\u043d\u043e \u0440\u0430\u0437\u043d\u044b\u0445 \u043f\u043e\u0434\u0445\u043e\u0434\u0430\u0445 \u0432 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 REST API, \u0430 \u0438\u043c\u0435\u043d\u043d\u043e \u0434\u043b\u044f CodeFirst &#8212; \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b SpringRestDocs (\u0430 \u0442\u0430\u043a\u0436\u0435 \u0435\u0433\u043e \u043d\u0430\u0434\u0441\u0442\u0440\u043e\u0439\u043a\u0443 SpringAutoRestDocs) \u0438 \u0434\u043b\u044f ApiFirst &#8212; \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u044d\u043a\u043e\u0441\u0438\u0441\u0442\u0435\u043c\u044b Swagger(Open-Api).<\/p>\n<p><em>\u0414\u0438\u0441\u043a\u043b\u0435\u0439\u043c\u0435\u0440: \u0412 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u0445\u043e\u043b\u0438\u0432\u0430\u0440\u0430 \u043d\u0430 \u0442\u0435\u043c\u0443 \u0447\u0442\u043e \u0436\u0435 \u043b\u0443\u0447\u0448\u0435 CodeFirst \u0438\u043b\u0438 ApiFirst \u044f \u0432\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0435 \u0431\u0443\u0434\u0443\u0442, \u0430 \u043f\u043e\u0441\u0442\u0430\u0440\u0430\u044e\u0441\u044c \u043f\u0440\u043e\u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u0443\u044e \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0443 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0432 \u043e\u0431\u043e\u0438\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430\u0445.<\/em><\/p>\n<h2>CodeFirst \u043f\u043b\u044e\u0441 SpringAutoRestDocs<\/h2>\n<p>\u041a\u0430\u043a \u0443\u0436\u0435 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u043b\u0438 \u0432 <a href=\"https:\/\/habr.com\/ru\/post\/341636\/\" rel=\"noopener noreferrer nofollow\">\u0441\u0442\u0430\u0442\u044c\u0435 \u043f\u0440\u043e SpringRestDocs<\/a> \u044d\u0442\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0448\u0438\u0440\u043e\u043a\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u0439 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u0443\u044e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e (\u0430\u0441\u043a\u0435\u0434\u043e\u043a, \u0445\u0442\u043c\u043b \u0438 \u0442.\u0434.) \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0442\u0435\u0441\u0442\u043e\u0432. \u041f\u043e\u0436\u0430\u043b\u0443\u0439 \u043e\u0434\u0438\u043d \u0438\u0437 \u043d\u0435\u043c\u043d\u043e\u0433\u0438\u0445 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u043e\u0432 \u044d\u0442\u043e\u0433\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0435\u0433\u043e \u043c\u043d\u043e\u0433\u043e\u0441\u043b\u043e\u0432\u043d\u043e\u0441\u0442\u044c \u0432 \u0442\u0435\u0441\u0442\u0430\u0445, \u0430 \u0438\u043c\u0435\u043d\u043d\u043e &#8212; \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043a\u0430\u0436\u0434\u044b\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440, \u043a\u0430\u0436\u0434\u043e\u0435 \u043f\u043e\u043b\u0435 \u0438 \u0442.\u0434. \u0412 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0442\u0435\u0441\u044b \u0432 SpringAutoRestDocs, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f JSR \u0438 Spring \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438, \u0430 \u0442\u0430\u043a\u0436\u0435 Javadoc, \u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0442\u0441\u044f \u0431\u043e\u043b\u0435\u0435 \u043a\u043e\u0440\u043e\u0442\u043a\u0438\u043c \u0438 \u043d\u0435\u043c\u043d\u043e\u0433\u043e\u0441\u043b\u043e\u0432\u043d\u044b\u043c\u0438.<\/p>\n<details class=\"spoiler\">\n<summary>\u0427\u0443\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043f\u0440\u043e SpringAutoRestDocs<\/summary>\n<div class=\"spoiler__content\">\n<p>SpringAutoRestDocs \u044d\u0442\u043e \u043d\u0430\u0434\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043d\u0430\u0434 SpringRestDocs, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u0442\u0430\u0432\u0438\u0442 \u0441\u0432\u043e\u0435\u0439 \u0446\u0435\u043b\u044c\u044e \u0443\u043c\u0435\u043d\u044c\u0448\u0435\u043d\u0438\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043a\u043e\u0434\u0430 \u0438 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438. \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u043e \u044d\u0442\u043e\u0433\u043e \u0438\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430 &#8212; \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043c\u0435\u043d\u044c\u0448\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0438 \u0431\u043e\u043b\u044c\u0448\u0430\u044f \u0441\u0432\u044f\u0437\u0430\u043d\u043e\u0441\u0442\u044c \u0441 \u0440\u0430\u0431\u043e\u0447\u0438\u043c \u043a\u043e\u0434\u043e\u043c.<\/p>\n<p>\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0437 \u0444\u0438\u0447\u0435\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430:<\/p>\n<ul>\n<li>\n<p>\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u043e\u043b\u0435\u0439 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438 \u043e\u0442\u0432\u0435\u0442\u0430, \u0445\u0435\u0434\u0435\u0440\u043e\u0432 \u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Jackson, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043e\u043f\u0438\u0441\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 Javadocs<\/p>\n<\/li>\n<li>\n<p>\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u0435\u0439 \u043f\u043e \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 JSR-303<\/p>\n<\/li>\n<li>\n<p>\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u0442\u043e\u0433\u043e\u0432\u044b\u0445 \u0441\u043d\u0438\u043f\u0435\u0442\u0442\u043e\u0432<\/p>\n<\/li>\n<\/ul>\n<p><em>\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0432 <\/em><a href=\"https:\/\/scacap.github.io\/spring-auto-restdocs\/\" rel=\"noopener noreferrer nofollow\"><em>\u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/em><\/a><em>.<\/em><\/p>\n<\/div>\n<\/details>\n<p>\u0414\u043b\u044f \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0432\u043e\u0437\u044c\u043c\u0435\u043c \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0439 <a href=\"https:\/\/petstore.swagger.io\/\" rel=\"noopener noreferrer nofollow\">Swagger PetStore<\/a> (\u0441 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043c\u043e\u0434\u0435\u0440\u043d\u0438\u0437\u0430\u0446\u0438\u0435\u0439, \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c <a href=\"https:\/\/github.com\/GrinRus\/rest-docs-demo\/blob\/master\/swagger-library\/specs\/some_swagger.yaml\" rel=\"noopener noreferrer nofollow\">\u0441\u043f\u0435\u043a\u0443 \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438<\/a>) \u0438 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u0435\u043c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 (<code>addPet<\/code>, <code>deletePet<\/code>, <code>getPetById<\/code>). \u0412 \u0441\u0442\u0430\u0442\u044c\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d \u043f\u0440\u0438\u043c\u0435\u0440 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043e\u0434\u043d\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 <code>getPetById<\/code><\/p>\n<p><strong>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440:<\/strong><\/p>\n<pre><code class=\"java\">@RestController @RequiredArgsConstructor public class PetController implements PetApi {      private final PetRepository petRepository;          @Override     public ResponseEntity&lt;Pet&gt; getPetById(Long petId) {         return new ResponseEntity&lt;&gt;(petRepository.getPetById(petId), HttpStatus.OK);     }   \/\/\u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b }<\/code><\/pre>\n<p>\u0420\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0431\u044b\u0447\u043d\u044b\u043c \u043b\u0438\u0441\u0442\u043e\u043c \u0441 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u0430.<\/p>\n<p><strong>\u0411\u0430\u0437\u043e\u0432\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0439 \u0430\u0432\u0442\u043e\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438:<\/strong><\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0442\u0435\u0441\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u043f\u0438\u0448\u0435\u0442 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043d\u0430\u0448\u0435\u0439 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438. \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u0447\u0442\u043e \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f, \u044d\u0442\u043e \u0441\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 <code>MockMvc<\/code> (\u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c <a href=\"https:\/\/github.com\/GrinRus\/rest-docs-demo\/blob\/master\/spring-auto-rest-docs\/src\/test\/groovy\/ru\/spring\/auto\/rest\/docs\/demo\/controllers\/MockMvcDocumentSpec.groovy#L37\" rel=\"noopener noreferrer nofollow\">\u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438<\/a>):<\/p>\n<pre><code class=\"java\">@Before void setUp() throws Exception {   this.mockMvc = MockMvcBuilders     .webAppContextSetup(context)     .alwaysDo(prepareJackson(objectMapper, new TypeMapping()))     .alwaysDo(commonDocumentation())     .apply(documentationConfiguration(restDocumentation)            .uris().withScheme(\"http\").withHost(\"localhost\").withPort(8080)            .and()            .snippets().withTemplateFormat(TemplateFormats.asciidoctor())            .withDefaults(curlRequest(), httpRequest(), httpResponse(),                          requestFields(), responseFields(), pathParameters(),                          requestParameters(), description(), methodAndPath(),                          section(), links(), embedded(), authorization(DEFAULT_AUTHORIZATION),                          modelAttribute(requestMappingHandlerAdapter.getArgumentResolvers())))     .build()   }  protected RestDocumentationResultHandler commonDocumentation(Snippet... snippets) {   return document(\"rest-auto-documentation\/{class-name}\/{method-name}\", commonResponsePreprocessor(), snippets)   }  protected OperationResponsePreprocessor commonResponsePreprocessor() {   return preprocessResponse(replaceBinaryContent(), limitJsonArrayLength(objectMapper), prettyPrint())   }<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u0427\u0443\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043f\u0440\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 MockMVC<\/summary>\n<div class=\"spoiler__content\">\n<p><code>WebApplicationContext<\/code> \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043e\u0442 <code><a class=\"mention\" href=\"\/users\/springboottest\">@SpringBootTest<\/a><\/code><\/p>\n<p><code>prepareJackson(objectMapper, new TypeMapping())<\/code> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c <code>ResultHandler<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u0442 \u043d\u0430\u0448\u0438 pojo \u0434\u043b\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f<\/p>\n<p><code>withDefaults(curlRequest(), httpRequest(), \u0438 \u0442.\u0434.)<\/code> \u043d\u0430\u0431\u043e\u0440 \u0441\u043d\u0438\u043f\u043f\u0435\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u044b<\/p>\n<p><code>commonDocumentation()<\/code> \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e, \u043a\u0443\u0434\u0430 \u0432 build \u043f\u0430\u043f\u043a\u0435 \u0440\u0430\u0437\u043c\u0435\u0441\u0442\u044f\u0442\u0441\u044f \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0441\u043d\u0438\u043f\u043f\u0435\u0442\u044b, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u0435\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0438\u043d\u0433 \u043e\u0442\u0432\u0435\u0442\u0430 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430.<\/p>\n<\/div>\n<\/details>\n<p><strong>\u041d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0441\u0430\u043c \u0442\u0435\u0441\u0442:<\/strong><\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0442\u0435\u0441\u0442\u0430 \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c <a href=\"https:\/\/github.com\/GrinRus\/rest-docs-demo\/blob\/master\/spring-auto-rest-docs\/src\/test\/groovy\/ru\/spring\/auto\/rest\/docs\/demo\/controllers\/PetControllerAutoTest.groovy\" rel=\"noopener noreferrer nofollow\">\u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438<\/a>.<\/p>\n<pre><code>@Test void getPetTest() { \/\/given def petId = 1L \/\/when def resultActions = mockMvc \t.perform(RestDocumentationRequestBuilders \t\t.get(\"\/pet\/{petId}\", petId) \t\t.header(\"Accept\", \"application\/json\")) \/\/then resultActions \t.andExpect(status().isOk()) \t.andExpect(content().string(objectMapper.writeValueAsString(buildReturnPet()))) }<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 <code>MockMvc<\/code> \u0442\u0435\u0441\u0442, \u0441 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u043c \u0441\u0442\u0430\u0442\u0443\u0441\u043e\u043c \u0438 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u043c \u0442\u0435\u043b\u043e\u043c \u043e\u0442\u0432\u0435\u0442\u0430.<\/p>\n<p><strong>\u0418\u0442\u043e\u0433\u043e \u043d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435:<\/strong><\/p>\n<p>\u041d\u0430\u0431\u043e\u0440 \u0441\u043d\u0438\u043f\u0435\u0442\u0442\u043e\u0432 \u0441 &#171;\u0433\u043b\u0430\u0432\u043d\u044b\u043c&#187; \u0441\u043d\u0438\u043f\u043f\u0435\u0442\u043e\u043c \u043f\u043e\u0434 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c <code>auto-section.adoc<\/code> (\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0438\u0437 \u0432\u0441\u0435\u0445 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445, \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0445 \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 <code>MockMVC<\/code>) \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043f\u043e\u0437\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u043e\u0431\u0449\u0438\u0439 <code>index.adoc<\/code> \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 API. \u0413\u043e\u0442\u043e\u0432\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0441\u043d\u0438\u043f\u043f\u0435\u0442\u043e\u0432:<\/p>\n<figure class=\"\"><figcaption><\/figcaption><\/figure>\n<p>\u0413\u043e\u0442\u043e\u0432\u044b\u0435 \u0441\u043d\u0438\u043f\u043f\u0435\u0442\u044b \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u044b \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438: <a href=\"https:\/\/github.com\/GrinRus\/rest-docs-demo\/tree\/master\/generated\/spring-auto-rest-docs\/generated-snippets\/rest-auto-documentation\/pet-controller-auto-test\" rel=\"noopener noreferrer nofollow\">\u0441\u043d\u0438\u043f\u043f\u0435\u0442\u044b, <\/a><a href=\"https:\/\/htmlpreview.github.io\/?https:\/\/github.com\/GrinRus\/rest-docs-demo\/blob\/master\/generated\/spring-auto-rest-docs\/generated-snippets\/asciidoc\/index.html\" rel=\"noopener noreferrer nofollow\">html \u0441\u0433\u0435\u043d\u0435\u0440\u0435\u043d\u043d\u044b\u0439 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0441\u043d\u0438\u043f\u043f\u0435\u0442\u043e\u0432<\/a>.<\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043f\u0440\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c \u0448\u0430\u0431\u043b\u043e\u043d\u044b \u043b\u0438\u0431\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u0432\u043e\u0438 \u0441\u043d\u0438\u043f\u043f\u0435\u0442\u044b \u0438 SprinAutoRestDocs \u0438\u0445 \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u0435\u0442 \u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u0442 \u0442\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c, \u0447\u0442\u043e \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u0430. \u0414\u043e\u043a\u0430 \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u0438 <a href=\"https:\/\/scacap.github.io\/spring-auto-restdocs\/#snippets-customization\" rel=\"noopener noreferrer nofollow\">\u0441\u043d\u0438\u043f\u043f\u0435\u0442\u043e\u0432<\/a>, <a href=\"https:\/\/scacap.github.io\/spring-auto-restdocs\/#constraints-custom\" rel=\"noopener noreferrer nofollow\">\u043a\u043e\u043d\u0441\u0442\u0440\u0435\u0439\u043d\u0442\u043e\u0432<\/a>.<\/p>\n<details class=\"spoiler\">\n<summary>\u0427\u0443\u0442\u044c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u0440\u043e \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u044e \u0441\u043d\u0438\u043f\u043f\u0435\u0442\u043e\u0432 \u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439<\/summary>\n<div class=\"spoiler__content\">\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0432 SpringAutoRestDocs \u0431\u0430\u0437\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043d\u0430 \u0442\u0430\u043a\u043e\u0432\u043e\u043c \u0436\u0435 \u0432 SpringRestDocs.<\/p>\n<ul>\n<li>\n<p>\u041d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0430\u0441\u043a\u0435\u0434\u043e\u043a \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432 &#8212; \u0432 \u0440\u0435\u0441\u0443\u0440\u0441\u044b \u0432\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0432 \u043f\u0430\u043f\u043a\u0443 org\/springframework\/restdocs\/templates\/asciidoctor \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u0443\u0436\u043d\u044b\u0439 \u0432\u0430\u043c \u0441\u043d\u0438\u043f\u043f\u0435\u0442 \u0431\u0435\u0437 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0438 <code>default-<\/code><a href=\"https:\/\/github.com\/ScaCap\/spring-auto-restdocs\/tree\/master\/spring-auto-restdocs-core\/src\/main\/resources\/org\/springframework\/restdocs\/templates\/asciidoctor\" rel=\"noopener noreferrer nofollow\">\u0421\u043f\u0438\u0441\u043e\u043a \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0445 \u0430\u0441\u043a\u0435\u0434\u043e\u043a \u0441\u043d\u0438\u043f\u043f\u0435\u0442\u043e\u0432.<\/a><\/p>\n<\/li>\n<li>\n<p>\u041d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439 &#8212; \u0432 \u0440\u0435\u0441\u0443\u0440\u0441\u044b \u0432\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0432 \u043f\u0430\u043f\u043a\u0443 org\/springframework\/restdocs\/constraints \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0444\u0430\u0439\u043b <code>DefaultConstraintDescriptions.properties<\/code> \u0441 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c \u0441\u043f\u0438\u0441\u043a\u043e\u043c \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439 <a href=\"https:\/\/github.com\/spring-projects\/spring-restdocs\/blob\/main\/spring-restdocs-core\/src\/main\/resources\/org\/springframework\/restdocs\/constraints\/DefaultConstraintDescriptions.properties\" rel=\"noopener noreferrer nofollow\">\u0421\u043f\u0438\u0441\u043e\u043a \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0445 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439 \u0438 \u0438\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f<\/a>.<\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/details>\n<p>\u041a \u043f\u0440\u0438\u043c\u0435\u0440\u0443 <a href=\"https:\/\/github.com\/GrinRus\/rest-docs-demo\/tree\/master\/spring-auto-rest-docs\/src\/test\/resources\/org\/springframework\/restdocs\" rel=\"noopener noreferrer nofollow\">\u0440\u0443\u0441\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u0448\u0430\u043f\u043e\u043a \u0441\u043d\u0438\u043f\u043f\u0435\u0442\u043e\u0432 \u0438 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439:<\/a><\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<h2>ApiFirst \u043f\u043b\u044e\u0441 Swagger<\/h2>\n<p>\u041a\u0430\u043a \u0443\u0436\u0435 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u043b\u043e\u0441\u044c \u0432\u043e \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0435 \u0441\u0442\u0430\u0442\u0435\u0439 (<a href=\"https:\/\/habr.com\/ru\/post\/434798\/\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u0438\u043c\u0435\u04401<\/a>, <a href=\"https:\/\/habr.com\/ru\/post\/541592\/\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u0438\u043c\u0435\u04402<\/a>) swagger &#8212; \u044d\u0442\u043e open-source \u043f\u0440\u043e\u0435\u043a\u0442, \u0432\u043a\u043b\u044e\u0447\u0430\u044e\u0449\u0438\u0439 OpenApi Specification \u0438 \u0448\u0438\u0440\u043e\u043a\u0438\u0439 \u043d\u0430\u0431\u043e\u0440 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f, \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f REST api.<\/p>\n<details class=\"spoiler\">\n<summary>\u0427\u0443\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043f\u0440\u043e Swagger<\/summary>\n<div class=\"spoiler__content\">\n<p>Swagger \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0434\u0432\u0443\u0445 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u0447\u0430\u0441\u0442\u0435\u0439 &#8212; \u044d\u0442\u043e OpenApi Specification \u0438 Swagger Tools.<\/p>\n<ul>\n<li>\n<p>OpenApi Specification &#8212; \u044d\u0442\u043e \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0449\u0430\u044f \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f REST \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u0430 \u0434\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u044f API. \u0421\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u043f\u0438\u0441\u0430\u043d\u0430 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 YAML \u0438 JSON. \u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u0430, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043c\u043e\u0436\u043d\u043e \u0438\u0437\u0443\u0447\u0438\u0442\u044c \u043f\u043e <a href=\"https:\/\/swagger.io\/docs\/specification\/basic-structure\/\" rel=\"noopener noreferrer nofollow\">\u0441\u0441\u044b\u043b\u043a\u0435<\/a>.<\/p>\n<\/li>\n<li>\n<p>Swagger Tools &#8212; \u044d\u0442\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0438 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u043d\u043e-\u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 REST api. \u0421\u043e\u0441\u0442\u043e\u044f\u0442 \u0438\u0437 \u0442\u0440\u0435\u0445 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u0431\u043b\u043e\u043a\u043e\u0432: <a href=\"http:\/\/editor.swagger.io\/\" rel=\"noopener noreferrer nofollow\">Swagger Editor<\/a>(\u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043d\u044b\u0439 \u044d\u0434\u0438\u0442\u043e\u0440, \u0434\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u0443\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u0430 \u0441 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u043e\u0439 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u0441\u0438\u0442\u0430\u043a\u0441\u0438\u0441\u0430),  <a href=\"https:\/\/swagger.io\/swagger-ui\/\" rel=\"noopener noreferrer nofollow\">Swagger UI<\/a>(\u0440\u0435\u043d\u0434\u0435\u0440 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 API), <a href=\"https:\/\/github.com\/swagger-api\/swagger-codegen\" rel=\"noopener noreferrer nofollow\">Swagger Codegen<\/a>(\u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e-\u043a\u043b\u0438\u0435\u043d\u0442\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0442\u0438\u043f\u043e\u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0439)<\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/details>\n<p>\u041d\u0438\u0436\u0435 \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043c\u0443\u043b\u044c\u0442\u0438-\u043c\u043e\u0434\u0443\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0441\u043e \u0441\u043b\u0435\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043e\u0439: \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0441\u043e \u0441\u0432\u0430\u0433\u0435\u0440 \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u043c (<a href=\"https:\/\/github.com\/GrinRus\/rest-docs-demo\/tree\/master\/swagger-library\" rel=\"noopener noreferrer nofollow\">swagger-library<\/a>), \u0441\u0442\u0430\u0440\u0442\u0435\u0440 \u0441 swagger-ui(<a href=\"https:\/\/github.com\/GrinRus\/rest-docs-demo\/tree\/master\/swagger-webjar-ui-starter\" rel=\"noopener noreferrer nofollow\">swagger-webjar-ui-starter<\/a>), \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u0435\u0442 \u043a\u043b\u0430\u0441\u0441\u044b \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438(<a href=\"https:\/\/github.com\/GrinRus\/rest-docs-demo\/tree\/master\/spring-auto-rest-docs\" rel=\"noopener noreferrer nofollow\">spring-auto-rest-docs<\/a>).<\/p>\n<figure class=\"\"><figcaption><\/figcaption><\/figure>\n<p>\u0414\u043b\u044f \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 Swagger \u0432\u043e\u0437\u044c\u043c\u0435\u043c \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0439 <a href=\"https:\/\/petstore.swagger.io\/\" rel=\"noopener noreferrer nofollow\">Swagger PetStore<\/a> \u0438\u0437 \u043f\u0440\u0438\u043c\u0435\u0440\u0430 SpringAutoRestDocs \u0432\u044b\u0448\u0435.<\/p>\n<p><strong>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 build.gradle \u0434\u043b\u044f \u043c\u043e\u0434\u0443\u043b\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438:<\/strong><\/p>\n<p>\u0414\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 server stub \u0438 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 Swagger \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <a href=\"https:\/\/github.com\/OpenAPITools\/openapi-generator\" rel=\"noopener noreferrer nofollow\">OpenApi Generator<\/a>.<\/p>\n<details class=\"spoiler\">\n<summary>\u0427\u0443\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043f\u0440\u043e OpenApi Generator<\/summary>\n<div class=\"spoiler__content\">\n<p>\u0412 \u043c\u043e\u0434\u0443\u043b\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f gradle \u043f\u043b\u044e\u0441 <a href=\"https:\/\/github.com\/OpenAPITools\/openapi-generator\/tree\/master\/modules\/openapi-generator-gradle-plugin\" rel=\"noopener noreferrer nofollow\">gradle plugin OpenApi Generator<\/a>.<\/p>\n<p>\u0421\u0430\u043c \u043f\u043b\u0430\u0433\u0438\u043d \u0434\u0430\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0433\u0435\u043d\u0435\u0440\u0438\u0442\u044c \u043a\u0430\u043a \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e-\u043a\u043b\u0438\u0435\u043d\u0442\u043d\u0443\u044e \u0447\u0430\u0441\u0442\u044c, \u0442\u0430\u043a \u0438 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u044b \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438. \u0411\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 <a href=\"https:\/\/github.com\/OpenAPITools\/openapi-generator\" rel=\"noopener noreferrer nofollow\">\u0441\u0441\u044b\u043b\u043a\u0435 \u043d\u0430 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439<\/a>.<\/p>\n<\/div>\n<\/details>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0442\u0430\u0441\u043a\u0430 \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438 \u0435\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438:<\/p>\n<pre><code>openApiGenerate {     generatorName = 'spring'     inputSpec = specFile     outputDir = \"${project.projectDir}\/\"     id = \"${artifactId}\"     groupId = projectPackage     ignoreFileOverride = ignoreFile     apiPackage = \"${projectPackage}.rest.api\"     invokerPackage = \"${projectPackage}.rest.invoker\"     modelPackage = \"${projectPackage}.rest.model\"     configOptions = [             dateLibrary            : 'java8',             hideGenerationTimestamp: 'true',             interfaceOnly          : 'true',             delegatePattern        : 'false',             configPackage          : \"${projectPackage}.configuration\"     ] }<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u0427\u0443\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043f\u0440\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0442\u0430\u0441\u043a\u0438 openApiGenerate<\/summary>\n<div class=\"spoiler__content\">\n<ul>\n<li>\n<p>generatorName &#8212; \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043e\u0441\u043d\u043e\u0432\u044b \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <\/p>\n<\/li>\n<li>\n<p>Spring (<a href=\"https:\/\/github.com\/OpenAPITools\/openapi-generator\/blob\/master\/docs\/generators\/spring.md\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u043e\u043f\u0435\u0440\u0442\u0438 \u0434\u043b\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440\u0430 spring<\/a>)<\/p>\n<\/li>\n<li>\n<p>dateLibrary &#8212; \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0448\u0430\u0431\u043b\u043e\u043d \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 \u0432 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0434\u0430\u0442\u043e\u0439 (joda, JSR-310 \u0438 \u0442.\u0434.)<\/p>\n<\/li>\n<li>\n<p>\u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c <a href=\"https:\/\/github.com\/OpenAPITools\/openapi-generator\/blob\/master\/docs\/global-properties.md\" rel=\"noopener noreferrer nofollow\">\u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u043e\u043f\u0435\u0440\u0442\u0438 \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440\u0430<\/a>, \u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u044f\u0449\u0438\u0435 \u043e\u0442 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438<\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/details>\n<p>\u041d\u0435\u0437\u0430\u0431\u044b\u0432\u0430\u0435\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044e \u043a\u043e\u0434\u0430 \u0434\u043e \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430:<\/p>\n<pre><code>task codegen(dependsOn: ['openApiGenerate', 'copySpecs'])  compileJava.dependsOn(codegen) compileJava.mustRunAfter(codegen)<\/code><\/pre>\n<p>\u041a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u0441\u043f\u0435\u043a\u0438 \u0432 \u0440\u0435\u0441\u0443\u0440\u0441\u044b, \u0447\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u0430 \u043f\u043e\u0437\u0436\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u044c UI \u043f\u0440\u044f\u043c\u043e \u0438\u0437 \u0441\u043f\u0435\u043a:<\/p>\n<pre><code>task copySpecs(type: Copy) {     from(\"${project.projectDir}\/specs\")     into(\"${project.projectDir}\/src\/main\/resources\/META-INF\/specs\") }<\/code><\/pre>\n<p>\u041f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0442\u044c <a href=\"https:\/\/github.com\/GrinRus\/rest-docs-demo\/blob\/master\/swagger-library\/build.gradle#L51\" rel=\"noopener noreferrer nofollow\">Asciidoc<\/a> \u0438\u043b\u0438 <a href=\"https:\/\/github.com\/GrinRus\/rest-docs-demo\/blob\/master\/swagger-library\/build.gradle#L62\" rel=\"noopener noreferrer nofollow\">Html2<\/a>.<\/p>\n<p><strong>Swagger-ui \u0441\u0442\u0430\u0440\u0442\u0435\u0440:<\/strong><\/p>\n<p>\u0421\u0442\u0430\u0440\u0442\u0435\u0440 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u0432 \u0440\u0435\u0433\u0438\u0441\u0442\u0440 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u0441\u043f\u0435\u043a\u0438 \u0441 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c\u0438 \u0432 <a href=\"https:\/\/github.com\/GrinRus\/rest-docs-demo\/blob\/master\/swagger-webjar-ui-starter\/src\/main\/java\/ru\/ryabov\/swagger\/webjar\/ui\/autoconfiguration\/SwaggerProperties.java#L13\" rel=\"noopener noreferrer nofollow\">\u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u043c\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438 <\/a>\u0438 webjar swagger-ui \u0441 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u043d\u044b\u043c \u043f\u0443\u0442\u0435\u043c \u0434\u043e \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u0430.<\/p>\n<p><strong>Rest-docs API:<\/strong><\/p>\n<p>\u0412 \u0441\u0430\u043c\u043e\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e <a href=\"https:\/\/github.com\/GrinRus\/rest-docs-demo\/blob\/master\/spring-auto-rest-docs\/src\/main\/java\/ru\/spring\/auto\/rest\/docs\/demo\/controllers\/PetController.java\" rel=\"noopener noreferrer nofollow\">\u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441<\/a> \u0438 <a href=\"https:\/\/github.com\/GrinRus\/rest-docs-demo\/blob\/master\/spring-auto-rest-docs\/src\/main\/resources\/config\/application.yml#L3-L10\" rel=\"noopener noreferrer nofollow\">\u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 UI \u0441\u0442\u0430\u0440\u0442\u0435\u0440\u0430<\/a>:<\/p>\n<pre><code>@RestController @RestController @RequiredArgsConstructor public class PetController implements PetApi {      private final PetRepository petRepository;          @Override     public ResponseEntity&lt;Pet&gt; getPetById(Long petId) {         return new<\/code><\/pre>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-322785","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/322785","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=322785"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/322785\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=322785"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=322785"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=322785"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}