ããã«ã¡ã¯ãREST APIã®ããã¥ã¡ã³ãåã®ãããã¯ã«è§ŠããããšæããŸãã ãã®è³æã¯ããã«äºçŽãå
¥ããSpringãšã³ã·ã¹ãã ã§åããšã³ãžãã¢ã«çŠç¹ãåœãŠãŸãã
ããã€ãã®æè¿ã®ãããžã§ã¯ãã§ã¯ãSpringRestDocsãã¬ãŒã ã¯ãŒã¯ã䜿çšããŸããããããŒããã©ãªãªã§æ£åžžã«ä¿®æ£ãããããã䜿ãå§ããç¥äººã«ãèŠããããŸããããããŠããã®æ©èœãšå©ç¹ã«ã€ããŠã®èšäºã§å
±æããããšæããŸãã ãã®èšäºã¯ãSpringRestDocsã®äœ¿çšæ¹æ³ãç解ãã䜿çšãéå§ããã®ã«åœ¹ç«ã¡ãŸãã
ãã®ããŒã«ã«æ
£ããç¬éãããç§ã¯åŸ
ã¡æãã§ãããœãªã¥ãŒã·ã§ã³ããããéçºã§ã¯äžååã§ããããšã«æ°ä»ããŸããã èªåã§å€æããŠãã ãã-ããªãã¯ããã«ã€ããŠã®ã¿å€¢ãèŠãããšãã§ããŸãïŒ
- ããã¥ã¡ã³ãã¯ããã¹ãã®å®è¡æã«èªåçã«çæãããŸãã
- ããã¥ã¡ã³ããã¡ã€ã«ã®ãœãŒã¹åœ¢åŒãå¶åŸ¡ã§ããŸããããšãã°ãhtmlãã³ã³ãã€ã«ããŸãã SpringããŒãã䜿çšãããããgradleã§æé ãšã¿ã¹ã¯ãå€æŽããããã¥ã¡ã³ããã¡ã€ã«ãã³ããŒããŠjarã«å«ãããªã¢ãŒããµãŒããŒã§ããã¥ã¡ã³ãããã¥ã¡ã³ããäœæããããã¥ã¡ã³ããã¢ãŒã«ã€ãã«ã³ããŒã§ããŸãã ãããã£ãŠããµãŒãã¹ããããã€ãããŠããå Žæã«ã¯åžžã«ãããã¥ã¡ã³ããåããéçãšã³ããã€ã³ãããããŸãã ãªãã©ã€ã³ããŒãžã§ã³ã®å Žåãpdfãepubãabookã®ã¢ã¯ã»ã¹èš±å¯ãæ¥ç¶ã§ããŸãã
- RESTãµãŒãã¹ã®ããã¥ã¡ã³ãã¯ãäœæ¥ããžãã¯ã«å¯Ÿå¿ããããšãä¿èšŒãããŠããŸãã ããã¥ã¡ã³ãã¯ãã¢ããªã±ãŒã·ã§ã³ããžãã¯ãšåæãããŸãã å€æŽãå ããããããããã¥ã¡ã³ãã«åæ ããã®ãå¿ããŠããŸãã-ããã«ãéæºæ ã®éãã®è©³çŽ°ãªèª¬æãšãšãã«èœäžãã¹ãã衚瀺ãããŸãã
- ããã¥ã¡ã³ãã¯ãã¹ãããçæãããŸãã ããã§ãããã¥ã¡ã³ãã«æ°ããã»ã¯ã·ã§ã³ãè¿œå ããããããã¥ã¡ã³ãã®å®è¡ãéå§ãããããã«ã¯ããã¹ããäœæããããšããå§ããŸãïŒã¯ãããã¹ãïŒã å®éãéåžžã«å€ãã®å Žåãéçºè
ã¯æéã®äžè¶³ããããžã§ã¯ãã®æªé
ä¿¡ããã»ã¹ããŸãã¯ãã®ä»ã®çç±ã§å€§éã®ã³ãŒããèšè¿°ããŸããããã¹ãã®éèŠæ§ã«æ³šæãæããŸããã å¥åŠãªããšã«ãããã¥ã¡ã³ããã¬ãŒã ã¯ãŒã¯ã¯TDDã§ã®äœæ¥ã奚å±ããŠããŸã
- ãã®çµæãã«ãã¬ããžãé«ãä¿ã¡ãŸãã ããæ£ç¢ºã«ã¯ãéèŠãªã®ã¯ã³ãŒãåæã·ã¹ãã ãã¬ããŒãã«æãããã«ãã¬ããžã®å²åã§ã¯ãããŸããã ããŸããŸãªã·ããªãªãåå¥ã®ãã¹ãã§ã«ããŒãããã®çµæãããã¥ã¡ã³ãã«å«ããããšãéèŠã§ãã ã°ãªãŒã³ãã¹ãã¯åžžã«æ¥œãã¿ã§ãã
SpringRestDocsã®äœæ¥ãç解ããŠã¿ãŸãããããã¬ãŒã ã¯ãŒã¯ãæ§æããŠäœ¿çšã§ãããã®ãèªãã åŸããã®è³æãçè«äžã®ã€ã³ã»ãããšçµã¿åããããã¥ãŒããªã¢ã«ã®å®çšçãªã©ã€ã³ãã¬ã€ãããŸãã
SpringRestDocsãã€ãã©ã€ã³
SpringRestDocsã§ã®äœæ¥ãéå§ããã«ã¯ããã®ãã€ãã©ã€ã³ã®åçãç解ããå¿
èŠããããŸããããã¯éåžžã«ã·ã³ãã«ã§ç·åœ¢ã§ãã
ãªãœãŒã¹æ€èšŒã®ããžãã¯ãé€ãããã¹ãŠã®ã¢ã¯ã·ã§ã³ã¯ãã¹ãããååŸãããã¹ãããããçæãããŸãã ã¹ããããã¯ãã³ã³ãããŒã©ãŒã察話ããç¹å®ã®HTTPå±æ§ã®ã·ãªã¢ã«åãããå€ã§ãã çæãããã¹ãããããå«ããã»ã¯ã·ã§ã³ã瀺ãç¹å¥ãªãã³ãã¬ãŒããã¡ã€ã«ãæºåããŠããŸãã åºåã¯ã³ã³ãã€ã«ãããããã¥ã¡ã³ããã¡ã€ã«ã§ããããã¥ã¡ã³ã圢åŒãèšå®ã§ããããšã«æ³šæããŠãã ããã圢åŒã¯htmlãpdfãepubãabookã§ãã
ããã«èšäºã®ããã¹ãã«æ²¿ã£ãŠããã®ãã€ãã©ã€ã³ãåéãããã¹ããäœæããSpringRestDocsãæ§æããããã¥ã¡ã³ããã³ã³ãã€ã«ããŸãã
äŸåé¢ä¿
以äžã¯ãã¹ããªã³ã°ã¬ã¹ãããã¥ã¡ã³ããæäœãããããžã§ã¯ãã®äŸåé¢ä¿ã§ãããã®äŸã§ã¯ãäœæ¥ãåæããŸãã
dependencies { compile "org.springframework.boot:spring-boot-starter-data-jpa" compile "org.springframework.boot:spring-boot-starter-hateoas" compile "org.springframework.boot:spring-boot-starter-web" compile "org.springframework.restdocs:spring-restdocs-core:$restdocsVersion" compile "com.h2database:h2:$h2Version" compile "org.projectlombok:lombok" testCompile "org.springframework.boot:spring-boot-starter-test" asciidoctor "org.springframework.restdocs:spring-restdocs-asciidoctor:$restdocsVersion" testCompile "org.springframework.restdocs:spring-restdocs-mockmvc:$restdocsVersion" testCompile "com.jayway.jsonpath:json-path" }
ãã¹ãå¯èœãªã³ã³ãããŒã©ãŒ
ãã¹ããèšè¿°ããSpringRestDocsãæ¥ç¶ããããã¥ã¡ã³ããçæããã³ã³ãããŒã©ãŒã®äžéšã瀺ããŸãã
@RestController @RequestMapping("/speakers") public class SpeakerController { @Autowired private SpeakerRepository speakerRepository; @GetMapping(path = "/{id}") public ResponseEntity<SpeakerResource> getSpeaker(@PathVariable long id) { return speakerRepository.findOne(id) .map(speaker -> ResponseEntity.ok(new SpeakerResource(speaker))) .orElse(new ResponseEntity(HttpStatus.NOT_FOUND)); }
ãã®ããžãã¯ãèŠãŠã¿ãŸãããã SpringDataRepositoryã®å©ããåããŠãã³ã³ãããŒã©ãŒã«æž¡ãããIDãæã€ã¬ã³ãŒãã®ããŒã¿ããŒã¹ã«ã¢ã¯ã»ã¹ããŸãã SpringDataRepositoryã¯Optionalãè¿ããŸã-å€ãããå ŽåãJPAãšã³ãã£ãã£ããªãœãŒã¹ã«å€æããŸãïŒåæã«ãå¿çã«è¡šç€ºããããªããã£ãŒã«ãã®äžéšãã«ãã»ã«åã§ããŸãïŒãOptional.isEmptyïŒïŒã®å Žåã404 NOT_FOUNDã³ãŒããè¿ããŸãã
SpeakerResourceãªãœãŒã¹ã³ãŒã
@NoArgsConstructor @AllArgsConstructor @Getter @Relation(value = "speaker", collectionRelation = "speakers") public class SpeakerResource extends ResourceSupport { private String name; private String company; public SpeakerResource(Speaker speaker) { this.name = speaker.getName(); this.company = speaker.getCompany(); add(linkTo(methodOn(SpeakerController.class).getSpeaker(speaker.getId())).withSelfRel()); add(linkTo(methodOn(SpeakerController.class).getSpeakerTopics(speaker.getId())).withRel("topics")); } }
ãã®ãšã³ããã€ã³ãã®åºæ¬çãªãã¹ããæžããŸãããã
@RunWith(SpringRunner.class) @SpringBootTest @AutoConfigureMockMvc @AutoConfigureRestDocs(outputDir = "build/generated-snippets") public class SpControllerTest { @Autowired private MockMvc mockMvc; @Autowired private SpeakerRepository speakerRepository; @After public void tearDown() { speakerRepository.deleteAll(); } @Test public void testGetSpeaker() throws Exception {
ãã¹ãã§ã¯ãèªåæ§æmockMVCãRestDocsãæ¥ç¶ããŸãã restdocsã®å Žåãã¹ãããããçæããããã£ã¬ã¯ããª
ïŒoutputDir = "buid / generated-snippets"ïŒãæå®ããå¿
èŠããããŸããããã¯ãmockMvcã䜿çšããéåžžã®ãã¹ãã§ãã spring.tests mockMvc Dependenceã®ç¬èªã®ã©ã€ãã©ãªã䜿çšããŸãããRestAssuredã䜿çšããå Žåã¯ãèªããã®ããã¹ãŠé¢é£ããŸããããããªå€æŽã®ã¿ããããŸãã ç§ã®ãã¹ãã§ã¯ãã³ã³ãããŒã©ãŒã®HTTPã¡ãœãããåŒã³åºããŠãã¹ããŒã¿ã¹ããã£ãŒã«ãã確èªããèŠæ±/å¿çãããŒãã³ã³ãœãŒã«ã«åºåããŸãã
ResultsHandler
åºåã§ãã¹ããå®è¡ãããšã次ã®ããã«è¡šç€ºãããŸãã
MockHttpServletRequest: HTTP Method = GET Request URI = /speakers/1 Parameters = {} Headers = {} Handler: Type = smartjava.domain.speaker.SpeakerController Method = public org.springframework.http.ResponseEntity<smartjava.domain.speaker.SpeakerResource> smartjava.domain.speaker.SpeakerController.getSpeaker(long) Async: Async started = false Async result = null Resolved Exception: Type = null ModelAndView: View name = null View = null Model = null FlashMap: Attributes = null MockHttpServletResponse: Status = 200 Error message = null Headers = {Content-Type=[application/hal+json;charset=UTF-8]} Content type = application/hal+json;charset=UTF-8 Body = { "name" : "Roman", "company" : "Lohika", "_links" : { "self" : { "href" : "http://localhost:8080/speakers/1" }, "topics" : { "href" : "http://localhost:8080/speakers/1/topics" } } }
ããã¯ãHTTPèŠæ±ããã³å¿çã³ã³ãã³ãã®ã³ã³ãœãŒã«ãžã®åºåã§ãã ãããã£ãŠãã³ã³ãããŒã©ãŒã«éä¿¡ãããå€ãšãã³ã³ãããŒã©ãŒããã®å¿çã远跡ã§ããŸãã ã³ã³ãœãŒã«ãžã®åºåã¯ãæ¥ç¶ããããã³ãã©ãŒã«ãã£ãŠå®è¡ãããŸãã
resultActions.andDo(print());
ResultHandlerã¯æ©èœçãªã€ã³ã¿ãŒãã§ãŒã¹ã§ãã ç¬èªã®å®è£
ãäœæããŠãã¹ãã§æ¥ç¶ãããšããã¹ãã§å®è¡ãããHttpRequest / HttpResponseã«ã¢ã¯ã»ã¹ããå®è¡çµæã解éã§ããŸãïŒã³ã³ãœãŒã«ããã¡ã€ã«ã·ã¹ãã ãç¬èªã®ããã¥ã¡ã³ããã¡ã€ã«ãªã©ã«ãããã®å€ãèšé²ããå ŽåïŒã
public interface ResultHandler { void handle(MvcResult result) throws Exception; }
Mvcresult
ã芧ã®ãšãããResultHandlerã¯MvcResultã®å€ã«ã¢ã¯ã»ã¹ããŠè§£éããããšãã§ããŸããããã¯ãmockMvcãã¹ãã®çµæãå«ããªããžã§ã¯ãã§ãããMockHttpServletRequestãMockHttpServletResponseã®2ã€ã®ããŒãã¬ãŒã€ãŒã®å±æ§ã«ã¢ã¯ã»ã¹ã§ããŸãã ãããã®å±æ§ã®ãªã¹ãã®äžéšã次ã«ç€ºããŸãã
次ã«ãåŒã³åºãããHTTPã¡ãœããã®ã¿ã€ããšå¿çã³ãŒãã®ã¹ããŒã¿ã¹ãèšé²ããMyResultHandlerã®äŸã瀺ããŸãã
public class MyResultHandler implements ResultHandler { private Logger logger = LoggerFactory.getLogger(MyResultHandler.class); static public ResultHandler myHandler() { return new MyResultHandler(); } @Override public void handle(MvcResult result) throws Exception { MockHttpServletRequest request = result.getRequest(); MockHttpServletResponse response = result.getResponse(); logger.error("HTTP method: {}, status code: {}", request.getMethod(), response.getStatus()); } }
resultActions.andDo(new MyResultHandler())
Pivotalãããã¥ã¡ã³ãã®çæã«äœ¿çšããã®ã¯ãåŠçãšç»é²ã«é¢ãããã®èãæ¹ã§ãã ãã¹ãã§ã¯ãMockMvcRestDocumentationã¯ã©ã¹ã®ãã³ãã©ãŒãæ¥ç¶ããå¿
èŠããããŸãã
ã¹ãããããçæããŸããã
ãã¹ããå床å®è¡ããå®è¡åŸããã¡ã€ã«ãå«ããã©ã«ããŒã
build / generated-snippetsãã£ã¬ã¯ããªãŒã«äœæãããããšã«æ³šæããŠãã ããã
./sp-controller-test/test-get-speaker: total 48 -rw-r--r-- 1 rtsypuk staff 68B Oct 31 14:17 curl-request.adoc -rw-r--r-- 1 rtsypuk staff 87B Oct 31 14:17 http-request.adoc -rw-r--r-- 1 rtsypuk staff 345B Oct 31 14:17 http-response.adoc -rw-r--r-- 1 rtsypuk staff 69B Oct 31 14:17 httpie-request.adoc -rw-r--r-- 1 rtsypuk staff 36B Oct 31 14:17 request-body.adoc -rw-r--r-- 1 rtsypuk staff 254B Oct 31 14:17 response-body.adoc
ãããã¯çæãããã¹ããããã§ãã ããã©ã«ãã§ã¯ãrest docsã¯6çš®é¡ã®ã¹ãããããçæããŸããããã®ãã¡ã®ããã€ãã瀺ããŸãã
ã¹ããããã¯ãããã¹ã圢åŒã®ãã¡ã€ã«ã«ã·ãªã¢ã«åãããHTTPèŠæ±/å¿çã³ã³ããŒãã³ãã®äžéšã§ãã æãäžè¬çã«äœ¿çšãããã¹ããããã¯ãcurl-requestãhttp-requestãhttp-responseãrequest-bodyãresponse-bodyããªã³ã¯ïŒHATEOASãµãŒãã¹ã®å ŽåïŒããã¹ãã©ã¡ãŒã¿ãŒãå¿çãã£ãŒã«ããããããŒã§ãã
curl-request.adoc
[source,bash] ---- $ curl 'http://localhost:8080/speakers/1' -i ----
http-request.adoc
[source,bash] [source,http,options="nowrap"] ---- GET /speakers/1 HTTP/1.1 Host: localhost:8080 ----
http-response.adoc
[source,bash] [source,http,options="nowrap"] ---- HTTP/1.1 200 OK Content-Type: application/hal+json;charset=UTF-8 Content-Length: 218 { "name" : "Roman", "company" : "Lohika", "_links" : { "self" : { "href" : "http://localhost:8080/speakers/1" }, "topics" : { "href" : "http://localhost:8080/speakers/1/topics" } } } ----
ãã³ãã¬ãŒããã¡ã€ã«ã®æºå
次ã«ããã³ãã¬ãŒããã¡ã€ã«ãæºåããçæãããã¹ãããããããã¯ãå«ãŸããã»ã¯ã·ã§ã³ãããŒã¯ããå¿
èŠããããŸãã ãã³ãã¬ãŒãã¯æè»ãªasciidoc圢åŒã§ç¶æãããŸããããã©ã«ãã§ã¯ããã³ãã¬ãŒãã¯
src / docs / asciidocãã£ã¬ã¯ããªã«ãããŸãã
== Rest convention include::etc/rest_conv.adoc[] == Endpoints === Speaker ==== Get speaker by ID ===== Curl example include::{snippets}/sp-controller-test/test-get-speaker/curl-request.adoc[] ===== HTTP Request include::{snippets}/sp-controller-test/test-get-speaker/http-request.adoc[] ===== HTTP Response ====== Success HTTP responses include::{snippets}/sp-controller-test/test-get-speaker/http-response.adoc[] ====== Response fields include::{snippets}/sp-controller-test/test-get-speaker/response-fields.adoc[] ====== HATEOAS links include::{snippets}/sp-controller-test/test-get-speaker/links.adoc[]
asciidocæ§æã䜿çšããŠãéçãã¡ã€ã«ïŒããšãã°ãrest_conv.adocãã¡ã€ã«ã§ããµãŒãã¹ããµããŒãããã¡ãœããã®èª¬æãäœæããŸããããã®å Žåãã©ã®ã¹ããŒã¿ã¹ã³ãŒããè¿ãå¿
èŠããããŸãïŒãããã³èªåçæãããã¹ãããããã¡ã€ã«ãæ·»ä»ã§ããŸãã
éçrest_conv.adoc
=== HTTP verbs Speakers Service tries to adhere as closely as possible to standard HTTP and REST conventions in its use of HTTP verbs. |=== | Verb | Usage | `GET` | Used to retrieve a resource | `POST` | Used to create a new resource | `PATCH` | Used to update an existing resource, including partial updates | `PUT` | Used to update an existing resource, full updates only | `DELETE` | Used to delete an existing resource |=== === HTTP status codes Speakers Service tries to adhere as closely as possible to standard HTTP and REST conventions in its use of HTTP status codes. |=== | Status code | Usage | `200 OK` | Standard response for successful HTTP requests. The actual response will depend on the request method used. In a GET request, the response will contain an entity corresponding to the requested resource. In a POST request, the response will contain an entity describing or containing the result of the action. | `201 Created` | The request has been fulfilled and resulted in a new resource being created. | `204 No Content` | The server successfully processed the request, but is not returning any content. | `400 Bad Request` | The server cannot or will not process the request due to something that is perceived to be a client error (eg, malformed request syntax, invalid request message framing, or deceptive request routing). | `404 Not Found` | The requested resource could not be found but may be available again in the future. Subsequent requests by the client are permissible. | `409 Conflict` | The request could not be completed due to a conflict with the current state of the target resource. | `422 Unprocessable Entity` | Validation error has happened due to processing the posted entity. |===
build.gradleãæ§æãã
ããã¥ã¡ã³ããã³ã³ãã€ã«ããã«ã¯ãåºæ¬çãªã»ããã¢ãããè¡ãå¿
èŠããããŸã-å¿
èŠãªäŸåé¢ä¿ãæ¥ç¶ããasciidoctor-gradle-pluginãgradle.build buildscript.dependenciesã«è¿œå ããå¿
èŠããããŸã
buildscript { repositories { jcenter() mavenCentral() mavenLocal() maven { url "https://plugins.gradle.org/m2/" } } dependencies { classpath "org.asciidoctor:asciidoctor-gradle-plugin:$asciiDoctorPluginVersion" classpath "org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion" } }
ãã©ã°ã€ã³ãé©çšãã
apply plugin: 'org.asciidoctor.convert'
次ã«ãåºæ¬çãªasciidoctoræ§æãäœæããå¿
èŠããããŸãã
asciidoctor { dependsOn test backends = ['html5'] options doctype: 'book' attributes = [ 'source-highlighter': 'highlightjs', 'imagesdir' : './images', 'toc' : 'left', 'toclevels' : 3, 'numbered' : '', 'icons' : 'font', 'setanchors' : '', 'idprefix' : '', 'idseparator' : '-', 'docinfo1' : '', 'safe-mode-unsafe' : '', 'allow-uri-read' : '', 'snippets' : snippetsDir, linkattrs : true, encoding : 'utf-8' ] inputs.dir snippetsDir outputDir "build/asciidoc" sourceDir 'src/docs/asciidoc' sources { include 'index.adoc' } }
ããã¥ã¡ã³ãã¢ã»ã³ããªã確èªããŠãã³ã³ãœãŒã«ã§å®è¡ããŸããã
gradle asciidoctor
asciidoctorã¿ã¹ã¯ã¯ãã¹ãã®å®è¡ã«äŸåããããšã瀺ãããããæåã«ãã¹ãããã¬ãŒã¯ã¹ã«ãŒããã¹ãããããçæãããããã®ã¹ãããããçæãããããã¥ã¡ã³ãã«å«ãŸããŸãã
ããã¥ã¡ã³ã
説æãããã¹ãŠã®æ§ææé ã¯ããããžã§ã¯ããäžãããšãã«äžåºŠå®è¡ããå¿
èŠããããŸãã ããã§ããã¹ããå®è¡ãããã³ã«ãã¹ãããããšããã¥ã¡ã³ããè¿œå ã§çæãããŸãã ç§ã¯ããã€ãã®ã¹ã¯ãªãŒã³ã·ã§ããããããããŸãïŒ
HTTPã¡ãœãããšã¹ããŒã¿ã¹ã³ãŒãã«é¢ããå¥çŽã»ã¯ã·ã§ã³
ãã¹ãŠã®ã¹ããŒã«ãŒã¡ãœããããã¥ã¡ã³ãã®äŸã®ååŸ
åäžã®ããã¥ã¡ã³ããPDF圢åŒã§å
¥æã§ããŸãã ãªãã©ã€ã³ããŒãžã§ã³ãšããŠäŸ¿å©ã§ããµãŒãã¹ã®ä»æ§ãšãšãã«é¡§å®¢ã«éä¿¡ã§ããŸãã
jarã¿ã¹ã¯ã®å€æŽ
ããŠãã¹ããªã³ã°ããŒãã§äœæ¥ããŠããã®ã§ãèå³æ·±ãããããã£ã®1ã€ã䜿çšã§ããŸã
-src / staticãã£ã¬ã¯ããªãŸãã¯
src / publicã«ãããã¹ãŠã®ãªãœãŒã¹ã¯ããã©ãŠã¶ãŒããã¢ã¯ã»ã¹ãããšéçã³ã³ãã³ããšããŠå©çšå¯èœã«ãªããŸã
jar { dependsOn asciidoctor from ("${asciidoctor.outputDir}/html5") { include '**/index.html' include '**/images/*' into 'static/docs' } }
ããããŸãã«ç§ãã¡ãè¡ãããšã§ã-ããã¥ã¡ã³ããçµã¿ç«ãŠãåŸãããã/ static / docsãã£ã¬ã¯ããªã«ã³ããŒããŸãã ãããã£ãŠãåéãããåjarã¢ãŒãã£ãã¡ã¯ãã«ã¯ãããã¥ã¡ã³ãä»ãã®éçãšã³ããã€ã³ããå«ãŸããŸãã ãããã©ãã«ãããã€ãããããã©ã®ç°å¢ã«çœ®ããããã«é¢ä¿ãªããããã¥ã¡ã³ãã®çŸåšã®ããŒãžã§ã³ã¯ãã€ã§ãå
¥æå¯èœã§ãã
ãããã«
ããã¯ããã®ãã°ãããããŒã«ã®æ©èœã®ããäžéšã«ãããŸããã1ã€ã®èšäºã§ãã¹ãŠã網çŸ
ããããšã¯äžå¯èœã§ãã SpringRestDocsã«èå³ããã人ã®ããã«ãç§ã¯ãªãœãŒã¹ãžã®ãªã³ã¯ãæäŸããŠããŸãïŒ
- ã³ã³ãã€ã«ãããããã¥ã¡ã³ãã¯æ¬¡ã®ããã«ãªããŸãããã®äŸã§ã¯asciidoc圢åŒããã®ããŒã«ã®ãã¯ãã«ãã確èªã§ããŸãïŒã¡ãªã¿ã«ãgithubpagesã«ããã¯ãèªåçã«ããŠã³ããŒãã§ããŸãïŒ tsypuk.imtqy.com/springrestdoc
- SpringRestDocs github.com/tsypuk/springrestdocã§ã«ã¹ã¿ãã€ãºããããã¢ãããžã§ã¯ãã䜿çšããgithub ïŒãã¹ãŠãæ§æãããããžã§ã¯ãã®ã³ãŒãã䜿çšããŠã¯ã€ãã¯ã¹ã¿ãŒãããŸãããã¢æ§æasciidoctorãæ¡åŒµæ©èœã®äŸãå³ãç°¡åã«çæããŠããã¥ã¡ã³ãã«å«ããããšãã§ããŸãïŒ
- ãããŠãã¡ããå
¬åŒææž