数据服务层 API 具体源码实现

对于数据中台描述,我需要将情况讲清楚。

从一个具体的 Java 的 Data Object 对象的实现层面。

启动流程

qData 使用的是 Spring Boot 的框架。

在实现上,数据服务层的抽象使用 ApplicationRunner 接口实现,也就是说, DS API 的持续服务提供功能的初始启动状态是作为组件启动的。

具体情况中,我们的 qdata-module-ds 微服务启动时,位于 package tech.qiantong.qdata.module.ds.config.api 处的 StartedUpRunner 类实现了 ApplicationRunner 接口的类 StartedUpRunner ,也因此在主启动类(应用程序)顺利启动后,逻辑上它的 public void run(ApplicationArguments args) 函数会立即执行。

在 run() 函数中,可以看到核心逻辑。

  • 首先,检查 ConfigurableApplicationContext 的配置
  • 接着,使用 Service 对象实例的查询方法 lambdaQuery,其实现中调用 BaseMapper 和 BaseEntity 调用 DsApiDO 对象实现对数据库的读取,.eq() 筛选逻辑,再通过 .List(T) 以集合的形式返回,成为我们可使用的 Java 对象。
  • 接着,如果列表中存在任意一条 api 对象数据,调用 mapperHandlerMapping 的 registerMapping(api) 方法进行路由注册。再经过一轮逻辑检验,最终会调用 Spring Boot 中的 requestMappingHandlerMapping 类的 registerMapping(requestMapping, handler, method) 方法进行注册。

维护的数据服务层 API

API 服务 DO 对象 DS_API

设计上,qData 系统将 DO 对象存储

与数据源的连接设计抽象 ExecuteConfig

具体实现
@Data
public class ExecuteConfig implements Serializable {

    private static final long serialVersionUID=1L;

    @NotBlank(message = "数据源不能为空")
    private String sourceId;

    @NotNull(message = "配置方式不能为空")
    private String apiServiceType;

    private String tableId;

    private String tableName;

    private String dbName;

    @Valid
    private List<FieldParam> fieldParams;

    /**
     * 解析SQL
     */
    private String sqlText;
}

数据如何从数据源读出

使用了一个自定义的 Wrapper 类。

泛型擦除、反射机制。

实现代码
public interface DsApiMapper extends BaseMapperX<DsApiDO> {

    default PageResult<DsApiDO> selectPage(DsApiPageReqVO reqVO) {
        // 定义排序的字段(防止 SQL 注入,与数据库字段名称一致)
        MPJLambdaWrapper<DsApiDO> lambdaWrapper = new MPJLambdaWrapper();
        lambdaWrapper.selectAll(DsApiDO.class)
                .select("t2.NAME AS catName")
                .leftJoin("ATT_API_CAT t2 on t.CAT_CODE = t2.CODE AND t2.DEL_FLAG = '0'")
                .between(reqVO.getParamByKey("beginCreateTime") != null && reqVO.getParamByKey("endCreateTime") != null,
                        DsApiDO::getCreateTime,
                        reqVO.getParamByKey("beginCreateTime"),
                        reqVO.getParamByKey("endCreateTime"))
                .like(StringUtils.isNotBlank(reqVO.getName()),DsApiDO::getName, reqVO.getName())
                .in(reqVO.getApiIdList() != null && !reqVO.getApiIdList().isEmpty(),DsApiDO::getId,reqVO.getApiIdList())
                .in(reqVO.getCatIds() != null && !reqVO.getCatIds().isEmpty(),DsApiDO::getCatId,reqVO.getCatIds())
                .likeRight(StringUtils.isNotBlank(reqVO.getCatCode()), DsApiDO::getCatCode, reqVO.getCatCode())
                .eq(StringUtils.isNotBlank(reqVO.getStatus()),DsApiDO::getStatus, reqVO.getStatus())
                .orderByStr(StringUtils.isNotBlank(reqVO.getOrderByColumn()), StringUtils.equals("asc", reqVO.getIsAsc()), StringUtils.isNotBlank(reqVO.getOrderByColumn()) ? Arrays.asList(reqVO.getOrderByColumn().split(",")) : null);
        return selectJoinPage(reqVO, DsApiDO.class, lambdaWrapper);
    }
}

方法引用和普通方法调用

可以注意到非常有趣的一个小细节。

...(reqVO.getName(), DsAPIDO::getName)

这个实际上是方法引用和普通方法调用的差异。

方法引用实际上是一种预留,意味着在未来实际发生调用时,会使用该方法,而目前知识传递了方法的⌈引用⌋。目前在这里,DsAPIDO 还是未实例化的。而 reqVO 在实例化之后,这里使用 getName() 方法会进行实际的解析和数据调用。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇