KubeSphere中部署Wiki系统wiki.js并启用中文全文检索

目录
  • 背景
  • 准备 storageclass
  • 部署 PostgreSQL 数据库
    • 准备用户名密码配置
    • 准备数据库初始化脚本
    • 准备存储
    • 部署 PostgreSQL 数据库
    • 创建供其他 Pod 访问的 Service
    • 完成 PostgreSQL 部署
  • 部署 wiki.js
    • 准备用户名密码配置
    • 准备数据库连接配置
    • 创建数据库用户和数据库
    • 准备 wiki.js 的 yaml 部署文件
    • 创建集群内访问 wiki.js 的 Service
    • 创建集群外访问的 Ingress
    • 执行部署
  • 配置 wiki.js 支持中文全文检索
    • 授予 wikijs 用户临时超管权限
    • 启用数据库的中文分词能力
    • 取消 wikijs 用户的临时超管权限
    • 创建支持中文分词的配置 ConfigMap
    • 更新 wikijs 的 Deployment
    • 配置 wiki.js ,启用基于 PostgreSQL 的全文检索
  • 总结

背景

wiki.js 是优秀的开源 Wiki 系统,相较于 xwiki ,功能目前性上比 xwiki 不够完善,但也在不断进步。 Wiki 写作、分享、权限管理功能还是有的,胜在 UI 设计很漂亮,能满足小团队的基本知识管理需求。

以下工作是在 KubeSphere 3.2.1 + Helm 3 已经部署好的情况下进行的。

部署 KuberSphere 的方法官网有很详细的文档介绍,这里不再赘叙。 kubesphere.com.cn/docs/instal…

准备 storageclass

我们使用 OpenEBS 作为存储,OpenEBS 默认安装的 Local StorageSlass 在 Pod 销毁后自动删除,不适合用于我的 MySQL 存储,我们在 Local StorageClass 基础上稍作修改,创建新的 StorageClass,允许 Pod 销毁后,PV 内容继续保留,手动决定怎么处理。

apiVersion: v1
items:
- apiVersion: storage.k8s.io/v1
  kind: StorageClass
  metadata:
    annotations:
      cas.openebs.io/config: |
        - name: StorageType
          value: "hostpath"
        - name: BasePath
          value: "/var/openebs/localretain/"
      openebs.io/cas-type: local
      storageclass.beta.kubernetes.io/is-default-class: "false"
      storageclass.kubesphere.io/supported-access-modes: '["ReadWriteOnce"]'
    name: localretain
  provisioner: openebs.io/local
  reclaimPolicy: Retain
  volumeBindingMode: WaitForFirstConsumer
kind: List
metadata:
  resourceVersion: ""
  selfLink: ""

部署 PostgreSQL 数据库

我们团队其他项目中也需要使用 PostgreSQL, 为了提高 PostgreSQL 数据库的利用率和统一管理,我们独立部署 PostgreSQL,并在安装 wiki.js 时,配置为使用外部数据库。

准备用户名密码配置

我们使用 Secret 保存 PostgreSQL 用户密码等敏感信息。

kind: Secret
apiVersion: v1
metadata:
  name: postgres-prod
data:
  POSTGRES_PASSWORD: xxxx
type: Opaque

以上 POSTGRES_PASSWORD 自行准备,为 base64 编码的数据。

准备数据库初始化脚本

使用 ConfigMap 保存数据库初始化脚本,在 数据库创建时,将 ConfigMap 中的数据库初始化脚本挂载到 /docker-entrypoint-initdb.d, 容器初始化时会自动执行该脚本。

apiVersion: v1
kind: ConfigMap
metadata:
  name: wikijs-postgres-init
data:
  init.sql: |-
    CREATE DATABASE wikijs;
    CREATE USER wikijs with password 'xxxx';
    GRANT CONNECT ON DATABASE wikijs to wikijs;
    GRANT USAGE ON SCHEMA public TO wikijs;
    GRANT SELECT,update,INSERT,delete ON ALL TABLES IN SCHEMA public TO wikijs;
    ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO wikijs;

以上 wikijs 用户的密码自行准备,明文保存。

准备存储

我们使用 KubeSphere 默认安装的 OpenEBS 来提供存储服务。可以通过创建 PVC 来提供持久化存储。

这里声明一个 10G 的 PVC。

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: postgres-prod-data
  finalizers:
    - kubernetes.io/pvc-protection
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  storageClassName: localretain
  volumeMode: Filesystem

部署 PostgreSQL 数据库

在前面的步骤准备好各种配置信息和存储后,就可以开始部署 PostgreSQL 服务了。

我们的 Kubernetes 没有配置存储阵列,使用的是 OpenEBS 作为存储,采用 Deployment 方式部署 PostgreSQL。

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: postgres-prod
  name: postgres-prod
spec:
  replicas: 1
  selector:
    matchLabels:
      app: postgres-prod
  template:
    metadata:
      labels:
        app: postgres-prod
    spec:
      containers:
        - name: db
          imagePullPolicy: IfNotPresent
          image: 'abcfy2/zhparser:12-alpine'
          ports:
            - name: tcp-5432
              protocol: TCP
              containerPort: 5432
          envFrom:
          - secretRef:
              name: postgres-prod
          volumeMounts:
            - name: postgres-prod-data
              readOnly: false
              mountPath: /var/lib/postgresql/data
            - name: wikijs-postgres-init
              readOnly: true
              mountPath: /docker-entrypoint-initdb.d
      volumes:
        - name: postgres-prod-data
          persistentVolumeClaim:
            claimName: postgres-prod-data
        - name: wikijs-postgres-init
          configMap:
            name: wikijs-postgres-init

创建供其他 Pod 访问的 Service

apiVersion: v1
kind: Service
metadata:
  name: postgres-prod
spec:
  selector:
    app: postgres-prod
  ports:
    - protocol: TCP
      port: 5432
      targetPort: tcp-5432

完成 PostgreSQL 部署

测试略

部署 wiki.js

准备用户名密码配置

我们使用 Secret 保存 wiki.js 用于连接数据库的用户名密码等敏感信息。

apiVersion: v1
kind: Secret
metadata:
  name: wikijs
data:
  DB_USER: d2lraWpz
  DB_PASS: xxxx
type: Opaque

以上 DB_PASS 自行准备,为 base64 编码的数据。

准备数据库连接配置

我们使用 ConfigMap 保存 wiki.js 的数据库连接信息。

apiVersion: v1
kind: ConfigMap
metadata:
  name: wikijs
data:
  DB_TYPE: postgres
  DB_HOST: postgres-prod.infra
  DB_PORT: "5432"
  DB_NAME: wikijs
  HA_ACTIVE: "true"

创建数据库用户和数据库

如果 PostgreSQL 数据库里没有创建 wikijs 用户和数据 ,需要手工完成一下工作:

通过『数据库工具』连接 PostgreSQL 数据库,执行一下 SQL 语句,完成数据库和用户的创建、授权。

CREATE DATABASE wikijs;
CREATE USER wikijs with password 'xxxx';
GRANT CONNECT ON DATABASE wikijs to wikijs;
GRANT USAGE ON SCHEMA public TO wikijs;
GRANT SELECT,update,INSERT,delete ON ALL TABLES IN SCHEMA public TO wikijs;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO wikijs;

以上 wikijs 的密码自行修改。

准备 wiki.js 的 yaml 部署文件

采用 Deployment 方式 部署 wiki.js 的 yaml 文件如下:

# wikijs-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: wikijs
  name: wikijs
spec:
  replicas: 1
  selector:
    matchLabels:
      app: wikijs
  template:
    metadata:
      labels:
        app: wikijs
    spec:
      containers:
        - name: wikijs
          image: 'requarks/wiki:2'
          ports:
            - name: http-3000
              protocol: TCP
              containerPort: 3000
          envFrom:
          - secretRef:
              name: wikijs
          - configMapRef:
              name: wikijs

创建集群内访问 wiki.js 的 Service

# wikijs-svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: wikijs
spec:
  selector:
    app: wikijs
  ports:
    - protocol: TCP
      port: 3000
      targetPort: http-3000

创建集群外访问的 Ingress

# wikijs-ing.yaml
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
  name: wikijs
spec:
  ingressClassName: nginx
  rules:
    - host: wiki.xxxx.cn
      http:
        paths:
          - path: /
            pathType: ImplementationSpecific
            backend:
              service:
                name: wikijs
                port:
                  number: 3000

以上 host 域名需要自行配置。

执行部署

$ kubectl apply -f wikijs-deploy.yaml
$ kubectl apply -f wikijs-svc.yaml
$ kubectl apply -f wikijs-ing.yaml

配置 wiki.js 支持中文全文检索

wiki.js 的全文检索支持基于 PostgreSQL 的检索,也支持 Elasticsearch 等,相对来说, PostgreSQL 比较轻量级,本项目中,我们使用 PostgreSQL 的全文检索。

但是,因为 PostgreSQL 不支持中文分词,需要额外安装插件并配置启用中文分词,下面描述了为 wiki.js 启动基于 PostgreSQL 数据库中文分词的全文检索。

授予 wikijs 用户临时超管权限

通过数据库管理工具登录有超管权限的 PostgreSQL 用户,临时授予 wiki.js 用户临时超管权限,便于启动中文分词功能。

ALTER USER wikijs WITH SUPERUSER;

启用数据库的中文分词能力

使用数据库管理工具登录 PostgreSQL 数据库的 wikijs 用户,执行以下命令,启动数据库的中文分词功能。

CREATE EXTENSION pg_trgm;
CREATE EXTENSION zhparser;
CREATE TEXT SEARCH CONFIGURATION pg_catalog.chinese_zh (PARSER = zhparser);
ALTER TEXT SEARCH CONFIGURATION chinese_zh ADD MAPPING FOR n,v,a,i,e,l WITH simple;
-- 忽略标点影响
ALTER ROLE wikijs SET zhparser.punctuation_ignore = ON;
-- 短词复合
ALTER ROLE wikijs SET zhparser.multi_short = ON;
-- 测试一下
select ts_debug('chinese_zh', '青春是最美好的年岁,青春是最灿烂的日子。每一个人的青春都无比宝贵,宝贵的青春只有与奋斗为伴才最闪光、最出彩。');

取消 wikijs 用户的临时超管权限

登录 PostgreSQL 数据库 wikijs 用户,取消 wikijs 用户的超管权限。

ALTER USER wikijs WITH NOSUPERUSER;

创建支持中文分词的配置 ConfigMap

# zh-parse.yaml
kind: ConfigMap
apiVersion: v1
metadata:
  name: wikijs-zhparser
data:
  definition.yml: |-
    key: postgres
    title: Database - PostgreSQL
    description: Advanced PostgreSQL-based search engine.
    author: requarks.io
    logo: https://static.requarks.io/logo/postgresql.svg
    website: https://www.requarks.io/
    isAvailable: true
    props:
      dictLanguage:
        type: String
        title: Dictionary Language
        hint: Language to use when creating and querying text search vectors.
        default: english
        enum:
          - simple
          - danish
          - dutch
          - english
          - finnish
          - french
          - german
          - hungarian
          - italian
          - norwegian
          - portuguese
          - romanian
          - russian
          - spanish
          - swedish
          - turkish
          - chinese_zh
        order: 1
  engine.js: |-
    const tsquery = require('pg-tsquery')()
    const stream = require('stream')
    const Promise = require('bluebird')
    const pipeline = Promise.promisify(stream.pipeline)
    /* global WIKI */
    module.exports = {
      async activate() {
        if (WIKI.config.db.type !== 'postgres') {
          throw new WIKI.Error.SearchActivationFailed('Must use PostgreSQL database to activate this engine!')
        }
      },
      async deactivate() {
        WIKI.logger.info(`(SEARCH/POSTGRES) Dropping index tables...`)
        await WIKI.models.knex.schema.dropTable('pagesWords')
        await WIKI.models.knex.schema.dropTable('pagesVector')
        WIKI.logger.info(`(SEARCH/POSTGRES) Index tables have been dropped.`)
      },
      /**
       * INIT
       */
      async init() {
        WIKI.logger.info(`(SEARCH/POSTGRES) Initializing...`)
        // -> Create Search Index
        const indexExists = await WIKI.models.knex.schema.hasTable('pagesVector')
        if (!indexExists) {
          WIKI.logger.info(`(SEARCH/POSTGRES) Creating Pages Vector table...`)
          await WIKI.models.knex.schema.createTable('pagesVector', table => {
            table.increments()
            table.string('path')
            table.string('locale')
            table.string('title')
            table.string('description')
            table.specificType('tokens', 'TSVECTOR')
            table.text('content')
          })
        }
        // -> Create Words Index
        const wordsExists = await WIKI.models.knex.schema.hasTable('pagesWords')
        if (!wordsExists) {
          WIKI.logger.info(`(SEARCH/POSTGRES) Creating Words Suggestion Index...`)
          await WIKI.models.knex.raw(`
            CREATE TABLE "pagesWords" AS SELECT word FROM ts_stat(
              'SELECT to_tsvector(''simple'', "title") || to_tsvector(''simple'', "description") || to_tsvector(''simple'', "content") FROM "pagesVector"'
            )`)
          await WIKI.models.knex.raw('CREATE EXTENSION IF NOT EXISTS pg_trgm')
          await WIKI.models.knex.raw(`CREATE INDEX "pageWords_idx" ON "pagesWords" USING GIN (word gin_trgm_ops)`)
        }
        WIKI.logger.info(`(SEARCH/POSTGRES) Initialization completed.`)
      },
      /**
       * QUERY
       *
       * @param {String} q Query
       * @param {Object} opts Additional options
       */
      async query(q, opts) {
        try {
          let suggestions = []
          let qry = `
            SELECT id, path, locale, title, description
            FROM "pagesVector", to_tsquery(?,?) query
            WHERE (query @@ "tokens" OR path ILIKE ?)
          `
          let qryEnd = `ORDER BY ts_rank(tokens, query) DESC`
          let qryParams = [this.config.dictLanguage, tsquery(q), `%${q.toLowerCase()}%`]
          if (opts.locale) {
            qry = `${qry} AND locale = ?`
            qryParams.push(opts.locale)
          }
          if (opts.path) {
            qry = `${qry} AND path ILIKE ?`
            qryParams.push(`%${opts.path}`)
          }
          const results = await WIKI.models.knex.raw(`
            ${qry}
            ${qryEnd}
          `, qryParams)
          if (results.rows.length < 5) {
            const suggestResults = await WIKI.models.knex.raw(`SELECT word, word <-> ? AS rank FROM "pagesWords" WHERE similarity(word, ?) > 0.2 ORDER BY rank LIMIT 5;`, [q, q])
            suggestions = suggestResults.rows.map(r => r.word)
          }
          return {
            results: results.rows,
            suggestions,
            totalHits: results.rows.length
          }
        } catch (err) {
          WIKI.logger.warn('Search Engine Error:')
          WIKI.logger.warn(err)
        }
      },
      /**
       * CREATE
       *
       * @param {Object} page Page to create
       */
      async created(page) {
        await WIKI.models.knex.raw(`
          INSERT INTO "pagesVector" (path, locale, title, description, "tokens") VALUES (
            ?, ?, ?, ?, (setweight(to_tsvector('${this.config.dictLanguage}', ?), 'A') || setweight(to_tsvector('${this.config.dictLanguage}', ?), 'B') || setweight(to_tsvector('${this.config.dictLanguage}', ?), 'C'))
          )
        `, [page.path, page.localeCode, page.title, page.description, page.title, page.description, page.safeContent])
      },
      /**
       * UPDATE
       *
       * @param {Object} page Page to update
       */
      async updated(page) {
        await WIKI.models.knex.raw(`
          UPDATE "pagesVector" SET
            title = ?,
            description = ?,
            tokens = (setweight(to_tsvector('${this.config.dictLanguage}', ?), 'A') ||
            setweight(to_tsvector('${this.config.dictLanguage}', ?), 'B') ||
            setweight(to_tsvector('${this.config.dictLanguage}', ?), 'C'))
          WHERE path = ? AND locale = ?
        `, [page.title, page.description, page.title, page.description, page.safeContent, page.path, page.localeCode])
      },
      /**
       * DELETE
       *
       * @param {Object} page Page to delete
       */
      async deleted(page) {
        await WIKI.models.knex('pagesVector').where({
          locale: page.localeCode,
          path: page.path
        }).del().limit(1)
      },
      /**
       * RENAME
       *
       * @param {Object} page Page to rename
       */
      async renamed(page) {
        await WIKI.models.knex('pagesVector').where({
          locale: page.localeCode,
          path: page.path
        }).update({
          locale: page.destinationLocaleCode,
          path: page.destinationPath
        })
      },
      /**
       * REBUILD INDEX
       */
      async rebuild() {
        WIKI.logger.info(`(SEARCH/POSTGRES) Rebuilding Index...`)
        await WIKI.models.knex('pagesVector').truncate()
        await WIKI.models.knex('pagesWords').truncate()
        await pipeline(
          WIKI.models.knex.column('path', 'localeCode', 'title', 'description', 'render').select().from('pages').where({
            isPublished: true,
            isPrivate: false
          }).stream(),
          new stream.Transform({
            objectMode: true,
            transform: async (page, enc, cb) => {
              const content = WIKI.models.pages.cleanHTML(page.render)
              await WIKI.models.knex.raw(`
                INSERT INTO "pagesVector" (path, locale, title, description, "tokens", content) VALUES (
                  ?, ?, ?, ?, (setweight(to_tsvector('${this.config.dictLanguage}', ?), 'A') || setweight(to_tsvector('${this.config.dictLanguage}', ?), 'B') || setweight(to_tsvector('${this.config.dictLanguage}', ?), 'C')), ?
                )
              `, [page.path, page.localeCode, page.title, page.description, page.title, page.description, content,content])
              cb()
            }
          })
        )
        await WIKI.models.knex.raw(`
          INSERT INTO "pagesWords" (word)
            SELECT word FROM ts_stat(
              'SELECT to_tsvector(''simple'', "title") || to_tsvector(''simple'', "description") || to_tsvector(''simple'', "content") FROM "pagesVector"'
            )
          `)
        WIKI.logger.info(`(SEARCH/POSTGRES) Index rebuilt successfully.`)
      }
    }

更新 wikijs 的 Deployment

wiki.js 的基于 PostgreSQL 的全文检索引擎配置位于 /wiki/server/modules/search/postgres ,我们将前面配置的 ConfigMap 加载到这个目录。

# wikijs-zh.yaml
kind: Deployment
apiVersion: apps/v1
metadata:
  name: wikijs
  labels:
    app: wikijs
spec:
  replicas: 1
  selector:
    matchLabels:
      app: wikijs
  template:
    metadata:
      labels:
        app: wikijs
    spec:
      volumes:
        - name: volume-dysh4f
          configMap:
            name: wikijs-zhparser
            defaultMode: 420
      containers:
        - name: wikijs
          image: 'requarks/wiki:2'
          ports:
            - name: http-3000
              containerPort: 3000
              protocol: TCP
          envFrom:
            - secretRef:
                name: wikijs
            - configMapRef:
                name: wikijs
          volumeMounts:
            - name: volume-dysh4f
              readOnly: true
              mountPath: /wiki/server/modules/search/postgres

配置 wiki.js ,启用基于 PostgreSQL 的全文检索

  • 重新 apply 新的 Delployment 文件后
$ kubectl apply -f zh-parse.yaml
$ kubectl apply -f wikijs-zh.yaml
  • 打开 wiki.js 管理
  • 点击搜索引擎
  • 选择 Database - PostgreSQL
  • 在 Dictionary Language 的下拉菜单里选择 chinese_zh。
  • 点击应用,并重建索引。
  • 完成配置。

总结

本文介绍的 wiki.js 部署方式支持中文全文检索的支持,集成了 PostgreSQL 和 zhparser 中文分词插件。

相对于标准的 wiki.js 安装部署过程,主要做了以下配置:

  • PostgreSQL 镜像采用了 abcfy2/zhparser:12-alpine ,这个镜像自带 zhparser 中文分词插件。
  • wiki.js 镜像外挂了 ConfigMap ,用于修改原 Docker 镜像里关于 PostgreSQL 搜索引擎配置的信息,以支持 chinese_zh 选项。

以上就是KubeSphere中部署Wiki系统wiki.js并启用中文全文检索的详细内容,更多关于KubeSphere部署wiki.js并启用的资料请关注我们其它相关文章!

(0)

相关推荐

  • FreeBSD5.4Release下安装wiki的方法

    今天利用早上一段时间,完成了mediawiki服务的安装,使用的版本为mediawiki-1.5.2,安装步骤: 1.下载以下所需软件 php-4.3.9.tar.gz apache_1.3.33.tar.gzmysql-4.0.21.tar.gzmediawiki-1.5.2.tar.gz 将下载的软件通过ftp拷贝到服务器上(/home/funpower) 2.安装apache和php # cd /home/funpower# tar zxvf apache_1.3.33.tar.gz# t

  • 通过kubesphere部署redis的方法

    docker部署redis命令 docker run --name redis -p 6379:6379 -d --restart=always a4d3716dbb72 redis-server --appendonly yes --requirepass "123456" 创建配置,点击配置中心->配置->创建配置 这里的配置信息就和上面redis-server后面的一样 创建存储卷 创建redis服务 选择无状态服务,因为有状态服务不能对外暴露端口,只有无状态服务才可

  • wiki-shan写的php在线加密的解密程序

    对应的写了一个简单的解密的,专门针对eval.这个原理很有用途的,在这里记下. 复制代码 代码如下: <?php /* author:zhiwushan date:20080411 */ //已经加密的文件内容 $a=" eval(gzinflate(str_rot13(base64_decode('DdNUsptVAADQq2vn7+oFGU6VPb+EyE4EiSA2LhAZUZN2OP343eF9//f7+1S+Jd1KbNZ90SVY/jUv098JLgT1lSZmztJ/s/wN

  • HDwiki 5.1下iis的rewrite规则分享

    一.注意事项: 1.本功能对服务器环境有特殊要求,独立主机用户需要对 Web 服务器增加相应的 Rewrite 规则,因此需要服务器权限才可使用.对于虚拟主机用户,您需要向您的空间服务商进行咨询:空间是否支持 Rewrite 以及是否支持对站点目录中 .htaccess 的文件解析,只有满足这两条件,URL 静态化 功能才会生效. 2.打开 URL 静态化后,如果您的服务器环境不支持或者尚未配置好,访问这些链接会出现"网页无法显示"的错误信息,HDwiki将无法正常访问.发生无法访问的

  • KubeSphere中部署Wiki系统wiki.js并启用中文全文检索

    目录 背景 准备 storageclass 部署 PostgreSQL 数据库 准备用户名密码配置 准备数据库初始化脚本 准备存储 部署 PostgreSQL 数据库 创建供其他 Pod 访问的 Service 完成 PostgreSQL 部署 部署 wiki.js 准备用户名密码配置 准备数据库连接配置 创建数据库用户和数据库 准备 wiki.js 的 yaml 部署文件 创建集群内访问 wiki.js 的 Service 创建集群外访问的 Ingress 执行部署 配置 wiki.js 支持

  • Ubuntu系统中部署Vagrant和VirtualBox的图文教程

    一.前言 1.Vagrant是一个搭建完整的虚拟开发环境的工具 2.实验环境 在Win10中利用VMWare Workstation创建一台Ubuntu虚拟机,版本为64位Ubuntu Desktop 16.04,4核,4G内存:然后在Ubuntu中安装Vagrant和VirtualBox,所用到的Vagrant和VirtualBox版本都是截至2018/04/08时候的最新版. 之所以使用VMWare Workstation来创建Ubuntu的虚拟机而不是VirtualBox,跟下面即将说到的

  • Vue.js中的组件系统

    vue.js既然是框架,那就不能只是简单的完成数据模板引擎的任务,它还提供了页面布局的功能.本文详细介绍使用vue.js进行页面布局的强大工具,vue.js组件系统. Vue.js组件系统 每一个新技术的诞生,都是为了解决特定的问题.组件的出现就是为了解决页面布局等等一系列问题.vue中的组件分为两种,全局组件和局部组件. 组件的注册 全局组件的注册 通过Vue.component()创建一个全局组件之后,我们可以在一个通过 new Vue 创建的 Vue 根实例中,把这个组件作为自定义元素来使

  • 谈谈node.js中的模块系统

    Node.js 的模块 JavaScript 做为一门为网页添加交互功能的简单脚本语言问世,在诞生时并不包含模块系统,随着 JavaScript 解决问题越来越复杂,把所有代码写在一个文件内,用 function 区分功能单元已经不能支撑复杂应用开发了,ES6 带来了大部分高级语言都有的 class 和 module,方便开发者组织代码 import _ from 'lodash'; class Fun {} export default Fun; 上面三行代码展示了一个模块系统最重要的两个要素

  • 在Docker中部署Confluence和jira-software的方法步骤

    version: centos==7.2 jdk==1.8 confluence==6.15.4 jira-software==8.2.1 docker==18.09 安装前提示: 1. 需要准备2个数据库,因为confluence和jira-software的mysql配置要求不一样     2. confluence需要配置jdk,jira-software自带jdk 选择使用docker部署的原因: 1. confluence和jira-software环境需求不同,需要分开配置.    

  • 在docker中部署tomcat并且部署java应用程序的步骤详解

    先给大家简单说下Docker的概念 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化.容器是完全使用沙箱机制,相互之间不会有任何接口. 1.先说如何在docker中部署tomcat 第一步:root用户登录在系统根目录下创建文件夹tomcat7,命令如:mkdir tomcat7,并且切换到该目录下:cd tomcat7: 第二步:创建Dockerfile,命令如:touch Docker

  • Java中SSM+Shiro系统登录验证码的实现方法

     先给大家展示下效果图: 1.验证码生成类: import java.util.Random; import java.awt.image.BufferedImage; import java.awt.Graphics; import java.awt.Font; import java.awt.Color; /** * 验证码生成器类,可生成数字.大写.小写字母及三者混合类型的验证码. 支持自定义验证码字符数量: 支持自定义验证码图片的大小: 支持自定义需排除的特殊字符: * 支持自定义干扰线

  • 在ubuntu中部署samba服务器的方法

    Samba服务在Ubuntu服务器版本中默认并没有安装.今天公司上了一批新电脑,准备把它装成服务器,于是为了方便开发的使用,我在上面部署了一个samba,用来实现window和linux的联系: 具体步骤,我详细的查看了百度,高手云集,以下就是总结了网友的经验,现在记下来,以后有用就不用到处找了. 一. samba的安装: sudo apt-get install samba sudo apt-get install smbfs 二. 创建共享目录: mkdir /home/phinecos/s

  • Android中WebView无法后退和js注入漏洞的解决方案

    因重定向无法正常goBack()解决方案 首先说下问题,初始页面为A,点击某个链接跳转到B(http://xxx.com.cn/),B页面重定向到C页面(http://xxx.com.cn/website/index.html) 当调用webview.goBack()时,页面回退到B,然后接着会重定向回C页面. 这样会导致两个问题: 1. 无法回退到webview的初始页面A 2. 无法正常退出Activity或者Fragment(只有还未加载完C时进行回退才能退出页面) 关于如何解决这个问题,

  • 在IDEA 2020.3.1中部署Tomcat并且创建第一个web项目的过程详解

    Tomcat介绍 Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache.Sun 和其他一些公司及个人共同开发而成.由于有了Sun 的参与和支持,最新的Servlet 和JSP 规范总是能在Tomcat 中得到体现,Tomcat 5支持最新的Servlet 2.4 和JSP 2.0 规范.因为Tomcat 技术先进.性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前

随机推荐