搭建个人博客,Docsify+Github webhook+JGit解决方案

docsify搭建和简单使用(mac) 文章目录一.前言二. 安装docsifystep1.安装node环境step2.配置npmstep3.安装docsify三.使用docsifystep0. 常用命令step1. 快速开始step2. 自定义组件 一.前言 docsify是一款文档生成静态页面的轻量级软件,与gitbook相比轻量且更易扩展。 作为一款实时渲染文档为静态网页,其不需要编译静态网页,所以更专注与文档创作。 常见的组合拳 typora + docsify/gitbook + github.pages/gitee.pages 快速 阅读详情

一开始博客使用的 Halo,发现问题比较多啊,时不时的莫名其妙主题各种报错,有时候还要升级,麻烦的要死,于是就想弄简单点。

这两天抽空反复倒腾了一遍,不小心还把镜像给尼玛删了,发的文章都没了,痛定思痛,要做改变!

众所周知,我懒出名了,我觉得这种事情你不要老是让我操心啊,最好是一年都不要动一下才好,这搞的跟什么一样。

研究一会儿,最终还是决定 docsify+github 来弄,初步的想法是本地写好 MD 文件直接 push 到 github上,然后触发 github 的webhook,触发脚本去 pull 代码到服务器上。

这样的话还有点想象空间,以后可以省去一大部分同步文章的工作,都可以出发回调去通过 API 同步,不过暂时还没有调研这些平台是否能支持,不过应该问题不大。

试试解决方案可不可行吧,我觉得很 nice。

docsify 搭建安装

首先安装 docsify-cli 工具

npm i docsify-cli -g

然后进入自己的目录,初始化

docsify init ./

这样就差不多了,多了几个文件,简单修改一下 index.html,配置下名字和代码仓库的信息,开启下左边的侧边栏。

同时补充一点插件,都从网上搂的。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
  <meta name="description" content="Description">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
  <link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify@4/lib/themes/vue.css">
</head>
<body>
  <div id="app"></div>
  <script>
    window.$docsify = {
      name: '艾小仙',
      repo: 'https://github.com/irwinai/JavaInterview.git',
      loadSidebar: true,
      autoHeader: true,
      subMaxLevel: 3,
      sidebarDisplayLevel: 1, // set sidebar display level
      count:{
        countable:true,
        fontsize:'0.9em',
        color:'rgb(90,90,90)',
        language:'chinese'
      },
      search: {
        maxAge: 86400000, // Expiration time, the default one day
        paths: [], // or 'auto'
        placeholder: '开始搜索',
        noData: '啥也没有!'
      },
      copyCode: {
        buttonText : '点击复制',
        errorText  : '错误',
        successText: '复制成功'
      },
      footer: {
        copy: '<span>艾小仙 © 2022</span>',
        auth: '赣ICP备2021008029号-1',
        pre: '<hr/>',
        style: 'text-align: right;',
        class: 'className'
      }
    }
  </script>
  <!-- Docsify v4 -->
  <script src="//cdn.jsdelivr.net/npm/docsify@4"></script>
  <!-- 搜索 -->
  <script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/search.min.js"></script>
  <!-- 图片放大缩小支持 -->
  <script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/zoom-image.min.js"></script>
  <!-- 拷贝文字内容 -->
  <script src="//cdn.jsdelivr.net/npm/docsify-copy-code/dist/docsify-copy-code.min.js"></script>
  <!-- 字数插件 -->
  <script src="https://cdn.jsdelivr.net/npm/docsify-count@latest/dist/countable.min.js"></script>
  <!-- 分页导航 -->
  <script src="//unpkg.com/docsify-pagination/dist/docsify-pagination.min.js"></script>
  <!-- 侧边栏扩展与折叠 -->
  <script src="//cdn.jsdelivr.net/npm/docsify-sidebar-collapse/dist/docsify-sidebar-collapse.min.js"></script>
  <!-- 页脚信息 -->
  <script src="//unpkg.com/docsify-footer-enh/dist/docsify-footer-enh.min.js"></script>
  <!-- GitTalk评论 -->
  <!-- <link rel="stylesheet" href="//cdn.jsdelivr.net/npm/gitalk/dist/gitalk.css">
  <script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/gitalk.min.js"></script>
  <script src="//cdn.jsdelivr.net/npm/gitalk/dist/gitalk.min.js"></script> -->
</body>
</html>

然后运行,本地会启动 http://localhost:3000 ,直接看看效果

docsify serve

大概就这个样子了

侧边栏还没有,使用命令生成一下,会自动帮我们根据目录创建一个 _sidebar.md 文件,也就是我们的侧边栏了。

docsify generate .

然后再看看效果怎么样,差不多就这样,需要注意的是文件名不能有空格,否则生成的侧边栏目录会有问题,需要修改一下文件名使用中划线或者下换线替换空格(我无法理解为什么不能用空格)。

多级目录生成问题

另外还有一个问题是无法生成多级目录,也就是不能超过二级目录,这个我自己随便改了一下。

去 docsify-cli 官方 git 仓库下载源码,然后把这个丢进去,在目录下执行 node generate.js 就可以,底部测试目录改成自己的目录。

'use strict'

const fs = require('fs')
const os = require('os')
const {cwd, exists} = require('../util')
const path = require('path')
const logger = require('../util/logger')
const ignoreFiles = ['_navbar', '_coverpage', '_sidebar']

// eslint-disable-next-line
function test (path = '', sidebar) {
  // 获取当前目录
  const cwdPath = cwd(path || '.')

  // console.log('cwdPath', cwdPath, !!exists(cwdPath));

  // console.log('///////', cwdPath, path, cwd(path || '.'))
  if (exists(cwdPath)) {
    if (sidebar) {
      const sidebarPath = cwdPath + '/' + sidebar || '_sidebar.md';

      if (!exists(sidebarPath)) {
        genSidebar(cwdPath, sidebarPath)
        logger.success(`Successfully generated the sidebar file '${sidebar}'.`)
        return true
      }

      logger.error(`The sidebar file '${sidebar}' already exists.`)
      process.exitCode = 1
      return false
    }
    return false;
  }

  logger.error(`${cwdPath} directory does not exist.`)
}

let tree = '';
function genSidebar(cwdPath, sidebarPath) {
  // let tree = '';
  let lastPath = ''
  let nodeName = ''
  let blankspace = '';
  let test = 0;

  const files = getFiles(cwdPath);
  console.log(JSON.stringify(files));
  getTree(files);

  fs.writeFile(sidebarPath, tree, 'utf8', err => {
    if (err) {
      logger.error(`Couldn't generate the sidebar file, error: ${err.message}`)
    }
  })

  return;

  getDirFiles(cwdPath, function (pathname) {
    path.relative(pathname, cwdPath) // 找cwdPath的相对路径
    pathname = pathname.replace(cwdPath + '/', '')
    let filename = path.basename(pathname, '.md') // 文件名
    let splitPath = pathname.split(path.sep) // 路径分割成数组
    let blankspace = '';

    if (ignoreFiles.indexOf(filename) !== -1) {
      return true
    }

    nodeName = '- [' + toCamelCase(filename) + '](' + pathname + ')' + os.EOL

    if (splitPath.length > 1) {
      if (splitPath[0] !== lastPath) {
        lastPath = splitPath[0]
        tree += os.EOL + '- ' + toCamelCase(splitPath[0]) + os.EOL
      }
      tree += '  ' + nodeName
      // console.error('tree=====', tree, splitPath, splitPath.length);
    } else {
      if (lastPath !== '') {
        lastPath = ''
        tree += os.EOL
      }

      tree += nodeName
    }
  })
  fs.writeFile(sidebarPath, tree, 'utf8', err => {
    if (err) {
      logger.error(`Couldn't generate the sidebar file, error: ${err.message}`)
    }
  })
}

function getFiles (dir) {
  // let path = require('path');
  // let fs = require('fs');
  let rootDir = dir;
  var filesNameArr = []
  let cur = 0
  // 用个hash队列保存每个目录的深度
  var mapDeep = {}
  mapDeep[dir] = 0
  // 先遍历一遍给其建立深度索引
  function getMap(dir, curIndex) {
    var files = fs.readdirSync(dir) //同步拿到文件目录下的所有文件名
    files.map(function (file) {
      //var subPath = path.resolve(dir, file) //拼接为绝对路径
      var subPath = path.join(dir, file) //拼接为相对路径
      var stats = fs.statSync(subPath) //拿到文件信息对象
      // 必须过滤掉node_modules文件夹
      if (file != 'node_modules') {
        mapDeep[file] = curIndex + 1
        if (stats.isDirectory()) { //判断是否为文件夹类型
          return getMap(subPath, mapDeep[file]) //递归读取文件夹
        }
      }
    })
  }
  getMap(dir, mapDeep[dir])
  function readdirs(dir, folderName, myroot) {
    var result = { //构造文件夹数据
      path: dir,
      title: path.basename(dir),
      type: 'directory',
      deep: mapDeep[folderName]
    }
    var files = fs.readdirSync(dir) //同步拿到文件目录下的所有文件名
    result.children = files.map(function (file) {
      //var subPath = path.resolve(dir, file) //拼接为绝对路径
      var subPath = path.join(dir, file) //拼接为相对路径
      var stats = fs.statSync(subPath) //拿到文件信息对象
      if (stats.isDirectory()) { //判断是否为文件夹类型
        return readdirs(subPath, file, file) //递归读取文件夹
      }
      if (path.extname(file) === '.md') {
        const path =  subPath.replace(rootDir + '/', '');
        // console.log(subPath, rootDir, '========', path);
        return { //构造文件数据
          path: path,
          name: file,
          type: 'file',
          deep: mapDeep[folderName] + 1,
        }
      }
    })
    return result //返回数据
  }
  filesNameArr.push(readdirs(dir, dir))
  return filesNameArr
}

function getTree(files) {
  for (let i=0; i<files.length;i++) {
    const item = files[i];
    if (item) {
      if (item.deep === 0) {
        if (item.children) {
          getTree(item.children)
        }
      } else {
        let blankspace = ''
        for (let i = 1; i < item.deep; i++) {
          blankspace += '  '
        }
        // console.log('-' + blankspace + '-', item.deep)
        if (item.type === 'directory') {
          tree += os.EOL + blankspace + '- ' + toCamelCase(item.title) + os.EOL
        } else if (item.type === 'file') {
          tree += os.EOL + blankspace + '- [' + item.name + '](' + item.path + ')' + os.EOL
          // console.log('tree', tree);
        }
        if (item.children) {
          getTree(item.children)
        }
      }
    }
  }
}

function getDirFiles(dir, callback) {
  fs.readdirSync(dir).forEach(function (file) {
    let pathname = path.join(dir, file)

    if (fs.statSync(pathname).isDirectory()) {
      getDirFiles(pathname, callback)
    } else if (path.extname(file) === '.md') {
      callback(pathname)
    }
  })
}

function toCamelCase(str) {
  return str.replace(/\b(\w)/g, function (match, capture) {
    return capture.toUpperCase()
  }).replace(/-|_/g, ' ')
}


test("/Users/user/Documents/JavaInterview/", "sidebar.md");

这样的话一切不就都好起来了吗?看看最终的效果。

nginx 配置

webhook 暂时还没弄,先手动 push 上去然后把文件都传到服务器上去,再设置一下 nginx 。

server {
    listen 80;
    listen [::]:80;
    server_name aixiaoxian.vip;
    client_max_body_size 1024m;
    location / {
        root /你的目录;
        index index.html;
    }
}

server {
    listen       443 ssl;
    server_name  aixiaoxian.vip;
    root         /usr/share/nginx/html;

    ssl_certificate cert/aixiaoxian.pem;
    ssl_certificate_key cert/aixiaoxian.key;
    ssl_session_cache shared:SSL:1m;
    ssl_session_timeout  10m;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
    ssl_prefer_server_ciphers on;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #表示使用的TLS协议的类型。
    include /etc/nginx/default.d/*.conf;

    location / {
        root /你的目录;
        index index.html;
    }
}

这时候你去 reload nginx 会发现网站可能 403 了,把你的 ng 文件第一行改了,甭管后面是啥,改成 root 完事儿。

user root;

这样就 OK 了。

内网穿透

然后,就需要搞一个 webhook 的程序了,但是在此之前,为了本地能测试 webhook 的效果,需要配置个内网穿透的程序,我们使用 ngrok 。

先安装。

brew install ngrok/ngrok/ngrok

然后需要注册一个账号,这里没关系,直接 google 登录就好了,之后进入个人页面会提示你使用步骤。

按照步骤来添加 token,然后映射 80 端口。

如果后面发现 ngrok 命令找不到,可以去官网手动下一个文件,丢到 /usr/local/bin 目录中就可以了。

成功之后可以看到 ngrok 的页面,使用他给我们提供的 Forwarding 地址,就是我们的公网地址。

我随便弄了个 80 端口,这里用自己到时候项目的端口号映射就行了,后面我们改成 9000。

webhook

配置好之后,就去我们的 github 项目设置 webhook,使用上面得到的地址。

这样就设置OK了,然后搞个 Java 程序去,监听 9000 端口,随便写个 Controller 。

@PostMapping("/webhook")
public void webhook(@RequestBody JsonNode jsonNode) {
	System.out.println("json===" + jsonNode);
}

然后随便改点我们的文档,push 一下,收到了 webhook 的回调,其实我们根本不关注回调的内容,我们只要收到这个通知,就去触发重新拉取代码的指令就行。

{
    "repository": {
        "id": 306793662,
        "name": "JavaInterview",
        "full_name": "irwinai/JavaInterview",
        "private": false,
        "owner": {
            "name": "irwinai",
            "email": "415586662@qq.com",
            "login": "irwinai"
        },
        "html_url": "https://github.com/irwinai/JavaInterview",
        "description": null,
        "fork": false
    },
    "pusher": {
        "name": "irwinai",
        "email": "415586662@qq.com"
    },
    "sender": {
        "login": "irwinai",
        "id": 4981449
    }
}

接着,我们实现代码逻辑,根据回调执行命令去拉取最新的代码到本地,为了能通过 Java 操作 Git,引入 JGit。

<dependency>
  <groupId>org.eclipse.jgit</groupId>
  <artifactId>org.eclipse.jgit</artifactId>
  <version>5.13.1.202206130422-r</version>
</dependency>

为了简单,我每次都是重新 clone 仓库下来,正常来说应该第一次 clone,后面直接 pull 代码,这里为了省事儿,就先这样操作。

@RestController
public class WebhookController {
    private static final String REMOTE_URL = "https://github.com/irwinai/JavaInterview.git";

    @PostMapping("/webhook")
    public void webhook(@RequestBody JsonNode jsonNode) throws Exception {
        File localPath = new File("/Users/user/Downloads/TestGitRepository");

        // 不管那么多,先删了再说
        FileUtils.deleteDirectory(localPath);

        //直接 clone 代码
        try (Git result = Git.cloneRepository()
                .setURI(REMOTE_URL)
                .setDirectory(localPath)
                .setProgressMonitor(new SimpleProgressMonitor())
                .call()) {
            System.out.println("Having repository: " + result.getRepository().getDirectory());
        }
    }

    private static class SimpleProgressMonitor implements ProgressMonitor {
        @Override
        public void start(int totalTasks) {
            System.out.println("Starting work on " + totalTasks + " tasks");
        }

        @Override
        public void beginTask(String title, int totalWork) {
            System.out.println("Start " + title + ": " + totalWork);
        }

        @Override
        public void update(int completed) {
            System.out.print(completed + "-");
        }

        @Override
        public void endTask() {
            System.out.println("Done");
        }

        @Override
        public boolean isCancelled() {
            return false;
        }
    }
}

代码执行后已经是 OK 了,可以直接拉取到代码,那么至此,差不多已经 OK 了,后面把代码直接丢服务器上去跑着就拉倒了。

服务器的问题

好了,你以为到这里就结束了吗?年轻了,年轻了。。。

这代码丢到服务器上跑会发现报错连不上 github,如果你是阿里云服务器的话。

解决方案是找到 /etc/ssh/ssh_config ,删掉 GSSAPIAuthentication no 这行前面的注释,然后保存,你才会发现真的是能下载了。

同时,nginx 我们映射另外一个域名作为回调的域名,这里需要主要以下你的 https 证书,因为我是免费版的,所以 https 这个域名无法生效,那 webhook 回调注意用 http 就行。

server {
    listen 80;
    listen [::]:80;
    server_name test.aixiaoxian.vip;
    client_max_body_size 1024m;
    location / {
        proxy_pass http://127.0.0.1:9000;
        proxy_set_header HOST $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
server {
    listen       443 ssl;
    server_name  test.aixiaoxian.vip;
    root         /usr/share/nginx/html;

    ssl_certificate cert/aixiaoxian.pem;
    ssl_certificate_key cert/aixiaoxian.key;
    ssl_session_cache shared:SSL:1m;
    ssl_session_timeout  10m;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
    ssl_prefer_server_ciphers on;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #表示使用的TLS协议的类型。
    include /etc/nginx/default.d/*.conf;

    location / {
        proxy_pass http://127.0.0.1:9000;
        proxy_set_header HOST $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

OK,如果你用上面的方式还无法解决,可以换一种方式,直接通过 Java 直接 shell 脚本去处理。

rm -rf /root/docs/JavaInterview
git clone https://github.91chi.fun//https://github.com/irwinai/JavaInterview.git

用脚本的目的是可以用加速的 git 地址,否则服务器访问经常会失败,这个找个插件就可以有加速地址了。

public class ShellCommandsHelper extends CommandHelper {
    private static final File file = new File(FILE_PATH);

    @Override
    public void exec() {
        try {
            FileUtils.forceMkdir(file);

            log.info("Starting clone repository...");

            Process process = Runtime.getRuntime().exec("sh " + SHELL_PATH, null, file);
            int status = process.waitFor();

            if (status != 0) {
                log.error("[ShellCommandsHelper] exec shell error {}", status);
            }
        } catch (Exception e) {
            log.error("[ShellCommandsHelper] exec shell error", e);
        }
    }

}

代码上传的问题

好了,这样通过手动上传代码的方式其实已经可以用了,但是为了部署更方便一点,我建议安装一个插件 Alibaba Cloud Toolkit ,其他云服务器有的也有这种类型的插件。

安装好插件之后会进入配置的页面,需要配置一个 accessKey 。

去自己的阿里云账号下面配置。

配置好了之后,点击 Tools-Deploy to xxx ,我是 ECS ,所以选择 ECS 服务器即可。

然后在这里会自动加载出你的服务器信息,然后选择自己的部署目录,同时选择一个 Command 也就是执行命令。

这个命令随便找个目录创建一个这个脚本,放那里就行了,最后点击 Run,代码就飞快的上传了。

source /etc/profile
killall -9 java
nohup java -jar /root/tools/sync-tools-0.0.1-SNAPSHOT.jar > nohup.log 2>&1 &

结束

基本的工作已经做完了,那其实还有挺多细节问题没有处理的,比如失败重试、回调鉴权等等问题,这只是一个非常初级的版本。

同步代码 git 地址: GitHub - irwinai/sync-tools

org.eclipse.jgit-5.13.0.202109080827-r.jar中文-英文对照文档.zip 注:下文中的 *** 代表文件名中的组件名称。 # 包含: 中文-英文对照文档:【***-javadoc-API文档-中文(简体)-英语-对照版.zip】 jar包下载地址:【***.jar下载地址(官方地址+国内镜像地址).txt】 Maven依赖:【***.jar Maven依赖信息(可用于项目pom.xml).txt】 Gradle依赖:【***.jar Gradle依赖信息(可用于项目build.gradle).txt】 源代码下载地址:【***-sources.jar下载地址(官方地址+国内镜像地址).txt】 # 本文件关键字: 中文-英文对照文档,中英对照文档,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压 【***.jar中文文档.zip】,再解压其中的 【***-javadoc-API文档-中文(简体)版.zip】,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·本文档为双语同时展示,一行原文、一行译文,可逐行对照,避免了原文/译文来回切换的麻烦; ·有原文可参照,不再担心翻译偏差误导; ·边学技术、边学英语。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件; 立即下载

相关推荐

Linux DRM驱动实战:手把手教你用drmModeSetCrtc显示纯色画面(附完整代码)

本文提供了一份完整的Linux DRM驱动实战指南,手把手教你使用drmModeSetCrtc在屏幕上显示纯色画面。文章详细解析了从打开设备、获取资源、创建帧缓冲区到最终提交画面的完整调用流程,并附带了可直接编译运行的完整代码示例,帮助开发者快速上手Linux图形底层开发。

weixin_29216353的博客 510

Docsify 侧边栏 : 自动生成sidebar与子目录sidebar

Docsify 侧边栏 : 自动生成sidebar与子目录sidebar https://github.com/xxxxue/Docsify-Build-Sidebar

未将对象引用设置到对象的实例 5527

别再死记硬背了!用‘瞬时极性法’5分钟搞定三极管反馈电路类型判断

本文介绍了使用‘瞬时极性法’快速判断三极管反馈电路类型的高效技巧。通过假设输入信号变化并追踪传递路径,该方法能准确区分正负反馈、电压电流反馈、串联并联反馈及交直流反馈,避免传统死记硬背的弊端,显著提升电路分析效率。

weixin_42524708的博客 181

Docsify 使用指南

Docsify 使用指南 【免费下载链接】docsify ???? A magical documentation site generator. 项目地址: https://gitcode.com/gh_mirrors/do/docs...

gitblog_00258的博客 1106

cmu15445(2024fall) project 2

project 2比p1难度要更大,代码量更大且涉及的知识更多,实现中出现的bug更多,好在是最后全部解决了。我最大的收获在于对于多线程编程的理解更深入了,实际发现解决了多个多线程相关的bug,学会了更多多线程下debug的技巧方法,也见识了更多多线程的bug情况。在之后可以更系统的学习一下多线程编程。同时学会实现B+树也是需要掌握的基础。

Jerome_Yi的博客 1553

基于plc的工厂除尘控制系统设计(S7-200、仿真、调试、高质量)

工业作为我国第二支柱产业,在近十几年来发展非常迅速,虽然带了了可观的经济效益,但在工业生产中所产生的大量粉尘气体对大气的污染现象也不容忽视。为减少工业粉尘对环境的污染,世界各国制定了严格的环境保护要求。为了减少工业中粉尘的排放,除尘器的研发改良,以及燃煤的使用等等都在不断更改以符合粉尘排放标准。而目前最先进的除尘设备无机膜除尘器具备除尘效率高,稳定性好,结构紧凑易于维护等优点,且无机膜对于粉尘吸附效率高,抗腐蚀能力优秀,耐高温,因此能更有效应用于高温烟气的除尘。本文根据PLC技术在除尘方面的应用,来优化设计

老高的博客 1279

webhook服务器_几分钟即可设置免费的无服务器Webhook!

webhook服务器 注意:本文已过时几个月; 毕竟,如今,谁愿意从Google Cloud仪表板部署无服务器Webhook,而您只需单击几下即可在世界上最好的无服务器IDE上进行同样的操作 ?! 通常,您需要设置一个HTTP / S端点(webhook)来接受从另一个应用程序或服务发布的数据。 例如GitHub webhooks 。 这是设置单个服务器的快速方法,而无需运行,购买或维护...

danpu0978的博客 3700

Windows10环境下激活虚拟环境报错【source : 无法将“source”项识别为 cmdlet、函数、脚本文件或可运行程序的名称】

在使用Django创建Web程序前,需要创建一个虚拟的工作环境,在使用【source ll_env/bin/activate】命令激活虚拟环境时报错:source : 无法将“source”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次。所在位置 行:1 字符: 2。

提供C#相关开发 、云计算、运维测试、网络安全相关技术分享与服务,有意向可联系。 1万+

【亲测免费】 微信工作平台Webhook推送助手使用指南

微信工作平台Webhook推送助手([wework-webhook-starter](https://github.com/swalikh/wework-webhook-starter))是一款基于Java的库,旨在简化企业微信通过Webhook接口发送各种类型通知的过程。它支持包括文本、图片、文本卡片、图文消息以及Markdown消息等在内的多种消息格式,非常适合集成到自动化流程中,实现与企业微...

gitblog_01037的博客 3012

【ComfyUI报错解决】K采样器 mat1和mat2形状不匹配错误分析与修复 mat1 and mat2 shapes cannot be multiplied (77x2048 and 4096x

如果你在 ComfyUI 里遇到K采样器报错:mat1 和 mat2 shapes cannot be multiplied确认大模型和 LoRA 是否是同一版本(SDXL vs SD1.5,不能混用)。如果用了双 CLIP 加载器,要确认加载的类型和选择的模型类型是否匹配。加载→ 类型选flux加载 SDXL 专用的 clip/t5 → 类型选sdxl避免不同版本模型和 LoRA 混搭,保持一致性。模型+LoRA+CLIP 类型必须保持同一版本,不然就会报错。

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 2407

OPTEE常见13类问题与解答

OPTEE常见13类问题并解答

AI-安全-功耗 1202

Jenkins 流水线 获取git 分支列表_Jenkins多分支流水线:Webhook按分支触发自动构建

Jenkins多分支流水线(Multibranch Pipeline )项目类型能够在同一个项目的不同分支上实现不同的Jenkinsfile。在多分支流水线项目中, Jenkins 自动的发现、管理和执行在源代码控制中包含Jenkinsfile的分支的流水线,这消除了手动创建和管理流水线的需要。在实际应用中,我们经常需要Git+Jenkins实现代码提交触发Job的自动构建。对于普通Job,web...

weixin_39637661的博客 1140

2025华为OD机试真题最新题库 (B+C+D+E+2025A+2025B卷) + 在线OJ在线刷题使用(C++、Java、Python C语言 JS合集)(正在更新2025B卷,目前已收录710道)

2024年,华为目前已经启用D卷,目前D卷和C卷的题目一样一次订阅永久阅读,支持在线刷题,持续更新,有问题随时解答,本专栏题目数量已收录到484道。每篇文章的思路分析都非常详细,题目新增图解思路,问题解疑,多样例测试,超过百字的思路参考解析。

KJ.JK 11万+

Hook0云服务评测:免费套餐是否满足你的Webhook需求?

Hook0是一款开源Webhook服务器,旨在帮助开发者轻松为用户提供Webhook服务,无需重复开发那些繁琐的功能。对于开发者而言,选择合适的Webhook服务至关重要,而Hook0的免费套餐是否能满足日常需求呢?本文将从功能、性能、易用性等方面进行详细评测。 ## 一、Hook0核心功能解析 Hook0作为一款专业的Webhook服务器,提供了丰富的功能来简化Webhook的管理和维护。它

gitblog_01129的博客 417

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

【永久免费】Tracking API&Webhook

若要获取最新的物流轨迹节点,请使用 GET API 接口 https://api.51Tracking.com/v4/trackings/get/tracking_numbers=9261290312833844954982。您可以使用51Tracking的查询API无缝管理物流轨迹,并从管理门户使用51Tracking的购买服务。要获取您的 API 密钥,请注册51Tracking账户,注册成功后自动生成属于您的API Key,同时也可在账户后台生成新的API Key。

kallen3的博客 2666

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

【免费下载】 探索TradingView免费Webhook警报系统

TradingView-Free-Webhook-Alerts是一个开源项目,自2022年2月1日开始,旨在为TradingView基础计划用户提供免费的Webhook服务。该项目通过监听电子邮件收件箱,将TradingView的警报邮件转换为Webhook消息,从而实现无需Pro/Pro+/Premium账户即可接收实时交易警报的功能。 ## 项目技术分析 该项目主要使用Python 3.8...

gitblog_01065的博客 2655

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

用k8s私有化部署docsify做开放API平台

参照模板:【工行的API开放平台】 API开放平台,用于给第三方系统做接入用,开放的自然也是用于对接的那部分API。主要有两类:前者简单,后者得考虑鉴权、限流等问题。这类API开放平台不需要考虑在线调用,能展示就行,实现方式可考虑:关于第三种的具体思路:关于API文档内容的维护,可考虑采用上传word文档或者在线富文本框的方式,提到后端,后端转md或其他前端需要的格式后,返回给前端。这种实现类似工行的开放平台,优点是灵活,自己爱咋展示咋展示,维护、上下架接口、编辑、删除都可以做成一个前端页面,可以在线操作,

llg___的博客 1869

Java高级技术

本阶段课程涵盖Java开发流行的自动化构建工具:Maven,版本控制系统:SVN和Git,容器虚拟化技术:Docker,权限模型:RBAC,集成测试:Jenkins,微服务架构:SpringCloud等核心内容。旨在应对各种实际开发情况下的的各种开发场景及业务的需要。

自定义GitHub的WebHook

背景/介绍 如果我们想利用github搭建cicd平台的话需要使用webhook,即网络钩子。它的作用是当发生一些事件的时候会向目标服务器发送一个请求,通知服务器该仓库发生了变更,具体什么粒度我们可以指定,一般push即可 搭建简易服务器 from flask import Flask, request app = Flask(__name__) @app.route("/ping") def hello_world(): return "pong!" @app.route("/rive

一条小黑龙的博客 2966

关于git webhook的使用(超级完整,超级详细)

首先创建仓库,git的基本使用我就略过了。我的博客里面有对应的文章。 一:服务器弄个网站 参考:,网站下新建一个文件,名字随意,我的是 hook.php; hook.php的代码如下 <?php ##要打开shell_exec函数,默认为禁用 $json = file_get_contents("php://input"); $data = json_decode($json,true); ##加一些验证,不要裸奔 ##我这里就是弄了密码,webhook弄了个密码 if($data['pas

channel)海峡的博客 6501

GitHook+JGit实现最新代码的自动克隆或者项目的自动部署

需求 思路 开工 设置webhook 响应webhook的服务器 http接口 clone和checkout操作 遍历本地仓库 IO流读取内容 运行结果需求 分析师写的sql需要映射到另外一个后台系统报表中,由于要经常进行sql优化,需要经常修改sql,而有时候由于马虎sql也会写错,而此刻以前的sql也忘记了,难以维护,所以决定把sql托管在gitlab上。 需求就是保证后台系统的报表s

苏苏爱自由 5147

GIT实现自动拉取代码(可实现自动部署)

一、利用crontab定时任务 编辑用户的定时任务: crontab -e 在用户定时任务文件里写入定时命令 每过1分钟执行后面的命令 : */1 * * * * cd /home/wwwroot/default/GIT/autoload;/usr/local/bin/git pull cd /home/wwwroot/default/GIT/autoload 表示进入到git项目目录 /usr

刘俊龙的博客 1万+

Docsify搭建

Docsify搭建 官网:https://docsify.js.org/#/zh-cn/ 前提 要配置好 nodeJs 、npm 安装 Docsify 插件 自己创建一个要下载到本地的文件夹,然后在这里直接利用命令下载 推荐全局安装 docsify-cli 工具,可以方便地创建及在本地预览生成的文档。 npm i docsify-cli -g ​ 下载完成之后,进入 ./node_modules/.bin 使用终端查看安装是否成功 docsify -v 出现版本号,表明安装成功,自己再将该路径

Bkhole的博客 1035

网站自动生成html还是仅使用动态文档,docsify: Docsify 一个神奇的文档网站生成工具。 是什么 docsify 是一个动态生成文档网站的工具。不同于 GitBook、Hexo 的地方是...

A magical documentation site generator. Gold Sponsor via Open CollectiveLinksFeaturesNo statically built html filesSimple and lightweightSmart full-text search pluginMultiple themesUsef...

weixin_33914982的博客 336

GitHub Actions 自动化:5 个真实运维提效案例

回顾五个案例的共同思路:把高频、规则明确、易出错的运维动作交给流水线,把人的精力留给判断与优化。给出从单点试点到体系化推广的推进建议。

2205_76017107的博客 135
上一篇: Redis 与 MySQL 数据一致性问题
下一篇: Java亿级流量架构之网关设计思路
JavaShark
博客等级 码龄4年 184粉丝 438原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值