searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

一个基于k8s的轻量级java应用脚手架设计

2024-12-17 09:12:16
0
0

一个好用的企业级java应用脚手架设计可以大大提高企业的研发效率,在本文中将结合个人实践经验探讨如何设计这样的一个脚手架。

脚手架主要满足以下要求:

1、应用部署简单,适合于企业级大规模的应用部署,比如基于k8s体系+标准化的CICD体系

2、标准的代码规范,让研发人员快速上手,比如:restful的openai接口规范,mysql规范

3、配置信息能够尽量和代码一起同步,可以支持随时回滚,保证生产环境发布的安全

4、java脚手架尽量提供必备的工具包提升研发效率:比如sql自动生成,通过openapi规范后端代码自动生成

部署方案:

部署流程:

image (5).png

配置文件代码结构:
image (6).png

● 不同环境的配置文件通过git代码分支版本管理,引入helms

包含以下yaml文件(deployment,configmap,service,ingress)

● secret.yaml包含敏感信息,不能放入git,通过pod的环境变量导入

● 通过gitlab的webhook触发流程+argocd实现自动化的CICD

● configmap的key-value集中管理,直接通过Spring Kubernetes PropertySource 实现

● 开发阶段如果启动,使用spring的application-profile.yaml方式启动

工具类规范

● 日志框架

使用默认的 logback.xml 定义格式等

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

private final static Logger log = LoggerFactory.getLogger(XXX.class);

log.error(XXXX);

● 数据库ORM框架:可以自动生成dao类

<dependency>
      <groupId>com.baomidou</groupId>
      <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
    </dependency>

    <dependency>
      <groupId>com.baomidou</groupId>
      <artifactId>mybatis-plus-generator</artifactId>
    </dependency>

可以参考使用 cn.ctyun.agent.builder.app.CodeGenerator.java 自动生成mybatisplus代码

● json序列化框架

<dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.10</version>
        </dependency>
        
        或者使用spring 内置的 jackson 做json序列化

POJO定义规范

  1. VO(View Object):展示对象,它用于表示层展示数据。在Web应用中,VO通常用于Web层向模板渲染引擎层传输的对象,封装了页面所需的数据。
  2. BO(Business Object):业务对象,它封装了业务逻辑,可以包含一个或多个其他对象,如PO或DO。BO对应具体的业务块,例如,一个用户的BO可能包含其个人信息、交易记录等多个PO。
  3. PO(Persistent Object):持久化对象,通常与数据库中的表结构一一对应。PO是简单的数据对象,通常只包含属性和访问这些属性的getter和setter方法。它们通过ORM(对象关系映射)框架与数据库表进行映射。
  4. DO(Domain Object):领域对象,是从现实世界中抽象出来的业务实体。在领域驱动设计(DDD)中,DO通常包含业务逻辑,并且可以与PO一一对应,也可以包含多个PO。DO是业务领域内的核心对象,代表了特定的业务概念。

openapi.yaml文档定义规范

以Product对象的增删改查为例

接口名称 提交方式 路径 参数说明
添加产品 POST /products 请求体: Product 对象,包含以下字段: ● id (整数, int64): 产品ID ● name (字符串): 产品名称 ● type (整数, int32): 产品类型 ● createTime (字符串, date-time): 创建时间 ● price (数字, double): 产品价格 ● show (布尔): 是否展示 ● password (字符串, password): 产品密码
根据ID获取产品 GET /products/{id} 路径参数: ● id (整数, int64): 产品ID
更新产品信息 PUT /products/{id} 路径参数: ● id (整数, int64): 产品ID请求体: Product 对象,字段同上
删除产品信息 DELETE /products/{id} 路径参数: ● id (整数, int64): 产品ID
获取产品列表 GET /products
批量删除 DELETE /products 请求体: id数组 对象

推荐使用标准的restful风格的openapi3规范书写

openapi: "3.0.3"
info:
  title: inventory-api
  version: 1.0.0
servers:
  - url: 127.0.0.1:8080
paths:
  /products:
    get:
      tags:
        - Product
      description: 获取所有产品
      operationId: getAllProducts
      responses:
        '200':
          description: 成功返回所有产品
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProductList'
        '404':
          description: 未找到任何产品
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
    post:
      tags:
        - Product
      description: 添加产品
      operationId: addProduct
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Product'
      responses:
        '201':
          description: 产品添加成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Product'
        '400':
          description: 请求错误
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /products/{id}:
    get:
      tags:
        - Product
      description: 根据 ID 获取产品
      operationId: getProductById
      parameters:
        - in: path
          name: id
          schema:
            type: integer
            format: int64
            description: 产品 ID
          required: true
      responses:
        '200':
          description: 成功获取产品
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Product'
        '404':
          description: 未找到产品
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
    put:
      tags:
        - Product
      description: 更新产品信息
      operationId: updateProduct
      parameters:
        - in: path
          name: id
          schema:
            type: integer
            format: int64
            description: 产品 ID
          required: true
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Product'
      responses:
        '200':
          description: 产品更新成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Product'
        '400':
          description: 请求错误
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: 产品不存在
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
    delete:
      tags:
        - Product
      description: 删除指定 ID 的产品
      operationId: deleteProductById
      parameters:
        - in: path
          name: id
          schema:
            type: integer
            format: int64
            description: 产品 ID
          required: true
      responses:
        '204':
          description: 产品删除成功
        '404':
          description: 产品不存在
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    ProductList:
      type: array
      items:
        $ref: '#/components/schemas/Product'

    Product:
      type: object
      properties:
        id:
          type: integer
          format: int64
          description: 产品 ID
        name:
          type: string
          description: 产品名称
        type:
          type: integer
          format: int32
          description: 产品类型
        create_time:
          type: string
          format: date-time
          description: 产品创建时间
        price:
          type: number
          format: double
          description: 产品价格
        show:
          type: boolean
          description: 产品是否显示
        password:
          type: string
          format: password
          description: 产品密码
    Error:
      type: object
      properties:
        message:
          type: string

Controller层定义规范

以下是运行 mvn clean package 命令:

openapi-processor-maven-plugin插件自动生成的代码:

package io.openapiprocessor.generated.api;

import io.openapiprocessor.generated.model.ProductVO;
import io.openapiprocessor.generated.support.Generated;
import java.util.List;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;

@Generated(value = "openapi-processor-spring", version = "2024.1", date = "2024-08-15T21:03:15.601329+08:00")
public interface ProductApi {

    @GetMapping(path = "/products", produces = {"application/json"})
    ResponseEntity<List<ProductVO>> getAllProducts();

    @PostMapping(path = "/products", consumes = {"application/json"}, produces = {"application/json"})
    ResponseEntity<ProductVO> addProduct(@RequestBody(required = false) ProductVO body);

    @GetMapping(path = "/products/{id}", produces = {"application/json"})
    ResponseEntity<ProductVO> getProductById(@PathVariable(name = "id") Long id);

    @PutMapping(path = "/products/{id}", consumes = {"application/json"}, produces = {"application/json"})
    ResponseEntity<ProductVO> updateProduct(
            @PathVariable(name = "id") Long id,
            @RequestBody(required = false) ProductVO body);

    @DeleteMapping(path = "/products/{id}", produces = {"application/json"})
    ResponseEntity<Void> deleteProductById(@PathVariable(name = "id") Long id);

}

在source目录写一个RestController 实现ProductApi即可。

0条评论
0 / 1000
c****b
2文章数
0粉丝数
c****b
2 文章 | 0 粉丝
c****b
2文章数
0粉丝数
c****b
2 文章 | 0 粉丝
原创

一个基于k8s的轻量级java应用脚手架设计

2024-12-17 09:12:16
0
0

一个好用的企业级java应用脚手架设计可以大大提高企业的研发效率,在本文中将结合个人实践经验探讨如何设计这样的一个脚手架。

脚手架主要满足以下要求:

1、应用部署简单,适合于企业级大规模的应用部署,比如基于k8s体系+标准化的CICD体系

2、标准的代码规范,让研发人员快速上手,比如:restful的openai接口规范,mysql规范

3、配置信息能够尽量和代码一起同步,可以支持随时回滚,保证生产环境发布的安全

4、java脚手架尽量提供必备的工具包提升研发效率:比如sql自动生成,通过openapi规范后端代码自动生成

部署方案:

部署流程:

image (5).png

配置文件代码结构:
image (6).png

● 不同环境的配置文件通过git代码分支版本管理,引入helms

包含以下yaml文件(deployment,configmap,service,ingress)

● secret.yaml包含敏感信息,不能放入git,通过pod的环境变量导入

● 通过gitlab的webhook触发流程+argocd实现自动化的CICD

● configmap的key-value集中管理,直接通过Spring Kubernetes PropertySource 实现

● 开发阶段如果启动,使用spring的application-profile.yaml方式启动

工具类规范

● 日志框架

使用默认的 logback.xml 定义格式等

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

private final static Logger log = LoggerFactory.getLogger(XXX.class);

log.error(XXXX);

● 数据库ORM框架:可以自动生成dao类

<dependency>
      <groupId>com.baomidou</groupId>
      <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
    </dependency>

    <dependency>
      <groupId>com.baomidou</groupId>
      <artifactId>mybatis-plus-generator</artifactId>
    </dependency>

可以参考使用 cn.ctyun.agent.builder.app.CodeGenerator.java 自动生成mybatisplus代码

● json序列化框架

<dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.10</version>
        </dependency>
        
        或者使用spring 内置的 jackson 做json序列化

POJO定义规范

  1. VO(View Object):展示对象,它用于表示层展示数据。在Web应用中,VO通常用于Web层向模板渲染引擎层传输的对象,封装了页面所需的数据。
  2. BO(Business Object):业务对象,它封装了业务逻辑,可以包含一个或多个其他对象,如PO或DO。BO对应具体的业务块,例如,一个用户的BO可能包含其个人信息、交易记录等多个PO。
  3. PO(Persistent Object):持久化对象,通常与数据库中的表结构一一对应。PO是简单的数据对象,通常只包含属性和访问这些属性的getter和setter方法。它们通过ORM(对象关系映射)框架与数据库表进行映射。
  4. DO(Domain Object):领域对象,是从现实世界中抽象出来的业务实体。在领域驱动设计(DDD)中,DO通常包含业务逻辑,并且可以与PO一一对应,也可以包含多个PO。DO是业务领域内的核心对象,代表了特定的业务概念。

openapi.yaml文档定义规范

以Product对象的增删改查为例

接口名称 提交方式 路径 参数说明
添加产品 POST /products 请求体: Product 对象,包含以下字段: ● id (整数, int64): 产品ID ● name (字符串): 产品名称 ● type (整数, int32): 产品类型 ● createTime (字符串, date-time): 创建时间 ● price (数字, double): 产品价格 ● show (布尔): 是否展示 ● password (字符串, password): 产品密码
根据ID获取产品 GET /products/{id} 路径参数: ● id (整数, int64): 产品ID
更新产品信息 PUT /products/{id} 路径参数: ● id (整数, int64): 产品ID请求体: Product 对象,字段同上
删除产品信息 DELETE /products/{id} 路径参数: ● id (整数, int64): 产品ID
获取产品列表 GET /products
批量删除 DELETE /products 请求体: id数组 对象

推荐使用标准的restful风格的openapi3规范书写

openapi: "3.0.3"
info:
  title: inventory-api
  version: 1.0.0
servers:
  - url: 127.0.0.1:8080
paths:
  /products:
    get:
      tags:
        - Product
      description: 获取所有产品
      operationId: getAllProducts
      responses:
        '200':
          description: 成功返回所有产品
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProductList'
        '404':
          description: 未找到任何产品
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
    post:
      tags:
        - Product
      description: 添加产品
      operationId: addProduct
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Product'
      responses:
        '201':
          description: 产品添加成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Product'
        '400':
          description: 请求错误
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /products/{id}:
    get:
      tags:
        - Product
      description: 根据 ID 获取产品
      operationId: getProductById
      parameters:
        - in: path
          name: id
          schema:
            type: integer
            format: int64
            description: 产品 ID
          required: true
      responses:
        '200':
          description: 成功获取产品
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Product'
        '404':
          description: 未找到产品
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
    put:
      tags:
        - Product
      description: 更新产品信息
      operationId: updateProduct
      parameters:
        - in: path
          name: id
          schema:
            type: integer
            format: int64
            description: 产品 ID
          required: true
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Product'
      responses:
        '200':
          description: 产品更新成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Product'
        '400':
          description: 请求错误
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: 产品不存在
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
    delete:
      tags:
        - Product
      description: 删除指定 ID 的产品
      operationId: deleteProductById
      parameters:
        - in: path
          name: id
          schema:
            type: integer
            format: int64
            description: 产品 ID
          required: true
      responses:
        '204':
          description: 产品删除成功
        '404':
          description: 产品不存在
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    ProductList:
      type: array
      items:
        $ref: '#/components/schemas/Product'

    Product:
      type: object
      properties:
        id:
          type: integer
          format: int64
          description: 产品 ID
        name:
          type: string
          description: 产品名称
        type:
          type: integer
          format: int32
          description: 产品类型
        create_time:
          type: string
          format: date-time
          description: 产品创建时间
        price:
          type: number
          format: double
          description: 产品价格
        show:
          type: boolean
          description: 产品是否显示
        password:
          type: string
          format: password
          description: 产品密码
    Error:
      type: object
      properties:
        message:
          type: string

Controller层定义规范

以下是运行 mvn clean package 命令:

openapi-processor-maven-plugin插件自动生成的代码:

package io.openapiprocessor.generated.api;

import io.openapiprocessor.generated.model.ProductVO;
import io.openapiprocessor.generated.support.Generated;
import java.util.List;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;

@Generated(value = "openapi-processor-spring", version = "2024.1", date = "2024-08-15T21:03:15.601329+08:00")
public interface ProductApi {

    @GetMapping(path = "/products", produces = {"application/json"})
    ResponseEntity<List<ProductVO>> getAllProducts();

    @PostMapping(path = "/products", consumes = {"application/json"}, produces = {"application/json"})
    ResponseEntity<ProductVO> addProduct(@RequestBody(required = false) ProductVO body);

    @GetMapping(path = "/products/{id}", produces = {"application/json"})
    ResponseEntity<ProductVO> getProductById(@PathVariable(name = "id") Long id);

    @PutMapping(path = "/products/{id}", consumes = {"application/json"}, produces = {"application/json"})
    ResponseEntity<ProductVO> updateProduct(
            @PathVariable(name = "id") Long id,
            @RequestBody(required = false) ProductVO body);

    @DeleteMapping(path = "/products/{id}", produces = {"application/json"})
    ResponseEntity<Void> deleteProductById(@PathVariable(name = "id") Long id);

}

在source目录写一个RestController 实现ProductApi即可。

文章来自个人专栏
openapi规范
2 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0