1. 目标与前置条件

目标:基于 JSQLParser + FreeMarker + Vue3 构建一套“可配置的数据透视报表”能力,实现从任意基础 SQL/视图出发,按维度/指标灵活聚合、筛选、排序、分页、导出,并支持钻取、联动、TopN、同比环比等常见分析操作。

前置条件(结合你的技术栈)

  • 运行环境:Java 21 / Spring Boot 3.x / Spring Data / Shiro

  • 数据库:MySQL 8.x(支持窗口函数、CTE、ROLLUP 等特性)

  • 前端:Vue3 + Element Plus(也可替换任意 UI 组件库)

  • 模板存储:DB(公共宏 + 业务模板),启动时预加载 + 变更热更新


2. 总体架构(高层)

Vue3(报表设计器/查看器)│  REST/JSON▼
Pivot API(Controller) —— 鉴权(Shiro) —— 限流/审计▼
PivotService(组装查询)├─ TemplateRegistry(FreeMarker 宏/模板加载与渲染)├─ SqlPipeline(JSQLParser 操作:包裹子查询、注入条件、生成聚合)├─ QueryEngine(JdbcTemplate/EntityManager 执行 + 数据权限)└─ CacheLayer(聚合结果缓存/预聚合物化)▼MySQL 8(基础明细表/视图)

关键思想

  1. 任意 SQL → 子查询:把用户/模板提供的基础 SQL 用 JSQLParser 包装成 SELECT ... FROM ( <base_sql> ) t,统一在外层做维度聚合与筛选。

  2. 模板只关心“表达式”:维度/指标的 SQL 片段通过宏/模板生成,避免手写大量 if/else 拼接。

  3. 强安全:白名单列/表校验、参数化绑定、限时/限量、敏感字段脱敏、SQL 审计日志。


3. 配置模型(后端/前端统一)

{"baseSqlId": "sales_order_detail",             "dimensions": [                                  { "expr": "date_format(order_date,'%Y-%m-%d')", "alias": "d" },{ "expr": "shop_code", "alias": "shop" }],"measures": [                                    { "func": "sum", "field": "amount", "alias": "gmv", "fmt": "currency" },{ "func": "count", "field": "order_id", "alias": "orders" }],"filters": {                                     "where": [{ "expr": "order_date >= :from" },{ "expr": "order_date < :to" },{ "expr": "shop_code in (:shops)" }],"having": [ { "expr": "sum(amount) > :minGmv" } ]},"sort": [ { "by": "gmv", "dir": "desc" }, { "by": "d", "dir": "asc" } ],"limit": 100,"offset": 0,"topn": { "by": "gmv", "n": 10 },           "time": { "grain": "day" },"compare": { "yoy": true, "wow": false },     "drill": { "enabled": true, "key": "order_id" },"export": { "type": "csv" },"params": { "from": "2025-08-01", "to": "2025-09-01", "shops": ["S1","S2"], "minGmv": 1000 }
}

说明:baseSqlId 映射到一段受控的基础 SQL(或视图),在 TemplateRegistry/DB 中维护;前后端均以该 JSON 做协议。


4. FreeMarker 模板设计

4.1 宏(公共库:pivot-macros.ftl

<#-- 维度渲染 -->
<#macro renderDimensions dims><#list dims as d>${d.expr} AS `${d.alias}`<#if d?has_next>,</#if></#list>
</#macro><#-- 指标渲染(支持 func(field) as alias) -->
<#macro renderMeasures ms><#list ms as m>${m.func}(${m.field}) AS `${m.alias}`<#if m?has_next>,</#if></#list>
</#macro><#-- ORDER BY -->
<#macro renderOrder sort><#if sort?? && (sort?size>0)>ORDER BY<#list sort as s>`${s.by}` ${s.dir?upper_case}<#if s?has_next>,</#if></#list></#if>
</#macro>

4.2 聚合模板(外层):pivot-aggregate.ftl

<#import "pivot-macros.ftl" as p />
SELECT<@p.renderDimensions dims=dimensions/><#if dimensions?size > 0 && measures?size > 0>,</#if><@p.renderMeasures ms=measures/>
FROM (${baseSql}
) t
<#-- WHERE 只作用于内层,通常由 SqlPipeline 注入。HAVING 用于外层聚合后过滤 -->
<#if filters?? && filters.having?? && (filters.having?size>0)>
HAVING<#list filters.having as h>${h.expr}<#if h?has_next> AND </#if></#list>
</#if>
<#if dimensions?size > 0>
GROUP BY<#list dimensions as d>${d.alias}<#if d?has_next>,</#if></#list>
</#if>
<@p.renderOrder sort=sort/>
<#if limit??> LIMIT ${limit} </#if>
<#if offset??> OFFSET ${offset} </#if>

注:baseSql 是经过 JSQLParser 处理过、带参数的内层 SQL。


5. JSQLParser 管道(核心)

目标:把任意基础 SQL 统一变为可注入条件的子查询,并做安全校验。

关键步骤

  1. 解析Statement stmt = CCJSqlParserUtil.parse(baseSql);

  2. 规整:移除外层 ORDER BY / LIMIT(由外层模板控制);

  3. 追加 WHERE:把 filters.where 中的条件以 AND 方式追加到内层查询;

  4. 包装SELECT * FROM ( <normalized_sql> ) t

  5. 白名单校验:检查涉及的表/列是否在白名单;

  6. 参数绑定:使用 NamedParameterJdbcTemplate 执行,避免字符串拼接。

示例工具类(片段):

public class SqlPipeline {public String wrapAsSubquery(String baseSql) {Select select = (Select) CCJSqlParserUtil.parse(baseSql);// 1) 清理外层 ORDER BY/LIMITselect.getSelectBody().accept(new OrderByAndLimitCleaner());// 2) 生成包装 SQLString normalized = select.toString();return "SELECT * FROM (" + normalized + ") t";}public String injectWhere(String wrappedSql, List<String> whereExprs) {// whereExprs 如: ["order_date >= :from", "order_date < :to"]PlainSelect ps = (PlainSelect) ((Select) CCJSqlParserUtil.parse(wrappedSql)).getSelectBody();Expression where = ps.getWhere();for (String expr : whereExprs) {Expression e = CCJSqlParserUtil.parseCondExpression(expr);where = (where == null) ? e : new AndExpression(where, e);}ps.setWhere(where);return ps.toString();}
}

生产建议:对 parse 异常做降级(如回退到安全模式),记录审计日志;在注入前对 expr 做黑/白名单校验。


6. 端到端示例

6.1 基础 SQL(注册为 sales_order_detail

SELECTorder_id,order_date,shop_code,sku_code,qty,amount
FROM sales_order_detail

6.2 前端配置(节选)

{"baseSqlId": "sales_order_detail","dimensions": [{ "expr": "date_format(order_date,'%Y-%m-%d')", "alias": "d" },{ "expr": "shop_code", "alias": "shop" }],"measures": [{ "func": "sum", "field": "amount", "alias": "gmv" },{ "func": "count", "field": "order_id", "alias": "orders" }],"filters": {"where": [ { "expr": "order_date >= :from" }, { "expr": "order_date < :to" } ]},"sort": [ { "by": "gmv", "dir": "desc" } ],"limit": 50,"params": { "from": "2025-08-01", "to": "2025-09-01" }
}

6.3 管道出 SQL(简化展示)

SELECTdate_format(order_date,'%Y-%m-%d') AS `d`,shop_code AS `shop`,sum(amount) AS `gmv`,count(order_id) AS `orders`
FROM (SELECT order_id, order_date, shop_code, sku_code, qty, amountFROM sales_order_detailWHERE order_date >= :from AND order_date < :to
) t
GROUP BY d, shop
ORDER BY `gmv` DESC
LIMIT 50

7. 后端实现(关键类与 API)

7.1 API 契约

  • POST /api/pivot/preview:入参 PivotConfig,返回渲染后的 SQL(仅开发/调试环境开放)。

  • POST /api/pivot/run:入参 PivotConfig,返回分页数据(含列定义与格式)。

  • POST /api/pivot/export:入参 PivotConfig + export.type,流式导出 CSV/Excel。

7.2 DTO(简化)

record Dim(String expr, String alias) {}
record Meas(String func, String field, String alias, String fmt) {}
record Filter(List<String> where, List<String> having) {}
record Sort(String by, String dir) {}record PivotConfig(String baseSqlId,List<Dim> dimensions,List<Meas> measures,Filter filters,List<Sort> sort,Integer limit,Integer offset,Map<String,Object> params
) {}

7.3 Service 关键流程

public PivotResult run(PivotConfig cfg) {String baseSql = templateRegistry.loadBaseSql(cfg.baseSqlId());String inner = pipeline.wrapAsSubquery(baseSql);inner = pipeline.injectWhere(inner, cfg.filters().where());String aggregated = templateRegistry.render("pivot-aggregate.ftl", Map.of("baseSql", inner,"dimensions", cfg.dimensions(),"measures", cfg.measures(),"filters", cfg.filters(),"sort", cfg.sort(),"limit", cfg.limit(),"offset", cfg.offset()));return queryEngine.query(aggregated, cfg.params());
}

7.4 数据权限建议

  • 在注入 WHERE 前,合并 data_scope 表达式(如门店/区域/用户标签范围);

  • Shiro Subject → 上下文携带 org_ids/shop_codes

  • 对外仅暴露经过模板注册的 baseSqlId,禁止用户直接传任意 SQL。


8. 性能与可用性

  1. 索引:维度列、时间列、常用过滤列建立联合/覆盖索引;

  2. 预聚合

    • 定时生成日/周/月粒度物化表;

    • 热点 TopN 结果放入 Redis,配置 ttl 和“参数签名”作为 Key;

  3. 分页策略:聚合后分页(LIMIT/OFFSET);统计总条数使用二次查询:

    SELECT COUNT(1) FROM (-- 把上面 GROUP BY 的 SELECT 去掉 ORDER BY/LIMIT
    ) x
    
  4. 大结果导出:使用 fetchSize + ResultSet.TYPE_FORWARD_ONLY 流式写 CSV;

  5. 并发:常见报表使用“参数签名”做结果缓存(如 60s);

  6. ROLLUP:可选支持:

    SELECT d, shop, SUM(amount) gmv
    FROM t
    GROUP BY d, shop WITH ROLLUP
    

9. 高级功能示例

9.1 TopN(对店铺按 GMV 取 Top10,其它归为 OTHER

WITH ranked AS (SELECT shop_code, SUM(amount) gmvFROM (${baseSqlWithWhere}) tGROUP BY shop_code
), r AS (SELECT shop_code, gmv, DENSE_RANK() OVER (ORDER BY gmv DESC) rnk FROM ranked
)
SELECT IF(rnk<=10, shop_code, 'OTHER') AS shop,SUM(gmv) gmv
FROM r
GROUP BY shop

也可在外层聚合后,用窗口函数 + CASE WHEN 分桶。

9.2 同比/环比(以日粒度为例)

SELECT d,SUM(amount) AS gmv,LAG(SUM(amount)) OVER (ORDER BY d) AS gmv_prev,(SUM(amount) - LAG(SUM(amount)) OVER (ORDER BY d)) / NULLIF(LAG(SUM(amount)) OVER (ORDER BY d),0) AS wow
FROM (SELECT DATE(order_date) d, amount FROM sales_order_detail WHERE order_date BETWEEN :from AND :to
) t
GROUP BY d

YoY 可用 DATE_SUB(d, INTERVAL 1 YEAR) 关联对比或双区间查询再 JOIN。

9.3 钻取

  • 规则:每条聚合行返回一个 drillKey(如 d|shop),前端点击发起 /api/pivot/drill?key=...,后端映射回内层 WHERE + 原始明细查询,限制 LIMIT 1000


10. 前端(Vue3)

10.1 组件划分

  • PivotDesigner:左侧维度/指标/过滤器选择区;

  • PivotTable:结果展示 + 汇总行 + 导出;

  • FieldCatalog:基础 SQL 字段字典(从后端 /api/pivot/fields?baseSqlId=... 取);

10.2 关键代码(示例,Composition API)

// usePivot.ts
import { ref } from 'vue'
import axios from 'axios'export function usePivot(){const config = ref({ baseSqlId: '', dimensions: [], measures: [], filters: { where:[], having:[] }, sort:[], limit:50, offset:0, params:{} })const loading = ref(false)const data = ref({ columns:[], rows:[], total:0 })async function run(){loading.value = truetry{const res = await axios.post('/api/pivot/run', config.value)data.value = res.data} finally { loading.value = false }}return { config, data, loading, run }
}
<!-- PivotTable.vue -->
<template><div><el-space><el-button :loading="loading" @click="run">运行</el-button><el-button @click="exportCsv">导出CSV</el-button></el-space><el-table :data="data.rows" style="width: 100%" :border="true"><el-table-column v-for="c in data.columns" :key="c.prop" :prop="c.prop" :label="c.label" :fixed="c.fixed" :width="c.width" /></el-table><el-paginationv-model:current-page="page"v-model:page-size="size":total="data.total"@current-change="onPageChange"@size-change="onSizeChange"/></div>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue'
import { usePivot } from './usePivot'
const { config, data, loading, run } = usePivot()
const page = ref(1); const size = ref(50)
function onPageChange(p:number){ config.value.offset = (p-1)*size.value; run() }
function onSizeChange(s:number){ size.value = s; config.value.limit = s; config.value.offset = 0; run() }
function exportCsv(){ window.open('/api/pivot/export?type=csv') }
watch(()=>config.value.baseSqlId, run)
</script>

10.3 交互要点

  • 维度/指标拖拽排序即 dimensionsmeasures 顺序;

  • 过滤器 UI → 生成 expr(提供字段/操作符/占位参数拼装器,避免用户手写表达式);

  • 支持字段格式化:金额、百分比、千分位等(后端返回 columns[x].fmt)。


11. 安全与风控

  • 只允许调用已注册的 baseSqlId(DB 中维护 SQL 文本与字段白名单);

  • 所有 :paramNamedParameterJdbcTemplate 绑定;

  • 表达式校验:限制可用函数/关键字(例如禁止 ;, --, /* */, sleep 等);

  • 超时/行数限制:默认 timeout=15smax-rows=50,000

  • 审计:记录用户、SQL 摘要(hash)、耗时、扫描行数、命中缓存与否。


12. 测试计划

  • 单测

    • JSQLParser:Where 注入、Order/LIMIT 清理、别名冲突处理;

    • 模板渲染:预期 SQL 与实际对比;

  • 集成测试

    • 常见维度组合/TopN/同比/环比/分页/导出;

    • 大数据量性能基准(QPS、P95 延迟);

  • 回归:每次修改模板库后自动跑一批“黄金用例”。


13. 运维与监控

  • 暴露健康检查与关键指标(查询耗时、并发数、失败率、缓存命中率)到 Prometheus;

  • 热更新:DB 模板变更 → 发送 MQ(Artemis)→ 节点刷新本地缓存;

  • 失败熔断:同一用户在短时内多次慢查询/失败,临时降级其配额。


14. 可扩展方向

  • 预聚合引擎:按配置定时物化(增量更新);

  • 维度字典服务:统一的字段目录/血缘追踪;

  • 多数据源:在 baseSqlId 上绑定数据源路由;

  • 报表版本化:配置与模板版本追踪,可回滚。


15. 落地清单(Checklist)

  • 定义 PivotConfig 协议与前端模型

  • 建立 TemplateRegistry(加载宏/模板/基础 SQL)

  • 实现 SqlPipeline(包装/注入/校验)

  • 渲染聚合模板并执行(QueryEngine)

  • 前端设计器与表格组件

  • 缓存、导出、审计与告警

有了以上骨架,你可以先从“单一基础 SQL + 2 个维度 + 2 个指标”开始最小可用版本(MVP),再迭代加入 TopN、钻取、同比/环比等能力。


16. 模板/基础SQL注册与热更新设计(结合 Artemis)

16.1 表结构(JPA 实体)

// 基础 SQL(白名单入口)
@Entity @Table(name="pivot_base_sql")
public class PivotBaseSql extends AbstractEntity {@Id @GeneratedValue private Long id;@Comment("唯一编码") @FormField(order=1) private String code; // 如 sales_order_detail@Lob @Comment("SQL 文本") @FormField(order=2, type="textarea") private String sqlText;@Comment("启用状态") private Boolean enabled = true;@Comment("允许的字段白名单(JSON)") @Lob private String fieldWhitelistJson; // ["order_id","order_date",...]@Comment("数据源标识") private String datasourceKey; // 多数据源路由@CreateByUser private Long createUserId;@Comment("版本号") private Long version;@Comment("最后修改时间") private Instant updatedAt;
}// 公共宏/模板
@Entity @Table(name="pivot_template")
public class PivotTemplate extends AbstractEntity {@Id @GeneratedValue private Long id;@Comment("类型: macro|aggregate|other") private String type;@Comment("名称") private String name; // pivot-macros.ftl, pivot-aggregate.ftl@Lob @Comment("模板内容") private String content;@Comment("启用") private Boolean enabled = true;private Instant updatedAt;
}

常见坑与规避

  • 内层对时间列做函数导致走不到索引 → 把函数放到外层显示,内层只做区间过滤;

  • 维度别名与保留字冲突(如 dategroup)→ 统一反引号包裹;

  • COUNT(*)COUNT(col) 语义差异;

  • ORDER BY 字段不在 SELECT 中的 MySQL 行为差异;

  • 导出超大文件内存膨胀 → 必须流式 + 临时文件。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/94019.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/94019.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/94019.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot3 Ruoyi芋道管理后台vben5.0

新技术栈&#xff08;Vue3、Vite6、TypeScript、SpringBoot3/SpringCloud基于Vben5.0最新版本&#xff0c;全面采用Vue3 Vite6 Ant Design Vue TypeScript技术栈&#xff0c;并同时支持SpringBoot3单体架构与SpringCloud微服务架构前端技术栈&#xff1a;Vue3 Vite6 TS A…

K8S - NetworkPolicy的使用

1 前置条件2 控制范围3 隔离类型4 如何识别5 主要字段6 案例演示 前置条件 网络策略通过网络插件来实现。 要使用网络策略&#xff0c;你必须使用支持 NetworkPolicy 的网络解决方案。 创建一个 NetworkPolicy 资源对象而没有控制器来使它生效的话&#xff0c;是没有任何作用的…

Linux:TCP协议

TCP是一个面向连接的、可靠的、基于字节流的传输层协议。文次我们会通过介绍TCP的报头并通过分析各字段的用途来进一步解释其核心特性:可靠传输&#xff1a; 有确认应答、超时重传、确保有序。流量控制和拥塞控制&#xff1a; 动态调节发送速率&#xff0c;防止丢包与拥塞。面向…

uniapp使用map打包app后自定义气泡不显示解决方法customCallout

前言&#xff1a;使用uniapp开发后在小程序可以正常显示&#xff0c;但是运行打包成App后就不显示了&#xff0c;其实这一块对于uniapp框架开发来说&#xff0c;是有系统性的bug&#xff0c;如果你再开发时使用的是vue文件进行&#xff0c;就会出现这个问题。解决方法&#xff…

【typenum】 22 类型级别二进制对数运算(Logarithm2)

一、源码 这段代码实现了一个类型级别的二进制对数运算系统 定义&#xff08;type_operators.rs&#xff09; /// A **type operator** for taking the integer binary logarithm of Self. /// /// The integer binary logarighm of n is the largest integer m such /// that …

golang 非error错误分类

1.应用级别&#xff0c;可recover这些 panic 一般是 逻辑或使用不当导致的运行时错误&#xff0c;Go 程序可以用 recover 捕获并继续运行&#xff1a;类型示例描述类型不一致atomic.Value 存不同类型 v.Store(100); v.Store("abc")panic: store of inconsistently ty…

【Ansible】变量与敏感数据管理:Vault加密与Facts采集详解

1. 变量Ansible利用变量存储可重复使用的值&#xff0c;可以简化项目的创建和维护&#xff0c;减少错误数量。1.1 变量名称由字符串组成&#xff0c;必须以字母开头&#xff0c;并且只能含有字母、数字和下划线&#xff0c;和其它编程语言很类似。1.2 常见变量要创建的用户要安…

ROS2下YOLO+Moveit+PCL机械臂自主避障抓取方案

整体运行架构 1.运行相机取像节点 . ./install/setup.bash ros2 launch orbbec_camera gemini_330_series.launch.py depth_registration:true 2.运行根据图像x,y获取z的service 基本操作记录&#xff1a; 创建python包,在src目录下 ros2 pkg create test_python_topic --bu…

快速入门Vue3——初体验

目录 前言 一、搭建环境 1.1、安装Node.js 1.2、安装Vite 二、项目创建 三、运行项目 四、集成Pinia 4.1、Pinia介绍 4.2、Pinia安装 五、集成VueUse 5.1、vueuse简介 5.2、vueuse安装 六、集成Vant 6.1、Vant简介 6.2、Vant安装 前言 本专栏主要介绍如何使用…

深入理解Kubernetes核心:标签与标签选择器实战解析

在管理 Kubernetes 集群时&#xff0c;随着 Pods、Services 等资源数量的增长&#xff0c;如何有效地组织和筛选它们&#xff0c;成为了一个核心问题。Kubernetes 为此提供了一个简单却极其强大的机制&#xff1a;标签&#xff08;Labels&#xff09;和标签选择器&#xff08;L…

哈希和字符串哈希

哈希&#xff08;Hash&#xff09; Hash 表 Hash 表又称为散列表&#xff0c;一般由 Hash 函数&#xff08;散列函数&#xff09;与链表结构共同实现。与离散化思想类似&#xff0c;当我们要对若干复杂信息进行统计时&#xff0c;可以用 Hash 函数把这些复杂信息映射到一个容…

【Docker基础】Docker-Compose核心配置文件深度解析:从YAML语法到高级配置

目录 前言 1 YAML基础语法解析 1.1 YAML格式简介 1.2 Docker-compose中的YAML语法规则 1.3 YAML数据类型在Compose中的应用 2 docker-compose.yml文件结构剖析 2.1 基本文件结构 2.2 版本声明详解 3 services配置深度解析 3.1 服务定义基础 3.2 镜像与构建配置 3.3…

如何判断是否应该为了一个小功能而引入一个大体积的库

在软件开发中&#xff0c;判断是否应该为了一个看似微小的功能&#xff0c;而引入一个大体积的第三方库&#xff0c;是一项极其重要的、需要进行审慎的“投入产出比”分析的技术决策。这个决策&#xff0c;绝不能&#xff0c;仅仅基于“实现功能的便利性”&#xff0c;而必须&a…

相机定屏问题分析五:【跳帧异常】照片模式1x以上的焦段拍照之后定屏

【关注我&#xff0c;后续持续新增专题博文&#xff0c;谢谢&#xff01;&#xff01;&#xff01;】 上一篇我们讲了&#xff1a; 这一篇我们开始讲&#xff1a; 相机定屏问题分析五&#xff1a;【跳帧异常】照片模式1x以上的焦段拍照之后定屏9573412 目录 一、问题背景 二…

Non-stationary Diffusion For Probabilistic Time Series Forecasting论文阅读笔记

Non-stationary Diffusion For Probabilistic Time Series Forecasting 摘要 时间序列数据受到潜在的物理动力学和外部影响&#xff0c;其不确定性通常随时间而变化。现有的去噪扩散概率模型&#xff08;DDPMs&#xff09;受到加性噪声模型&#xff08;ANM&#xff09;的恒定方…

解决Docker 无法连接到官方镜像仓库

这个错误&#xff1a; Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)表示 Docker 无法连接到官方镜像仓库 registry-1.docker…

解决RAGFlow启动时Elasticsearch容器权限错误的技术指南

文章目录 问题现象 根本原因分析 解决方案步骤 1. 定位宿主机数据目录 2. 修复目录权限 3. 验证权限状态 4. 重启服务 5. 检查启动状态 永久解决方案:优化Docker Compose配置 高级故障排除 技术原理 问题现象 在启动RAGFlow项目时,执行 docker logs ragflow-es-01 发现Elast…

【C++高阶六】哈希与哈希表

【C高阶六】哈希与哈希表1.什么是哈希&#xff1f;2.unordered系列容器3.哈希表3.1将key与存储位置建立映射关系3.1.1直接定址法3.1.2除留余数法&#xff08;产生哈希冲突&#xff09;3.2解决哈希冲突的方法3.2.1闭散列&#xff08;开放定址法&#xff09;3.3.2开散列&#xff…

Vue 3 +Ant Design Vue 父容器样式不影响子级,隔离

公共样式文件 common.scss.zz-ant-status-bar {div {font-size: 12px;padding: 0 8px;} }页面代码<div class"zz-ant-status-bar"><a-row><a-col :span"6" ><a-progress :percent"progress.percent" size"small"…

k8s 简介及部署方法以及各方面应用

Kubernetes 简介及部署方法Kubernetes&#xff08;简称 K8s&#xff09;是一个开源的容器编排平台&#xff0c;用于自动化容器化应用的部署、扩展、管理和运维。它由 Google 基于内部的 Borg 系统经验开发&#xff0c;2014 年开源后由云原生计算基金会&#xff08;CNCF&#xf…