1. Swagger 소개
이전 기사에서는 RESTFUL에 대한 Spring Boot의 지원을 소개했습니다. 이 기사에서는이 주제에 대해 계속 논의합니다. 그러나 더 이상 RESTFUL API가 구현되는 방법에 대해서는 더 이상 논의하지 않고 RESTFUL API 문서의 유지 보수에 대해 논의 할 것입니다.
매일 작업에서는 종종 프론트 엔드 (웹 엔드, iOS, Android) 또는 제 3 자에 대한 인터페이스를 제공해야합니다. 현재 우리는 자세한 API 문서를 제공해야합니다. 그러나 자세한 문서를 유지하는 것은 쉬운 일이 아닙니다. 우선, 자세한 문서를 작성하는 것은 시간이 많이 걸리고 힘든 일입니다. 반면에, 코드와 문서가 분리되어 있으므로 문서와 코드 사이에 불일치가 쉽습니다. 이 기사에서는 API 문서를 유지하는 방법, 즉 Swagger를 통해 Restuful API 문서를 자동으로 생성하는 방법을 공유합니다.
그래서 Swagger는 무엇입니까? 공식 설명을 직접 읽을 수 있습니다.
세계에서 가장 인기있는 API 도구 wagger는 OpenAPI 사양 (OAS)을위한 API 개발자 도구의 세계 최대 프레임 워크이며, 설계 및 문서에서 테스트 및 배포에 이르기까지 전체 API 라이프 사이클의 개발을 가능하게합니다.
이 구절은 먼저 Swagger가 세계에서 가장 인기있는 API 도구이며 Swagger의 목적은 설계, 문서, 테스트 및 배포를 포함하여 전체 API 수명주기의 개발을 지원하는 것입니다. 이 기사에서는 Swagger의 문서 관리 및 테스트 기능을 사용합니다.
Swagger의 역할에 대한 기본적인 이해를 얻은 후 사용 방법을 살펴 보겠습니다.
2. Swagger 및 Spring Boot 통합
1 단계 : 해당 JAR 패키지를 소개합니다.
<pectionency> <groupid> io.springfox </groupid> <artifactid> springfox-swagger2 </artifactid> <버전> 2.6.0 </version> </dependency> <prectionency> <groupid> io.springfox </groupid> <artifactid> springfox-swagger-ui </artifactid>
2 단계 : 기본 정보 구성 :
@configuration @enablebsger2public class swagger2config {@bean public docket createrestapi () {return new Docket (hoceptype.swagger_2) .apiinfo (apiinfo ()) .apis (retureHandLerselectors.baSepackage ( "com.pandy.blog.blog.rest")). .paths (pathSelectors.Regex ( "/rest /.*")) .build (); } private apiinfo apiinfo () {return new apiinfobuilder () .Title ( "블로그 시스템 RESTFUL API") .Description ( "블로그 시스템 RESTFUL API") .termsofServiceUrl ( "http://127.0.1:8080/") .짓다(); }}기본 구성은 전체 API 문서와 모든 인터페이스에 대해 작동하는 일부 전역 구성에 대한 설명입니다. 여기에는 두 가지 주석이 있습니다.
@Configuration이란 이는 구성 클래스, JDK가 제공하는 주석이며 이전 기사에서 설명되었음을 의미합니다.
@enableswagger2의 기능은 Swagger2 관련 함수를 활성화하는 것입니다.
이 구성 클래스에서 나는 주로 정보의 세 가지 측면을 포함하는 도켓 객체를 인스턴스화했습니다.
(1) 전체 API의 설명 정보, 즉 APIINFO 객체에 포함 된 정보는 정보 의이 부분이 페이지에 표시됩니다.
(2) API 문서를 생성 할 패키지 이름을 지정하십시오.
(3) API를 생성하는 경로를 지정하십시오. 경로 기반 API는 4 가지 모드를 지원할 수 있으며,이 모드는 소스 코드를 참조하는 데 사용할 수 있습니다.
Public Class PathSelectors {private PathSelectors () {새로운 UnsupportedOperationException (); } public static predicate <string> any () {return predicates.alwaystrue (); } public static predicate <string> none () {return predicates.alwaysfalse (); } public static predicate <string> regex (Final String Pathregex) {return new prescticate <string> () {public boolean apply (문자열 입력) {return input.matches (pathregex); }}; } public static predicate <string> ant (Final String antpattern) {return new Prescticate <string> () {public boolean apply (문자열 입력) {AntpathMatcher matcher = new AntpathMatcher (); Return matcher.match (Antpattern, Input); }}; }}소스 코드에서 볼 수 있듯이 Swagger는 모든 경로 생성, 모든 경로의 비 생성 및 정기적 인 매칭 및 개미 패턴 일치의 네 가지 방법을 지원합니다. ANT 매칭의 마지막 세 가지 유형에 더 익숙 할 수 있습니다. Ant에 익숙하지 않다면 무시하십시오. 처음 세 가지 유형은 모든 사람이 일상 업무에 사용하기에 충분해야합니다.
위의 구성을 통해 효과를 볼 수 있습니다. com.pandy.blog.rest 패키지 아래에 ArticLerestController 클래스가 있습니다. 소스 코드는 다음과 같습니다.
Spring Boot를 시작한 다음 http://127.0.0.1:8080/swagger-ui.html을 방문하십시오.
이 페이지에서 마지막 인터페이스 /테스트 /{id}를 제외하고 다른 인터페이스는 해당 문서를 생성하는 것을 볼 수 있습니다. 마지막 인터페이스는 "/rest/."를 구성한 경로를 충족하지 않기 때문에 문서가 생성되지 않습니다.
각각의 특정 인터페이스를 볼 수 있도록 클릭 할 수도 있습니다. "Post /Rest /Article"인터페이스를 예로 들어 보겠습니다.
보시다시피, Swagger는 각 인터페이스에 대한 리턴 결과 및 요청 매개 변수의 예를 생성하고 아래의 "Try Out"을 통해 인터페이스에 직접 액세스 할 수 있습니다. 인터페이스와 관련하여 모든 사람은 인터페이스를 테스트합니다. 전반적으로 Swagger는 여전히 매우 강력하며 구성은 비교적 간단합니다.
@RestControllerPublic 클래스 ArticLerestController {@autowired private articleService articleService; @requestmapping (value = "/rest/article", method = post, produces = "application/json") public webresponse <map <string, object >> savearticle (@requestbody article) {article.setuserid (1l); articleService.savearticle (기사); Map <string, object> ret = new Hashmap <> (); ret.put ( "id", article.getId ()); webresponse <map <string, object >> response = webresponse.getSuccessResponse (ret); 반환 응답; } @requestmapping (value = "/rest/article/{id}", method = delete, produces = "application/json") public webresponse <?> deletearticle (@pathvariable long id) {article article = articleService.getByid (id); article.setstatus (-1); articleService.updatearticle (기사); Webresponse <boodge> 응답 = Webresponse.getSuccessResponse (null); 반환 응답; } @requestmapping (value = "/rest/article/{id}", method = put, produces = "application/json") public webresponse <botort> updatearticle (@pathvariable long id, @requestbody article) {article.setid (id); articleService.updatearticle (기사); Webresponse <boodge> 응답 = Webresponse.getSuccessResponse (null); 반환 응답; } @RequestMapping (value = "/rest/article/{id}", method = get, produces = "application/json") public webresponse> getarticle (@pathvariable long id) {article article = articleService.getByid (id); Webresponse <article> 응답 = Webresponse.getSuccessResponse (기사); 반환 응답; } @requestmapping (value = "/test/{id}", method = get, get, produces = "application/json") public webresponse <?> getnoapi () {webresponse <?> 응답 = webresponse.getSuccessResponse (null); 반환 응답; }}3. Swagger API의 세부 구성
그러나 당신은 이것을 볼 때 확실히 몇 가지 질문이있을 것입니다.
첫 번째 질문 : 리턴 결과와 요청 매개 변수에 대한 문자 그대로 설명이 없습니다. 이것이 구성 할 수 있습니까?
두 번째 질문 :이 요청 매개 변수는 객체에 따라 직접 반영되어야하지만 객체의 모든 속성이 필요한 것은 아니며 매개 변수의 값이 우리의 요구를 충족시키지 못할 수 있습니다. 이것이 구성 할 수 있습니까?
대답은 확실히 괜찮습니다. 이제이 두 가지 문제를 해결하고 구성 코드를 직접 살펴 보겠습니다.
package com.pandy.blog.rest; import com.pandy.blog.dto.webresponse; import com.pandy.blog.po.article; import com.pandy.blog.service.articleservice; import io.swagger.annotations.annotations.Antimpparams; io.swagger.annotations.apioperation; import io.swagger.annotations.apiresponse; import io.swagger.annotations.apiresponse; import io.swagger.annotations.apiresponse; import io.swagger.annotations.annotations.Antom.AntoT.Bean.Bean.AffOURED org.springframework.context.annotation.profile; import org.springframework.bind.annotation.pathvariable; import org.springframework.bind.annotation.requestbody; import org.springframework.beb.bind.annotation.requestmapping; import org.springframework.web.bind.annotation.restcontroller; import java.util.hashmap; import java.util.list; import java.util.map; import static org.springframework.web.bind.annotation.requestmethod.delete; org.springframework.web.bind.annotation.requestmethod.get; import static org.springframework.bind.bind.bind.bind.bind.bind.bind.bind.bind.bind.bind.bind.bind.bind.bind.bind.bind.bind.bind.bind.bind.bind.bind.bind.bind.bind.bind.bind.springframework.web.bind.annotation.requestmetod.put;@restcontroller@restcontroller ( "/restcontmapping ("/rest ") ArticlerestController {@autowired 개인 articleservice articleservice; @RequestMapping (value = "/article", method = post, produces = "application/json") @apioperation (value = "add add add add add add add add add add add add add add add add add", tags = "article", httpmethod = "post") @apiimplicitparams ({@apiimplicitparam (@apiimplicitparam (@apiimplicitparam) " @apiimplicitparam (name = "summary", value = "article summary", required = true, datatype = "string"), @apiimplicitparam (name = "status", value = "value ="publish status ", required = true, dataType ="}) @apIResponses (@apirSponse (code = 200, message =) Webresponse <map <string, object >> savearticle (@requestbody article article) {articleService.savearticle (article); Map <string, object> ret = new Hashmap <> (); ret.put ( "id", article.getId ()); webresponse <map <string, object >> response = webresponse.getSuccessResponse (ret); 반환 응답; } @apioperation (value = "삭제 삭제", notes = "adte the grys by id", tags = "article", httpmethod = "delete") @apiimplicitparam ({@apiimplicitparam (name = "id", value = "article id", restip, datatype = "long") @requestmapping (value =/{id}). delete, produces = "application/json") public webresponse <?> deletearticle (@pathvariable long id) {article article = articleService.getByid (id); article.setstatus (-1); articleService.savearticle (기사); return webresponse.getSuccessResponse (New Hashmap <> ()); } @apioperation (value = "value ="기사 목록 가져 오기 ", notes ="제목에 따른 전체 쿼리 ", tags ="article ", httpmethod ="get ") @apiimplicitparams ({@apiimplicitparam ({@apiimplicitparam (@apiimplicitparam", value = "article", required = "false, datatype ="string ") 페이지 당 ", 필수 = 거짓, dataType ="정수 "), @apiimplicitparam (name ="pagenum ", value ="pagepage number ", 필수 = false, datatype ="integer "}}) @requestmapping (value ="/article/list ", method = get, acplicates ="application/json "). pagenum) {if (pagesize == null) {pagesize = 10; } if (pagenum == null) {pagenum = 1; } int offset = (pagenum -1) * pagesize; List <article> articles = articleService.getArticles (제목, 1L, 오프셋, pagesize); Webresponse.getSuccessResponse (기사)를 반환합니다. } @apioperation (value = "ratud article", notes = "sudde article content", tags = "article", httpmethod = "put") @apiimplicitparams ({@apiimplicitparam (name = "id", value = "article id", required = true, datatype = "long") = "string"), @apiimplicitparam (이름 = "요약", value = "article summary", required = false, dataType = "string"), @apiimplicitparam (name = "status", value = "value ="false, dataType = "integer")) @RequestMapping (value = "/artict/jon}", metter =, metter =, ind} " webresponse <?> updatearticle (@pathvariable long id,@requestbody article) {article.setid (id); articleService.updatearticle (기사); return webresponse.getSuccessResponse (New Hashmap <> ()); }}코드의 여러 주석 및 관련 속성의 특정 기능을 설명해 봅시다.
@apioperation, 전체 인터페이스 속성 구성 :
값 : 인터페이스 목록에 표시된 인터페이스 설명.
참고 : 인터페이스 세부 정보 페이지에 표시된 인터페이스에 대한 자세한 설명.
태그 : 인터페이스의 태그. 동일한 태그가있는 인터페이스가 탭 페이지 아래에 표시됩니다.
httpmethod : 지원되는 http 방법.
@apiimplicitparam의 컨테이너 인 @apiimplicitparams는 여러 @apiimplicitparam 주석을 포함 할 수 있습니다.
@apiimplicitparam, 요청 매개 변수 속성 구성 :
이름 : 매개 변수 이름
값 : 매개 변수 설명
필수 : 필요합니다
데이터 유형 : 데이터 유형
@apiresponses, @apiresponse 컨테이너에는 여러 @apiresponse 주석이 포함될 수 있습니다
@apiresponse, 결과 속성 구성을 반환합니다.
코드 : 결과의 인코딩을 반환합니다.
메시지 : 결과에 대한 설명을 반환합니다.
응답 : 결과의 해당 클래스를 반환합니다.
위의 구성을 완료 한 후 페이지 효과를 살펴 보겠습니다.
목록 페이지 :
보시다시피, 인터페이스는 이제 기사 태그 아래에 있으며 인터페이스 뒤에 구성에 대한 지침도 있습니다. "Post /Rest /Article"인터페이스의 세부 정보 페이지를 살펴 보겠습니다.
그림이 너무 크고 제목 속성의 표시 만 가로 채고 다른 매개 변수는 비슷합니다. 페이지에서 요청 매개 변수에 대한 지침이 있음을 알 수 있지만 이것이 우리가 예상 한 영향은 아닙니다. 우리의 매개 변수가 단순한 유형이라면이 메소드가 정상이어야하지만 이제 문제는 요청 매개 변수가 객체이므로 구성하는 방법은 무엇입니까? 여기에는 @apimodel과 @apimodelproperty의 두 가지 다른 주석이 포함됩니다. 먼저 코드를보고 설명하기가 더 쉽습니다.
@apimodel (value = "article object", description = "추가 및 업데이트 기사 객체 설명") 공개 클래스 기사 {@id @generatedValue @apimodelProperty (name = "id", value = "article id", required = false = "1") private long id; @apimodelProperty (name = "title", value = "article gitle", required = true = "테스트 기사 제목") 개인 문자열 제목; @apimodelProperty (name = "summary", value = "article summary", required = true, example = "테스트 기사 요약") 개인 문자열 요약; @apimodelProperty (hidden = true) 개인 날짜 createTime; @apimodelProperty (hidden = true) 개인 날짜 게시; @apimodelProperty (hidden = true) 개인 날짜 updateTime; @apimodelProperty (hidden = true) private long userId; @apimodelProperty (name = "status", value = "article release status", required = true, example = "1") 개인 정수 상태; @apimodelProperty (name = "type", value = "article category", required = true, example = "1") 개인 정수 유형;}@apimodel은 전체 클래스의 속성 구성입니다.
가치 : 수업 설명
설명 : 자세한 설명
@apimodelProperty는 각 필드의 속성을 자세히 설명하는 것입니다.
이름 : 필드 이름
가치 : 필드 설명
필수 : 필요합니다
예 : 예제 값
숨겨진 : 표시 여부
위의 구성을 완료 한 후 효과를 살펴 보겠습니다.
이제 필드 설명이 표시되었으며 예제의 필드 값도 구성한 예제 특성의 해당 값이되었습니다. 이러한 방식으로 전체 API 문서가 생성되고 문서는 두 개의 격리 된 부분이 아닌 코드와 밀접하게 연결됩니다. 또한이 문서를 통해 쉽게 테스트 할 수도 있습니다. 예제 값 하에서 옐로우 박스를 클릭하면 내부의 내용이 기사의 해당 값 상자에 자동으로 복사 된 다음 "시도 시도"를 클릭하여 HTTP 요청을 시작합니다.
시도해 보면 반환 된 결과를 볼 수 있습니다.
작업은 여전히 매우 편리합니다. Junit 및 Postman과 비교할 때 Swagger를 통한 테스트가 더 편리합니다. 물론 Swagger의 테스트는 단위 테스트를 대체 할 수 없지만 공동 디버깅에 여전히 매우 중요한 영향을 미칩니다.
4. 요약
전반적으로 Swagger의 구성은 비교적 간단하며 Swagger의 문서를 자동으로 생성 할 수있는 능력은 실제로 많은 작업을 저장했으며 후속 유지 보수에 큰 도움을주었습니다. 또한 Swagger는 구성에 따라 우리를 위해 테스트 데이터를 자동으로 생성하고 해당 HTTP 방법을 제공 할 수 있으며, 이는 자체 테스트 및 공동 디버깅 작업에도 도움이됩니다. 따라서 여전히 매일 개발에 Swagger를 사용하는 것이 좋습니다. 이는 일정히 업무 효율성을 향상시키는 데 도움이됩니다. 마지막으로, 당신이 생각할 질문, 즉 문서에 페이지를 통해 직접 액세스 할 수 있으므로, 프로덕션 환경, 특히 외부 서비스를 제공 해야하는 시스템에 인터페이스를 직접 노출시킬 수는 없습니다. 그렇다면 생산 과정에서 어떻게이 기능을 끄질 수 있습니까? 많은 방법이 있습니다. 직접 시도해 볼 수 있습니다.
위는 편집자가 소개 한 Spring Boot Integrated Swagger2 프로젝트의 실제 전투입니다. 나는 그것이 당신에게 도움이되기를 바랍니다. 궁금한 점이 있으면 메시지를 남겨 주시면 편집자가 제 시간에 답장을 드리겠습니다. Wulin.com 웹 사이트를 지원해 주셔서 대단히 감사합니다!