使用Spring Boot和Swagger進行API優先開發 - reflectoring.io
遵循API優先方法,我們在開始編碼之前先指定一個API。通過API描述語言,團隊可以進行協作而無需執行任何操作。
使用OpenAPI,我們可以建立一個API規範,我們可以在團隊之間共享以交流合同。OpenAPI Maven外掛使我們可以根據這樣的規範為Spring Boot生成樣板程式碼,因此我們只需要自己實現業務邏輯即可。
這些描述語言指定了端點,安全性模式,物件模式等。而且,大多數時候我們也可以生成這樣的規範程式碼。通常,API規範也成為該API的文件。
您可以在GitHub上瀏覽示例程式碼。
API優先的好處
要開始進行元件或系統之間的整合,團隊需要簽訂合同。在我們的案例中,合同是API規範。API-first幫助團隊之間相互通訊,而無需實現任何事情。它還使團隊可以並行工作。
API優先方法的亮點在於構建更好的API。僅關注需要提供的功能。簡約的API意味著需要維護的程式碼更少。
使用Swagger編輯器建立API規範
讓我們在YAML文件中建立自己的OpenAPI規範。為了更容易理解,我們將討論分為正在建立的YAML文件的各個部分。如果您想了解有關OpenAPI規範的更多詳細資訊,可以訪問Github儲存庫。
我們從文件頂部的一些有關API的常規資訊開始:
openapi: 3.0.2 info: title: Reflectoring description: "Tutorials on Spring Boot and Java." termsOfService: http://swagger.io/terms/ contact: email: petros.stergioulas94@gmail.com license: name: Apache 2.0 url: http://www.apache.org/licenses/LICENSE-2.0.html version: 0.0.1-SNAPSHOT externalDocs: description: Find out more about Reflectoring url: https://reflectoring.io/about/ servers: - url: https://reflectoring.swagger.io/v2 |
openapi欄位允許我們定義文件遵循的OpenAPI規範的版本。
在這一info部分中,我們新增了有關API的一些資訊。這些欄位應該是不言自明的。
最後,在本servers節中,我們提供了實現API的伺服器列表。
然後是關於我們的API的一些其他後設資料:
tags: - name: user description: Operations about user externalDocs: description: Find out more about our store url: http://swagger.io |
tags部分提供了其他後設資料的欄位,我們可以使用這些欄位使我們的API更具可讀性並易於遵循。我們可以新增多個標籤,但是每個標籤都應該是唯一的。
接下來,我們將描述一些路徑。路徑儲存有關單個端點及其操作的資訊:
paths: /user/{username}: get: tags: - user summary: Get user by user name operationId: getUserByName parameters: - name: username in: path description: 'The name that needs to be fetched. ' required: true schema: type: string responses: 200: description: successful operation content: application/json: schema: $ref: '#/components/schemas/User' 404: description: User not found content: {} |
$ref欄位允許我們引用自定義模式中的物件。在這種情況下,我們指的是User架構物件(請參閱下一節有關Components)。summary是該操作的簡短說明。使用operationId,我們可以為操作定義唯一的識別符號。我們可以將其視為我們的方法名稱。最後,responses物件允許我們定義操作的結果。我們必須為任何操作呼叫至少定義一個成功的響應程式碼。
元件
本components節中全部介紹了API的物件。除非我們從元件物件外部的屬性中明確引用了它們,否則在元件物件中定義的物件將不會影響API,如上所述:
components: schemas: User: type: object properties: id: type: integer format: int64 username: type: string firstName: type: string ... more attributes userStatus: type: integer description: User Status format: int32 securitySchemes: reflectoring_auth: type: oauth2 flows: implicit: authorizationUrl: http://reflectoring.swagger.io/oauth/dialog scopes: write:users: modify users read:users: read users api_key: type: apiKey name: api_key in: header |
schemas部分允許我們定義要在API中使用的物件。在本securitySchemes節中,我們可以定義操作可以使用的安全性方案。有兩種使用安全方案的可能方法。
首先,我們可以使用security欄位將安全方案新增到特定操作:
paths: /user/{username}: get: tags: - user summary: Get user by user name security: - api_key: [] |
在上面的示例中,我們明確指定使用api_key我們上面定義的方案保護路徑/ user / {username} 。
但是,如果我們要在整個專案中應用安全性,則只需將其指定為頂級欄位即可:
paths: /user/{username}: get: tags: - user summary: Get user by user name security: - api_key: [] |
現在,我們的所有路徑都應通過該api_key方案來保證。
從API規範生成程式碼
定義了API之後,我們現在將根據上面的YAML文件建立程式碼。
我們將研究兩種不同的生成程式碼的方法:
- 使用Swagger編輯器手動生成程式碼,以及
- 使用OpenAPI Maven外掛從Maven構建生成程式碼。
1.從Swagger編輯器生成程式碼
儘管這是我不會採用的方法,但讓我們討論一下並討論為什麼我認為這是一個壞主意。
讓我們轉到Swagger Editor,然後將我們的YAML檔案貼上到其中。然後,我們從選單中選擇“ 生成伺服器”,然後選擇我們要生成哪種伺服器(我使用“ Spring”)。
那麼,為什麼這是個壞主意呢?
首先,為我生成的程式碼是使用Java 7和Spring Boot 1.5.22,它們都已經過時了。
其次,如果我們對規範進行更改(並且更改始終在發生),我們將不得不復制並貼上手動更改的檔案。
2.使用OpenAPI Maven外掛生成程式碼
更好的替代方法是使用OpenAPI Maven外掛從Maven構建中生成程式碼。
讓我們看一下資料夾結構。我選擇使用一個多模組Maven專案,其中有兩個專案:
- app,它是根據我們的規範實現API的應用程式。
- specification,其唯一的工作就是為我們的應用提供API規範。
資料夾結構如下所示:
spring-boot-openapi ├── app │ └── pom.xml │ └── src │ └── main │ └── java │ └── io.reflectoring │ └── OpenAPIConsumerApp.java ├── specification │ └── pom.xml │ └── src │ └── resources │ └── openapi.yml └── pom.xml |
為了簡單起見,我們省略了測試資料夾。
我們app是一個簡單的Spring啟動的專案,我們可以自動生成上start.spring.io,讓我們著眼於pom.xml從specification模組,在那裡我們配置的OpenAPI Maven外掛:
<plugin> <groupId>org.openapitools</groupId> <artifactId>openapi-generator-maven-plugin</artifactId> <version>4.2.3</version> <executions> <execution> <goals> <goal>generate</goal> </goals> <configuration> <inputSpec> ${project.basedir}/src/main/resources/openapi.yml </inputSpec> <generatorName>spring</generatorName> <apiPackage>io.reflectoring.api</apiPackage> <modelPackage>io.reflectoring.model</modelPackage> <supportingFilesToGenerate> ApiUtil.java </supportingFilesToGenerate> <configOptions> <delegatePattern>true</delegatePattern> </configOptions> </configuration> </execution> </executions> </plugin> |
您可以在GitHub上檢視完整pom.xml檔案。
在本教程中,我們使用spring生成器。
簡單地執行命令./mvnw install將生成實現我們的OpenAPI規範的程式碼!
檢視資料夾target/generated-sources/openapi/src/main/java/io/reflectoring/model,我們找到了User在YAML中定義的模型的程式碼:
@javax.annotation.Generated(...) public class User { @JsonProperty("id") private Long id; @JsonProperty("username") private String username; @JsonProperty("firstName") private String firstName; // ... more properties @JsonProperty("userStatus") private Integer userStatus; // ... getters and setters } |
生成器不僅生成模型,還生成端點。讓我們快速看一下我們生成的內容:
public interface UserApiDelegate { default Optional<NativeWebRequest> getRequest() { return Optional.empty(); } /** * POST /user : Create user * Create user functionality * * @param body Created user object (required) * @return successful operation (status code 200) * @see UserApi#createUser */ default ResponseEntity<Void> createUser(User body) { return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); } // ... omit deleteUser, getUserByName and updateUser } |
當然,生成器無法為我們生成我們的業務邏輯,但是它確實會UserApiDelegate為我們實現上述介面。
它還建立一個UserApi介面,將呼叫委託給UserApiDelegate:
@Validated @Api(value = "user", description = "the user API") public interface UserApi { default UserApiDelegate getDelegate() { return new UserApiDelegate() {}; } /** * POST /user : Create user * Create user functionality * * @param body Created user object (required) * @return successful operation (status code 200) */ @ApiOperation(value = "Create user", nickname = "createUser", notes = "Create user functionality", tags={ "user", }) @ApiResponses(value = { @ApiResponse(code = 200, message = "successful operation") }) @RequestMapping(value = "/user", method = RequestMethod.POST) default ResponseEntity<Void> createUser( @ApiParam(value = "Created user object" ,required=true ) @Valid @RequestBody User body) { return getDelegate().createUser(body); } // ... other methods omitted } |
生成器還為我們建立了一個Spring控制器,用於實現UserApi介面:
@javax.annotation.Generated(...) @Controller @RequestMapping("${openapi.reflectoring.base-path:/v2}") public class UserApiController implements UserApi { private final UserApiDelegate delegate; public UserApiController( @Autowired(required = false) UserApiDelegate delegate) { this.delegate = Optional.ofNullable(delegate) .orElse(new UserApiDelegate() {}); } @Override public UserApiDelegate getDelegate() { return delegate; } } |
如果Spring UserApiDelegate在應用程式上下文中找到我們的實現,它將注入到控制器的建構函式中。否則,將使用預設實現。
讓我們啟動應用程式並點選GET端點/v2/user/{username}。
curl -I http://localhost:8080/v2/user/Petros HTTP/1.1 501 Content-Length: 0 |
但是為什麼我們會收到501響應(未實現)?
因為我們沒有實現UserApiDelegate介面,所以UserApiController使用了預設介面,該介面 返回HttpStatus.NOT_IMPLEMENTED。
現在讓我們實現UserApiDelegate:
@Service public class UserApiDelegateImpl implements UserApiDelegate { @Override public ResponseEntity<User> getUserByName(String username) { User user = new User(); user.setId(123L); user.setFirstName("Petros"); // ... omit other initialization return ResponseEntity.ok(user); } } |
在類中新增@Service或@Component批註很重要,以便Spring可以將其拾取並注入到中UserApiController。
如果現在curl http://localhost:8080/v2/user/Petros再次執行,將收到有效的JSON響應:
{ "id": 123, "firstName": "Petros", // ... omit other properties } |
我認為,使用Maven外掛而不是Swagger Editor生成OpenAPI規範是更好的選擇。那是因為我們對我們的選擇有更多的控制權。該外掛提供了一些配置和使用Git作為版本控制工具,我們可以放心地跟蹤在任的任何變化pom.xml和openapi.yml。
可以在GitHub上瀏覽示例程式碼。
相關文章
- 使用Spring Boot REST API進行測試驅動開發Spring BootRESTAPI
- 使用 Kotlin + Spring Boot 進行後端開發KotlinSpring Boot後端
- Spring Boot整合swagger使用教程Spring BootSwagger
- Spring Boot使用MyBatis Generator、SwaggerSpring BootMyBatisSwagger
- 使用 Spring Boot 和 @SpringBootTest 進行測試Spring Boot
- Spring Boot:Spring Boot配置SwaggerSpring BootSwagger
- Spring Boot整合SwaggerSpring BootSwagger
- Spring Boot系列十九 Spring boot整合 swaggerSpring BootSwagger
- Spring boot 之自動生成API文件swagger2Spring BootAPISwagger
- Gradle進階:1: 結合spring boot進行web開發GradleSpring BootWeb
- Spring Boot 快速整合SwaggerSpring BootSwagger
- 【Spring Boot】快速整合SwaggerSpring BootSwagger
- Spring Boot2中Swagger3使用Spring BootSwagger
- 使用Spring Boot DevTools優化你的開發體驗Spring Bootdev優化
- 使用API進行區塊鏈開發API區塊鏈
- 如何使用Spring Boot和Flyway建立不同資料庫的多租戶應用? - reflectoring.ioSpring Boot資料庫
- Spring Boot使用JWT進行token驗證Spring BootJWT
- 使用 Spring Boot 進行單元測試Spring Boot
- Spring Boot 整合 Swagger2,構建強大的 API 文件Spring BootSwaggerAPI
- Spring Boot 整合 SpringDoc Swagger 3Spring BootSwagger
- spring-boot 使用hibernate validation對引數進行優雅的校驗Springboot
- spring boot 使用redis進行釋出訂閱Spring BootRedis
- 開始使用GraphQL Java和Spring BootJavaSpring Boot
- Spring Boot如何生成swagger.json?Spring BootSwaggerJSON
- Spring Boot 教程 (4) - swagger-uiSpring BootSwaggerUI
- 使用Spring Boot開發Web專案Spring BootWeb
- 如何使用Spring Boot,Spring Data和H2 DB實現REST APISpring BootRESTAPI
- Spring Cloud Zuul中使用Swagger彙總API介面文件SpringCloudZuulSwaggerAPI
- Spring Boot整合Springfox Swagger3和簡單應用Spring BootSwagger
- 如何在spring boot 使用 gitlab的ApiSpring BootGitlabAPI
- 在Spring Boot設定Swagger 2 - BaeldungSpring BootSwagger
- Spring Boot 整合 Swagger 構建介面文件Spring BootSwagger
- 使用Spring Boot和GraphQL構建靈活的API服務Spring BootAPI
- 測試開發專題:spring-boot如何使用JPA進行雙向一對多配置Springboot
- 使用Spring Boot + Redis 進行實時流處理 - vinsguruSpring BootRedis
- Spring Boot中使用Swagger2構建RESTful APIs介紹Spring BootSwaggerRESTAPI
- 手把手教你Spring Boot整合Mybatis Plus和Swagger2Spring BootMyBatisSwagger
- sqlserver使用order by case when進行優先順序排序SQLServer排序