自研框架跻身全球 JS 框架榜单,排名紧随 React、Angular 之后!

news2024/11/15 8:36:41

前言

终于实现了一个重要目标!我独立研发的 JavaScript 框架 Strve,最近发布了重大版本 6.0.2。距离上次大版本发布已经接近两个月,期间进行了大量的优化,使得框架性能和稳定性都得到了大幅度的提升。在上次的大版本更新中,成功实现了对 JSX 语法的全面支持,使得 Strve 在代码智能提示和代码格式化方面更加友好,进一步提高了开发效率。

介绍

相信有些小伙伴没有听说过 Strve 到底是什么,那我这里就大体介绍一下。

Strve 是一个可以将字符串转换为视图(用户界面)的 JavaScript 库。Strve 不仅易于使用,而且可以灵活地拆解不同的代码块。使用模板字符串开发用户界面,主要是利用 JavaScript 的能力,只关注 JavaScript 文件。Strve 又是一个易用性的 JavaScript 框架,它提供了很多实用的功能与生态工具。

我们可以通过一些简单的示例来了解 Strve 的使用方法。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Strve.js</title>
  </head>

  <body>
    <script src="https://cdn.jsdelivr.net/npm/strve-js@6.0.2/dist/strve.full.prod.js"></script>
    <script>
      const { html, setData, createApp } = Strve;
      const state = {
        count: 0,
      };

      function add() {
        setData(() => {
          state.count++;
        });
      }

      function App() {
        return html`<h1 onClick=${add}>${state.count}</h1>`;
      }

      const app = createApp(App);
      app.mount('#app');
    </script>
  </body>
</html>

在上述代码中,我们通过引入 Strve 库,并使用 createApp 方法创建了一个 App 组件,然后通过 mount 方法挂载到页面上,这里的 App 组件就是通过模板字符串来定义的。这样就可以在 JS 代码中编写用户界面,是不是很方便呢?我们发现,在模板字符串中,我们使用 ${} 来引用数据,并且使用 onClick 方法来绑定事件。这样就可以实现一个计数器的功能。

除了这种简单的示例,Strve 还支持很多复杂的功能,我们可以使用 JSX 语法来编写组件,也可以使用函数式组件来编写组件,还可以使用组件来编写组件,甚至可以编写一些自定义的组件。

如果想了解更多关于 Strve 的信息,稍后可以到文章末尾处查阅官方文档。

性能评估

我们既然发布了 Strve,那么肯定需要对其性能进行评估,我们评估的工具就用js-framework-benchmarkjs-framework-benchmark 是什么?我们这里就简单介绍下 js-framework-benchmark,它是一个用于比较 JavaScript 框架性能的项目。它旨在通过执行一系列基准测试来评估不同框架在各种场景下的性能表现。这些基准测试包括渲染大量数据、更新数据、处理复杂的 UI 组件等。通过运行这些基准测试,可以比较不同框架在各种方面的性能优劣,并帮助开发人员选择最适合其需求的框架。js-framework-benchmark 项目提供了一个包含多个流行 JavaScript 框架的基准测试套件。这些框架包括 Angular、React、Vue 等。每个框架都会在相同的测试场景下运行,然后记录下执行时间和内存使用情况等性能指标。通过比较这些指标,可以得出不同框架的性能差异。这个项目的目标是帮助开发人员了解不同 JavaScript 框架的性能特点,以便在选择框架时能够做出更加明智的决策。同时,它也可以促进框架开发者之间的竞争,推动框架的不断改进和优化

在评估之前,我们必须要了解 js-framework-benchmark 中有两种模式。一种是 keyed,另一种是 non-keyed。在 js-framework-benchmark 中,“keyed” 模式是指通过给数据项分配一个唯一标识符作为 “key” 属性,从而实现数据项与 DOM 节点之间的一对一关系。当数据发生变化时,与之相关联的 DOM 节点也会相应更新。而 non-keyed 模式是指当数据项发生变化时,可能会修改之前与其他数据项关联的 DOM 节点。

因为 Strve 支持keyed模式,所以我们将使用此模式来评估 Strve 的性能。

对以下操作进行了基准测试:

  • 创建行:页面加载后创建 1,000 行的持续时间(无预热)。
  • 替换所有行:替换表中所有 1,000 行的持续时间(5 次预热迭代)。
  • 部分更新:对于具有 10,000 行的表,每 10 行更新一次文本(进行 5 次预热迭代)。
  • 选择行:响应单击该行而突出显示该行的持续时间。 (5 次预热迭代)。
  • 交换行:在包含 1,000 行的表中交换 2 行的时间。 (5 次预热迭代)。
  • 删除行:删除具有 1,000 行的表的行的持续时间。 (5 次预热迭代)。
  • 创建多行:创建 10,000 行的持续时间(无预热)
  • 将行追加到大型表:在包含 10,000 行的表中添加 1,000 行的持续时间(无预热)。
  • 清除行:清除填充有 10,000 行的表的持续时间。 (无热身)
  • 就绪内存:页面加载后的内存使用情况。
  • 运行内存:添加 1,000 行后的内存使用情况。
  • 更新内存:1000 行的表点击 5 次更新后的内存使用情况。
  • 替换内存:点击 5 次创建 1000 行后的内存使用情况。
  • 重复清除内存:创建并清除 1,000 行 5 次后的内存使用情况。
  • 更新内存:1000 行的表点击 5 次更新后的内存使用情况。
  • 启动时间:加载和解析 javascript 代码以及渲染页面的持续时间。
  • 持续交互:灯塔指标 TimeToConstantlyInteractive:悲观 TTI - 当 CPU 和网络都非常空闲时。 (不再有超过 50 毫秒的 CPU 任务)
  • 脚本启动时间:灯塔指标 ScriptBootUpTtime:解析/编译/评估所有页面脚本所需的总毫秒数
  • 主线程工作成本:灯塔指标 MainThreadWorkCost:在主线程上工作所花费的总时间包括样式/布局等。
  • 总字节权重:灯塔指标 TotalByteWeight:加载到页面中的所有资源的网络传输成本(压缩后)。

对于所有基准测试,都会测量持续时间,包括渲染时间。

因为js-framework-benchmark是一个自动化测试的工具,只需要符合标准的代码就可以进行测试。Strve 支持 JSX 语法,所以我们将使用 JSX 语法来编写测试代码。

import { setData, createApp } from 'strve-js';
import { buildData } from './data.js';

let selected;
let rows = [];

function setRows(update = rows.slice()) {
  setData(
    () => {
      rows = update;
    },
    {
      name: TbodyComponent,
    }
  );
}

function add() {
  const data = rows.concat(buildData(1000));
  setData(
    () => {
      rows = data;
    },
    {
      name: TbodyComponent,
    }
  );
}

function remove(id) {
  rows.splice(
    rows.findIndex((d) => d.id === id),
    1
  );
  setRows();
}

function select(id) {
  setData(
    () => {
      selected = id;
    },
    {
      name: TbodyComponent,
    }
  );
}

function run() {
  setRows(buildData());
  selected = undefined;
}

function update() {
  for (let i = 0; i < rows.length; i += 10) {
    rows[i].label += ' !!!';
  }
  setRows();
}

function runLots() {
  setRows(buildData(10000));
  selected = undefined;
}

function clear() {
  setRows([]);
  selected = undefined;
}

function swapRows() {
  if (rows.length > 998) {
    const d1 = rows[1];
    const d998 = rows[998];
    rows[1] = d998;
    rows[998] = d1;
    setRows();
  }
}

function TbodyComponent() {
  return (
    <tbody>
      {rows.map((item) => (
        <tr class={item.id === selected ? 'danger' : ''} data-label={item.label} key={item.id}>
          <td class='col-md-1'>{item.id}</td>
          <td class='col-md-4'>
            <a onClick={() => select(item.id)}>{item.label}</a>
          </td>
          <td class='col-md-1'>
            <a onClick={() => remove(item.id)}>
              <span class='glyphicon glyphicon-remove' aria-hidden='true'></span>
            </a>
          </td>
          <td class='col-md-6'></td>
        </tr>
      ))}
    </tbody>
  );
}

function MainBody() {
  return (
    <fragment>
      <div class='jumbotron'>
        <div class='row'>
          <div class='col-md-6'>
            <h1>Strve-keyed</h1>
          </div>
          <div class='col-md-6'>
            <div class='row'>
              <div class='col-sm-6 smallpad'>
                <button type='button' class='btn btn-primary btn-block' id='run' onClick={run}>
                  Create 1,000 rows
                </button>
              </div>
              <div class='col-sm-6 smallpad'>
                <button
                  type='button'
                  class='btn btn-primary btn-block'
                  id='runlots'
                  onClick={runLots}
                >
                  Create 10,000 rows
                </button>
              </div>
              <div class='col-sm-6 smallpad'>
                <button type='button' class='btn btn-primary btn-block' id='add' onClick={add}>
                  Append 1,000 rows
                </button>
              </div>
              <div class='col-sm-6 smallpad'>
                <button
                  type='button'
                  class='btn btn-primary btn-block'
                  id='update'
                  onClick={update}
                >
                  Update every 10th row
                </button>
              </div>
              <div class='col-sm-6 smallpad'>
                <button type='button' class='btn btn-primary btn-block' id='clear' onClick={clear}>
                  Clear
                </button>
              </div>
              <div class='col-sm-6 smallpad'>
                <button
                  type='button'
                  class='btn btn-primary btn-block'
                  id='swaprows'
                  onClick={swapRows}
                >
                  Swap Rows
                </button>
              </div>
            </div>
          </div>
        </div>
      </div>
      <table class='table table-hover table-striped test-data'>
        <component $name={TbodyComponent.name}>{TbodyComponent()}</component>
      </table>
      <span class='preloadicon glyphicon glyphicon-remove' aria-hidden='true'></span>
    </fragment>
  );
}

createApp(() => MainBody()).mount('#main');

以下页面就是将进行基准测试的页面:

在这里插入图片描述
我们大体看下测试过程,我们将使用动图来展示页面效果,这样会觉得更加直观。

在这里插入图片描述

最终,Strve 通过了压力测试!

在这里插入图片描述

基准测试结果

既然我们通过测试,我们就需要提交到js-framework-benchmark官方项目中,进行综合评估,与全球其他框架进行比较。

我们提交的 PR 在 2023 年 9 月 18 号被作者合并了。

在这里插入图片描述

在接下来的时间里,作者进行了一系列的测试。最终,Chrome 118 版本于上周发布,并在 GitHub 上公布了官方的测试结果。

在这里插入图片描述

我们打开下面的网址,看下 Strve 的官方测试结果:

https://krausest.github.io/js-framework-benchmark/2023/table_chrome_118.0.5993.70.html

经过查询,全球 JavaScript 框架榜单中共有 142 个框架。

性能测试基准分为三类:

  • 持续时间
  • 启动指标
  • 内存分配

【持续时间】

在此测试基准中,Strve 平均值 1.42,排名第 90 位。

React、Angular 和 Vue,平均值分别为1.401.381.20,分别排名第 85 位、第 83 位和第 51 位。

平均值越小,排名则越靠前。颜色越绿代表越优。

在这里插入图片描述

【启动指标】

在此测试基准中,Strve 平均值 1.07

React、Angular 和 Vue,平均值分别为 1.681.801.30

平均值越小,排名则越靠前。颜色越绿代表越优。

在这里插入图片描述

【内存分配】

在此测试基准中,Strve 平均值 1.33

React、Angular 和 Vue,平均值分别为 2.462.821.86

平均值越小,排名则越靠前。颜色越绿代表越优。

在这里插入图片描述

新特性

我们在上面的测试中,可以看到 Strve 性能表现非常不错。

这次我们发布的大版本号为 6.0.2,我们将这个具有里程碑意义的大版本命名为 Strve6,而 “Strve6,从芯出发!” 这个口号正是 Strve6 的核心理念。这一版本象征着我们从底层技术出发,致力于为用户提供更优质、更高效的开发体验。

此次版本我们在性能与体验之间做了权衡。在源码层面,我们将普通 Diff 算法升级为 双端 Diff 算法,大大提升了性能。另外,我们在用户体验层面也做了很大的改进。

这里,我们提到了双端 Diff 算法,我们在面试中经常提到这个概念,但是很少用到实际项目中去。那么,为了更好地理解双端 Diff 算法如何提高性能,我们来看一个关于 Strve 简单的示例。

我们来遍历一个数组,并且每次点击按钮,往数组头部中添加一个元素。

【普通 Diff 算法】

<script type="module">
  import {
    html,
    setData,
    createApp,
  } from 'https://cdn.jsdelivr.net/npm/strve-js@6.0.2/dist/strve.full-esm.js';

  const state = {
    arr: [1, 2],
    count: 3,
  };

  function useUnshift() {
    setData(() => {
      state.count++;
      state.arr.unshift(state.count);
    });
  }

  function App() {
    return html`
      <fragment>
        <button onClick=${useUnshift}>Unshift</button>
        <ul>
          ${state.arr.map((todo) => html`<li>${todo}</li>`)}
        </ul>
      </fragment>
    `;
  }

  const app = createApp(App);
  app.mount('#app');
</script>

我们可以看到右侧 DOM 树,每次点击按钮,都会重新渲染整个列表。这样是肯定耗损浏览器性能的。

在这里插入图片描述

【双端 Diff 算法】

<script type="module">
  import {
    html,
    setData,
    createApp,
  } from 'https://cdn.jsdelivr.net/npm/strve-js@6.0.2/dist/strve.full-esm.js';

  const state = {
    arr: [1, 2],
    count: 3,
  };

  function useUnshift() {
    setData(() => {
      state.count++;
      state.arr.unshift(state.count);
    });
  }

  function App() {
    return html`
      <fragment>
        <button onClick=${useUnshift}>Unshift</button>
        <ul>
          ${state.arr.map((todo) => html`<li key=${todo}>${todo}</li>`)}
        </ul>
      </fragment>
    `;
  }

  const app = createApp(App);
  app.mount('#app');
</script>

我们可以看到右侧 DOM 树,每次点击按钮,仅添加必要的元素,而不是重新渲染整个列表。这是因为我们在每个列表项中添加了 key 属性,并且这个 key 是唯一的。key 这个特殊的 attribute 主要作为 Strve 的虚拟 DOM 算法提示,在比较新旧节点列表时用于识别 vnode。只要标签类型与 key 值都相等,就说明当前元素可以被复用。

在这里插入图片描述

热门话题

文章接近尾声,让我们来回顾一下最近社区的几个热门话题。

  1. 为什么要开发这个框架?初衷是什么?

答:其实,我的动机特别简单,完全受 JSX 语法的影响。刚接触 JSX 语法的时候,就被它那种魔法深深地吸引住了,可以在 JS 中写 HTML。所以,我就想我自己可不可以也搞一个类似 JSX 语法的库或者框架呢!一方面可以锻炼自己的代码能力,另一方面体验开发框架的整个流程,也方便我以后更全面的学习其他框架(Vue.js、React.js 等)。

做自己喜欢的事情是特别有意义的!

  1. 为什么选择 Strve 作为框架的名字?

答:Strve 最初定位是可以将字符串转换为视图(用户界面)的 JavaScript 库,所以是由 StringView 两个单词缩减组成的新单词。

  1. 跟前端热门框架比较,是想超过它们吗?

答:不是,我主要是想学习一下前端热门框架的实现原理,然后自己实现一个框架。有一句话说得好:“只有站在巨人的肩膀上才能望得更远!”。

  1. 记得之前也写过登上框架榜单的文章,这次为什么还要写?

答:之前,Strve 测评的模式是使用"non-keyed"。现在,Strve 新的版本支持"keyed"模式,所以,我重新写了一篇文章,来介绍 Strve 的新特性。

  1. Strve 6.0.2 版本发布,普通 Diff 算法升级为双端 Diff 算法,可以简单讲下双端 Diff 算法的概念吗?

答:双端 diff 算法就是头尾指针向中间移动,分别判断头尾节点是否可以复用,如果没有找到可复用的节点再去遍历查找对应节点的下标,然后移动。全部处理完之后要对剩下的节点进行批量的新增和删除。

  1. Strve 是个 JavaScript 库还是 JavaScript 框架?

答:首先,我们来看下框架与库有什么区别?库更多是一个封装好的特定的集合,提供给开发者使用,而且是特定于某一方面的集合(方法和函数),库没有控制权,控制权在使用者手中,在库中查询需要的功能在自己的应用中使用,我们可以从封装的角度理解库;框架顾名思义就是一套架构,会基于自身的特点向用户提供一套相当于叫完整的解决方案,而且控制权的在框架本身,使用者要找框架所规定的某种规范进行开发。Strve 可以是框架,因为 Strve 提供了路由、插件等生态工具;Strve 也可以是库, 因为 Strve 可以单独作为一个渲染库。

  1. Strve 你还要继续维护下去吗?

答:是的,我还会继续维护下去,因为我也想学习下去,也希望能帮助到更多前端开发者。

关于

Strve 我是从 2021 年下半年开始开发,到现在也快两年了。在这两年中,从一个之前只会 调用 API 的码农,到现在可以独立开发一个框架,让我收获了很多。学习了如何去分析一个框架的实现原理,也学习了如何去设计一个框架。

Strve 源码仓库:https://github.com/maomincoding/strve

Strve 中文文档:https://maomincoding.gitee.io/strve-doc-zh/

如果大家觉得 Strve 还不错,麻烦帮我点下 Star 吧,谢谢!

结语

感谢各位读者的阅读,希望本文能对你有所帮助,如果喜欢本文,欢迎点赞,欢迎关注!

最后,分享一段话给大家:

很多时候

不是有希望才去坚持

而是在坚持的过程中慢慢看到希望

我们都是在暗夜里赶路的人

纵使满身疲惫也不肯轻言放弃

愿你所坚持的东西

终有一天反过来拥抱你

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

DevOps持续集成-Jenkins(2)

文章目录 DevOpsDevOps概述Integrate工具&#xff08;centos7-jenkins主机&#xff09;Integrate概述Jenkins介绍CI/CD介绍Linux下安装最新版本的Jenkins⭐Jenkins入门配置安装必备插件⭐安装插件&#xff08;方式一&#xff1a;可能有时会下载失败&#xff09;安装插件&#x…

负载均衡--Haproxy

haproxy 他也是常用的负载均衡软件 nginx 支持四层转发&#xff0c;七层转发 haproxy也可以四层和七层转发 haproxy&#xff1a;法国人开发的威利塔罗在2000年基于C语言开发的一个开源软件 可以支持一万以上的并发请求 高性能的tcp和http负载均衡2.4 1.5.9 haproxy&#…

微服务-Eureka

文章目录 提供者与消费者Eureka注册中心搭建EurekaServer服务注册服务发现项目结构 提供者与消费者 Eureka注册中心 服务消费者该如何获取服务提供者的地址信息&#xff1f; 服务提供者启动时向eureka注册自己的信息 eureka保存这些信息 消费者根据服务名称向eureka拉取提供者信…

10.Z-Stack协议栈移植

一、下载Z-Stack协议栈源文件 安装过程全部默认下一步即可&#xff0c;安装完成后会在C盘根目录下生成一个【Texas Instruments】文件夹 二、删除一些不必要的文件 将【ZStack-CC2530-2.3.0-1.4.0】文件夹&#xff0c;复制到自己放置ZigBee工程的文件夹下进入到【ZStack-CC253…

vue + html + Lodop打印功能

1.官网下载 http://www.lodop.net/download.html 2.解压安装运行 点击CLodop_Setup_for_Win32NT.exe进行安装 3.vue代码实现&#xff08;具体操作见官网&#xff1a;http://www.lodop.net/faq/pp35.html&#xff09; 3.1把官方提供的LodopFuncs.js文件保存到项目某个目录下 …

C# 使用base64编码用于加密和解密

base64编码原理&#xff1a;Base64编码是一种将二进制数据转换为ASCII字符的编码方式。它使用64个字符来表示二进制数据&#xff0c;包括大小写字母、数字和两个符号。将3个字节的二进制数据转换为4个字符的文本数据&#xff0c;如果不足3个字节&#xff0c;则在末尾补0&#x…

el-tree横向纵向滚动条

el-tree未展开时样式 el-tree展开时样式 给容器一个高度&#xff0c;然后样式加上overflow: scroll&#xff0c;这样纵向滚动条就出来了。 <el-card style"height: 528px;overflow: scroll"><el-inputplaceholder"输入关键字进行过滤"v-model&…

是顺流还是逆流?未来物流作业是否将被机器人全面取代?

原创 | 文 BFT机器人 随着人工智能的加速发展&#xff0c;各行业为适应数字时代的潮流&#xff0c;纷纷引入智能制造&#xff0c;帮助企业实现产业升级。而物流行业也不例外&#xff0c;现今人们的生活速度加快&#xff0c;为了快捷便利&#xff0c;很多的人喜欢通过网购、快递…

【Linux】Ubuntu升级nodejs版本

在下载nvm对nodejs版本进行管理时&#xff0c;由于网络因素一直下载失败&#xff0c;于是采用了新的方法对nodejs版本进行升级。 首先我们先查询一下现存的nodejs版本号&#xff0c;发现是12 我们下载一个名为n的软件包&#xff0c;n 是一个非常方便的 Node.js 版本管理工具&am…

【C++】Map和Set -- 详解

一、关联式容器 在初阶阶段&#xff0c;我们已经接触过 STL 中的部分容器&#xff0c;比如&#xff1a;vector、list、deque、forward_list&#xff08;C11&#xff09;等&#xff0c;这些容器统称为 序列式容器 &#xff0c;因为其底层为线性序列的数据结构&#xff0c;里面存…

CCF中国开源大会,中电金信与行业共探AI技术在金融行业的应用和前景

10月21日&#xff0c;以“开源联合&#xff0c;聚力共赢”为主题的2023 CCF中国开源大会在长沙开幕。中电金信副总经理、研究院院长况文川参加峰会&#xff0c;在“算力与大模型”主题论坛上发表演讲&#xff0c;与行业共同交流AI、大模型等技术在金融行业的应用与前景。 况文川…

bp前端验证码绕过及token绕过

前端验证码绕过及token绕过 原文参考&#xff1a;xiu 文章目录 前端验证码绕过及token绕过原文参考&#xff1a;[xiu](http://www.xiusafe.com/2023/10/25/%E9%AA%8C%E8%AF%81%E7%A0%81%E7%BB%95%E8%BF%87/)1 验证码爆破1. 登录Pikachu&#xff0c;先获取登录的api接口2 验证码…

基于Java的药品商城管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09; 代码参考数据库参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&am…

jenkins配置gitlab凭据

下载Credentials Binding插件&#xff08;默认是已经安装了&#xff09; 在凭据配置里添加凭据类型 点击保存 Username with password&#xff1a; 用户名和密码 SSH Username with private 在凭据管理里面添加gitlab账号和密码 点击全局 点击添加凭据&#xff08;版本不同…

指针相关面试题目

数组名的意义&#xff1a; 1. sizeof( 数组名 ) &#xff0c;这里的数组名表示整个数组&#xff0c;计算的是整个数组的大小。 2. & 数组名&#xff0c;这里的数组名表示整个数组&#xff0c;取出的是整个数组的地址。 3. 除此之外所有的数组名都表示首元素的地址。 下…

【wespeaker】模型ECAPA_TDNN介绍

本次主要介绍开源项目wespeaker模型介绍 1. 模型超参数 model_args: feat_dim: 80 embed_dim: 192 pooling_func: “ASTP” projection_args: project_type: “softmax” # add_margin, arc_margin, sphere, softmax scale: 32.0 easy_margin: False 2. 模型结构 2.1 Layer…

python打包和运行技巧

一、打包的几种方法 Python 有多种打包方式可用于将脚本打包成可执行文件&#xff0c;以便在没有 Python 解释器的环境中运行。以下是一些常见的 Python 打包方式&#xff1a; 使用 pyinstaller&#xff1a;pyinstaller 是一个常用的第三方工具&#xff0c;可以将 Python 脚本…

中间件安全-CVE 复现K8sDockerJettyWebsphere漏洞复现

目录 服务攻防-中间件安全&CVE 复现&K8s&Docker&Jetty&Websphere中间件-K8s中间件-Jetty漏洞复现CVE-2021-28164-路径信息泄露漏洞CVE-2021-28169双重解码信息泄露漏洞CVE-2021-34429路径信息泄露漏洞 中间件-Docker漏洞复现守护程序 API 未经授权访问漏洞…

题目 1119: C语言训练-“水仙花数“问题1(python详解)——练气三层中期

✨博主&#xff1a;命运之光 &#x1f984;专栏&#xff1a;算法修炼之练气篇&#xff08;C\C版&#xff09; &#x1f353;专栏&#xff1a;算法修炼之筑基篇&#xff08;C\C版&#xff09; &#x1f352;专栏&#xff1a;算法修炼之练气篇&#xff08;Python版&#xff09; ✨…

微服务技术导学

文章目录 微服务结构认识微服务技术栈 微服务结构 技术&#xff1a; 解决异常定位&#xff1a; 持续集成&#xff0c;解决自动化的部署&#xff1a; 总结如下&#xff1a; 认识微服务 微服务演变&#xff1a; 技术栈 SpringCloud与SpringBoot版本对应关系