a new and efficient development model, to achieve code and API separation, efficient development, development must see!!!

什么是openapi 3.0

OpenAPI 3.0.0 是 OpenAPI The first official version of the specification,因为它是由 SmartBear Software 捐赠给 OpenAPI Initiative,并在2015年从 Swagger 规范重命名为 OpenAPI 规范.

介绍:

OpenAPI 规范(OAS),is to define a standard、programming language-independentRESTful API的规范.OpenAPI Specifications enable both humans and computers to“Do not contact with any program source code and documentation、Does not monitor network traffic”understand the role of a service in the context of.If you are defining your API well done,那么使用 API of people can easily understand what you provide API And interact with it.

如果您遵循 OpenAPI 规范来定义您的 API,then you can use the documentation generator to present your API,Use code generation tools to automatically generate server-side and client-side code in various programming languages,Testing with automated testing tools and more.

具体请看官方文档

openapi 中文文档 openapi.apifox.cn/

swagger openapi3.0官方文档 swagger.io/specification/

Please be sure to read the official documentation first,Avoid below foryamlconfiguration cannot be understood,No need to memorize,Because the usual configuration will not check the documentation

swagger editor.swagger.io/ 在线查看文档

为什么需要openapi3.0

在以往的项目中,If the project wants to provideapi文档的话,有二种方法,

Is a kind of integration projectsswaager ,Then use annotations to generate accessible to the other partyapi文档,Provide convenience when docking with the front end

优点: externally accessibleapi

缺点:The code has serious invasive,不可维护,Need to write a lot of unnecessary code in the control layer

框架代表: swagger2.0, knife4j

代码示例:

加入配置:

 @Bean(value = "defaultApi2")
public Docket defaultApi2() {
Docket docket=new Docket(DocumentationType.SWAGGER_2)
.apiInfo(new ApiInfoBuilder()
//.title("swagger-bootstrap-ui-demo RESTful APIs")
.description("# swagger-bootstrap-ui-demo RESTful APIs")
.termsOfServiceUrl("http://www.xx.com/")
.contact("[email protected]")
.version("1.0")
.build())
//分组名称
.groupName("2.X版本")
.select()
//这里指定Controller扫描包路径
.apis(RequestHandlerSelectors.basePackage("com.example.springbootknife4jintegrate.controller"))
.paths(PathSelectors.any())
.build();
return docket;
}

The control layer needs to add more annotations

 @ApiImplicitParam(name = "name",value = "姓名",required = true)
@ApiOperation(value = "例子")
@ApiOperationSupport(author = "[email protected]")

and need to add some configuration,这对于开发来说,非常难受.

第二种.By the development of manual to provide external access to write the interface document

例如 小幺鸡,yapi, apifox They can all provide the interface address for online access,但是,Requires developers to fill in manually,Seriously delay the development progress

How to solve the new development model

First look at the project structure diagram

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JoEhnqyx-1659105806398)(/Users/qurenneng/Library/Application Support/typora-user-images/image-20220729214718750.png)]

apiConnected with the business system,apiService interface design,提供对外访问的api文档,Responsible for implementing the business systemAPI接口.

优点:

1.Section coupling:The business system does not need to write some unnecessary configuration,以及注解.

2.安全:All interface permissions are a service,对apicontrol is more efficient

3.开发高效,Development to design interface,Then give to the front-end interface document first,subsequently developing,No need to wait for both parties

4.对于开发来说,Define the interface first,More clear for the business logic,To avoid the worker

架构实现

1.api服务

新建一个springbootConfiguration since the project was added

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>spring-boot-openapi-integrat</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-openapi-integrat</name>
<description>spring-boot-openapi-integrat</description>
<properties>
<openapi.generator.version>5.2.0</openapi.generator.version>
<openapi.package>com.openapi</openapi.package>
//jdk版本在11或更高版本
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- spring web 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>org.openapitools</groupId>
<artifactId>jackson-databind-nullable</artifactId>
<version>0.2.1</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.5.22</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>3.0.0-M1</version>
<configuration>
<updateReleaseInfo>true</updateReleaseInfo>
</configuration>
</plugin>
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>${openapi.generator.version}</version>
<executions>
<execution>
<id>open</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<!-- API specifications should be split to multiple YML files, when the feature is implemented:
https://github.com/OpenAPITools/openapi-generator/issues/6379 -->
//api定义的yml文件所在
<inputSpec>${project.basedir}/src/main/resources/openapi.yaml</inputSpec>
<generatorName>spring</generatorName>
<apiPackage>${openapi.package}.open.controller</apiPackage>
<modelPackage>${openapi.package}.open.controller.model</modelPackage>
<supportingFilesToGenerate>ApiUtil.java</supportingFilesToGenerate>
<modelNamePrefix>Open</modelNamePrefix>
//如果api定义为 /users 或者 /oders So here to add to the path of the order Otherwise unable to generate the correspondingapi接口
<apisToGenerate>users</apisToGenerate>
<configOptions>
<delegatePattern>true</delegatePattern>
</configOptions>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

添加配置文件: openapi.yaml 名称可以随便命名,不过pom.xmlwhere needs to be modified

For configuration, you can only go to the official documentation yourself or if you really don’t know it,就访问 editor.swagger.io/ 地址

There’s some cases,复制下来,放到yaml文件中
在这里插入图片描述

Just protect yourself

I’ll post my example:

openapi: 3.0.3
info:
title: SpringBoot Open APIs
description: SpringBoot Open APIs
version: 1.0.0-SNAPSHOT
externalDocs:
description: Check the source code here
url: https://gitee.com/xxx/spring-boot-integrate
servers:
- url: http://localhost:8080/v1
description: LOCAL Environment
variables:
env:
default: dev
enum:
- dev # DEVELOPMENT ENVIRONMENT
- gamma # GAMMA ENVIRONMENT
- url: http://localhost:8080/v1
description: applicationion Environment URL
paths:
/users:
get:
summary: '检索用户'
description: 'Retrieve all user information under the account'
operationId: ListUsers
parameters:
- $ref: '#/components/parameters/IndexParam'
- $ref: '#/components/parameters/LimitParam'
- name: name
description: '用户名'
in: query
schema:
type: string
minLength: 2
maxLength: 255
- name: keyword
description: '模糊搜索'
in: query
schema:
type: string
responses:
'200':
description: '用户列表'
content:
application/json:
schema:
$ref: '#/components/schemas/UserList'
'500':
$ref: '#/components/responses/Fault'
default:
$ref: '#/components/responses/Error'
post:
summary: '添加用户'
description: '添加用户信息'
operationId: CreateUser
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/CreateUserRequest'
responses:
'201':
description: '创建用户成功'
content:
application/json:
schema:
$ref: '#/components/schemas/User'
'500':
$ref: '#/components/responses/Fault'
default:
$ref: '#/components/responses/Error'
/users/{id}:
delete:
summary: '删除用户'
description: '删除用户信息'
operationId: DeleteUser
parameters:
- name: id
in: path
schema:
type: string
required: true
responses:
'200':
description: '删除用户成功'
'500':
$ref: '#/components/responses/Fault'
default:
$ref: '#/components/responses/Error'
put:
summary: '更新用户'
description: '更新用户信息'
operationId: UpateUser
parameters:
- name: id
in: path
schema:
type: string
required: true
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/UpateUserRequest'
responses:
'200':
description: '更新用户成功'
content:
application/json:
schema:
$ref: '#/components/schemas/User'
'500':
$ref: '#/components/responses/Fault'
default:
$ref: '#/components/responses/Error'
components:
securitySchemes:
ApiKeyAuth: # arbitrary name for the security scheme
type: apiKey
name: Authorization # name of the header, query parameter or cookie
in: header # can be "header", "query" or "cookie"
schemas:
UpateUserRequest:
type: object
properties:
name:
description: '用户的名称'
type: string
minLength: 2
maxLength: 64
remark:
description: '用户备注'
type: string
CreateUserRequest:
type: object
properties:
name:
description: '用户的名称'
type: string
minLength: 2
maxLength: 64
remark:
description: '用户备注'
type: string
UserList:
description: '用户列表'
type: object
properties:
users:
description: '用户列表'
type: array
items:
$ref: '#/components/schemas/User'
pagination:
$ref: '#/components/schemas/Pagination'
User:
description: '用户'
type: object
properties:
id:
description: '用户的唯一标识'
type: string
name:
description: '用户的名称'
type: string
minLength: 2
maxLength: 64
remark:
description: '用户备注'
type: string
Pagination:
description: '分页'
type: object
properties:
index:
type: integer
description: '当前页'
limit:
type: integer
description: '每页数量'
total:
type: integer
format: int64
description: '总数'
Error:
type: object
properties:
error:
allOf:
- $ref: '#/components/schemas/ErrorBody'
- type: object
properties:
details:
type: array
items:
$ref: '#/components/schemas/ErrorBody'
required: [ error ]
Fault:
type: object
properties:
fault:
type: object
properties:
code:
type: string
default: "InternalFault"
message:
type: string
default: "服务内部错误, 请联系管理员"
ErrorBody:
type: object
properties:
code:
type: string
id:
type: string
message:
type: string
target:
type: string
required: [ code, id, message ]
parameters:
IndexParam:
name: index
in: query
description: "当前页"
schema:
type: integer
minimum: 1
default: 1
LimitParam:
name: limit
in: query
description: "每页数量"
schema:
type: integer
default: 10

It defines the user some basic operations.

定义好了之后,我们使用mavencommand to generate the corresponding code

mvn clean compile package

如果成功的话,will generate a corresponding projecttarget目录,里面的class The directory corresponds to the generated interface.

The complete project
在这里插入图片描述

说明apiService and build successfully,Next we need to set up the service layer.

2.业务服务

Still create a new onespringboot服务

Pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>spring-boot-api-service-integrat</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-api-service-integrat</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>spring-boot-openapi-integrat</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

请注意,增加了一个api服务的依赖 spring-boot-openapi-integrat This is we just newly builtapi服务

控制层

/**
* Realize the generated interface,Then you can implement the corresponding service
*/
public class UsersApiDelegateImpl implements UsersApiDelegate {
private final UserService userService;
private final UserConversion userConversion;
public UsersApiDelegateImpl(UserService userService,UserConversion userConversion) {
this.userService = userService;
this.userConversion = userConversion;
}
@Override
public ResponseEntity<OpenUser> createUser(OpenCreateUserRequest openCreateUserRequest) {
User user = this.userService.createUser(this.userConversion.toUser(openCreateUserRequest));
return ResponseEntity.status(HttpStatus.CREATED).body(this.userConversion.toControllerOpenUser(user));
}
@Override
public ResponseEntity<Void> deleteUser(String id) {
this.userService.deleteUser(id);
return ResponseEntity.ok().build();
}
@Override
public ResponseEntity<OpenUser> upateUser(String id, OpenUpateUserRequest openUpateUserRequest) {
User user = this.userService.upateUser(id, this.userConversion.toUser(openUpateUserRequest));
return ResponseEntity.status(HttpStatus.CREATED).body(this.userConversion.toControllerOpenUser(user));
}
}

这里实现了apiService generated interface,然后,In the control layer to implement the corresponding interface,

转换层

一般来说,The object passed by the control layer needs a special trip model 层,然后才能在 serviceLayer for service operation development,Then when operating the database, it needs to be converted to the entity corresponding to the database layer,The advantage of this is isolation.

代码示例:

@Component
public class UserConversion {
public User toUser(OpenCreateUserRequest openCreateUserRequest){
return new User().setName(openCreateUserRequest.getName())
.setRemark(openCreateUserRequest.getRemark());
}
public User toUser(OpenUpateUserRequest openUpateUserRequest){
return new User().setName(openUpateUserRequest.getName())
.setRemark(openUpateUserRequest.getRemark());
}
public OpenUser toControllerOpenUser(User user){
if(user == null) return null;
return new OpenUser().id(String.valueOf(user.getId()))
.name(user.getName())
.remark(user.getRemark());
}
}

启动项目,If we want to add user then request

http://localhost:8080/v1/users post

在这里插入图片描述

其他请求同理,

总结

Open3.0 Development mode is not just for development,Is good for the whole company,开发的api逻辑清晰,Efficient front-end docking,Every field has comments

统一的result api风格,对外提供api更加便捷,Ok got here in this paper,Favorite classmates pay attention to the author,谢谢.

Read more here: Source link