みなさん、こんにちは!この記事では、REST API開発への根本的に異なるアプローチ、つまりCodeFirst-SpringRestDocsツール(およびそのSpringAutoRestDocsアドオン)とApiFirst-Swaggerエコシステムツール(Open-Api)のドキュメントツールについて検討したいと思います。
免責事項:CodeFirstまたはApiFirstよりも優れている点については、ホリバーの詳細には触れませんが、両方のバージョンで可能なドキュメントの実践方法を示すようにします。
CodeFirstとSpringAutoRestDocs
SpringRestDocs , (, ..) . , , - , .. SpringAutoRestDocs, JSR Spring , Javadoc, .
Swagger PetStore ( , ) (addPet
, deletePet
, getPetById
). getPetById
:
@RestController
@RequiredArgsConstructor
public class PetController implements PetApi {
private final PetRepository petRepository;
@Override
public ResponseEntity<Pet> getPetById(Long petId) {
return new ResponseEntity<>(petRepository.getPetById(petId), HttpStatus.OK);
}
//
}
.
:
@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())
}
MockMVC
WebApplicationContext
@SpringBootTest
prepareJackson(objectMapper, new TypeMapping())
ResultHandler
, pojo
withDefaults(curlRequest(), httpRequest(), ..)
,
commonDocumentation()
, build , .
:
@Test
void getPetTest() {
//given
def petId = 1L
//when
def resultActions = mockMvc
.perform(RestDocumentationRequestBuilders
.get("/pet/{petId}", petId)
.header("Accept", "application/json"))
//then
resultActions
.andExpect(status().isOk())
.andExpect(content().string(objectMapper.writeValueAsString(buildReturnPet())))
}
MockMvc
, .
:
"" auto-section.adoc
( , MockMVC
) index.adoc
API. :
SpringAutoRestDocs SpringRestDocs.
- org/springframework/restdocs/templates/asciidoctor
default-
.
- org/springframework/restdocs/constraints
DefaultConstraintDescriptions.properties
.
ApiFirst Swagger
(1, 2) swagger - open-source , OpenApi Specification , REST api.
Swagger
Swagger - OpenApi Specification Swagger Tools.
OpenApi Specification - REST API. YAML JSON. , .
Swagger Tools - , - REST api. : Swagger Editor( , ), Swagger UI( API), Swagger Codegen( - , )
- : (swagger-library), swagger-ui(swagger-webjar-ui-starter), (spring-auto-rest-docs).
Swagger Swagger PetStore SpringAutoRestDocs .
build.gradle :
server stub Swagger OpenApi Generator.
OpenApi Generator
:
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"
]
}
openApiGenerate
generatorName -
Spring ( spring)
dateLibrary - (joda, JSR-310 ..)
-
:
task codegen(dependsOn: ['openApiGenerate', 'copySpecs'])
compileJava.dependsOn(codegen)
compileJava.mustRunAfter(codegen)
, UI :
task copySpecs(type: Copy) {
from("${project.projectDir}/specs")
into("${project.projectDir}/src/main/resources/META-INF/specs")
}
Swagger-ui :
Rest-docs API:
UI :
@RestController
@RestController
@RequiredArgsConstructor
public class PetController implements PetApi {
private final PetRepository petRepository;
@Override
public ResponseEntity<Pet> getPetById(Long petId) {
return new ResponseEntity<>(petRepository.getPetById(petId), HttpStatus.OK);
}
//
}
swagger:
ui:
indexHandler:
enabled: true
resourceHandler: "/api/**"
apis:
- url: http://localhost:8080/specs/some_swagger.yaml
name: My api
:
Server stub - API.
Swagger UI - API UI:
:
SpringAutoRestDocs:
( index.html ), .
, "" .
スニペットと制限をカスタマイズする機能。
Swaggerが提供するもの:
開発のすべての段階で単一のアーティファクト。
コードは契約に基づいて生成されるため、ドキュメントとデータモデルは常にコードと同期しています。
契約と同じ情報をすべて含むUIを使用する機能と、リクエストをルーティングする機能。
どちらの開発パスを選択しても、上記のツールを使用すると、ほとんどの場合、製品コードに密接に関連する最新のドキュメントを保持できます。