使用Cloudflare和notion搭建自己的博客

2023-10-27

欢迎访问我的个人博客ximikang.icu

使用Cloudflare和notion搭建自己的博客

使用过Nation的小伙伴一定在某个时刻冒出过这样子的想法:这个笔记应用这么好用,而且是基于Web端开发的,那为什么不可以用他来作为我自己的博客呢?这样我是不是可以用记笔记的方式来快速的实现和维护自己的博客了呢?

我搭建的个人博客,欢迎大家访问。https://notion.ximikang.icu/

Untitled

购买一个域名并将域名转移到Cloudflare

首先我们需要将域名的域名服务器设置为 Cloudflare 的域名服务器,这样就可以使用 Cloudflare 的 DNS 服务了。

注册Cloudflare ,然后在这里添加自己的域名:

Untitled

将你的域名指向notion

切换到 dns 页面,添加一条 CNAME 记录,如果你自己的二级域名为 blog.xxx.com,那么名称那就填 blog,目标填 Notion 的域名,保存。

Untitled

Untitled

或者需要将主域名设置为则为

Untitled

注意需要将代理状态切换至已代理,这样才能用cloudflare的免费CDN。

添加后下方就会显示已添加的域名,点击已添加的域名进入设置页面。

配置Cloudflare的Web Worker

配置workder使得我们访问我们上面定义的http请求可以自动改写。

Untitled

  1. 首先**管理Workers,**新建一个对应的notion的worker。

    Untitled

    获取notion页面中的链接ID,如图中的id需要在worker配置中使用。

    Untitled

    创建worker后编辑worker,将如下代码复制到worker中。

    /* CONFIGURATION STARTS HERE */
      
      /* 添加域名 notion.ximikang.icu*/
    
      const MY_DOMAIN = '';
      
      /*
    		添加刚才的id
    		例如:
    		'': 'bb1678c7e8fe47b29bf49aac08aebbb',
       */
      const SLUG_TO_PAGE = {
        '': '',
      };
      
      /* 添加主页面的标题和描述  */
      const PAGE_TITLE = '';
      const PAGE_DESCRIPTION = '';
      
      /* 可以选择显示的字体 https://fonts.google.com 
    	例如:const GOOGLE_FONT = 'Noto Sans Simplified Chinese';*/
      const GOOGLE_FONT = '';
      
      /* 添加自定义脚本,可以添加Google Analytics */
      const CUSTOM_SCRIPT = ``;
      
      /* CONFIGURATION ENDS HERE */
      
      const PAGE_TO_SLUG = {};
      const slugs = [];
      const pages = [];
      Object.keys(SLUG_TO_PAGE).forEach(slug => {
        const page = SLUG_TO_PAGE[slug];
        slugs.push(slug);
        pages.push(page);
        PAGE_TO_SLUG[page] = slug;
      });
      
      addEventListener('fetch', event => {
        event.respondWith(fetchAndApply(event.request));
      });
    
      function generateSitemap() {
        let sitemap = '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
        slugs.forEach(
          (slug) =>
            (sitemap +=
              '<url><loc>https://' + MY_DOMAIN + '/' + slug + '</loc></url>')
        );
        sitemap += '</urlset>';
        return sitemap;
      }
      
      const corsHeaders = {
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Methods': 'GET, HEAD, POST, PUT, OPTIONS',
        'Access-Control-Allow-Headers': 'Content-Type',
      };
      
      function handleOptions(request) {
        if (request.headers.get('Origin') !== null &&
          request.headers.get('Access-Control-Request-Method') !== null &&
          request.headers.get('Access-Control-Request-Headers') !== null) {
          // Handle CORS pre-flight request.
          return new Response(null, {
            headers: corsHeaders
          });
        } else {
          // Handle standard OPTIONS request.
          return new Response(null, {
            headers: {
              'Allow': 'GET, HEAD, POST, PUT, OPTIONS',
            }
          });
        }
      }
      
      async function fetchAndApply(request) {
        if (request.method === 'OPTIONS') {
          return handleOptions(request);
        }
        let url = new URL(request.url);
        url.hostname = 'www.notion.so';
        if (url.pathname === '/robots.txt') {
          return new Response('Sitemap: https://' + MY_DOMAIN + '/sitemap.xml');
        }
        if (url.pathname === '/sitemap.xml') {
          let response = new Response(generateSitemap());
          response.headers.set('content-type', 'application/xml');
          return response;
        }
        let response;
        if (url.pathname.startsWith('/app') && url.pathname.endsWith('js')) {
          response = await fetch(url.toString());
          let body = await response.text();
          response = new Response(body.replace(/www.notion.so/g, MY_DOMAIN).replace(/notion.so/g, MY_DOMAIN), response);
          response.headers.set('Content-Type', 'application/x-javascript');
          return response;
        } else if ((url.pathname.startsWith('/api'))) {
          // Forward API
          response = await fetch(url.toString(), {
            body: url.pathname.startsWith('/api/v3/getPublicPageData') ? null : request.body,
            headers: {
              'content-type': 'application/json;charset=UTF-8',
              'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36'
            },
            method: 'POST',
          });
          response = new Response(response.body, response);
          response.headers.set('Access-Control-Allow-Origin', '*');
          return response;
        } else if (slugs.indexOf(url.pathname.slice(1)) > -1) {
          const pageId = SLUG_TO_PAGE[url.pathname.slice(1)];
          return Response.redirect('https://' + MY_DOMAIN + '/' + pageId, 301);
        } else {
          response = await fetch(url.toString(), {
            body: request.body,
            headers: request.headers,
            method: request.method,
          });
          response = new Response(response.body, response);
          response.headers.delete('Content-Security-Policy');
          response.headers.delete('X-Content-Security-Policy');
        }
      
        return appendJavascript(response, SLUG_TO_PAGE);
      }
      
      class MetaRewriter {
        element(element) {
          if (PAGE_TITLE !== '') {
            if (element.getAttribute('property') === 'og:title'
              || element.getAttribute('name') === 'twitter:title') {
              element.setAttribute('content', PAGE_TITLE);
            }
            if (element.tagName === 'title') {
              element.setInnerContent(PAGE_TITLE);
            }
          }
          if (PAGE_DESCRIPTION !== '') {
            if (element.getAttribute('name') === 'description'
              || element.getAttribute('property') === 'og:description'
              || element.getAttribute('name') === 'twitter:description') {
              element.setAttribute('content', PAGE_DESCRIPTION);
            }
          }
          if (element.getAttribute('property') === 'og:url'
            || element.getAttribute('name') === 'twitter:url') {
            element.setAttribute('content', MY_DOMAIN);
          }
          if (element.getAttribute('name') === 'apple-itunes-app') {
            element.remove();
          }
        }
      }
      
      class HeadRewriter {
        element(element) {
          if (GOOGLE_FONT !== '') {
            element.append(`<link href="https://fonts.googleapis.com/css?family=${GOOGLE_FONT.replace(' ', '+')}:Regular,Bold,Italic&display=swap" rel="stylesheet">
            <style>* { font-family: "${GOOGLE_FONT}" !important; }</style>`, {
              html: true
            });
          }
          element.append(`<style>
          div.notion-topbar > div > div:nth-child(3) { display: none !important; }
          div.notion-topbar > div > div:nth-child(4) { display: none !important; }
          div.notion-topbar > div > div:nth-child(5) { display: none !important; }
          div.notion-topbar > div > div:nth-child(6) { display: none !important; }
          div.notion-topbar-mobile > div:nth-child(3) { display: none !important; }
          div.notion-topbar-mobile > div:nth-child(4) { display: none !important; }
          div.notion-topbar > div > div:nth-child(1n).toggle-mode { display: block !important; }
          div.notion-topbar-mobile > div:nth-child(1n).toggle-mode { display: block !important; }
          </style>`, {
            html: true
          })
        }
      }
      
      class BodyRewriter {
        constructor(SLUG_TO_PAGE) {
          this.SLUG_TO_PAGE = SLUG_TO_PAGE;
        }
        element(element) {
          element.append(`<div style="display:none">Powered by <a href="http://fruitionsite.com">Fruition</a></div>
          <script>
          window.CONFIG.domainBaseUrl = 'https://${MY_DOMAIN}';
          const SLUG_TO_PAGE = ${JSON.stringify(this.SLUG_TO_PAGE)};
          const PAGE_TO_SLUG = {};
          const slugs = [];
          const pages = [];
          const el = document.createElement('div');
          let redirected = false;
          Object.keys(SLUG_TO_PAGE).forEach(slug => {
            const page = SLUG_TO_PAGE[slug];
            slugs.push(slug);
            pages.push(page);
            PAGE_TO_SLUG[page] = slug;
          });
          function getPage() {
            return location.pathname.slice(-32);
          }
          function getSlug() {
            return location.pathname.slice(1);
          }
          function updateSlug() {
            const slug = PAGE_TO_SLUG[getPage()];
            if (slug != null) {
              history.replaceState(history.state, '', '/' + slug);
            }
          }
          function onDark() {
            el.innerHTML = '<div title="Change to Light Mode" style="margin-left: auto; margin-right: 14px; min-width: 0px;"><div role="button" tabindex="0" style="user-select: none; transition: background 120ms ease-in 0s; cursor: pointer; border-radius: 44px;"><div style="display: flex; flex-shrink: 0; height: 14px; width: 26px; border-radius: 44px; padding: 2px; box-sizing: content-box; background: rgb(46, 170, 220); transition: background 200ms ease 0s, box-shadow 200ms ease 0s;"><div style="width: 14px; height: 14px; border-radius: 44px; background: white; transition: transform 200ms ease-out 0s, background 200ms ease-out 0s; transform: translateX(12px) translateY(0px);"></div></div></div></div>';
            document.body.classList.add('dark');
            __console.environment.ThemeStore.setState({ mode: 'dark' });
          };
          function onLight() {
            el.innerHTML = '<div title="Change to Dark Mode" style="margin-left: auto; margin-right: 14px; min-width: 0px;"><div role="button" tabindex="0" style="user-select: none; transition: background 120ms ease-in 0s; cursor: pointer; border-radius: 44px;"><div style="display: flex; flex-shrink: 0; height: 14px; width: 26px; border-radius: 44px; padding: 2px; box-sizing: content-box; background: rgba(135, 131, 120, 0.3); transition: background 200ms ease 0s, box-shadow 200ms ease 0s;"><div style="width: 14px; height: 14px; border-radius: 44px; background: white; transition: transform 200ms ease-out 0s, background 200ms ease-out 0s; transform: translateX(0px) translateY(0px);"></div></div></div></div>';
            document.body.classList.remove('dark');
            __console.environment.ThemeStore.setState({ mode: 'light' });
          }
          function toggle() {
            if (document.body.classList.contains('dark')) {
              onLight();
            } else {
              onDark();
            }
          }
          function addDarkModeButton(device) {
            const nav = device === 'web' ? document.querySelector('.notion-topbar').firstChild : document.querySelector('.notion-topbar-mobile');
            el.className = 'toggle-mode';
            el.addEventListener('click', toggle);
            nav.appendChild(el);
            onLight();
          }
          const observer = new MutationObserver(function() {
            if (redirected) return;
            const nav = document.querySelector('.notion-topbar');
            const mobileNav = document.querySelector('.notion-topbar-mobile');
            if (nav && nav.firstChild && nav.firstChild.firstChild
              || mobileNav && mobileNav.firstChild) {
              redirected = true;
              updateSlug();
              addDarkModeButton(nav ? 'web' : 'mobile');
              const onpopstate = window.onpopstate;
              window.onpopstate = function() {
                if (slugs.includes(getSlug())) {
                  const page = SLUG_TO_PAGE[getSlug()];
                  if (page) {
                    history.replaceState(history.state, 'bypass', '/' + page);
                  }
                }
                onpopstate.apply(this, [].slice.call(arguments));
                updateSlug();
              };
            }
          });
          observer.observe(document.querySelector('#notion-app'), {
            childList: true,
            subtree: true,
          });
          const replaceState = window.history.replaceState;
          window.history.replaceState = function(state) {
            if (arguments[1] !== 'bypass' && slugs.includes(getSlug())) return;
            return replaceState.apply(window.history, arguments);
          };
          const pushState = window.history.pushState;
          window.history.pushState = function(state) {
            const dest = new URL(location.protocol + location.host + arguments[2]);
            const id = dest.pathname.slice(-32);
            if (pages.includes(id)) {
              arguments[2] = '/' + PAGE_TO_SLUG[id];
            }
            return pushState.apply(window.history, arguments);
          };
          const open = window.XMLHttpRequest.prototype.open;
          window.XMLHttpRequest.prototype.open = function() {
            arguments[1] = arguments[1].replace('${MY_DOMAIN}', 'www.notion.so');
            return open.apply(this, [].slice.call(arguments));
          };
        </script>${CUSTOM_SCRIPT}`, {
            html: true
          });
        }
      }
      
      async function appendJavascript(res, SLUG_TO_PAGE) {
        return new HTMLRewriter()
          .on('title', new MetaRewriter())
          .on('meta', new MetaRewriter())
          .on('head', new HeadRewriter())
          .on('body', new BodyRewriter(SLUG_TO_PAGE))
          .transform(res);
      }
    
  2. 配置对应的路由,也就是访问我们的域名后,需要执行我们定义的notion worker

    Untitled

    路由为我们的域名加上/*

    Worker为刚才新建的worker

    Untitled

    现在你的个人博客就大功告成了

添加Google Analytics脚本监控你的网站

进入Google Analytics后台 ,点击左上侧管理,选择需要添加代码的网站对应的账号和媒体资源后,依次点击媒体资源下的管理-数据流,可以看到如下所示界面:

Untitled

将如下的代码添加到worker中的自定义片段中就可以对你的博客进行访问监控。

Untitled

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用Cloudflare和notion搭建自己的博客 的相关文章

  • Wordpress入门建站教程二:搭建WP站点的准备工作

    WordPress入门第一课就简单介绍了WordPress 它是一个使用 PHP语言和 MySQL数据库开发的开源 免费的建站程序 那么搭建WordPress站点 就要求一个能够运行PHP语言的主机空间和一个MySQL数据库 也许有些朋友会
  • Django 快速搭建博客 第十节(修复首页,阅读量的数据)

    写到这里 我们已经使用django博客基础开发框架什么的快开发到底了 接下来的是django进阶阶段 难度会稍微大一些 这里主要是进行一些遗漏掉的地方的 1 我们博客的首页的点击事件未实现 2 文章的阅读量未填满 对于第一点 我们只要把相应
  • 请用美丽欢呼-------Day38

    周末 双休 疯了两天 敲了寥寥的代码 却没少看了相关的文章 这电子书大行于世的年代 对工具的漠然简直就是对生命的亵渎 颠簸的公交车上算是告别了YY的惬意 这生活 感觉傻了点 可真够味 原本只是想写篇 html的发展历程 的 可XHTML 2
  • Django 快速搭建博客 第三节(数据库表设计)

    上一节我们已经能在pycharm下新建了blog app了 这个时候 我们需要设计一下博客的数据库设计 关于数据库表的设计 作为新手的我们并不需要要求懂太多稍微的懂一些也就可以了 毕竟数据库也是需要有一定的功底的 这里我们依据博客学习 将博
  • 2013年春季学期最佳博客内容奖评选开始啦

    各位亲爱的俱乐部主席们 大家好啊 暑假来啦 CSDN高校俱乐部的福利也来啦 首先感谢你们为高校俱乐部的工作所付出的一切努力 从高校俱乐部的首页改版之后起 大家开始使用博客来记录自己俱乐部的工作内容 并且向俱乐部会员和主席们分享自己的学习生活
  • 让你的手机号码变成空号!没试过

    输入 21 13800000000 再按拨号键 注意13800000000这是个空号 原理就是 21 是无条件转移所有来电 13800000000是个空号 如果13800000000的号不起作用你就随便输入个号码什么的 自然别人打进来您的号
  • 如何安装以及用相关插件配置OBSIDIAN?

    之前看人推荐logseq就尝试了一下 吐槽跨设备同步难搞 然后被人种草了Obsidian 这几天使用下来感觉确实比logseq好用多了 第三方插件同步虽然有点冲突但大体上还好 现在考虑怎么去合理规划tag以及wiznote笔记的迁移 虽说感
  • PHP爬取一个网站,该网站正在使用cloudflare

    我想从网站 不是我自己的网站 中抓取一些特定值 例如新闻文本 file get contents 不工作 可能被 php ini 阻止 所以我尝试用curl来做到这一点 问题是 我得到的只是来自 cloudflare 的重定向文本 我的爬虫
  • 【2024年趋势】推荐5个好用的产品手册制作工具

    随着科技的快速发展 人们对于网站产品手册的需求也日益增加 一份详细且易用的产品手册可以帮助用户更好地了解和使用产品 提高用户满意度和忠诚度 之前整理了一期关于2023年我推荐的一些知识库软件 已经12月了 最近我也去关注了一些2024年的趋
  • 在 GWT 中获取 com.google.gwt.user.client.rpc.StatusCodeException: 0

    我有时 经常在 GWT 中遇到此异常 但不知道为什么 SEVERE com google gwt user client rpc StatusCodeException 0 java lang RuntimeException com go
  • 使用 cloudflare 将 CNAME 分配给我在 amazon S3 中的静态网站存储桶

    我正在为我的兄弟创建一个网站 我的第一个网站 并决定通过亚马逊 s3 托管整个网站 到目前为止我已经完成了通常的设置 使用所需域的名称 www website com 创建存储桶 将存储桶设为网站并分配索引文档和错误页面 上传所有内容并公开
  • 是否可以增加 CloudFlare 超时?

    是否可以增加 CloudFlare 超时 如果是 怎么办 我的代码需要一段时间才能执行 而且我不打算在未来几天对其进行 Ajax 化 不 CloudFlare 仅提供这种服务企业计划定制 https www cloudflare com e
  • 证书验证失败:验证证书时客户端证书验证失败

    我正在尝试获得相互客户端认证以在 Azure 中工作 我正在使用以下配置运行一个网络应用程序 public class Startup public Startup IConfiguration configuration Configur
  • 如何防止在 Cloudflare 上暴露源 IP 地址?

    在 Cloudflare DNS 设置页面上 它指出An A AAAA CNAME or MX record is pointed to your origin server exposing your origin IP address
  • 使用 Google Cloud + CloudFlare 创建子域

    我在 CloudFlare 上有一个域名 bar com 该域名链接到 Google Cloud 上托管的网站 我可以在 CloudFlare 上为子域名 foo 创建新的 A 记录 但如何将其映射到 Google Cloud 上的 bar
  • puppeteer 通过启用 cookie 和 Javascript 绕过 cloudflare

    仅在 NodeJs gt 服务器端 我正在做一些网页抓取 一些页面受到 cloudflare anti ddos 页面的保护 我正在尝试绕过此页面 通过搜索 我发现了很多关于隐身方法或 reCapcha 的文章 但问题是 cloudflar
  • 如何限制 Nginx Ingress 上 X-Forwarded-For 标头的访问?

    我有一个 kubernetes 集群和 nginx 入口 请求从 cloudflare 发送到此入口 我可以通过 x forwarded for 标头限制对入口的访问吗 例如 我的 IP 是 1 1 1 1 cloudlare 2 2 2
  • 通过 CloudFlare 获取正确的访客 IP [重复]

    这个问题在这里已经有答案了 我正在使用其他人转售给我的 cPanel 这可能意味着我无法使用mod cloudflare 我想获取访问者的 IP 而不是 CloudFlare IP 我正在使用的代码部分 SERVER REMOTE ADDR
  • Cloudflare Worker 缓存 API 出现问题

    我现在花了无数的时间尝试让缓存 API 来缓存一个简单的请求 我让它在中间工作过一次 但忘记向缓存键添加一些内容 现在它不再工作了 不用说 cache put 没有指定请求是否实际被缓存的返回值并不完全有帮助 我只能进行反复试验 有人可以给
  • 未处理的异常:SocketException:主机查找失败:(操作系统错误:没有与主机名关联的地址,errno = 7)

    我们已经在 Playstore 中发布了一个发行版本 并且运行得很好 但现在突然间 当我们尝试再次构建并运行代码时 因为我们想要添加新功能 它将不再与我们的后端通信 所以我使用错误作为关键字在网络上进行搜索 发现需要 INTERNET PE

随机推荐

  • 数据里面的poi指的什么_如何通过短视频POI功能,获取无数流量

    什么是POI POI功能可以让企业获得独家专享的唯一地址 呈现方式就是抖音视频中的定位图标 点击图标进去 用户可以看到定位这一地址中的全部视频内容 企业通过POI页面可以向用户推荐商品 优惠券 店铺活动等 POI可以让企业和用户之间产生一个
  • 围棋人机大战属于计算机在什么方面的应用,《信息技术基础》第一章复习题库...

    第12题 智能手机 数码相机 MP3播放器等产品中一般都含有嵌入式计算机 答案 Y 第13题 现代遥感遥测技术进步很快 其功能往往远超过人的感觉器官 答案 Y 第14题 集成电路的工作速度主要取决于组成逻辑门电路的晶体管的尺寸 尺寸越小 速
  • ConcurrentHashMap在jdk1.7和jdk1.8中的不同;

    原博客 https www cnblogs com lujiango p 7580558 html http www importnew com 28263 html CouncurrentHashMap 线程安全 一 Councurren
  • Python蒙特卡洛相关变量SciPy模拟

    SciPy 的概率分布和分布拟合 简述 概率分布对随机过程进行建模并将其拟合到观测数据 SciPy 的概率分布 它们的属性和方法 通过拟合 Weibull 极值分布来模拟组件寿命的示例 一个自动化的拟合程序 从大约 60 个候选分布中选择最
  • python logging日志根据等级适配颜色

    安装模块 pip install colorlog 代码参考如下 设置下formatter即可 import logging from colorlog import ColoredFormatter formatter ColoredFo
  • C语言猜数字游戏(详解)

    使用C语言写出猜数字游戏 1 思路 1 我们需要电脑生成一个随机数 2 玩家进行猜数字 3 玩过一次可以再玩一次 那么至少要进去一次 可以使用do while循环 2 大体结构 主函数 使用do while循环 使游戏至少进入一次 然后根据
  • uniapp基于阿里图标库引入彩色的图标iconfont

    1 进入阿里巴巴矢量图标库链接 https www iconfont cn 添加图标到项目 然后下载至本地 2 对下载的文件进行解压 命令行进入解压后的文件下 执行一下命令 全局安装iconfont tools工具 npm install
  • Android编程权威指南第3版 简单的项目作业

    文章目录 前言 1 要求描述 2 MainActivity java 3 InfoActivity java 4 activity info xml 5 activity main xml 6 strings xml 7 AndroidMa
  • Hbase学习笔记(二)——安装与部署

    Hbase 安装与部署 一 安装包 二 修改配置文件 三 分发给其他机器 四 配置环境变量 五 Hbase的启动 一 安装包 hbase 1 2 0 cdh5 14 0 tar gz 二 修改配置文件 配置文件所在位置 cd export
  • 2020美赛MCM/ICM参赛及获奖分析

    文章目录 一 美赛简介 二 参赛队伍数分析 三 选题及获奖情况 四 完整获奖名单pdf 一 美赛简介 美赛 是美国大学生数学建模竞赛的缩写 包括MCM The Mathematical Contest in Modeling数学建模竞赛 和
  • PhpStorm内置的REST客户端 使用方法

    http confluence jetbrains com display PhpStorm Built in REST Client in PhpStorm 跳到元数据结束 由Maarten Balliauw创建 最后由米哈伊尔 温克于2
  • Android之团队开发时高德/百度地图出现INVALID_USER_SCODE

    初次集成前端地图 高德 百度 的同志都可能会遇到INVALID USER SCODE提示 虽然基础地图功能没有影响 但是这个提示直接Toas给用户的 真是够了 如果集成地图导航时可能因为该原因无法打开导航页面 那么我们就研究下为啥出现这个I
  • jQuery实现静态html+ajax请求访问MySQL数据库并显示

    文章目录 静态html ajax与jsp ajax访问流程图 前期准备 配置jQuery 准备index html 准备dao 准备servlet jQuery实现ajax 附 关于Maven项目引入js无法使用的问题 静态html aja
  • Java并发编程与高并发解决方案(精选)

    Java并发编程与高并发面试 一 课程准备 1 1 课程导学 本课程主要是围绕并发编程和高并发解决方案两个核心来进行讲解 希望这门课程能够带领大家攻克并发编程与高并发的难题 课程特点 大量的图示及代码演示 全面覆盖并发知识点 建立完整的知识
  • 计算机操作系统的启动与加载过程

    注 uboot 嵌入式系统的bootloader 包含了BIOS的功能 相当于PC机的BIOS 引导程序
  • MFC的使用——在共享DLL中使用MFC、在静态库中使用MFC

    前言 我们在使用Microsoft Visual Studio软件 也就是我们常常说的VS 时 其中项目属性中有一项叫做 MFC的使用 里面包含有不同的设置 会影响我们所编写的程序的使用 今天我就遇到了这个情况 我们一起来总结一下 避免犯下
  • 数据结构——队列的C语言代码实现

    系列文章目录 数据结构 顺序表的C语言代码实现 数据结构 八种链表的C语言代码实现 数据结构 栈的C语言代码实现 数据结构 队列的C语言代码实现 数据结构 堆的C语言代码实现 文章目录 系列文章目录 前言 一 基础知识 队列的概念 queu
  • pandas时间序列

    目录 1 pandas中6个时间相关的类 2 Timestamp类 1 查看时间列 是str字符串列 还是时间格式列 2 使用pd to datetime 将字符串 转换为日期格式 3 Timestamp类只能表示1677年 2262年的时
  • js 数组移动函数

  • 使用Cloudflare和notion搭建自己的博客

    欢迎访问我的个人博客ximikang icu 使用Cloudflare和notion搭建自己的博客 使用过Nation的小伙伴一定在某个时刻冒出过这样子的想法 这个笔记应用这么好用 而且是基于Web端开发的 那为什么不可以用他来作为我自己的