Halo semuanya! Dalam artikel ini, saya ingin mempertimbangkan alat dokumentasi dalam pendekatan yang berbeda secara fundamental untuk pengembangan REST API, yaitu, untuk alat CodeFirst - SpringRestDocs (serta add-on SpringAutoRestDocs) dan untuk ApiFirst - alat ekosistem Swagger (Open-Api).
Penafian: Saya tidak akan membahas detail holivar tentang apa yang lebih baik dari CodeFirst atau ApiFirst, tetapi saya akan mencoba menunjukkan kemungkinan praktik dokumentasi di kedua versi.
CodeFirst ditambah 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 ), .
, "" .
Kemampuan untuk menyesuaikan cuplikan dan batasan.
Apa yang diberikan Swagger:
Artefak tunggal di semua tahap perkembangan.
Dokumentasi dan model data selalu sinkron dengan kode, karena kode dibuat berdasarkan kontrak.
Kemampuan untuk menggunakan UI yang berisi semua informasi yang sama seperti dalam kontrak dengan kemampuan untuk merutekan permintaan.
Jalur pengembangan mana pun yang Anda pilih, alat di atas hampir selalu memungkinkan Anda untuk selalu memperbarui dokumentasi yang terkait erat dengan kode produksi.