• OPENAPI3.0 与 SpringBoot 开发实战: 新型高效开发模式,实现代码与API分离,高效开发,开发必看!!!


    什么是openapi 3.0

    OpenAPI 3.0.0 是 OpenAPI 规范的第一个正式版本,因为它是由 SmartBear Software 捐赠给 OpenAPI Initiative,并在2015年从 Swagger 规范重命名为 OpenAPI 规范。

    介绍:

    OpenAPI 规范(OAS),是定义一个标准的、与具体编程语言无关的RESTful API的规范。OpenAPI 规范使得人类和计算机都能在“不接触任何程序源代码和文档、不监控网络通信”的情况下理解一个服务的作用。如果您在定义您的 API 时做的很好,那么使用 API 的人就能非常轻松地理解您提供的 API 并与之交互了。

    如果您遵循 OpenAPI 规范来定义您的 API,那么您就可以用文档生成工具来展示您的 API,用代码生成工具来自动生成各种编程语言的服务器端和客户端的代码,用自动测试工具进行测试等等。

    具体请看官方文档

    openapi 中文文档 https://openapi.apifox.cn/

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

    请大家一定要先看看官方文档,避免下文对于yaml的配置无法理解,也不需要死记,因为平常的配置不会就查文档

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

    为什么需要openapi3.0

    在以往的项目中,如果项目想要给别人提供api文档的话,有二种方法,

    一种就是项目集成swaager ,然后通过注解的方式来生成对方可访问的api文档,在与前端对接的时候提供便利

    优点: 提供了对外可访问的api

    缺点:对代码有严重的侵入式,不可维护,需要在控制层写很多不必要的代码

    框架代表: 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("1796789910@qq.com")
                            .version("1.0")
                            .build())
                    //分组名称
                    .groupName("2.X版本")
                    .select()
                    //这里指定Controller扫描包路径
                    .apis(RequestHandlerSelectors.basePackage("com.example.springbootknife4jintegrate.controller"))
                    .paths(PathSelectors.any())
                    .build();
            return docket;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    控制层需要加入更多注解

     @ApiImplicitParam(name = "name",value = "姓名",required = true)
        @ApiOperation(value = "例子")
        @ApiOperationSupport(author = "1796789910@qq.com")
    
    • 1
    • 2
    • 3

    并且需要加入一些配置,这对于开发来说,非常难受.

    第二种.由开发手动去编写接口文档提供外部访问

    例如 小幺鸡,yapi, apifox 他们都可以提供在线访问的接口地址,但是,需要开发人员手动去填写,严重耽误开发进度

    新型开发模式如何解决

    先看下项目架构图

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

    api与业务系统节藕开,api服务只设计接口,提供对外访问的api文档,业务系统负责实现API接口.

    优点:

    1.节藕合:业务系统不需要去写一些不必要的配置,以及注解.

    2.安全:所有的接口权限是一个服务,对api的控制更加高效

    3.开发高效,开发先设计接口,然后先把接口文档给到前端,随后在开发,双方无需等待

    4.对于开发来说,先定义清楚接口,对于业务逻辑更加清晰,避免反工

    架构实现

    1.api服务

    新建一个springboot项目增加以来配置

    pom.xml:

    
    
      4.0.0
      
        org.springframework.boot
        spring-boot-starter-parent
        2.7.2
         
      
      com.example
      spring-boot-openapi-integrat
      0.0.1-SNAPSHOT
      spring-boot-openapi-integrat
      spring-boot-openapi-integrat
      
        5.2.0
        com.openapi
        //jdk版本在11或更高版本
        11
        11
        UTF-8
      
    
      
        
        
          org.springframework.boot
          spring-boot-starter-web
        
        
          jakarta.validation
          jakarta.validation-api
          2.0.2
        
        
          org.openapitools
          jackson-databind-nullable
          0.2.1
        
        
          io.springfox
          springfox-swagger2
          3.0.0
        
        
          io.swagger
          swagger-annotations
          1.5.22
        
      
    
      
        
          
            org.apache.maven.plugins
            maven-deploy-plugin
            3.0.0-M1
            
              true
            
          
    
          
            org.openapitools
            openapi-generator-maven-plugin
            ${openapi.generator.version}
            
              
                open
                
                  generate
                
                
                  
                  //api定义的yml文件所在 
                  ${project.basedir}/src/main/resources/openapi.yaml
                  spring
                  ${openapi.package}.open.controller
                  ${openapi.package}.open.controller.model
                  ApiUtil.java
                  Open
                  //如果api定义为 /users 或者 /oders 那么这里要加上对于的路径 order 否则无法生成对应的api接口
                  users
                  
                    true
                  
                
              
            
          
        
      
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96

    添加配置文件: openapi.yaml 名称可以随便命名,不过pom.xml哪里也需要修改

    配置就只能自己去看官方文档了或者如果实在不知道的,就访问 https://editor.swagger.io/ 地址

    里面会有一些案例,复制下来,放到yaml文件中
    在这里插入图片描述

    自己防着来一下就好了

    我贴上我的例子吧:

    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: '检索帐号下所有用户信息'
          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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238

    里面定义了用户的一些基本操作.

    定义好了之后,我们使用maven的命令来生成对应的代码

    mvn clean compile package
    
    • 1

    如果成功的话,会在对应的项目中生成一个target目录,里面的class 目录里面就对应生成的接口了

    完整的项目图
    在这里插入图片描述

    说明api服务以及搭建成功了,接下来我们需要搭建服务层.

    2.业务服务

    还是一样新建一个springboot服务

    Pom.xml:

    
    
        4.0.0
        
            org.springframework.boot
            spring-boot-starter-parent
            2.4.5
             
        
        com.example
        spring-boot-api-service-integrat
        0.0.1-SNAPSHOT
        spring-boot-api-service-integrat
        Demo project for Spring Boot
        
            1.8
        
        
            
                com.example
                spring-boot-openapi-integrat
                0.0.1-SNAPSHOT
            
            
                org.springframework.boot
                spring-boot-starter-data-jpa
            
            
                org.springframework.boot
                spring-boot-starter-web
            
            
                org.springframework.boot
                spring-boot-devtools
                runtime
                true
            
    
            
                mysql
                mysql-connector-java
                runtime
            
    
            
                org.springframework.boot
                spring-boot-starter-test
                test
            
    
            
                org.projectlombok
                lombok
                1.18.20
                provided
            
    
        
    
        
            
                
                    org.springframework.boot
                    spring-boot-maven-plugin
                
            
        
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71

    请注意,增加了一个api服务的依赖 spring-boot-openapi-integrat 这是我们刚刚新建的api服务

    控制层

    /**
     * 实现生成的接口,然后实现对应的服务既可
     */
    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 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 deleteUser(String id) {
            this.userService.deleteUser(id);
            return ResponseEntity.ok().build();
        }
    
        @Override
        public ResponseEntity 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));
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    这里实现了api服务生成的接口,然后,在控制层去实现对应的接口就好了,

    转换层

    一般来说,控制层传递的对象需要专程 model 层,然后才能在 service层进行服务操作开发,然后在操作数据库的时候需要转换为数据库层对应的实体,这样子做的好处是隔离.

    代码示例:

    @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());
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    启动项目,如果我们想添加用户的话请求

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

    在这里插入图片描述

    其他请求同理,

    总结

    Open3.0 开发模式不仅仅是对于开发来说,对于整个公司都是有利的,开发的api逻辑清晰,前端对接高效,每个字段都有注释

    统一的result api风格,对外提供api更加便捷,好了文章介绍就到这里了,喜欢的同学给作者点个关注,谢谢.

  • 相关阅读:
    Embind进阶用法(vector)
    疫苗预约小程序,疫苗预约微信小程序,疫苗接种小程序毕业设计作品
    mapstruct进阶属性
    [SpringMVC]基于RESTful页面数据交互案例
    【Flink】使用水位线实现热门商品排行以及Flink如何处理迟到元素
    markdown语法转换成html渲染到页面
    为什么使用前端框架
    HTML学生个人网站作业设计成品 HTML+CSS肖战明星人物介绍网页 web结课作业的源码...
    背包问题详解(含代码)
    tsne 学习使用
  • 原文地址:https://blog.csdn.net/qq_41971087/article/details/126065322