commander.js使用及源码分析

commander.js

commander是一个轻巧的nodejs模块,提供了用户命令行输入和参数解析强大功能。

commander的特性:

  • 自记录代码
  • 自动生成帮助
  • 合并短参数
  • 默认选项
  • 强制选项​​
  • 命令解析
  • 提示符

安装

npm install commander

使用

在文件中引入commander,可以通过直接引入一个program对象或者创建一个实例的方式进行使用。

const { program } = require('commander');
program.version("v1.0.0");
const { Command } = require('commander');
const program = new Command();
program.version("v1.0.0");

通过查看源码可以得知program其实就是一个刚创建的实例,可以更明确地访问全局命令。

源码片段:

exports = module.exports = new Command();
exports.program = exports;

exports.Command = Command;

option选项

Commander 使用.option()方法来定义选项,同时可以附加选项的简介。每个选项可以定义一个短选项名称(-后面接单个字符)和一个长选项名称(--后面接一个或多个单词),使用逗号、空格或|分隔。

语法:
options(flags, description, fn, defaultValue)

commander.option(
    "-f, --filename [filename]",
    "The filename to use when reading from stdin. This will be used in source-maps, errors etc."
);

源码解析:

lib\command.js option()

采用柯里化写法, 实际调用的是_optionsEx()方法

  options(flags, description, fn, defaultValue) {
    return this._optionEx({}, flags, description, fn, defaultValue);
  }

_optionsEx(), 创建一个options实例,fn可以是函数、正则等形式,需要注意的是尽量不要使用正则形式,自 Commander v7 起,该功能不再推荐使用。

  _optionEx(config, flags, description, fn, defaultValue) {
    // 创建一个option实例
    const option = this.createOption(flags, description);
    if (typeof fn === "function") {
      option.default(defaultValue).argParser(fn);
    } else if (fn instanceof RegExp) {
      // deprecated
      ...
    } else {
      option.default(fn);
    }

    return this.addOption(option);
  }

Option构造函数中,会调用一个splitOptionFlags()方法,用于解析长、断标识,比如说-m,--mixed attributeName()会返回一个camelcase的字符,例如--file-name会被解析成fileName

通过空格、|,来切割出不同的字符。

function splitOptionFlags(flags) {
  let shortFlag;
  let longFlag;
  const flagParts = flags.split(/[ |,]+/);
  if (flagParts.length > 1 && !/^[[<]/.test(flagParts[1]))
    shortFlag = flagParts.shift();
  longFlag = flagParts.shift();
  if (!shortFlag && /^-[^-]$/.test(longFlag)) {
    shortFlag = longFlag;
    longFlag = undefined;
  }
  return { shortFlag, longFlag };
}

同时,根据flags中的字符进行判断是否有设置接收参数。 表示执行该命令时必须传入一个参数,表示可接受多个参数,[value]表示可配置参数。

this.required = flags.includes("<"); 
this.optional = flags.includes("[");
this.variadic = /\w\.\.\.[>\]]$/.test(flags)

在创建了一个option对象后,将其放入addOption()中进行处理,该方法会对option进行注册、监听等操作。

  addOption(option) {
    const oname = option.name();
    const name = option.attributeName();
    // 注册
    this.options.push(option);

    const handleOptionValue = (val, invalidValueMessage, valueSource) => {
      // ...
    };

    this.on("option:" + oname, (val) => {
      const invalidValueMessage = `error: option '${option.flags}' argument '${val}' is invalid.`;
      handleOptionValue(val, invalidValueMessage, "cli");
    });

    if (option.envVar) {
      this.on("optionEnv:" + oname, (val) => {
        const invalidValueMessage = `error: option '${option.flags}' value '${val}' from env '${option.envVar}' is invalid.`;
        handleOptionValue(val, invalidValueMessage, "env");
      });
    }

    return this;
  }

Command继承了node中的事件模块EventEmitter实现对option的监听和触发。

在写好option配置后,需要调用program.parse(process.argv)方法对用户的输入进行解析。

parse(argv, parseOptions)

parse(argv, parseOptions) {
  const userArgs = this._prepareUserArgs(argv, parseOptions);
  this._parseCommand([], userArgs);

  return this;
}

_prepareUserArgvs方法中解析读取用户的输入。process.argv获取的数组前两个元素分别是node安装地址跟运行的script路径,后边的才是用户的输入,因此需要先过滤掉这两个。同时还支持多个argv约定。

_prepareUserArgs(argv, parseOptions) {
  parseOptions = parseOptions || {};
  this.rawArgs = argv.slice();

  let userArgs;
  switch (parseOptions.from) {
    case undefined:
    case 'node':
      this._scriptPath = argv[1];
      userArgs = argv.slice(2);
      break;
    case 'electron':
      if (process.defaultApp) {
        this._scriptPath = argv[1];
        userArgs = argv.slice(2);
      } else {
        userArgs = argv.slice(1);
      }
      break;
    case 'user':
      userArgs = argv.slice(0);
      break;
    default:
      throw new Error(
        `unexpected parse option { from: '${parseOptions.from}' }`
      );
  }
  if (!this._scriptPath && require.main) {
    this._scriptPath = require.main.filename;
  }

  this._name =
    this._name ||
    (this._scriptPath &&
      path.basename(this._scriptPath, path.extname(this._scriptPath)));

  return userArgs;
}

在获取了用户输入后,就是对这些参数进行解析。

_parseCommand()

_parseCommand(operands, unknown) {
    const parsed = this.parseOptions(unknown);
    // command部分下边继续讲解
}

parseOptions读取输入的配置

parseOptions(argv) {
  const operands = [];
  const unknown = [];
  let dest = operands;
  const args = argv.slice();

  // 判断是否是option配置, 必须要有一个-开头
  function maybeOption(arg) {
    return arg.length > 1 && arg[0] === '-';
  }

  let activeVariadicOption = null;
  // 逐步读取配置
  while (args.length) {
    const arg = args.shift();
    // --终止读取 也就是说 -- 后边的配置并不会生效
    // 例如 node src/index.js -  --number 1 2 3 -- -c a b
    // -c其实没有用
    if (arg === '--') {
      if (dest === unknown) dest.push(arg);
      dest.push(...args);
      break;
    }

    // 处理多参数情况
    if (activeVariadicOption && !maybeOption(arg)) {
      // 当触发这个监听时会执行handleOptionValue,里边会判断variadic的值将所有的参数放进一个数组中
      this.emit(`option:${activeVariadicOption.name()}`, arg);
      continue;
    }
    activeVariadicOption = null;

    if (maybeOption(arg)) {
      // 查看是否已经配置有该命令
      const option = this._findOption(arg);
      if (option) {
          // 前边提到的当配置option时如果有配置  必填参数,那么该option的required值为true
        if (option.required) {
            // 读取value
          const value = args.shift();
          if (value === undefined) this.optionMissingArgument(option);
          // 触发监听方法
          this.emit(`option:${option.name()}`, value);
        // 配置了可选参数
        } else if (option.optional) {
          let value = null;
          if (args.length > 0 && !maybeOption(args[0])) {
            value = args.shift();
          }
          this.emit(`option:${option.name()}`, value);
        } else {
          // boolean flag
          this.emit(`option:${option.name()}`);
        }
        // 前面提到当配置的option中存在 ...> 如时,variadic值为true
        activeVariadicOption = option.variadic ? option : null;
        continue;
      }
    }

    // 组合flag, 比如像 -abc , 会遍历判断 -a -b -c是否是配置过的option
    if (arg.length > 2 && arg[0] === '-' && arg[1] !== '-') {
      // 拆解组合
      const option = this._findOption(`-${arg[1]}`);
      if (option) {
        if (
          option.required ||
          (option.optional && this._combineFlagAndOptionalValue)
        ) {
          this.emit(`option:${option.name()}`, arg.slice(2));
        } else {
          this.emit(`option:${option.name()}`);
          args.unshift(`-${arg.slice(2)}`);
        }
        continue;
      }
    }

    // 解析--foo=bar传参格式
    if (/^--[^=]+=/.test(arg)) {
      const index = arg.indexOf('=');
      const option = this._findOption(arg.slice(0, index));
      if (option && (option.required || option.optional)) {
        this.emit(`option:${option.name()}`, arg.slice(index + 1));
        continue;
      }
    }

    if (maybeOption(arg)) {
      dest = unknown;
    }

    // 解析command 下面在讲解
    dest.push(arg);
  }

  return { operands, unknown };
}

从上面的源码解析中可以总结如下:

  1. 多个短选项可以合并简写,最后一个选项可以附加参数, 比如-a -b -c 1可以写成-abc 1
  2. --可以标记选项的结束,后续的参数均不会被命令解释,可以正常使用。
  3. 可以通过=传参
  4. 可以传递多个参数

常用选项类型

  1. boolean型, 选项无需配置参数, 通常我们使用的都是此类型。
  2. 设置参数(使用尖括号声明在该选项后,如--expect ),如果在命令行中不指定具体的选项及参数,则会被定义为undefined
const { Command } = require('commander');
const program = new Command();

program.option('-e --example', 'this is a boolean type option');

program.option('-t --type ', 'must set an param or an error will occur');

program.parse(process.argv);
console.log(program.opts());

eg.

node index.js -e
{ example: true }

node index.js -t
error: option '-t --type ' argument missing


node index.js -t a
{ type: 'a' }
  1. 取反, 可以定义一个以 no- 开头的 boolean长选项。在命令行中使用该选项时,会将对应选项的值置为 false。当只定义了带 no- 的选项,未定义对应不带 no- 的选项时,该选项的默认值会被置为 true值。
program.option('--no-example', 'no example');
node index.js --no-example
{ example: false }

源码解析:

在配置了option之后,会对该命令进行监听,执行该flag会触发handleOptionValue方法,根据用户是否有设置取反或者有默认值,来设置该option的值

handleOptionValue

const handleOptionValue = (val, invalidValueMessage, valueSource) => {
  const oldValue = this.getOptionValue(name);
  
  // 参数处理这部分放在自定义选项部分讲解
  // .. 

  if (typeof oldValue === 'boolean' || typeof oldValue === 'undefined') {
    if (val == null) {
      this.setOptionValueWithSource(
        name,
        // 是否取反,取反的话值为false, 不取反就判断是否有值,没有就赋值为true
        option.negate ? false : defaultValue || true,
        valueSource
      );
    } else {
      this.setOptionValueWithSource(name, val, valueSource);
    }
  } else if (val !== null) {
    this.setOptionValueWithSource(
      name,
      option.negate ? false : val,
      valueSource
    );
  }
};
  1. 可选参数 (--optional [value]), 该选项在不带参数时可用作 boolean 选项,在带有参数时则从参数中得到值。
program.option('-f [filename]', 'optional');
node index.js -f
{ f: true }

node index.js -f index.js
{ f: 'index.js' }
  1. 必填选项
    通过.requiredOption()方法可以设置选项为必填。必填选项要么设有默认值,要么必须在命令行中输入,对应的属性字段在解析时必定会有赋值。该方法其余参数与.option()一致。
program.requiredOption('-r --required ', 'must');
node index.js   
error: required option '-r --required ' not specified

当然可以设置一个默认值

program.requiredOption('-r --required ', 'must''a');
node index.js   
{ required: 'a' }
  1. 变长参数选项
    定义选项时,可以通过使用...来设置参数为可变长参数。在命令行中,用户可以输入多个参数,解析后会以数组形式存储在对应属性字段中。在输入下一个选项前(---开头),用户输入的指令均会被视作变长参数。与普通参数一样的是,可以通过--标记当前命令的结束。
program.option('-n ', 'set numbers');
program.option('-c ', 'set chars');
node index.js -n 1 2 3 4 -c a b c
{ n: [ '1', '2', '3', '4' ], c: [ 'a', 'b', 'c' ] }
  1. 版本
    .version()方法可以设置版本,其默认选项为-V--version,设置了版本后,命令行会输出当前的版本号。
program.version('v1.0.0')

版本选项也支持自定义设置选项名称,可以在.version()方法里再传递一些参数(长选项名称、描述信息),用法与.option()方法类似。

program.version('v1.0.0', '-a --aversion', 'current version');

源码解析

version方法其实很简单,就是判断用户配置version信息时有没有自定义信息,比如说启动命令这些。之后就是创建一个option注册后监听。

version(str, flags, description) {
  if (str === undefined) return this._version;
  this._version = str;
  flags = flags || '-V, --version';
  description = description || 'output the version number';
  const versionOption = this.createOption(flags, description);
  this._versionOptionName = versionOption.attributeName();
  this.options.push(versionOption);
  this.on('option:' + versionOption.name(), () => {
    this._outputConfiguration.writeOut(`${str}\n`);
    this._exit(0, 'commander.version', str);
  });
  return this;
}

  1. 使用addOption方法
    大多数情况下,选项均可通过.option()方法添加。但对某些不常见的用例,也可以直接构造Option对象,对选项进行更详尽的配置。
program
  .addOption(
    new Option('-t, --timeout ', 'timeout in seconds').default(
      60,
      'one minute'
    )
  )
  .addOption(
    new Option('-s, --size ', 'size').choices([
      'small',
      'medium',
      'large',
    ])
  );
node index.js -s small
{ timeout: 60, size: 'small' }

node index.js -s mini
error: option '-s, --size ' argument 'mini' is invalid. Allowed choices are small, medium, large.

源码解析:就是添加一个fn在传入值的时候判断一下值就可以。

function choices(values) {
  this.argChoices = values;
  this.parseArg = (arg, previous) => {
    if (!values.includes(arg)) {
      throw new InvalidArgumentError(
        `Allowed choices are ${values.join(', ')}.`
      );
    }
    if (this.variadic) {
      return this._concatValue(arg, previous);
    }
    return arg;
  };
  return this;
}
  1. 自定义选项
    选项的参数可以通过自定义函数来处理,该函数接收两个参数,即用户新输入的参数值和当前已有的参数值(即上一次调用自定义处理函数后的返回值),返回新的选项参数值。 也就是option中的第三个参数。第四个参数就是初始值

自定义函数适用场景包括参数类型转换,参数暂存,或者其他自定义处理的场景。

program.option(
  '-f --float ',
  'process float argument',
  (value, previous) => {
    return Number(value) + previous;
  },
  2
);
node index.js -f 3
{ float: 5 }

源码解析:

const handleOptionValue = (val, invalidValueMessage, valueSource) => {
  const oldValue = this.getOptionValue(name);
  
  // 当配置了option的第三个参数
  if (val !== null && option.parseArg) {
    try {
      val = option.parseArg(
        val,
        // defaultValue为第四个参数
        oldValue === undefined ? defaultValue : oldValue
      );
    } catch (err) {
      if (err.code === "commander.invalidArgument") {
        const message = `${invalidValueMessage} ${err.message}`;
        this._displayError(err.exitCode, err.code, message);
      }
      throw err;
    }

  // 处理多参数情况
  } else if (val !== null && option.variadic) {
    val = option._concatValue(val, oldValue);
  }

  // ...
  // 查看取反部分讲解
}

配置命令

通过.command().addCommand()可以配置命令,有两种实现方式:为命令绑定处理函数,或者将命令单独写成一个可执行文件。子命令支持嵌套。

.command()的第一个参数为命令名称。命令参数可以跟在名称后面,也可以用.argument()单独指定。参数可为必选的(尖括号表示)、可选的(方括号表示)或变长参数(点号表示,如果使用,只能是最后一个参数)。

program
  .command('clone  [destination]')
  .description('clone a repository into a newly created directory')
  .action((source, destination) => {
    console.log('clone command called');
  });

Command对象上使用.argument()来按次序指定命令参数。该方法接受参数名称和参数描述。参数可为必选的(尖括号表示,例如)或可选的(方括号表示,例如[optional])。

program
  .command('login')
  .description('login')
  .argument('', 'user')
  .argument('[password]', 'password', 'no password')
  .action((username, password) => {
    console.log(`login, ${username} - ${password}`);
  });

在参数名后加上...来声明可变参数,且只有最后一个参数支持这种用法。可变参数会以数组的形式传递给处理函数。

program
  .command('readFile')
  .description('read multiple file')
  .argument('', 'user')
  .argument('[password]', 'password', 'no password')
  .argument('')
  .action((username, password, args) => {
    args.forEach((dir) => {
      console.log('rmdir %s', dir);
    });
    console.log(`username: ${username}, pass: ${password}, args: ${args}`);
  });

源码解析: 新建一个command

command(nameAndArgs, actionOptsOrExecDesc, execOpts) {
  let desc = actionOptsOrExecDesc;
  let opts = execOpts;
  if (typeof desc === 'object' && desc !== null) {
    opts = desc;
    desc = null;
  }
  opts = opts || {};
  // 解析获取输入的命令及参数
  const [, name, args] = nameAndArgs.match(/([^ ]+) *(.*)/);

  // 创建一个command
  const cmd = this.createCommand(name);
  if (desc) {
    cmd.description(desc);
    cmd._executableHandler = true;
  }
  if (opts.isDefault) this._defaultCommandName = cmd._name;
  cmd._hidden = !!(opts.noHelp || opts.hidden);
  cmd._executableFile = opts.executableFile || null;
  // 添加参数
  if (args) cmd.arguments(args);
  this.commands.push(cmd);
  cmd.parent = this;
  // 继承属性
  cmd.copyInheritedSettings(this);

  if (desc) return this;
  return cmd;
}

action用于注册命令回调。

action(fn) {
  const listener = (args) => {
    const expectedArgsCount = this._args.length;
    const actionArgs = args.slice(0, expectedArgsCount);
    if (this._storeOptionsAsProperties) {
      actionArgs[expectedArgsCount] = this;
    } else {
      actionArgs[expectedArgsCount] = this.opts();
    }
    actionArgs.push(this);

    return fn.apply(this, actionArgs);
  };
  this._actionHandler = listener;
  return this;
}

接下来就是如何解析执行命令部分了。还记得我们之前解析option时的流程嘛
parse() -> _parseCommand(), 在parseOptions方法中,我们还剩余了处理命令部分代码,现在来看一下。

源码解析:

parseOptions(argv) {
  const operands = [];
  const unknown = [];
  let dest = operands;
  const args = argv.slice();

  while (args.length) {
    // 解析option部分
    // ...

    // 当开启了enablePositionalOptions后, 会将命令后边的参数全部定义为未知参数,而不是命令选项,同时如果想要在子命令中启动enablePositionalOptions,需要在父命令中先开启。
    if (
      (this._enablePositionalOptions || this._passThroughOptions) &&
      operands.length === 0 &&
      unknown.length === 0
    ) {
      if (this._findCommand(arg)) {
        operands.push(arg);
        if (args.length > 0) unknown.push(...args);
        break;
      } else if (
        arg === this._helpCommandName &&
        this._hasImplicitHelpCommand()
      ) {
        operands.push(arg);
        if (args.length > 0) operands.push(...args);
        break;
      } else if (this._defaultCommandName) {
        unknown.push(arg);
        if (args.length > 0) unknown.push(...args);
        break;
      }
    }

    if (this._passThroughOptions) {
      dest.push(arg);
      if (args.length > 0) dest.push(...args);
      break;
    }
    dest.push(arg);
  }
  return { operands, unknown };
}

没有开启enablePositionalOptions配置,命令及后边的参数都会保存在operands数组中,当开启后,命令后边的参数都会变成unknown

在解析了用户输入的参数后继续往下执行_parseCommand方法

_parseCommand(operands, unknown) {
  // 解析配置
  const parsed = this.parseOptions(unknown);
  this._parseOptionsEnv(); // after cli, so parseArg not called on both cli and env
  operands = operands.concat(parsed.operands);
  unknown = parsed.unknown;
  this.args = operands.concat(unknown);

  // 匹配找到命令, 使用子进程运行命令
  if (operands && this._findCommand(operands[0])) {
    return this._dispatchSubcommand(operands[0], operands.slice(1), unknown);
  }

  // 没找到命令就判断一下是否有帮助命令, 而且用户输入的第一个参数是help
  if (this._hasImplicitHelpCommand() && operands[0] === this._helpCommandName) {
    // 有且只有个命令
    if (operands.length === 1) {
      this.help();
    }
    // 执行第二条命令
    return this._dispatchSubcommand(operands[1], [], [this._helpLongFlag]);
  }
  // 帮助命令也没有找到或者用户输入的第一个参数未知但是存在一个默认名字
  if (this._defaultCommandName) {
    outputHelpIfRequested(this, unknown); // Run the help for default command from parent rather than passing to default command
    return this._dispatchSubcommand(
      this._defaultCommandName,
      operands,
      unknown
    );
  }
  // ...

  const commandEvent = `command:${this.name()}`;
  // 存在command处理器
  if (this._actionHandler) {
    checkForUnknownOptions();
    // 处理参数
    this._processArguments();

    let actionResult;
    actionResult = this._chainOrCallHooks(actionResult, 'preAction');
    actionResult = this._chainOrCall(actionResult, () =>
      this._actionHandler(this.processedArgs)
    );
    // 触发父命令
    if (this.parent) this.parent.emit(commandEvent, operands, unknown); // legacy
    actionResult = this._chainOrCallHooks(actionResult, 'postAction');
    return actionResult;
  }
  // 触发父监听器
  if (this.parent && this.parent.listenerCount(commandEvent)) {
    checkForUnknownOptions();
    this._processArguments();
    this.parent.emit(commandEvent, operands, unknown);
  // 处理参数
  } else if (operands.length) {
    if (this._findCommand('*')) {
      return this._dispatchSubcommand('*', operands, unknown);
    }
    if (this.listenerCount('command:*')) {
      this.emit('command:*', operands, unknown);
    } else if (this.commands.length) {
      this.unknownCommand();
    } else {
      checkForUnknownOptions();
      this._processArguments();
    }
  // 不存在命令
  } else if (this.commands.length) {
    checkForUnknownOptions();
    this.help({ error: true });
  } else {
    checkForUnknownOptions();
    this._processArguments();
  }
}

到此,整个解析过程就完成了。

声明统一参数

命令处理函数的参数,为该命令声明的所有参数,除此之外还会附加两个额外参数:一个是解析出的选项,另一个则是该命令对象自身。

program
  .argument('')
  .option('-t, --title '</span><span class="token punctuation">,</span> <span class="token string">'title to use before name'</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">option</span><span class="token punctuation">(</span><span class="token string">'-d, --de'</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">action</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">name<span class="token punctuation">,</span> options<span class="token punctuation">,</span> command</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>options<span class="token punctuation">)</span><span class="token punctuation">;</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>command<span class="token punctuation">.</span><span class="token function">name</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre> 
  <h3>帮助信息</h3> 
  <p>帮助信息是 <code>Commander</code> 基于你的程序自动生成的,默认的帮助选项是<code>-h,--help</code>。</p> 
  <pre><code class="prism language-bash">node index.js -h
Usage: index <span class="token punctuation">[</span>options<span class="token punctuation">]</span>

Options:
  -h, --help  display <span class="token builtin class-name">help</span> <span class="token keyword">for</span> <span class="token builtin class-name">command</span>
</code></pre> 
  <p><code>源码解析:</code><br> <code>commander.js</code>提供了一个<code>help</code>类,但是它的方法都是静态的,允许被覆盖。在<code>command</code>类中有一个<code>createHelp</code>方法,通过<code>Object.assign()</code>方法覆盖<code>help</code>的原始方法。</p> 
  <pre><code class="prism language-js"><span class="token function">createHelp</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> Object<span class="token punctuation">.</span><span class="token function">assign</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Help</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">configureHelp</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre> 
  <p><code>formatHelp</code>生成帮助文字,解析处理设置的<code>command</code>、<code>option</code>、<code>argument</code>等</p> 
  <pre><code class="prism language-js"><span class="token function">formatHelp</span><span class="token punctuation">(</span><span class="token parameter">cmd<span class="token punctuation">,</span> helper</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> termWidth <span class="token operator">=</span> helper<span class="token punctuation">.</span><span class="token function">padWidth</span><span class="token punctuation">(</span>cmd<span class="token punctuation">,</span> helper<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> helpWidth <span class="token operator">=</span> helper<span class="token punctuation">.</span>helpWidth <span class="token operator">||</span> <span class="token number">80</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> itemIndentWidth <span class="token operator">=</span> <span class="token number">2</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> itemSeparatorWidth <span class="token operator">=</span> <span class="token number">2</span><span class="token punctuation">;</span>
  <span class="token comment">// 格式化</span>
  <span class="token keyword">function</span> <span class="token function">formatItem</span><span class="token punctuation">(</span><span class="token parameter">term<span class="token punctuation">,</span> description</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>description<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">const</span> fullText <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>term<span class="token punctuation">.</span><span class="token function">padEnd</span><span class="token punctuation">(</span>
        termWidth <span class="token operator">+</span> itemSeparatorWidth
      <span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>description<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
      <span class="token keyword">return</span> helper<span class="token punctuation">.</span><span class="token function">wrap</span><span class="token punctuation">(</span>
        fullText<span class="token punctuation">,</span>
        helpWidth <span class="token operator">-</span> itemIndentWidth<span class="token punctuation">,</span>
        termWidth <span class="token operator">+</span> itemSeparatorWidth
      <span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">return</span> term<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token keyword">function</span> <span class="token function">formatList</span><span class="token punctuation">(</span><span class="token parameter">textArray</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> textArray<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">'\n'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^</span><span class="token regex-delimiter">/</span><span class="token regex-flags">gm</span></span><span class="token punctuation">,</span> <span class="token string">' '</span><span class="token punctuation">.</span><span class="token function">repeat</span><span class="token punctuation">(</span>itemIndentWidth<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>

  <span class="token keyword">let</span> output <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Usage: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>helper<span class="token punctuation">.</span><span class="token function">commandUsage</span><span class="token punctuation">(</span>cmd<span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">]</span><span class="token punctuation">;</span>

  <span class="token comment">// 描述符</span>
  <span class="token keyword">const</span> commandDescription <span class="token operator">=</span> helper<span class="token punctuation">.</span><span class="token function">commandDescription</span><span class="token punctuation">(</span>cmd<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>commandDescription<span class="token punctuation">.</span>length <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    output <span class="token operator">=</span> output<span class="token punctuation">.</span><span class="token function">concat</span><span class="token punctuation">(</span><span class="token punctuation">[</span>commandDescription<span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>

  <span class="token comment">// 参数</span>
  <span class="token keyword">const</span> argumentList <span class="token operator">=</span> helper<span class="token punctuation">.</span><span class="token function">visibleArguments</span><span class="token punctuation">(</span>cmd<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">argument</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token function">formatItem</span><span class="token punctuation">(</span>
      helper<span class="token punctuation">.</span><span class="token function">argumentTerm</span><span class="token punctuation">(</span>argument<span class="token punctuation">)</span><span class="token punctuation">,</span>
      helper<span class="token punctuation">.</span><span class="token function">argumentDescription</span><span class="token punctuation">(</span>argument<span class="token punctuation">)</span>
    <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>argumentList<span class="token punctuation">.</span>length <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    output <span class="token operator">=</span> output<span class="token punctuation">.</span><span class="token function">concat</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string">'Arguments:'</span><span class="token punctuation">,</span> <span class="token function">formatList</span><span class="token punctuation">(</span>argumentList<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>

  <span class="token comment">// 选项</span>
  <span class="token keyword">const</span> optionList <span class="token operator">=</span> helper<span class="token punctuation">.</span><span class="token function">visibleOptions</span><span class="token punctuation">(</span>cmd<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">option</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token function">formatItem</span><span class="token punctuation">(</span>
      helper<span class="token punctuation">.</span><span class="token function">optionTerm</span><span class="token punctuation">(</span>option<span class="token punctuation">)</span><span class="token punctuation">,</span>
      helper<span class="token punctuation">.</span><span class="token function">optionDescription</span><span class="token punctuation">(</span>option<span class="token punctuation">)</span>
    <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>optionList<span class="token punctuation">.</span>length <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    output <span class="token operator">=</span> output<span class="token punctuation">.</span><span class="token function">concat</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string">'Options:'</span><span class="token punctuation">,</span> <span class="token function">formatList</span><span class="token punctuation">(</span>optionList<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>

  <span class="token comment">// 命令</span>
  <span class="token keyword">const</span> commandList <span class="token operator">=</span> helper<span class="token punctuation">.</span><span class="token function">visibleCommands</span><span class="token punctuation">(</span>cmd<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">cmd</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token function">formatItem</span><span class="token punctuation">(</span>
      helper<span class="token punctuation">.</span><span class="token function">subcommandTerm</span><span class="token punctuation">(</span>cmd<span class="token punctuation">)</span><span class="token punctuation">,</span>
      helper<span class="token punctuation">.</span><span class="token function">subcommandDescription</span><span class="token punctuation">(</span>cmd<span class="token punctuation">)</span>
    <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>commandList<span class="token punctuation">.</span>length <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    output <span class="token operator">=</span> output<span class="token punctuation">.</span><span class="token function">concat</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string">'Commands:'</span><span class="token punctuation">,</span> <span class="token function">formatList</span><span class="token punctuation">(</span>commandList<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>

  <span class="token keyword">return</span> output<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">'\n'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre> 
  <h4>自定义</h4> 
  <p>使用<code>addHelpText</code>方法添加额外的帮助信息。</p> 
  <pre><code class="prism language-js">program<span class="token punctuation">.</span><span class="token function">addHelpText</span><span class="token punctuation">(</span><span class="token string">'after'</span><span class="token punctuation">,</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">call help</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre> 
  <pre><code class="prism language-bash">node index.js -h
Usage: index <span class="token punctuation">[</span>options<span class="token punctuation">]</span>

Options:
  -h, --help  display <span class="token builtin class-name">help</span> <span class="token keyword">for</span> <span class="token builtin class-name">command</span>
call <span class="token builtin class-name">help</span>
</code></pre> 
  <p><code>addHelpText</code>方法的第一个参数是添加的帮助信息展示的位置,<br> 包括如下:</p> 
  <ul> 
   <li> <p><code>beforeAll</code>:作为全局标头栏展示</p> </li> 
   <li> <p><code>before</code>:在内建帮助信息之前展示</p> </li> 
   <li> <p><code>after</code>:在内建帮助信息之后展示</p> </li> 
   <li> <p><code>afterAll</code>:作为全局末尾栏展示</p> </li> 
  </ul> 
  <p><code>源码解析:</code><br> 在执行<code>addHelpText</code>方法后,会对该事件进行监听,同时执行输入帮助命令时会按顺序执行所有事件,从而实现自定义信息的展示。</p> 
  <p><code>addHelpText</code></p> 
  <pre><code class="prism language-js"><span class="token function">addHelpText</span><span class="token punctuation">(</span><span class="token parameter">position<span class="token punctuation">,</span> text</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> allowedValues <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">'beforeAll'</span><span class="token punctuation">,</span> <span class="token string">'before'</span><span class="token punctuation">,</span> <span class="token string">'after'</span><span class="token punctuation">,</span> <span class="token string">'afterAll'</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
  <span class="token comment">// 过滤</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>allowedValues<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span>position<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Unexpected value for position to addHelpText.
Expecting one of '</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>allowedValues<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">"', '"</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">'</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token keyword">const</span> helpEvent <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>position<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">Help</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
  <span class="token comment">// 监听事件</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span>helpEvent<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">context</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    <span class="token keyword">let</span> helpStr<span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> text <span class="token operator">===</span> <span class="token string">'function'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      helpStr <span class="token operator">=</span> <span class="token function">text</span><span class="token punctuation">(</span><span class="token punctuation">{</span> error<span class="token operator">:</span> context<span class="token punctuation">.</span>error<span class="token punctuation">,</span> command<span class="token operator">:</span> context<span class="token punctuation">.</span>command <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
      helpStr <span class="token operator">=</span> text<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token comment">// Ignore falsy value when nothing to output.</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>helpStr<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      context<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>helpStr<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">\n</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre> 
  <p><code>outputHelp</code></p> 
  <pre><code class="prism language-js"><span class="token function">outputHelp</span><span class="token punctuation">(</span><span class="token parameter">contextOptions</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">let</span> deprecatedCallback<span class="token punctuation">;</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> contextOptions <span class="token operator">===</span> <span class="token string">'function'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    deprecatedCallback <span class="token operator">=</span> contextOptions<span class="token punctuation">;</span>
    contextOptions <span class="token operator">=</span> <span class="token keyword">undefined</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token keyword">const</span> context <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">_getHelpContext</span><span class="token punctuation">(</span>contextOptions<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">// 遍历触发所有祖先命令的 beforeAllHelp 事件</span>
  <span class="token function">getCommandAndParents</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">reverse</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token comment">// 触发 beforeAllHelp</span>
    <span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">command</span><span class="token punctuation">)</span> <span class="token operator">=></span> command<span class="token punctuation">.</span><span class="token function">emit</span><span class="token punctuation">(</span><span class="token string">'beforeAllHelp'</span><span class="token punctuation">,</span> context<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">// 触发 beforeHelp</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">emit</span><span class="token punctuation">(</span><span class="token string">'beforeHelp'</span><span class="token punctuation">,</span> context<span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">let</span> helpInformation <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">helpInformation</span><span class="token punctuation">(</span>context<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>deprecatedCallback<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    helpInformation <span class="token operator">=</span> <span class="token function">deprecatedCallback</span><span class="token punctuation">(</span>helpInformation<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>
      <span class="token keyword">typeof</span> helpInformation <span class="token operator">!==</span> <span class="token string">'string'</span> <span class="token operator">&&</span>
      <span class="token operator">!</span>Buffer<span class="token punctuation">.</span><span class="token function">isBuffer</span><span class="token punctuation">(</span>helpInformation<span class="token punctuation">)</span>
    <span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span><span class="token string">'outputHelp callback must return a string or a Buffer'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
  context<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span>helpInformation<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">// 触发 help 指令</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">emit</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>_helpLongFlag<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// deprecated</span>
  <span class="token comment">// 触发 afterHelp</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">emit</span><span class="token punctuation">(</span><span class="token string">'afterHelp'</span><span class="token punctuation">,</span> context<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">// 遍历触发所有祖先命令的 afterAllHelp 事件</span>
  <span class="token function">getCommandAndParents</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">command</span><span class="token punctuation">)</span> <span class="token operator">=></span>
    <span class="token comment">// 触发 afterAllHelp</span>
    command<span class="token punctuation">.</span><span class="token function">emit</span><span class="token punctuation">(</span><span class="token string">'afterAllHelp'</span><span class="token punctuation">,</span> context<span class="token punctuation">)</span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre> 
  <h4><code>showHelpAfterError</code>展示帮助信息</h4> 
  <pre><code class="prism language-js">program<span class="token punctuation">.</span><span class="token function">showHelpAfterError</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 或者</span>
program<span class="token punctuation">.</span><span class="token function">showHelpAfterError</span><span class="token punctuation">(</span><span class="token string">'(add --help for additional information)'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre> 
  <pre><code class="prism language-bash">node index.js -asd
error: unknown option <span class="token string">'-asd'</span>
<span class="token punctuation">(</span>add --help <span class="token keyword">for</span> additional information<span class="token punctuation">)</span>
</code></pre> 
 </div> 
</div>
                            </div>
                        </div>
                    </div>
                    <!--PC和WAP自适应版-->
                    <div id="SOHUCS" sid="1644813476289372160"></div>
                    <script type="text/javascript" src="/views/front/js/chanyan.js"></script>
                    <!-- 文章页-底部 动态广告位 -->
                    <div class="youdao-fixed-ad" id="detail_ad_bottom"></div>
                </div>
                <div class="col-md-3">
                    <div class="row" id="ad">
                        <!-- 文章页-右侧1 动态广告位 -->
                        <div id="right-1" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad">
                            <div class="youdao-fixed-ad" id="detail_ad_1"> </div>
                        </div>
                        <!-- 文章页-右侧2 动态广告位 -->
                        <div id="right-2" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad">
                            <div class="youdao-fixed-ad" id="detail_ad_2"></div>
                        </div>
                        <!-- 文章页-右侧3 动态广告位 -->
                        <div id="right-3" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad">
                            <div class="youdao-fixed-ad" id="detail_ad_3"></div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div class="container">
        <h4 class="pt20 mb15 mt0 border-top">你可能感兴趣的:(javascript,js)</h4>
        <div id="paradigm-article-related">
            <div class="recommend-post mb30">
                <ul class="widget-links">
                    <li><a href="/article/1880533508066177024.htm"
                           title="JavaWeb开发 - Filter过滤器详解" target="_blank">JavaWeb开发 - Filter过滤器详解</a>
                        <span class="text-muted">秦老师Q</span>
<a class="tag" taget="_blank" href="/search/JavaWeb%E5%9F%BA%E7%A1%80/1.htm">JavaWeb基础</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/web/1.htm">web</a><a class="tag" taget="_blank" href="/search/java-ee/1.htm">java-ee</a>
                        <div>前言本章节主要学习JavaWeb开发中的Filter过滤器技术,收录于JavaWeb基础专栏,该专栏主要学习JavaWeb开发原生框架、Servlet、JSP、请求对象、响应对象、Session会话对象、Filter过滤器、三层开发模型等知识点,欢迎童鞋们互相交流。觉得不错可以三连订阅喔。目标1.概念2.Filter介绍3.入门案例4.验证登录案例4.1登录代码4.2过滤器验证内容1.概念Filt</div>
                    </li>
                    <li><a href="/article/1880533004040859648.htm"
                           title="华为OD机试E卷 --跳格子3 --24年OD统一考试(Java & JS & Python & C & C++)" target="_blank">华为OD机试E卷 --跳格子3 --24年OD统一考试(Java & JS & Python & C & C++)</a>
                        <span class="text-muted">飞码创造者</span>
<a class="tag" taget="_blank" href="/search/%E6%9C%80%E6%96%B0%E5%8D%8E%E4%B8%BAOD%E6%9C%BA%E8%AF%95%E9%A2%98%E5%BA%932024/1.htm">最新华为OD机试题库2024</a><a class="tag" taget="_blank" href="/search/%E5%8D%8E%E4%B8%BAod/1.htm">华为od</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/c%E8%AF%AD%E8%A8%80/1.htm">c语言</a>
                        <div>文章目录题目描述输入描述输出描述用例题目解析JS算法源码Java算法源码python算法源码c++算法源码题目描述小明和朋友们一起玩跳格子游戏,每个格子上有特定的分数score=[1,-1,-6,7,-17,7],从起点score[0]开始,每次最大的步长为k,请你返回小明跳到终点score[n-1]时,能得到的最大得分。输入描述第一行输入总的格子数量n第二行输入每个格子的分数score[i]第三</div>
                    </li>
                    <li><a href="/article/1880528842121080832.htm"
                           title="drogon orm分页问题,req->getJsonObject()为空会导致Segmentation fault" target="_blank">drogon orm分页问题,req->getJsonObject()为空会导致Segmentation fault</a>
                        <span class="text-muted">zh7314</span>

                        <div>2024年6月22日17:14:12req->getJsonObject()获取json数据的时候,如果没有提前判断if(req->getJsonObject()==nullptr){throwstd::invalid_argument("参数json不能为空");}autojsonPtr=req->getJsonObject();官方文档:https://github.com/drogonfra</div>
                    </li>
                    <li><a href="/article/1880518247896379392.htm"
                           title="华为OD机试C卷-- 机器人走迷宫(Java & JS & Python)" target="_blank">华为OD机试C卷-- 机器人走迷宫(Java & JS & Python)</a>
                        <span class="text-muted">飞码创造者</span>
<a class="tag" taget="_blank" href="/search/%E5%8D%8E%E4%B8%BAOD%E6%9C%BA%E8%AF%95%E9%A2%98%E5%BA%93/1.htm">华为OD机试题库</a><a class="tag" taget="_blank" href="/search/%E5%8D%8E%E4%B8%BAod/1.htm">华为od</a><a class="tag" taget="_blank" href="/search/c%E8%AF%AD%E8%A8%80/1.htm">c语言</a><a class="tag" taget="_blank" href="/search/%E6%9C%BA%E5%99%A8%E4%BA%BA/1.htm">机器人</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a>
                        <div>获取题库不需要订阅专栏,可直接私信我进入CSDN领军人物top1博主的华为OD交流圈观看完整题库、最新面试实况、考试报告等内容以及大佬一对一答疑。题目描述1.房间由XY的方格组成,例如下图为6*4的大小。每一个方格以坐标(x,y)描述。2.机器人固定从方格(0,0)出发,只能向东或者向北前进。出口固定为房间的最东北角,如下图的方格(5,3)。用例保证机器人可以从入口走到出口。3.房间有些方格是墙壁</div>
                    </li>
                    <li><a href="/article/1880501750482399232.htm"
                           title="使用 Node.js 处理异步编程的挑战" target="_blank">使用 Node.js 处理异步编程的挑战</a>
                        <span class="text-muted"></span>

                        <div>Node.js是一个强大的JavaScript运行时环境,它以其非阻塞、事件驱动的特性闻名,使其在构建高并发应用程序时非常出色。然而,这种异步编程模型也带来了挑战,尤其是当我们需要处理复杂的异步操作时。本文将深入探讨Node.js中异步编程的挑战,并介绍一些常见的解决方案。异步编程的挑战在Node.js中,许多操作都是异步的,比如文件操作、网络请求、数据库查询等。虽然异步操作可以提高应用程序的性能</div>
                    </li>
                    <li><a href="/article/1880500097997926400.htm"
                           title="华为OD机试E卷 - 机器人活动区域(Java & Python& JS & C++ & C )" target="_blank">华为OD机试E卷 - 机器人活动区域(Java & Python& JS & C++ & C )</a>
                        <span class="text-muted">算法大师</span>
<a class="tag" taget="_blank" href="/search/%E6%9C%80%E6%96%B0%E5%8D%8E%E4%B8%BAOD%E6%9C%BA%E8%AF%95/1.htm">最新华为OD机试</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%8D%8E%E4%B8%BAod/1.htm">华为od</a><a class="tag" taget="_blank" href="/search/%E6%9C%BA%E5%99%A8%E4%BA%BA/1.htm">机器人</a><a class="tag" taget="_blank" href="/search/c%E8%AF%AD%E8%A8%80/1.htm">c语言</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/%E5%8D%8E%E4%B8%BAOD%E6%9C%BA%E8%AF%95E%E5%8D%B7/1.htm">华为OD机试E卷</a>
                        <div>最新华为OD机试真题目录:点击查看目录华为OD面试真题精选:点击立即查看题目描述现有一个机器人,可放置于M×N的网格中任意位置,每个网格包含一个非负整数编号,当相邻网格的数字编号差值的绝对值小于等于1时,机器人可以在网格间移动。问题:求机器人可活动的最大范围对应的网格点数目。说明:网格左上角坐标为(0,0),右下角坐标为(m−1,n−1),机器人只能在相邻网格间上下左右移动输入描述第1行输入为M和</div>
                    </li>
                    <li><a href="/article/1880498583761907712.htm"
                           title="如何使用JavaScript开发AR(增强现实)移动应用 (一)" target="_blank">如何使用JavaScript开发AR(增强现实)移动应用 (一)</a>
                        <span class="text-muted"></span>

                        <div>Python中的class体内定义方法时,如果没有显式地包含self参数,有时候依然可以被调用。这是一个非常有趣的话题,因为它涉及到对Python中类与对象之间关系的更深理解。要理解为什么这种情况下方法依然能够被调用,我们需要逐步拆解Python类的构造方式以及方法绑定的原理。</div>
                    </li>
                    <li><a href="/article/1880494294058463232.htm"
                           title="JavaScript语言的计算机基础" target="_blank">JavaScript语言的计算机基础</a>
                        <span class="text-muted">疯狂小小小码农</span>
<a class="tag" taget="_blank" href="/search/%E5%8C%85%E7%BD%97%E4%B8%87%E8%B1%A1/1.htm">包罗万象</a><a class="tag" taget="_blank" href="/search/golang/1.htm">golang</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a>
                        <div>JavaScript语言的计算机基础引言自1995年由网景公司(Netscape)推出以来,JavaScript已经从一个简单的客户端脚本语言发展成为一种广泛使用的编程语言。如今,它不仅在网页开发中扮演着不可或缺的角色,还成为后端开发、移动应用开发、甚至桌面应用开发的一部分。在本文中,我们将探讨JavaScript语言的基本概念及其背后的计算机基础,以帮助读者更好地理解这种语言及其应用。一、计算机</div>
                    </li>
                    <li><a href="/article/1880488616954753024.htm"
                           title="华为OD机试E卷 --堆栈中的剩余数字--24年OD统一考试(Java & JS & Python & C & C++)" target="_blank">华为OD机试E卷 --堆栈中的剩余数字--24年OD统一考试(Java & JS & Python & C & C++)</a>
                        <span class="text-muted">飞码创造者</span>
<a class="tag" taget="_blank" href="/search/%E6%9C%80%E6%96%B0%E5%8D%8E%E4%B8%BAOD%E6%9C%BA%E8%AF%95%E9%A2%98%E5%BA%932024/1.htm">最新华为OD机试题库2024</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%8D%8E%E4%B8%BAod/1.htm">华为od</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/js/1.htm">js</a><a class="tag" taget="_blank" href="/search/c%E8%AF%AD%E8%A8%80/1.htm">c语言</a>
                        <div>文章目录题目描述输入描述输出描述用例题目解析JS算法源码Java算法源码python算法源码c算法源码题目描述向一个空栈中依次存入正整数,假设入栈元素n(1<=n<=2^31-1)按顺序依次为nx…n4、n3、n2、n1,每当元素入栈时,如果n1=n2+…+ny(y的范围[2,x],1<=x<=1000),则n1~ny全部元素出栈,重新入栈新元素m(m=2n1)。如:依次向栈存入6、1、2、3,当</div>
                    </li>
                    <li><a href="/article/1880488618221432832.htm"
                           title="华为OD机试E卷 --机器人活动区域--24年OD统一考试(Java & JS & Python & C & C++)" target="_blank">华为OD机试E卷 --机器人活动区域--24年OD统一考试(Java & JS & Python & C & C++)</a>
                        <span class="text-muted">飞码创造者</span>
<a class="tag" taget="_blank" href="/search/%E6%9C%80%E6%96%B0%E5%8D%8E%E4%B8%BAOD%E6%9C%BA%E8%AF%95%E9%A2%98%E5%BA%932024/1.htm">最新华为OD机试题库2024</a><a class="tag" taget="_blank" href="/search/%E5%8D%8E%E4%B8%BAod/1.htm">华为od</a><a class="tag" taget="_blank" href="/search/%E6%9C%BA%E5%99%A8%E4%BA%BA/1.htm">机器人</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/js/1.htm">js</a>
                        <div>文章目录题目描述输入描述输出描述用例题目解析JS算法源码Java算法源码python算法源码c算法源码c++算法源码题目描述现有一个机器人,可放置于M×N的网格Q中任意位置,每个网格包含一个非负整数编号。当相邻网格的数字编号差值的绝对值小于等于1时,机器人可在网格间移动问题:求机器人可活动的最大范围对应的网格点数目。说明:1)网格左上角坐标为(0,0),右下角坐标为(m-1,n-1)2)机器人只能</div>
                    </li>
                    <li><a href="/article/1880486223227711488.htm"
                           title="postcss插件-实现vw适配" target="_blank">postcss插件-实现vw适配</a>
                        <span class="text-muted">ordinary90</span>
<a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E5%85%A8%E6%A0%88%E5%BC%80%E5%8F%91/1.htm">前端全栈开发</a><a class="tag" taget="_blank" href="/search/VUE/1.htm">VUE</a><a class="tag" taget="_blank" href="/search/postcss/1.htm">postcss</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a>
                        <div>PostCSS是一个用JavaScript编写的插件工具,它可以帮助我们对CSS进行模块化、自动化处理和优化。使用PostCSS插件可以扩展CSS的功能,实现更多的特性,其中一个常用的插件就是实现vw适配的插件。vw(ViewportWidth)是CSS3中的一个单位,它表示相对于视口宽度的百分比。使用vw单位可以根据视口的大小,实现自适应布局。在移动端开发中,vw适配可以帮助我们在不同的屏幕尺寸</div>
                    </li>
                    <li><a href="/article/1880480929940566016.htm"
                           title="Vue+ArcGIS API for JS实现地图邮编分区以及定位的区域高亮" target="_blank">Vue+ArcGIS API for JS实现地图邮编分区以及定位的区域高亮</a>
                        <span class="text-muted">小伙伴123456</span>
<a class="tag" taget="_blank" href="/search/arcgis/1.htm">arcgis</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a><a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a>
                        <div>前言最近公司开发国际物流系统,如果使用国内地图,类似百度,腾讯,高德地图,那么国外的地理信息不会那么全,而且获取邮编api只对国内生效,所以考虑使用esri公司的arcgis地图,但是这个地图在国内社区并不完善,踩过很多坑,在网上也找不到相关的解决办法。在此分享给需要做类似需求的小伙伴,希望能帮到大家。官网:https://www.esri.com/zh-cn/arcgis/products/de</div>
                    </li>
                    <li><a href="/article/1880473231786307584.htm"
                           title="TypeScript 学习笔记(七):TypeScript 与后端框架的结合应用" target="_blank">TypeScript 学习笔记(七):TypeScript 与后端框架的结合应用</a>
                        <span class="text-muted">Evaporator Core</span>
<a class="tag" taget="_blank" href="/search/typescript/1.htm">typescript</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E6%A1%86%E6%9E%B6/1.htm">前端框架</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0/1.htm">学习</a>
                        <div>1.引言在前几篇学习笔记中,我们已经探讨了TypeScript的基础知识和在前端框架(如Angular和React)中的应用。本篇将重点介绍TypeScript在后端开发中的应用,特别是如何与Node.js和Express结合使用,以构建强类型、可维护的后端应用。2.TypeScript与Node.jsNode.js是一个基于ChromeV8引擎的JavaScript运行时,广泛用于构建后端应用。</div>
                    </li>
                    <li><a href="/article/1880470962999193600.htm"
                           title="Node.js --- 模板引擎EJS" target="_blank">Node.js --- 模板引擎EJS</a>
                        <span class="text-muted">蒜蓉大猩猩</span>
<a class="tag" taget="_blank" href="/search/Node.js/1.htm">Node.js</a><a class="tag" taget="_blank" href="/search/node.js/1.htm">node.js</a><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a><a class="tag" taget="_blank" href="/search/express/1.htm">express</a><a class="tag" taget="_blank" href="/search/%E4%B8%AD%E9%97%B4%E4%BB%B6/1.htm">中间件</a>
                        <div>1.前言模板引擎是一种工具或库,用于在开发中生成动态内容的HTML页面。它通过将预定义的模板与数据结合,生成最终的输出(如HTML页面、字符串等)。模板引擎广泛应用于前端和后端开发,尤其是在构建动态网站时。2.EJS模板引擎EJS(EmbeddedJavaScriptTemplates)是一种模板引擎,可以帮助我们在HTML页面中嵌入JavaScript代码,用于动态渲染内容。EJS语法简洁且与H</div>
                    </li>
                    <li><a href="/article/1880465670261501952.htm"
                           title="Vue.js组件开发-如何实现表头搜索" target="_blank">Vue.js组件开发-如何实现表头搜索</a>
                        <span class="text-muted">LCG元</span>
<a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a>
                        <div>在Vue.js组件开发中,实现表头搜索通常涉及在表格组件的表头添加输入框,并让用户能够输入搜索关键字来过滤表格数据。以下是一个使用ElementUI的el-table组件实现表头搜索的示例:一、准备阶段‌确保ElementUI已安装‌:确保Vue项目中已经安装了ElementUI,并且已经在项目中引入。‌准备表格数据‌:在Vue组件中准备一份表格数据,通常是一个数组。二、实现表头搜索‌定义搜索关键</div>
                    </li>
                    <li><a href="/article/1880465417542103040.htm"
                           title="Node的基本模块" target="_blank">Node的基本模块</a>
                        <span class="text-muted">ma_no_lo</span>
<a class="tag" taget="_blank" href="/search/node/1.htm">node</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%A4%A7%E6%95%B0%E6%8D%AE/1.htm">大数据</a><a class="tag" taget="_blank" href="/search/html/1.htm">html</a><a class="tag" taget="_blank" href="/search/node.js/1.htm">node.js</a>
                        <div>一,fs模块1.读fs用于文件,文件夹读写,以下是一些基本的api使用实例constfs=require("fs");首先,我们引入fs模块,这里用的是commonjs,也可以使用import,但是捣鼓费劲。引入模块后,对于读写,fs提供三种方式:第一种,同步,或者叫阻塞。在这种模式下,代码会阻塞在读取文件这一行代码上,直至完成任务后,程序才会继续。constres=fs.readFileSync</div>
                    </li>
                    <li><a href="/article/1880465165346992128.htm"
                           title="nodejs版本管理,使用 nvm 删除node版本,要删除 Node.js 的某个版本详细操作" target="_blank">nodejs版本管理,使用 nvm 删除node版本,要删除 Node.js 的某个版本详细操作</a>
                        <span class="text-muted">m0_74825108</span>
<a class="tag" taget="_blank" href="/search/node.js/1.htm">node.js</a>
                        <div>要删除Node.js的某个版本并保持NodeVersionManager(nvm)的管理整洁,可以按以下步骤操作:步骤1:查看已安装的Node.js版本nvmls这会列出你通过nvm安装的所有Node.js版本。输出类似于:->v18.17.1v16.20.2v14.21.3default->v18.17.1带箭头(->)的是当前使用的版本。步骤2:卸载某个版本使用以下命令卸载特定版本:nvmun</div>
                    </li>
                    <li><a href="/article/1880462644780003328.htm"
                           title="大数据毕业设计—基于python+Django自然灾害频发地区情况数据分析系统" target="_blank">大数据毕业设计—基于python+Django自然灾害频发地区情况数据分析系统</a>
                        <span class="text-muted">qq_1406299528</span>
<a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/%E8%AE%A1%E7%AE%97%E6%9C%BA%E6%AF%95%E4%B8%9A%E8%AE%BE%E8%AE%A1/1.htm">计算机毕业设计</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/%E5%A4%A7%E6%95%B0%E6%8D%AE/1.htm">大数据</a><a class="tag" taget="_blank" href="/search/%E8%AF%BE%E7%A8%8B%E8%AE%BE%E8%AE%A1/1.htm">课程设计</a>
                        <div>一、项目技术开发语言:Pythonpython框架:Django软件版本:python3.7/python3.8数据库:mysql5.7或更高版本数据库工具:Navicat11开发软件:PyCharm/vscode前端框架:vue.js二、项目内容和项目介绍  1.项目内容  1.开发语言:该系统采用Python作为开发语言,Python具有优雅的语法和动态类型,以及解释型语言的本质,使其成为许多</div>
                    </li>
                    <li><a href="/article/1880442727531868160.htm"
                           title="什么是原型,有什么用?" target="_blank">什么是原型,有什么用?</a>
                        <span class="text-muted">神明木佑</span>
<a class="tag" taget="_blank" href="/search/%E5%8E%9F%E5%9E%8B%E6%A8%A1%E5%BC%8F/1.htm">原型模式</a>
                        <div>在JavaScript中,每个对象都有一个原型(prototype),原型也是一个对象。对象可以从它的原型中继承属性和方法。原型是JavaScript实现继承的基础,它构成了JavaScript中对象之间的链式关系。什么是原型?在JavaScript中,每个对象(除了null)都有一个原型。可以通过`__proto__`属性来访问一个对象的原型。原型本身也是一个对象,它可能拥有自己的原型,这样就形</div>
                    </li>
                    <li><a href="/article/1880442475051544576.htm"
                           title="【JavaScript】事件监听:触摸事件" target="_blank">【JavaScript】事件监听:触摸事件</a>
                        <span class="text-muted">神明木佑</span>
<a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/microsoft/1.htm">microsoft</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a>
                        <div>JavaScript触摸事件是通过浏览器提供的TouchAPI来实现的。当用户在触摸屏设备上进行交互时,浏览器会捕捉到触摸事件,并将其传递给相应的JavaScript事件处理器。需要注意的是,触摸事件在不同的设备和浏览器上可能有差异,因此在使用触摸事件时应该进行兼容性测试,并根据需要进行适当的兼容性处理。此外,触摸事件通常与其他事件(如点击事件、滚动事件等)结合使用,以实现更复杂的交互效果。一、t</div>
                    </li>
                    <li><a href="/article/1880438561627500544.htm"
                           title="Springboot项目如何消费Kafka数据" target="_blank">Springboot项目如何消费Kafka数据</a>
                        <span class="text-muted">布朗克168</span>
<a class="tag" taget="_blank" href="/search/Kafka/1.htm">Kafka</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/boot/1.htm">boot</a><a class="tag" taget="_blank" href="/search/kafka/1.htm">kafka</a><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a>
                        <div>目录一、引入依赖二、添加Kafka配置三、创建Kafka消费者(一)Kafka生产的消息是JSON字符串1、方式一2、方式二:需要直接访问消息元数据(二)Kafka生产的消息是对象Order四、创建启动类五、配置Kafka生产者(可选)(一)消息类型为json串(二)消息类型为对象Order六、启动Kafka服务七、测试Kafka消费者九、测试和调试十、结语一、引入依赖你需要在pom.xml中添加</div>
                    </li>
                    <li><a href="/article/1880428729457504256.htm"
                           title="基于JAVA面向餐饮行业的会员营销系统计算机毕业设计源码+数据库+lw文档+系统+部署" target="_blank">基于JAVA面向餐饮行业的会员营销系统计算机毕业设计源码+数据库+lw文档+系统+部署</a>
                        <span class="text-muted">匠心网络</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a>
                        <div>基于JAVA面向餐饮行业的会员营销系统计算机毕业设计源码+数据库+lw文档+系统+部署基于JAVA面向餐饮行业的会员营销系统计算机毕业设计源码+数据库+lw文档+系统+部署本源码技术栈:项目架构:B/S架构开发语言:Java语言开发软件:ideaeclipse前端技术:Layui、HTML、CSS、JS、JQuery等技术后端技术:JAVA运行环境:Win10、JDK1.8数据库:MySQL5.7</div>
                    </li>
                    <li><a href="/article/1880427721171988480.htm"
                           title="理解 Base64 编码原理及其 JavaScript 实现" target="_blank">理解 Base64 编码原理及其 JavaScript 实现</a>
                        <span class="text-muted">red润</span>
<a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a>
                        <div>理解Base64编码原理及其JavaScript实现下一篇博客在JavaScript中处理中文字符串的Base64编码与解码注意:这里没有处理中文base64编码情况什么是Base64编码?Base64编码是一种将二进制数据转换为可打印字符的编码方式。它将每三个字节(24位)的二进制数据转换为四个字符,每个字符由64个字符集合中的一个表示。这使得数据可以通过文本协议传输(如电子邮件、HTTP请求等</div>
                    </li>
                    <li><a href="/article/1880423811430543360.htm"
                           title="js中 window.location.href使用post请求" target="_blank">js中 window.location.href使用post请求</a>
                        <span class="text-muted">ebg_coder</span>
<a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a>
                        <div>本来考虑使用ajax,但ajax是异步提交请求,无法跳转页面。而window.location.href是get的请求,漏洞扫描工具会检测到,参数过长或者出于安全考虑保密数据,要使用post。最后使用js的表单提交方法,代码如下:$('.test-button').click(function(){vartestId=$(this).attr('id');varhtml=""+""+"";docu</div>
                    </li>
                    <li><a href="/article/1880416623358177280.htm"
                           title="jsp有哪些内置对象?作用分别是什么?" target="_blank">jsp有哪些内置对象?作用分别是什么?</a>
                        <span class="text-muted">富哥92</span>
<a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95/1.htm">面试</a>
                        <div>1.HttpServletRequet类的Request对象:代表请求对象,主要用于接受客户端通过HTTP协议连接传输服务器端的数据。2.HttpSevletResponse类的Response对象:代表响应对象,主要用于向客户端发送数据。3.JspWriter类的out对象:主要用于向客户端输出数据,out的基类是jspWriter4.HttpSession类的session对象:主要用来分别保</div>
                    </li>
                    <li><a href="/article/1880413974210605056.htm"
                           title="java毕业设计宠物领养饲养交流管理平台Mybatis+系统+数据库+调试部署" target="_blank">java毕业设计宠物领养饲养交流管理平台Mybatis+系统+数据库+调试部署</a>
                        <span class="text-muted">静静学姐</span>
<a class="tag" taget="_blank" href="/search/mybatis/1.htm">mybatis</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%AE%A0%E7%89%A9/1.htm">宠物</a>
                        <div>java毕业设计宠物领养饲养交流管理平台Mybatis+系统+数据库+调试部署java毕业设计宠物领养饲养交流管理平台Mybatis+系统+数据库+调试部署本源码技术栈:项目架构:B/S架构开发语言:Java语言开发软件:ideaeclipse前端技术:Layui、HTML、CSS、JS、JQuery等技术后端技术:JAVA运行环境:Win10、JDK1.8数据库:MySQL5.7/8.0源码地址</div>
                    </li>
                    <li><a href="/article/1880406911166246912.htm"
                           title="Vue中常见设计模式的应用~" target="_blank">Vue中常见设计模式的应用~</a>
                        <span class="text-muted">Warm</span>
<a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a><a class="tag" taget="_blank" href="/search/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/1.htm">设计模式</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a>
                        <div>Vue是基于什么模式?表示既然是Vue中常见的设计模式,首当其冲就先聊聊MVVM模式啦一、mvvm模式Vue.js是一个基于MVVM设计模式的前端框架。它将前端中的UI视图与底层数据和业务逻辑分离开来,使得UI视图与数据和业务逻辑之间不存在耦合性,可以独立编写和测试。MVVM三个组成部分Model(模型):存放业务数据和对数据的操作等View(视图):用户界面,负责呈现UI,并向ViewModel</div>
                    </li>
                    <li><a href="/article/1880396946301054976.htm"
                           title="华为OD机试D卷 --跳格子3--24年OD统一考试(Java & JS & Python & C & C++)" target="_blank">华为OD机试D卷 --跳格子3--24年OD统一考试(Java & JS & Python & C & C++)</a>
                        <span class="text-muted">飞码创造者</span>
<a class="tag" taget="_blank" href="/search/%E6%9C%80%E6%96%B0%E5%8D%8E%E4%B8%BAOD%E6%9C%BA%E8%AF%95%E9%A2%98%E5%BA%932024/1.htm">最新华为OD机试题库2024</a><a class="tag" taget="_blank" href="/search/%E5%8D%8E%E4%B8%BAod/1.htm">华为od</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/c%E8%AF%AD%E8%A8%80/1.htm">c语言</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/c%2B%2B/1.htm">c++</a>
                        <div>文章目录题目描述输入描述输出描述用例题目解析java源码js源码python源码题目描述小明和朋友们一起玩跳格子游戏,每个格子上有特定的分数score=[1,-1,-6,7,-17,7],从起点score[0]开始,每次最大的步长为k,请你返回小明跳到终点score[n-1]时,能得到的最大得分。输入描述第一行输入总的格子数量n第二行输入每个格子的分数score[i第三行输入最大跳的步长k输出描述</div>
                    </li>
                    <li><a href="/article/1880395432257974272.htm"
                           title="【Rust】——不安全Rust" target="_blank">【Rust】——不安全Rust</a>
                        <span class="text-muted">Y小夜</span>
<a class="tag" taget="_blank" href="/search/Rust%EF%BC%88%E5%AE%98%E6%96%B9%E6%96%87%E6%A1%A3%E9%87%8D%E7%82%B9%E6%80%BB%E7%BB%93%EF%BC%89/1.htm">Rust(官方文档重点总结)</a><a class="tag" taget="_blank" href="/search/rust/1.htm">rust</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a>
                        <div>博主现有专栏:C51单片机(STC89C516),c语言,c++,离散数学,算法设计与分析,数据结构,Python,Java基础,MySQL,linux,基于HTML5的网页设计及应用,Rust(官方文档重点总结),jQuery,前端vue.js,Javaweb开发,Python机器学习等主页链接:Y小夜-CSDN博客目录不安全的超能力解引用裸指针调用不安全函数或方法创建不安全代码的安全抽象使用e</div>
                    </li>
                    <li><a href="/article/1880383080405987328.htm"
                           title="华为OD机试E卷 - 计算面积/绘图机器(Java & Python& JS & C++ & C )" target="_blank">华为OD机试E卷 - 计算面积/绘图机器(Java & Python& JS & C++ & C )</a>
                        <span class="text-muted">算法大师</span>
<a class="tag" taget="_blank" href="/search/%E6%9C%80%E6%96%B0%E5%8D%8E%E4%B8%BAOD%E6%9C%BA%E8%AF%95/1.htm">最新华为OD机试</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%8D%8E%E4%B8%BAod/1.htm">华为od</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/c%E8%AF%AD%E8%A8%80/1.htm">c语言</a><a class="tag" taget="_blank" href="/search/c%2B%2B/1.htm">c++</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%8D%8E%E4%B8%BAOD%E6%9C%BA%E8%AF%95E%E5%8D%B7/1.htm">华为OD机试E卷</a>
                        <div>最新华为OD机试真题目录:点击查看目录华为OD面试真题精选:点击立即查看题目描述绘图机器的绘图笔初始位置在原点(0,0)机器启动后按照以下规则来进行绘制直线。1.尝试沿着横线坐标正向绘制直线直到给定的终点E2.期间可以通过指令在纵坐标轴方向进行偏移,offsetY为正数表示正向偏移,为负数表示负向偏移给定的横坐标终点值E以及若干条绘制指令,请计算绘制的直线和横坐标轴以及x=E的直线组成的图形面积。</div>
                    </li>
                                <li><a href="/article/18.htm"
                                       title="jQuery 跨域访问的三种方式 No 'Access-Control-Allow-Origin' header is present on the reque" target="_blank">jQuery 跨域访问的三种方式 No 'Access-Control-Allow-Origin' header is present on the reque</a>
                                    <span class="text-muted">qiaolevip</span>
<a class="tag" taget="_blank" href="/search/%E6%AF%8F%E5%A4%A9%E8%BF%9B%E6%AD%A5%E4%B8%80%E7%82%B9%E7%82%B9/1.htm">每天进步一点点</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0%E6%B0%B8%E6%97%A0%E6%AD%A2%E5%A2%83/1.htm">学习永无止境</a><a class="tag" taget="_blank" href="/search/%E8%B7%A8%E5%9F%9F/1.htm">跨域</a><a class="tag" taget="_blank" href="/search/%E4%BC%97%E8%A7%82%E5%8D%83%E8%B1%A1/1.htm">众观千象</a>
                                    <div>XMLHttpRequest cannot load http://v.xxx.com. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:63342' is therefore not allowed access. test.html:1
</div>
                                </li>
                                <li><a href="/article/145.htm"
                                       title="mysql 分区查询优化" target="_blank">mysql 分区查询优化</a>
                                    <span class="text-muted">annan211</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%88%86%E5%8C%BA/1.htm">分区</a><a class="tag" taget="_blank" href="/search/%E4%BC%98%E5%8C%96/1.htm">优化</a><a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a>
                                    <div>


分区查询优化

  引入分区可以给查询带来一定的优势,但同时也会引入一些bug.
  
  分区最大的优点就是优化器可以根据分区函数来过滤掉一些分区,通过分区过滤可以让查询扫描更少的数据。
  所以,对于访问分区表来说,很重要的一点是要在where 条件中带入分区,让优化器过滤掉无需访问的分区。
  
  可以通过查看explain执行计划,是否携带 partitions</div>
                                </li>
                                <li><a href="/article/272.htm"
                                       title="MYSQL存储过程中使用游标" target="_blank">MYSQL存储过程中使用游标</a>
                                    <span class="text-muted">chicony</span>
<a class="tag" taget="_blank" href="/search/Mysql%E5%AD%98%E5%82%A8%E8%BF%87%E7%A8%8B/1.htm">Mysql存储过程</a>
                                    <div>DELIMITER $$ 
DROP PROCEDURE IF EXISTS getUserInfo $$ 
CREATE PROCEDURE getUserInfo(in date_day datetime)-- -- 实例-- 存储过程名为:getUserInfo-- 参数为:date_day日期格式:2008-03-08--    BEGINdecla</div>
                                </li>
                                <li><a href="/article/399.htm"
                                       title="mysql 和 sqlite 区别" target="_blank">mysql 和 sqlite 区别</a>
                                    <span class="text-muted">Array_06</span>
<a class="tag" taget="_blank" href="/search/sqlite/1.htm">sqlite</a>
                                    <div>转载: 
http://www.cnblogs.com/ygm900/p/3460663.html 
 
mysql 和 sqlite 区别 
 
SQLITE是单机数据库。功能简约,小型化,追求最大磁盘效率 
MYSQL是完善的服务器数据库。功能全面,综合化,追求最大并发效率 
 
MYSQL、Sybase、Oracle等这些都是试用于服务器数据量大功能多需要安装,例如网站访问量比较大的。而sq</div>
                                </li>
                                <li><a href="/article/526.htm"
                                       title="pinyin4j使用" target="_blank">pinyin4j使用</a>
                                    <span class="text-muted">oloz</span>
<a class="tag" taget="_blank" href="/search/pinyin4j/1.htm">pinyin4j</a>
                                    <div>首先需要pinyin4j的jar包支持;jar包已上传至附件内 
 
方法一:把汉字转换为拼音;例如:编程转换后则为biancheng 
     
 
/**
     * 将汉字转换为全拼
     * @param src 你的需要转换的汉字
     * @param isUPPERCASE 是否转换为大写的拼音; true:转换为大写;fal</div>
                                </li>
                                <li><a href="/article/653.htm"
                                       title="微博发送私信" target="_blank">微博发送私信</a>
                                    <span class="text-muted">随意而生</span>
<a class="tag" taget="_blank" href="/search/%E5%BE%AE%E5%8D%9A/1.htm">微博</a>
                                    <div>在前面文章中说了如和获取登陆时候所需要的cookie,现在只要拿到最后登陆所需要的cookie,然后抓包分析一下微博私信发送界面 
http://weibo.com/message/history?uid=****&name=**** 
可以发现其发送提交的Post请求和其中的数据, 
让后用程序模拟发送POST请求中的数据,带着cookie发送到私信的接入口,就可以实现发私信的功能了。 </div>
                                </li>
                                <li><a href="/article/780.htm"
                                       title="jsp" target="_blank">jsp</a>
                                    <span class="text-muted">香水浓</span>
<a class="tag" taget="_blank" href="/search/jsp/1.htm">jsp</a>
                                    <div>JSP初始化 
    容器载入JSP文件后,它会在为请求提供任何服务前调用jspInit()方法。如果您需要执行自定义的JSP初始化任务,复写jspInit()方法就行了 
 
 
JSP执行 
    这一阶段描述了JSP生命周期中一切与请求相关的交互行为,直到被销毁。 
    当JSP网页完成初始化后</div>
                                </li>
                                <li><a href="/article/907.htm"
                                       title="在 Windows 上安装 SVN Subversion 服务端" target="_blank">在 Windows 上安装 SVN Subversion 服务端</a>
                                    <span class="text-muted">AdyZhang</span>
<a class="tag" taget="_blank" href="/search/SVN/1.htm">SVN</a>
                                    <div>在 Windows 上安装 SVN Subversion 服务端2009-09-16高宏伟哈尔滨市道里区通达街291号 
  
最佳阅读效果请访问原地址:http://blog.donews.com/dukejoe/archive/2009/09/16/1560917.aspx 
  
现在的Subversion已经足够稳定,而且已经进入了它的黄金时段。我们看到大量的项目都在使</div>
                                </li>
                                <li><a href="/article/1034.htm"
                                       title="android开发中如何使用 alertDialog从listView中删除数据?" target="_blank">android开发中如何使用 alertDialog从listView中删除数据?</a>
                                    <span class="text-muted">aijuans</span>
<a class="tag" taget="_blank" href="/search/android/1.htm">android</a>
                                    <div>我现在使用listView展示了很多的配置信息,我现在想在点击其中一条的时候填出 alertDialog,点击确认后就删除该条数据,( ArrayAdapter ,ArrayList,listView 全部删除),我知道在 下面的onItemLongClick 方法中 参数 arg2  是选中的序号,但是我不知道如何继续处理下去        1   2   3   </div>
                                </li>
                                <li><a href="/article/1161.htm"
                                       title="jdk-6u26-linux-x64.bin 安装" target="_blank">jdk-6u26-linux-x64.bin 安装</a>
                                    <span class="text-muted">baalwolf</span>
<a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a>
                                    <div>1.上传安装文件(jdk-6u26-linux-x64.bin) 
2.修改权限 
[root@localhost ~]# ls -l /usr/local/jdk-6u26-linux-x64.bin 
3.执行安装文件 
[root@localhost ~]# cd /usr/local 
[root@localhost local]# ./jdk-6u26-linux-x64.bin&nbs</div>
                                </li>
                                <li><a href="/article/1288.htm"
                                       title="MongoDB经典面试题集锦" target="_blank">MongoDB经典面试题集锦</a>
                                    <span class="text-muted">BigBird2012</span>
<a class="tag" taget="_blank" href="/search/mongodb/1.htm">mongodb</a>
                                    <div>1.什么是NoSQL数据库?NoSQL和RDBMS有什么区别?在哪些情况下使用和不使用NoSQL数据库? 
NoSQL是非关系型数据库,NoSQL = Not Only SQL。 
关系型数据库采用的结构化的数据,NoSQL采用的是键值对的方式存储数据。 
在处理非结构化/半结构化的大数据时;在水平方向上进行扩展时;随时应对动态增加的数据项时可以优先考虑使用NoSQL数据库。 
在考虑数据库的成熟</div>
                                </li>
                                <li><a href="/article/1415.htm"
                                       title="JavaScript异步编程Promise模式的6个特性" target="_blank">JavaScript异步编程Promise模式的6个特性</a>
                                    <span class="text-muted">bijian1013</span>
<a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a><a class="tag" taget="_blank" href="/search/Promise/1.htm">Promise</a>
                                    <div>        Promise是一个非常有价值的构造器,能够帮助你避免使用镶套匿名方法,而使用更具有可读性的方式组装异步代码。这里我们将介绍6个最简单的特性。 
        在我们开始正式介绍之前,我们想看看Javascript Promise的样子: 
var p = new Promise(function(r</div>
                                </li>
                                <li><a href="/article/1542.htm"
                                       title="[Zookeeper学习笔记之八]Zookeeper源代码分析之Zookeeper.ZKWatchManager" target="_blank">[Zookeeper学习笔记之八]Zookeeper源代码分析之Zookeeper.ZKWatchManager</a>
                                    <span class="text-muted">bit1129</span>
<a class="tag" taget="_blank" href="/search/zookeeper/1.htm">zookeeper</a>
                                    <div>ClientWatchManager接口 
//接口的唯一方法materialize用于确定那些Watcher需要被通知
//确定Watcher需要三方面的因素1.事件状态 2.事件类型 3.znode的path
public interface ClientWatchManager {
    /**
     * Return a set of watchers that should</div>
                                </li>
                                <li><a href="/article/1669.htm"
                                       title="【Scala十五】Scala核心九:隐式转换之二" target="_blank">【Scala十五】Scala核心九:隐式转换之二</a>
                                    <span class="text-muted">bit1129</span>
<a class="tag" taget="_blank" href="/search/scala/1.htm">scala</a>
                                    <div>隐式转换存在的必要性, 
  
在Java Swing中,按钮点击事件的处理,转换为Scala的的写法如下: 
  
val button = new JButton
button.addActionListener(
    new ActionListener {
        def actionPerformed(event: ActionEvent) {
 </div>
                                </li>
                                <li><a href="/article/1796.htm"
                                       title="Android JSON数据的解析与封装小Demo" target="_blank">Android JSON数据的解析与封装小Demo</a>
                                    <span class="text-muted">ronin47</span>

                                    <div>转自:http://www.open-open.com/lib/view/open1420529336406.html 
package com.example.jsondemo; 
import org.json.JSONArray; 
import org.json.JSONException; 
import org.json.JSONObject; 
   
impor</div>
                                </li>
                                <li><a href="/article/1923.htm"
                                       title="[设计]字体创意设计方法谈" target="_blank">[设计]字体创意设计方法谈</a>
                                    <span class="text-muted">brotherlamp</span>
<a class="tag" taget="_blank" href="/search/UI/1.htm">UI</a><a class="tag" taget="_blank" href="/search/ui%E8%87%AA%E5%AD%A6/1.htm">ui自学</a><a class="tag" taget="_blank" href="/search/ui%E8%A7%86%E9%A2%91/1.htm">ui视频</a><a class="tag" taget="_blank" href="/search/ui%E6%95%99%E7%A8%8B/1.htm">ui教程</a><a class="tag" taget="_blank" href="/search/ui%E8%B5%84%E6%96%99/1.htm">ui资料</a>
                                    <div>  
从古至今,文字在我们的生活中是必不可少的事物,我们不能想象没有文字的世界将会是怎样。在平面设计中,UI设计师在文字上所花的心思和功夫最多,因为文字能直观地表达UI设计师所的意念。在文字上的创造设计,直接反映出平面作品的主题。 
如设计一幅戴尔笔记本电脑的广告海报,假设海报上没有出现“戴尔”两个文字,即使放上所有戴尔笔记本电脑的图片都不能让人们得知这些电脑是什么品牌。只要写上“戴尔笔</div>
                                </li>
                                <li><a href="/article/2050.htm"
                                       title="单调队列-用一个长度为k的窗在整数数列上移动,求窗里面所包含的数的最大值" target="_blank">单调队列-用一个长度为k的窗在整数数列上移动,求窗里面所包含的数的最大值</a>
                                    <span class="text-muted">bylijinnan</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95%E9%A2%98/1.htm">面试题</a>
                                    <div>import java.util.LinkedList;

/*

单调队列 滑动窗口
单调队列是这样的一个队列:队列里面的元素是有序的,是递增或者递减

题目:给定一个长度为N的整数数列a(i),i=0,1,...,N-1和窗长度k.

要求:f(i) = max{a(i-k+1),a(i-k+2),..., a(i)},i = 0,1,...,N-1

问题的另一种描述就</div>
                                </li>
                                <li><a href="/article/2177.htm"
                                       title="struts2处理一个form多个submit" target="_blank">struts2处理一个form多个submit</a>
                                    <span class="text-muted">chiangfai</span>
<a class="tag" taget="_blank" href="/search/struts2/1.htm">struts2</a>
                                    <div>web应用中,为完成不同工作,一个jsp的form标签可能有多个submit。如下代码: 
<s:form action="submit" method="post" namespace="/my">
<s:textfield name="msg" label="叙述:"></div>
                                </li>
                                <li><a href="/article/2304.htm"
                                       title="shell查找上个月,陷阱及野路子" target="_blank">shell查找上个月,陷阱及野路子</a>
                                    <span class="text-muted">chenchao051</span>
<a class="tag" taget="_blank" href="/search/shell/1.htm">shell</a>
                                    <div>date -d "-1 month" +%F 
    以上这段代码,假如在2012/10/31执行,结果并不会出现你预计的9月份,而是会出现八月份,原因是10月份有31天,9月份30天,所以-1 month在10月份看来要减去31天,所以直接到了8月31日这天,这不靠谱。 
    野路子解决:假设当天日期大于15号</div>
                                </li>
                                <li><a href="/article/2431.htm"
                                       title="mysql导出数据中文乱码问题" target="_blank">mysql导出数据中文乱码问题</a>
                                    <span class="text-muted">daizj</span>
<a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a><a class="tag" taget="_blank" href="/search/%E4%B8%AD%E6%96%87%E4%B9%B1%E7%A0%81/1.htm">中文乱码</a><a class="tag" taget="_blank" href="/search/%E5%AF%BC%E6%95%B0%E6%8D%AE/1.htm">导数据</a>
                                    <div>解决mysql导入导出数据乱码问题方法: 
 
1、进入mysql,通过如下命令查看数据库编码方式: 
 
mysql>  show variables like 'character_set_%'; 
+--------------------------+----------------------------------------+ 
| Variable_name&nbs</div>
                                </li>
                                <li><a href="/article/2558.htm"
                                       title="SAE部署Smarty出现:Uncaught exception 'SmartyException' with message 'unable to write" target="_blank">SAE部署Smarty出现:Uncaught exception 'SmartyException' with message 'unable to write</a>
                                    <span class="text-muted">dcj3sjt126com</span>
<a class="tag" taget="_blank" href="/search/PHP/1.htm">PHP</a><a class="tag" taget="_blank" href="/search/smarty/1.htm">smarty</a><a class="tag" taget="_blank" href="/search/sae/1.htm">sae</a>
                                    <div>  
对于SAE出现的问题:Uncaught exception 'SmartyException' with message 'unable to write file...。 
官方给出了详细的FAQ:http://sae.sina.com.cn/?m=faqs&catId=11#show_213 
解决方案为: 
        
01  
$path </div>
                                </li>
                                <li><a href="/article/2685.htm"
                                       title="《教父》系列台词" target="_blank">《教父》系列台词</a>
                                    <span class="text-muted">dcj3sjt126com</span>

                                    <div>Your love is also your weak point. 
你的所爱同时也是你的弱点。 
  
If anything in this life is certain, if history has taught us anything, it is 
that you can kill anyone. 
  
不顾家的人永远不可能成为一个真正的男人。 &</div>
                                </li>
                                <li><a href="/article/2812.htm"
                                       title="mongodb安装与使用" target="_blank">mongodb安装与使用</a>
                                    <span class="text-muted">dyy_gusi</span>
<a class="tag" taget="_blank" href="/search/mongo/1.htm">mongo</a>
                                    <div>一.MongoDB安装和启动,widndows和linux基本相同 
1.下载数据库, 
    linux:mongodb-linux-x86_64-ubuntu1404-3.0.3.tgz 
2.解压文件,并且放置到合适的位置 
    tar -vxf mongodb-linux-x86_64-ubun</div>
                                </li>
                                <li><a href="/article/2939.htm"
                                       title="Git排除目录" target="_blank">Git排除目录</a>
                                    <span class="text-muted">geeksun</span>
<a class="tag" taget="_blank" href="/search/git/1.htm">git</a>
                                    <div>在Git的版本控制中,可能有些文件是不需要加入控制的,那我们在提交代码时就需要忽略这些文件,下面讲讲应该怎么给Git配置一些忽略规则。 
  
有三种方法可以忽略掉这些文件,这三种方法都能达到目的,只不过适用情景不一样。 
1.  针对单一工程排除文件 
这种方式会让这个工程的所有修改者在克隆代码的同时,也能克隆到过滤规则,而不用自己再写一份,这就能保证所有修改者应用的都是同一</div>
                                </li>
                                <li><a href="/article/3066.htm"
                                       title="Ubuntu 创建开机自启动脚本的方法" target="_blank">Ubuntu 创建开机自启动脚本的方法</a>
                                    <span class="text-muted">hongtoushizi</span>
<a class="tag" taget="_blank" href="/search/ubuntu/1.htm">ubuntu</a>
                                    <div>转载自: http://rongjih.blog.163.com/blog/static/33574461201111504843245/ 
Ubuntu 创建开机自启动脚本的步骤如下:  
1) 将你的启动脚本复制到 /etc/init.d目录下   以下假设你的脚本文件名为 test。       
2) 设置脚本文件的权限    $ sudo chmod 755</div>
                                </li>
                                <li><a href="/article/3193.htm"
                                       title="第八章 流量复制/AB测试/协程" target="_blank">第八章 流量复制/AB测试/协程</a>
                                    <span class="text-muted">jinnianshilongnian</span>
<a class="tag" taget="_blank" href="/search/nginx/1.htm">nginx</a><a class="tag" taget="_blank" href="/search/lua/1.htm">lua</a><a class="tag" taget="_blank" href="/search/coroutine/1.htm">coroutine</a>
                                    <div>流量复制 
在实际开发中经常涉及到项目的升级,而该升级不能简单的上线就完事了,需要验证该升级是否兼容老的上线,因此可能需要并行运行两个项目一段时间进行数据比对和校验,待没问题后再进行上线。这其实就需要进行流量复制,把流量复制到其他服务器上,一种方式是使用如tcpcopy引流;另外我们还可以使用nginx的HttpLuaModule模块中的ngx.location.capture_multi进行并发</div>
                                </li>
                                <li><a href="/article/3320.htm"
                                       title="电商系统商品表设计" target="_blank">电商系统商品表设计</a>
                                    <span class="text-muted">lkl</span>

                                    <div>DROP TABLE IF EXISTS `category`; -- 类目表
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `category` (
  `id` int(11) NOT NUL</div>
                                </li>
                                <li><a href="/article/3447.htm"
                                       title="修改phpMyAdmin导入SQL文件的大小限制" target="_blank">修改phpMyAdmin导入SQL文件的大小限制</a>
                                    <span class="text-muted">pda158</span>
<a class="tag" taget="_blank" href="/search/sql/1.htm">sql</a><a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a>
                                    <div> 用phpMyAdmin导入mysql数据库时,我的10M的 
数据库不能导入,提示mysql数据库最大只能导入2M。      
phpMyAdmin数据库导入出错:     You probably tried to upload too large file. Please refer to documentation for ways to workaround this limit.  </div>
                                </li>
                                <li><a href="/article/3574.htm"
                                       title="Tomcat性能调优方案" target="_blank">Tomcat性能调优方案</a>
                                    <span class="text-muted">Sobfist</span>
<a class="tag" taget="_blank" href="/search/apache/1.htm">apache</a><a class="tag" taget="_blank" href="/search/jvm/1.htm">jvm</a><a class="tag" taget="_blank" href="/search/tomcat/1.htm">tomcat</a><a class="tag" taget="_blank" href="/search/%E5%BA%94%E7%94%A8%E6%9C%8D%E5%8A%A1%E5%99%A8/1.htm">应用服务器</a>
                                    <div>一、操作系统调优 
 对于操作系统优化来说,是尽可能的增大可使用的内存容量、提高CPU的频率,保证文件系统的读写速率等。经过压力测试验证,在并发连接很多的情况下,CPU的处理能力越强,系统运行速度越快。。 
 【适用场景】 任何项目。 
 二、Java虚拟机调优 
 应该选择SUN的JVM,在满足项目需要的前提下,尽量选用版本较高的JVM,一般来说高版本产品在速度和效率上比低版本会有改进。 
 J</div>
                                </li>
                                <li><a href="/article/3701.htm"
                                       title="SQLServer学习笔记" target="_blank">SQLServer学习笔记</a>
                                    <span class="text-muted">vipbooks</span>
<a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/1.htm">数据结构</a><a class="tag" taget="_blank" href="/search/xml/1.htm">xml</a>
                                    <div>1、create database school 创建数据库school 
 
2、drop database school 删除数据库school 
 
3、use school 连接到school数据库,使其成为当前数据库 
 
4、create table class(classID int primary key identity not null) 
 创建一个名为class的表,其有一</div>
                                </li>
                </ul>
            </div>
        </div>
    </div>

<div>
    <div class="container">
        <div class="indexes">
            <strong>按字母分类:</strong>
            <a href="/tags/A/1.htm" target="_blank">A</a><a href="/tags/B/1.htm" target="_blank">B</a><a href="/tags/C/1.htm" target="_blank">C</a><a
                href="/tags/D/1.htm" target="_blank">D</a><a href="/tags/E/1.htm" target="_blank">E</a><a href="/tags/F/1.htm" target="_blank">F</a><a
                href="/tags/G/1.htm" target="_blank">G</a><a href="/tags/H/1.htm" target="_blank">H</a><a href="/tags/I/1.htm" target="_blank">I</a><a
                href="/tags/J/1.htm" target="_blank">J</a><a href="/tags/K/1.htm" target="_blank">K</a><a href="/tags/L/1.htm" target="_blank">L</a><a
                href="/tags/M/1.htm" target="_blank">M</a><a href="/tags/N/1.htm" target="_blank">N</a><a href="/tags/O/1.htm" target="_blank">O</a><a
                href="/tags/P/1.htm" target="_blank">P</a><a href="/tags/Q/1.htm" target="_blank">Q</a><a href="/tags/R/1.htm" target="_blank">R</a><a
                href="/tags/S/1.htm" target="_blank">S</a><a href="/tags/T/1.htm" target="_blank">T</a><a href="/tags/U/1.htm" target="_blank">U</a><a
                href="/tags/V/1.htm" target="_blank">V</a><a href="/tags/W/1.htm" target="_blank">W</a><a href="/tags/X/1.htm" target="_blank">X</a><a
                href="/tags/Y/1.htm" target="_blank">Y</a><a href="/tags/Z/1.htm" target="_blank">Z</a><a href="/tags/0/1.htm" target="_blank">其他</a>
        </div>
    </div>
</div>
<footer id="footer" class="mb30 mt30">
    <div class="container">
        <div class="footBglm">
            <a target="_blank" href="/">首页</a> -
            <a target="_blank" href="/custom/about.htm">关于我们</a> -
            <a target="_blank" href="/search/Java/1.htm">站内搜索</a> -
            <a target="_blank" href="/sitemap.txt">Sitemap</a> -
            <a target="_blank" href="/custom/delete.htm">侵权投诉</a>
        </div>
        <div class="copyright">版权所有 IT知识库 CopyRight © 2000-2050 E-COM-NET.COM , All Rights Reserved.
<!--            <a href="https://beian.miit.gov.cn/" rel="nofollow" target="_blank">京ICP备09083238号</a><br>-->
        </div>
    </div>
</footer>
<!-- 代码高亮 -->
<script type="text/javascript" src="/static/syntaxhighlighter/scripts/shCore.js"></script>
<script type="text/javascript" src="/static/syntaxhighlighter/scripts/shLegacy.js"></script>
<script type="text/javascript" src="/static/syntaxhighlighter/scripts/shAutoloader.js"></script>
<link type="text/css" rel="stylesheet" href="/static/syntaxhighlighter/styles/shCoreDefault.css"/>
<script type="text/javascript" src="/static/syntaxhighlighter/src/my_start_1.js"></script>





</body>

</html>