关于脚手架:从0到1搭建自己的脚手架java后端-京东云技术团队

一、脚手架是什么脚手架是一种基础设施工具,用于疾速生成我的项目的框架代码和文件构造。它是一种标准化的开发工具,使开发人员可能在我的项目的晚期阶段疾速搭建出一个具备基本功能和构造的零碎。 二、脚手架的意义支流的微服务架构体系下很多公司会将原有的单体架构或者沉重的微服务进行拆分。这个时候依照模块(商品、订单、用户、库存、优惠、搜寻、治理后盾..)、依照畛域驱动设计(投保、理赔、领取、保单治理)等进行拆分就须要很多的微服务项目,如果一个一个的去创立微服务其实是在做反复的工作容易出错而且没有意义,节约人力物力。这个时候基础性的长久层、日志、异样解决、权限管制等在我的项目创立时一起生成不仅缩小了从新创立或局部复制带来的危险而且高效。 三、脚手架的创立3.1 编写我的项目模版首先咱们要有一个根底我的项目的模板,这个模板中集成了开发时所须要的罕用配置,你能够本人搭建,或者找一个根底我的项目如:SpringBoot 我的项目中曾经引入了 MyBatis-Plus, Redis, Logback, Hutool, Swagger-UI 等。或者将公司的架构积淀出一个根底我的项目的模板。 springboot模版我的项目: 3.2 生成脚手架3.2.1 应用 idea 关上我的项目模板应用 IDEA 关上根底我的项目,查看一下 maven 的配置门路,搭建过程中要保障 maven 门路始终统一,我的 maven 门路如下。 D:/Program Files/apache-maven-3.2.5D:\Program Files\apache-maven-3.2.5\conf\settings.xmlD:\Program Files\apache-maven-3.2.5\repository而后运行一下我的项目,要确保根底我的项目是失常的。 3.2.2 留神版本号而后注意一下 pom.xml 文件中的我的项目 gvn,这是我的项目的版本号,也与下文生成模板的版本号无关。 org.springframework.boot.demospring‐boot‐stage‐demo0.0.1‐SNAPSHOT3.2.3 构建脚手架形式一:关上命令行窗口 Terminal ,失常状况指向的是本我的项目的目录,如果不是则 cd 到本我的项目,而后输出: mvn archetype:create-from-project #从已有的我的项目中生成archetype. 形式二:以后我的项目所在文件夹下执行 eg: 我的项目的跟门路为 D:\spring-staggingcmd下执行 d: cd D:\spring-stagging mvn archetype:create-from-project 执行实现后脚手架我的项目也就创立实现,生成如下所示的构造 注:这里如果生成的是如下所示的构造 解决办法1.调整如图所示的artifactId与module前缀统一 将产生的target目录挪动到新的目录,关上gitbash进行如下操作 删除idea的相干文件 rm -rf .idea find . -name " .iml" -type f -print -exec rm -rf {} ; 删除不须要的实例代码find . -name "xxxMain" -type f -print -exec rm -rf {} ; eg:将脚手架放到D:\spring-stagging-archetype 目录下,目录下次要寄存src和pom文件即可 ...

June 1, 2023 · 1 min · jiezi

关于脚手架:脚手架常用工具commander-等工具的使用

本文是系列文章《从0到1打造一款脚手架》第1篇手脚架开发过程中应用了一些工具,比方交互提醒,获取用户输出,高亮,生成模板等等。这里对他们进行简略的介绍,不便后续的开发。 commandercommander 是一个命令行解决方案。通过它能够通知用户脚手架的命令与性能,以及解决用户输出。装置:npm install commander应用: 简略的应用: const { program } = require('commander');program.parse(); // 解析执行命令:node main.js --help 增加名称,形容,版本号,用法提醒。 const { program } = require('commander');// 名称,形容,版本号,用法提醒。program.name('cli').description('这是一个神奇的脚手架').version('0.0.1').usage('<command> [options]');program.parse();执行命令:node main.js --help,内容更加丰盛了: 增加 createPage 命令 const { program } = require('commander');// 名称,形容,版本号,用法提醒。program.name('cli').description('这是一个神奇的脚手架').version('0.0.1').usage('<command> [options]');// createPage 命令program.command('createPage').description('生成一个页面') // 命令形容.argument('<name>', '文件名字') // <name> 表 name 为必填.action((name) => { // 输出该命令的动作,逻辑实现。 console.log(`新建了一个文件:${name}`);});program.parse();执行命令:node main.js createPage index.vue chalkchalk 是一个终端字符串丑化工具。装置:npm install chalk@4.1.2 chalk 最新版是 ES6 Module 的写法,不反对 require 应用,如果遇到谬误 Error [ERR_REQUIRE_ESM]: require() of ES Module /node_modules/chalk/source/index.js from /Desktop/test/main.js not supported.装置旧版本能够防止该问题。应用:chalk.blue 表字体蓝色,chalk.red 表字体红色,chalk.underline 表下划线,chalk.bgRed 表背景红色 ...

March 13, 2023 · 2 min · jiezi

关于脚手架:自主搭建5个精品脚手架玩转前端提效悬浮窗

download:自主搭建5个精品脚手架玩转前端提效悬浮窗一、Volatile,final, static变量volatile是一种同步的弱模式(只保障可见性,并不保障操作的原子性),当申明为volatile类型后,编辑器在运行时会监督这个变量,volatile变量不会缓存在寄存器或缓存在对其余处理器暗藏的中央,所以它总是返回最新的值。拜访volatile变量不会加锁,所以不会引起线程的阻塞。写入volatile变量就像退出同步块,读取volatile变量就像进入同步块。相对来说它的用途不是很大。个别用于确保它们所援用的对象状态的可见性,或者用于标识重要生命周期事件的产生。个别只有满足下列所有条件时才会应用: 写入变量时并不依赖变量的以后值,或者可能确保只有繁多的线程批改变量的值;变量不须要与其余的状态变量独特参加不变束缚;拜访变量时,没有其余的起因须要加锁;二、公布与逸出公布一个对象的意思是使它可能被以后范畴之外的代码所应用。用线程平安的办法实现这些工作时可能须要同步;如果公布了外部状态,就可能危及到封装性使程序难以维持稳固。一个对象在尚未筹备好时就将它公布,这种状况称为逸出。 最常见的公布对象的形式有以下几种:1、对象存储在static域,公布一个对象还会间接影响到存储在此对象中的其余对象。2、把公有对象域放在一个非公有办法中返回。3、最初一种就是外部类。 上面是一种很典型的this逸出: public class ThisEscape { public ThisEscape(EventSource source) { source.registerListener(new EventListener() { public void onEvent(Event e) { doSomething(e); } });}这个例子的非凡之处在于,EventListener会封装在一个新线程中,这样有可能导致 EventListener还未实现结构,ThisEscape就会被内部线程可见。在构造函数中创立线程没有谬误,但最好不要立刻启动它。如果想在构造函数中注册侦听或启动线程,能够通过一个公有的构造函数和一个专用的工厂办法来实现: public class SafeListener { private final EventListener listener;private SafeListener() { listener = new EventListener() { public void onEvent(Event e) { doSomething(e); } };}public static SafeListener newInstance(EventSource source) { SafeListener safe = new SafeListener(); source.registerListener(safe.listener); return safe;}} 三、不可变性线程间的同步可能产生数据间的不可预见性。不可变对象永远是线程平安的。如果对象的状态无奈批改,这些变量也就永远不会变。只有满足下列的条件,才是一个不可变对象。 它的状态不能在创立后被批改;所有域都是final类型并且它被正确创立(创立期间不会产生this援用的逸出)但并不意味着把所有域都申明为final就是不可变对象。并留神下“对象不可变”和“对象的援用是不可变的”之间并不等同。程序存储在不可变对象中的状态依然能够通过替换一个带有新状态的不可变对象的实例失去更新。 平安公布下面的一些技术都在强调不公布对象封装对象,如果想平安公布的话须要思考很多,如果公布一个不可变对象,即便没有应用同步,依然是线程平安的。前提是满足不可变性的条件。如果final域指向可变对象,那么拜访这些对象的状态时依然须要同步。 public class StuffIntoPublic { public Holder holder;public void initialize() { holder = new Holder(42);}}//这个例子可能导致“部分创建对象”,用上面的代码能够进行测试,如果所holder申明为final就能够解决这个问题 ...

October 10, 2022 · 2 min · jiezi

关于脚手架:inquirer命令行交互原理二手写readline实现

目录inquirer命令行交互原理?(一)readline的实现办法和原理inquirer命令行交互原理?(二)手写readline实现 背景上篇曾经具体的形容了readline源码的实现,当初就是来测验下学习的状况,手动来实现一个readline 代码(1)先监听输出流function stepRead(callback) { function onkeypress(s) { output.write(s); } const input = process.stdin; const output = process.stdout; let line = ''; emikeypressEvents(input); input.on('keypress', onkeypress);};function emikeypressEvents(stream) { function onData(chunk){ g.next(chunk.toString()) } const g = emitkeys(stream); g.next() stream.on('data',onData)};function *emitkeys(stream) { while(true){ let ch = yield; stream.emit('keyPress',ch); }}stepRead();(2)一一字母监听输出流,并返回后果知识点:input.setRawMode(true);input.resume(); // 从新开始,重启function stepRead(callback) { function onkeypress(s) { output.write(s); line += s; switch (s) { case '\r': input.pause(); callback(line) break; } } const input = process.stdin; const output = process.stdout; let line = ''; emitKeypressEvents(input); input.on('keypress', onkeypress); input.setRawMode(true); input.resume();};function emitKeypressEvents(stream) { function onData(chunk){ g.next(chunk.toString()) } const g = emitkeys(stream); g.next() stream.on('data',onData)};function* emitkeys(stream) { while(true){ let ch = yield; stream.emit('keypress',ch); }}stepRead(function(s){ console.log(s); console.log('answer=', s);});解说(1)先将输出流和输入流进行缓存,将输出流要填写的信息放在line变量中; ...

August 28, 2022 · 1 min · jiezi

关于脚手架:新生代小鲜肉之代码生成器

如果你能急躁看完这个对话, 兴许你会想动动手配置一个代码生成器, 这样你的撸码生存可能从此就会有所变动,变得愈发轻松。从一个脚手架说起丹尼尔: 最近要搞个代码生成器,可能疾速生成我的项目代码那种,蛋兄有什么举荐? 蛋学生: 过往始终应用 yeoman,快超 10k star 的开源我的项目。然而,明天要举荐给你的,并非 yeoman,而是一个新生代的小鲜肉 ncgen,它可能显得更加的平易近人。 丹尼尔: 我最最喜爱简略的了,这个咋用呢? 蛋学生: 老规矩,你说你的需要,我试着一一解答 首先,你须要一个我的项目模板丹尼尔: 我有一个我的项目模板(比方:vue3-ncgen-demo),我心愿新建的我的项目都来自于这个我的项目模板,这样我只需分心保护好这个我的项目模板即可。 蛋学生: OK,这就是我的项目脚手架的性能了。咱们来看下 ncgen 是如何解决的。 第一步 装置 ncgen $ npm i ncgen -g # yarn global add ncgen第二步 生成配置文件 ncgen-config.js,该配置文件形容了代码生成器的逻辑 $ ncgen genConf第三步 批改 ncgen-config.js 中的 main.tmplSource 为我的项目模板的地址。 export default { main: { tmplSource: "https://github.com/daniel-dx/vue3-ncgen-demo.git", },};运行一下试试: ncgen ncgen-config.js 简略复制还不行,小修小改是常态丹尼尔: 哎呦不错哦。不过目前生成的我的项目跟我的项目模板是截然不同的,但它总会有属于本人的跟我的项目模板不一些的信息,比方项目名称,作者姓名等。这些我可不心愿每次生成完我的项目还要手工批改哦。 蛋学生: OK,要求十分正当。因为这些信息是创立我的项目的人才能提供,所以咱们须要通过一些问题来收集这些信息,而后就能够依据这些信息对生成的我的项目作一些批改。咱们批改下 ncgen-config.js 中的 main.prompt 和 main.updateFiles 示例阐明: 对生成我的项目中的 package.json 文件进行字符串替换,规定如下: 将 vue3-ncgen-demo 字符串替换成用户录入的项目名称 将 Daniel.xiao 字符串替换成用户录入的作者名称export default { main: { prompt: [ { type: "input", name: "author", message: "What is the author's name", }, ], ... updateFiles: { "package.json": function (content, options) { const answers = this.$answers return api.replace(content, { "vue3-ncgen-demo": answers.projectNameObj.kebabCase, "Daniel.xiao": answers.author, }); }, }, }}; ...

May 10, 2021 · 3 min · jiezi

关于脚手架:EMP-梳理记录

本文章次要记录emp的应用过程,蕴含一下知识点: 脚手架搭建lerna 根本应用办法NPM包公布WebPack 知识点筹备工作装置lerna:npm install --global lerna克隆emp:git clone https://github.com/efoxTeam/emp.git装置依赖包:cd emp && lerna bootstrap参考npm模块管理器应用lerna治理大型前端我的项目

February 19, 2021 · 1 min · jiezi

关于脚手架:Yeoman脚手架搭建工具一

Generators是Yeoman生态系统的一部分,它们是通过yo命令为最终用户生成文件的插件。 组织你的generators设置为一个node模块generator实质上是一个node.js的模块 1.创立一个空文件夹用来写你本人的generator。这个文件夹必须命名为generator-name(name是你本人的generator名字)。这一点很重要,因为Yeoman依赖文件系统来查找可用的generator。 进入你的generator文件当前,创立一个package.json文件。这个文件是一个node module的manifest。你能够用npm init 这个命令初始化这个文件。 { "name": "generator-name",//必须蕴含generator "version": "0.1.0", "description": "", "files": [ "generators" ], "keywords": ["yeoman-generator"],//必须蕴含yeoman-generator "dependencies": { "yeoman-generator": "^1.0.0" }}必须放弃yeoman-generator的最新版本做为依赖,装置命令 npm install --save yeoman-generator文件构造树Yeoman的性能取决于如何构建目录树。每个Sub-generators都蕴含在其本人的文件夹中。 调用yo name时应用的默认生成器是app generator。它必须蕴含在app/目录中。 在输出 yo name:subcommand, 会调用Sub-generators ,Sub-generators存储在名为与子命令完全相同的文件夹中。 eg: ├───package.json└───generators/ ├───app/ │ └───index.js └───router/ └───index.js这个generator会暴露出 yo name 和 yo name:router命令 Yeoman容许两种不同的目录构造。它将在./和generators/中注册可用的generator。 之前的例子也能够依照上面的构造组织 ├───package.json├───app/│ └───index.js└───router/ └───index.js如果你用这种构造,保障你在package.json中的files中指定 { "files": [ "app", "router" ]}扩大generator一旦有了这个构造,就能够编写理论的generator了。 Yeoman提供了一个base generator,你能够通过继承它来取得大部分的根底行为 index.jsvar Generator = require('yeoman-generator');module.exports = class extends Generator {};重写构造函数module.exports = class extends Generator { // The name `constructor` is important here constructor(args, opts) { // Calling the super constructor is important so our generator is correctly set up super(args, opts); // Next, add your custom code this.option('babel'); // This method adds support for a `--babel` flag }};加上本人的函数每次调用生成器后,增加到原型中的每个办法都会运行,并且通常是按程序运行的。然而,正如咱们将在下一节中看到的,一些非凡的办法名将触发特定的运行程序。 ...

December 10, 2020 · 1 min · jiezi