Spring Rest Doc - low-hill/Knowledge GitHub Wiki
- ์ ๋ขฐ๋๊ฐ ๋์ document๋ฅผ ์์ฑํด์ฃผ๋ RESTful ์๋น์ค์ ๋ฌธ์ํ ๋๊ตฌ. ๊ธฐ๋ณธ์ ์ผ๋ก Asciidoctor๋ฅผ ์ฌ์ฉํ์ฌ HTML๋ฅผ ์์ฑํ๋ค. ํ์ ํ ๊ฒฝ์ฐ Markdown์ ์ฌ์ฉํ๋๋ก ๋ณ๊ฒฝํ ์ ์๋ค.
์ฅ์
- Spring MVC test framework, Spring WebFlux WebTestClient, REST ASSured 3๋ฅผ ํตํด ์์ฑ๋ ํ
์คํธ๊ฐ ์ฑ๊ณตํด์ผ ๋ฌธ์ ์์ฑ ๋จ.
- API ์ ๋ขฐ๋๋ฅผ ๋์ด๊ณ ๋๋ถ์ด ํ ์คํธ ์ฝ๋์ ๊ฒ์ฆ์ ๊ฐ์ ๋ก ํ๊ฒ ๋ง๋๋ ๋ฌธ์ํ ๋๊ตฌ
- ์ค์ ์ฝ๋์ ์ถ๊ฐ๋๋ ์ฝ๋๊ฐ ์๋ค.
- ํ๋ก๋์ ์ฝ๋์ ๋ถ๋ฆฌ๋์ด Swagger๊ฐ์ด Config์ค์ ์ฝ๋๋ ์ด๋ ธํ ์ด์ ์ด ํ๋ก๋์ ์ฝ๋์ ์ถ๊ฐ๋ ์ผ์ด ์๋ค.
Spring Rest Docs Flow
- Test โ Snippets โ Template โ Document
- ํ
์คํธ ์ฝ๋๋ฅผ ์คํํ๋ฉด ./build/generated-snippetsํด๋์REST docs snippets ํ์ผ๋ค์ด ์์ฑ
- curl-request
- http-request
- http-response
- httpie-request
- request-body
- response-body
- ์์ฑ๋ ํ์ผ๋ค์ ์๋ํ๋ ๋๋ก ํ ํ๋ฆฟ์ ๋ฐฐ์น ํ ํ๋ฆฟ์ ๊ธฐ์ค์ผ๋ก html ํ์ผ์ ์์ฑ
- ํ
์คํธ ์ฝ๋๋ฅผ ์คํํ๋ฉด ./build/generated-snippetsํด๋์REST docs snippets ํ์ผ๋ค์ด ์์ฑ
Minimum requirements
- Java 8
- Spring Framework 5( 5.0.2 or later)
์์ ํ๊ฒฝ
- Java 11
- Spring boot 2.7.4
- MockMvc
- AsciiDoc
gradle ์์กด์ฑ ์ฃผ์
- ./build.gradle ์ค์
plugins { ...
id 'org.asciidoctor.jvm.convert' version '3.3.2'
...
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
repositories {
mavenCentral()
}
ext {
set('snippetsDir', file("build/generated-snippets")) //
}
configurations {
asciidoctorExtensions
}
dependencies {
...
implementation 'org.springframework.boot:spring-boot-starter-web'
asciidoctorExtensions 'org.springframework.restdocs:spring-restdocs-asciidoctor'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc'
...
}
tasks.named('asciidoctor') {
inputs.dir snippetsDir
dependsOn test
configurations 'asciidoctorExtensions' //
}
bootJar {
dependsOn asciidoctor
}
- gradle7์์ org.asciidoctor.convert(v 1.5.9) ํ๋ฌ๊ทธ์ธ์ด ์๋ฌ๊ฐ ๋ฐ์ํ์ฌ ์์ ๊ฐ์ ์ค์ ์ผ๋ก ์ฌ์ฉ -> Asciidoctor ๋น๋ ์ค๋ฅ ์ฐธ๊ณ
ํ ์คํธ ์ฝ๋ ์์ฑ
@Test
public void findById() throws Exception {
User userRes = new User(1L, "u1", "[email protected]");
this.mockMvc.perform(RestDocumentationRequestBuilders.get("/user/{userId}", userRes.getId()))
.andExpect(status().isOk())
.andDo(document("user-get-one",
pathParameters(
parameterWithName("userId").description("")
),
responseFields(
fieldWithPath("data").description(""),
fieldWithPath("data.id").type(JsonFieldType.NUMBER).description(""),
fieldWithPath("data.name").type(JsonFieldType.STRING).description(""),
fieldWithPath("data.email").type(JsonFieldType.STRING).description("")
)
));
}
document ์์ฑ ๋ฐฉ๋ฒ
- RestDocumentationRequestBuilders๋ก API ํธ์ถ
- path ํ๋ผ๋ฏธํฐ
pathParameters(
parameterWithName("userId").description("์์ด๋")
)
- Request body
requestFields(
fieldWithPath("id").description("")
)
- Json Response
responseFields( fieldWithPath("data").description("๊ฒฐ๊ณผ๋ฉ์์ง")
)
- response ์ ๊ทผ ๋ฐฉ๋ฒ
- ๋ฐฐ์ด์ผ๋ [].์ผ๋ก ์ ๊ทผ
- fieldWithPath("[].id").type(JsonFieldType.STRING).description("์์ธ ์ค๋ช ...")
- ๋ฐฐ์ด์ ์ด๋ฆ์ด ์์๋ *.[]๋ก ์ ๊ทผ
- fieldWithPath("data.[].id").type(JsonFieldType.STRING).description("์์ธ ์ค๋ช ...")
- ๋ฐฐ์ด์ผ๋ [].์ผ๋ก ์ ๊ทผ
- responsefield example
this.mockMvc.perform(get("/user"))
...
.andDo(document("user-get-all",
responseFields(
fieldWithPath("data").description(""),
fieldWithPath("data.[].id").type(JsonFieldType.NUMBER).description(""),
fieldWithPath("data.[].name").type(JsonFieldType.STRING).description(""),
fieldWithPath("data.[].email").type(JsonFieldType.STRING).description("")
- test ์ํ ์ ./build/generated-snippets/ ํ์์ ๋ฌธ์(*.adoc)๊ฐ ์์ฑ ๋๋ค.
snippets ์ฐ๊ฒฐ ๋ฐ ๋ฌธ์ํ
์์ฑ๋ snippets ํ์ผ๋ค์ ์ฐ๊ฒฐํด์ค ์ฌ์ฉ์ ์ ์ .adocํ์ผ์ "src/docs/aciidocs"๊ฒฝ๋ก์ ์์ฑํ๊ณ ๋ฌธ์๋ฅผ ๊ตฌ์ฑ ํ๋ค.
- snippets ํ์ผ ์ฐ๊ฒฐ
- include::{snippets}/test-example/curl-request.adoc[]
- Asciidoctor User Manual โ https://docs.asciidoctor.org/asciidoctor/latest/
- include๋ก ๊ฐ๊ฐ์ ํ์ผ ์ฝ์ ํ๋ ๋์ operation์ผ๋ก ์ํ๋ ํ์ผ๋ง ๊ฐ์ ธ์ด
[resources_user](/low-hill/Knowledge/wiki/resources_user)
== User Sample
[resources_user_list](/low-hill/Knowledge/wiki/resources_user_list)
=== User
`GET`
operation::user-get-all[snippets='response-fields,http-response']
[resources_user_get_one](/low-hill/Knowledge/wiki/resources_user_get_one)
=== User
operation::user-get-one[snippets='path-parameters,response-fields,http-response']
- ์์ฑ ํ build ์ build/docs/asciidoc์ hmtl ํ์ผ์ด ์์ฑ ๋๋ค.
Source files | Generated files |
---|---|
src/docs/asciidoc/*.adoc | build/docs/asciidoc/*.html |