Slide 1

Slide 1 text

Spring Boot ͱ Swagger 2015/8/1 ୈेೋճ #ौ୩Java bati (twitter: @bati11_)

Slide 2

Slide 2 text

໨࣍ • Swagger ͱ͸ • SpringFox • JsonSchema • Swagger CodeGen • σϓϩΠϝϯτύΠϓϥΠϯʹ૊ΈࠐΉ

Slide 3

Slide 3 text

Swagger ͱ͸ • Web API ͷ࢓༷Λ Swagger ͷϧʔϧʹଇͬͨ JSON Ͱهड़ • Swagger JSON ΛऔΓר֤͘छπʔϧ • ྫ͑͹ɺSwagger UI • σϞαΠτ http://petstore.swagger.io/

Slide 4

Slide 4 text

JSONͰهड़… { "swagger": "2.0", "info": { "description": "Api Documentation", "version": "1.0", "title": "Api Documentation", "termsOfService": "urn:tos", "contact": { "name": "Contact Email" }, "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0" } }, "host": "localhost:5555", "basePath": "/", "tags": [ { "name": "person-resource", "description": "Person Resource" } ], "paths": { "/persons": { "get": { "tags": [ "person-resource" ], "summary": "index", "operationId": "indexUsingGET", "consumes": [ "application/json" ], "produces": [ "application/json" ], "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { "$ref": "#/definitions/Person" }

Slide 5

Slide 5 text

JSON ΛखͰॻ͘ͷ͸ਏ͍ͷͰ… • Swagger Editor • ϒϥ΢β্Ͱಈ͘πʔϧ • YAMLɺϦΞϧλΠϜϓϨϏϡʔ • SpringFox • Spring MVC ͳΒͪ͜Βͷબ୒ࢶ΋͋Δ

Slide 6

Slide 6 text

http://springfox.github.io/springfox/

Slide 7

Slide 7 text

• SpringͷΞϊςʔγϣϯΛݩʹSwagger JSON Λੜ੒Ͱ͖Δ @RestController @RequestMapping(value = "persons", produces = MediaType.APPLICATION_JSON_VALUE) public class PersonResource { @RequestMapping(method = RequestMethod.GET) public List index() { ɾɾɾ } } SpringFox 4QSJOH#PPUͷίϯτϩʔϥʔ

Slide 8

Slide 8 text

SpringFoxΛ Spring Boot Ͱ࢖͏

Slide 9

Slide 9 text

spring-swagger2 ΛґଘϥΠϒϥϦʹ௥Ճ repositories { ɾɾɾ jcenter() } dependencies { ɾɾɾ compile ‘io.springfox:springfox-swagger2:2.0.3’ } CVJMEHSBEMF

Slide 10

Slide 10 text

Configuration ΫϥεΛ༻ҙ @EnableSwagger2 @Configuration public class SwaggerConfiguration { @Bean public Docket customDocket() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.basePackage(“sample.web")) .build(); } }

Slide 11

Slide 11 text

ىಈͯ͠ /v2/api-docs.json ʹΞΫηε͢Δͱ Swagger JSON ΛऔಘͰ͖Δ $ ./gradlew bootRun $ curl http://localhost:8080/v2/api-docs.json { "swagger": "2.0", "info": { "description": "Api Documentation", "version": "1.0", "title": "Api Documentation", "termsOfService": "urn:tos", "contact": { "name": "Contact Email" }, ɾ ɾ ɾ

Slide 12

Slide 12 text

Swagger UI Λ Spring Boot Ͱ࢖͏

Slide 13

Slide 13 text

spring-swagger-ui ΛґଘϥΠϒϥϦʹ௥Ճͯ͠ ىಈ͢Δ repositories { ɾɾɾ jcenter() } dependencies { ɾɾɾ compile ‘io.springfox:springfox-swagger2:2.0.3’ compile 'io.springfox:springfox-swagger-ui:2.0.3' } CVJMEHSBEMF

Slide 14

Slide 14 text

/swagger-ui.html ʹΞΫηε͢Δͱ API υΩϡ ϝϯτ͕ݟΕΔ

Slide 15

Slide 15 text

SpringFox ͷ ΞϊςʔγϣϯͰ Swagger JSON ͷ ಺༰Λฤू͢Δ

Slide 16

Slide 16 text

• ϦΫΤετʹؔΘΔΞϊςʔγϣϯ • @Api, @ApiOperation, @ApiParam

Slide 17

Slide 17 text

• ϨεϙϯεʹؔΘΔΞϊςʔγϣϯ • @ApiModel, @ApiModelProperty

Slide 18

Slide 18 text

Tips

Slide 19

Slide 19 text

LocalDateTimeͷϓϩύςΟΛจࣈྻʹ͢Δ @Bean public Docket customDocket() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.basePackage(“sample.web")) .build() .directModelSubstitute(LocalDateTime.class, String.class); }

Slide 20

Slide 20 text

OptionalͷϓϩύςΟΛจࣈྻʹ͢Δ @Bean public Docket customDocket() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.basePackage(“sample.web")) .build() .directModelSubstitute(LocalDateTime.class, String.class) .alternateTypeRules(new OptionalTypeRule(typeResolver)); } private static class OptionalTypeRule extends AlternateTypeRule { public OptionalTypeRule(TypeResolver typeResolver) { super(typeResolver.resolve(Optional.class), typeResolver.resolve(Object.class)); } @Override public ResolvedType alternateFor(ResolvedType type) { return appliesTo(type) ? type.getTypeBindings().getTypeParameters().get(0) : type; } @Override public boolean appliesTo(ResolvedType type) { return Optional.class.isAssignableFrom(type.getErasedType()); } }

Slide 21

Slide 21 text

JSON Schema • Swagger JSONͷdefinitationsϓϩύςΟ͸ JSON SchemaͰ࢖͑Δ • http://spacetelescope.github.io/ understanding-json-schema/structuring.html • ͚ͲɺnullʹରԠͯ͠ͳ͍ • type: [“string”, “null”] ʹ͢Δඞཁ͕͋Δ

Slide 22

Slide 22 text

ࣗ෼Ͱඞਢ߲໨Ͱͳ͍ϓϩύςΟΛ type: “hoge” ͔Β type: [“hoge”, “null”] ʹ͢Δ def root = new JsonSlurper().parseText(swaggerJson) root.definitions.entrySet().each { def required = it.value.required if (required != null) it.value.properties.each { if (!required.contains(it.key) && !it.value.containsKey('$ref')) { it.value.type = [it.value.type,"null"] } } } } def jsonBuilder = new JsonBuilder() jsonBuilder (root.definitions) definitions = jsonBuilder.toString() (SPPWZͷྫ

Slide 23

Slide 23 text

Swagger CodeGen • Swagger JSON ͔ΒίʔυΛࣗಈੜ੒Ͱ͖Δ • ΫϥΠΞϯτଆ΋αʔόʔଆ΋ੜ੒Ͱ͖Δ • ΫϥΠΞϯτίʔυΛ࢖༻Ͱ͖Δ͔ݕ౼த

Slide 24

Slide 24 text

σϓϩΠϝϯτύΠϓϥΠϯʹ ૊ΈࠐΉ Ϗϧυ ΠϯςάϨʔγϣϯ ςετ 4XBHHFS$PEF(FO 4XBHHFS+40/ +40/4DIFNB ΫϥΠΞϯτϥΠϒϥϦ 4XBHHFS6*

Slide 25

Slide 25 text

͓͠·͍