Skip to main content

· 4 min read
CheverJohn

关于运动

前期: 无氧每天练一个部位,一个部位挑选4个动作,每个动作做5组,每组做12个。

有氧: 从5分钟开始递增,第一次5分钟,第二次10分钟

大基数如何运动

大基数前期无氧为主,有氧为辅 无氧45分钟到1小时较好 有氧5分钟开始,一次递增5分钟/次。增加至45分钟即可

从大肌肉群练起来!!!

健身前吃点香蕉!

减脂期间可以在训练前吃半根大的或一根小的,其他时间不建议食用。香蕉碳水20+g/100g了,等同于很多主食了,果糖对减肥没好处

怎么吃

关于燕麦

燕麦 选择纯燕麦,热水泡发后加入牛奶好吃一些,午餐可以配合炒菜。因为燕麦本身就是主食

西麦的纯燕麦,可以泡着热水吃,可以牛奶泡着吃,可以热水泡开后放牛奶吃。

关于牛肉

烤着吃 炖着吃 炒着吃 注意一下酱牛肉,酱牛肉热量较高,钠含量也高,减肥期间不要多吃

早餐

经过一个长夜,身体代谢把身体掏空了,早上适合碳水的摄入,要规律饮食,避免中午的暴饮暴食,三餐要均衡呀

早餐碳水尽可能多一些,因为一晚上的断食和一上午的消耗需要供能,配合牛奶鸡蛋。 早上减肥人群尽可能避开精米精面,不建议喝粥,粥在熬的时候会淀粉糊化作用。禁止吃灌汤包油饼等糖油混合物

黑咖啡

黑咖啡早上可以喝,但是当早餐没啥意义,喝黑咖啡可以是为了提神。早餐还是碳水比较好,毕竟身体(汽车)大早上出门需要能量(汽油)

饮食

我们需要更注重长胖关键点也就是碳水化合物的摄入量,还有就是结合热量,其他量你可以不会算,这俩必须得会。女生碳水每日摄入最低50-70克,男生最低60-90克,根据自己体重来取值最低线(比如250斤,你就可以取值90为最低线) ,最高线就是你多少斤就吃多少克碳水。碳水量≠食物量,要看每个食物100里含有的碳水量,然后通过计算得出,你需要吃多少食物

鸡胸脯肉

先在水里切大块煮15分钟,然后拿出来撕碎放入炒菜中,炒着吃

不能吃什么!

最好的辨别方式就是看配料表和营养成分表,排名越靠前的在食品中占比越大,比如有白砂糖、果葡糖浆、植脂末氢化植物油、氢化脂肪、精炼植物油、人造黄油、植物黄油、人造奶油、植物奶油、麦淇淋(马淇淋)、奶精、代可可脂等成分 我们就不可以食用了

碳水计算公式

碳水蛋白质计算公式

BMR

· 7 min read
CheverJohn

首先请“无关人等”去做自己喜欢的事情呢! 这并没有恶意哈,因为确实 讲真不爱好技术的人,接下来的一两个小时着实会很难熬 人与人之间的区别是相当大的,你不能奢求每个人都跟你兴趣相投(All in的那种) 这绝不可能,然后如果你硬是要进行一个强行融入,那结果肯定是相当不好的。 况且一遍听课一遍打王者,耗电呀兄弟。

我一向的观点就是,要找到自己喜欢做的事情,并为之疯狂。

对了,该如何界定你是否适合本次课堂,很简单

如果我现在让你去买一本400RMB的技术书籍和一个树莓派4B(价值五六百了),如果你没有太多犹豫,那么就适合继续看下去呢。反之你坚决不打算买,并且认为这是一种浪费,那我真心劝你,别在我这儿浪费时间了。

定义一波Geek

技术狂热爱好者。

甚至之前的Geek是一些不合群且不注重任何其他因素独忠于技术的这么一群人。

当然个人的理解就是:把技术当做自己爱好的这么一群人,而且也喜欢做出一些很有意思的事情的一群人。(当然我现在还不算是呢,只能是做到前半部分,后半部分还差一点呢)

那么我这一次的讲演就是围绕这一块

先开始要将学习了呢

说实话,会学习的人不需要别人教导这些, 他们会自己去寻找一切有用的讯息,并有自己的执行力去完成自己的目标。讲真,这一部分我主要还是讲我自个是如何开始学习的。

如何提问·How to ask questions?

这个很重要啊,有很多人, 刚开始有了学习的念头, 然后确实在学习的时候遇到了一些问题, 然后确实去问了大佬们, 然后确实由于提出了不恰当的问题, 然后确实直接就遭到了大佬的冷落, 这往往是可悲的。

因为做不到这一点的人,其实讲真话,情商不太行呢(当然我情商也差得很噻:( )

Dang! Dang! Dang!

这边直接来了一个教程,教教你该如何去提问。

How to ask questions

书中自有黄金屋

上一波我这次寒假的书单

寒假书单

大致有二三十本书。当然还有一些其他书没有拿出来。这是我觉得最基础的。保证能够打造你牢固基础的以及拓宽你眼界的书,

我看书主要是三部分,

一部分是拓宽自己的基础知识知识,比如说底层原理、《编译原理》这样的龙书,

另外一部分是扩充自己的思想,比如说像《黑客与画家》、《大教堂与集市》

最后一步是哲学类的书籍,因为有一些类似于马克思主义的方法论,可以让你对自己我有个很好的认知,并且进一步的有一个和更好的学习状态。这边推荐邓晓芒的入门版哲学书。

doc文档

官方文档

这边举几个例子

OpenResty

CPP source code

第三方讯息平台

就截至目前来讲

不推荐csdn

推荐Stack Overflow == github > GeeksForGeeks == Reddit == 知乎 == 极客时间 == YouTube > B站(暂时就想到这些呢)

逮住一个方向使劲学

年轻人,不要好高骛远哟

说实话,现在的诱惑太多了,有好多好多有意思的事情,总是时刻在诱惑你,唉。

但是千万要知道的是,切记一定要找好自己的专精领域(一门语言,精确到源码?一项工作,精确到像卖油翁一样“纯手熟尔”?)

多做

这边其实有很多项目,对学生的项目,比如我一直推给大家的,腾讯的犀牛开源计划、中科院的开源计划、谷歌的GSOC编程之夏、甚至于很多社区假期已经发布了寒假实习的通告。

不要顾忌太多,年轻人冲就完事了,而且还有money赚,(说实话,我真想知道你们是怎么想的?为啥不冲呢?害怕完成不了?还是说看不上搞技术的?额,如果是第二种的话,那能听到这里我有点佩服你)

多问

搭配着第二个标题,要问好问题!

讲一波开源叭

这也是我最近的工作

Apache开源理念

国内的思想哈,认为技术牛就是真的牛。

啧啧啧

这边就引出Apache的基础理念——Community over code

告诉你有可能不是这样的呢

敲第一行代码

如题

· 43 min read
CheverJohn

本篇文章 inspired by 以下平台

  1. Apache·"the Apache way"
  2. InfoQ-二叉树视频团队
  3. InfoQ-写作平台
  4. 微信公众号-ALC Beijing

从“The Apache Way”开始说起

正如经典的名言“一千个人有一千个哈姆雷特”,哪怕你去问AFS的member什么是“The Apache Way”,他们可能会给出千奇百怪的回答。(来自官方的吐槽最致命哟)

但同时官方也从许多资深开源开发者的观点中总结了一些东西出来(至少我是这么理解Apache的官方意思的)

WHAT MAKES THE APACHE WAY SO HARD TO DEFINE?

那么是什么东西阻止了我们来对Apache行事准则进行精确的定义呢?(复述一遍题目表示强调一下)

从Apache的一个表面情况可以发现,Apache的行事准则其实就是里边各个社区在开发过程中的缩影。要想理解好Apache的行事准则,那就得从理解Apache里边大大小小的社区开始。

Apache项目以及其社区是独特的、多样化的。主要聚焦的是项目的生命周期,并为之付出一系列的行动。这类行动包括从培养社区(不管是培养技术人员还是布道师一类的人员)、挖掘更优秀的代码以及项目构建意识。简单来说,Apache更关注项目,只要项目有一个很不错的发展,随他呢,尽管去做吧(前提不影响公序良俗哈)。

摘取关键字词:社区独特且多元化、聚焦项目、做一切有利于项目的事情、The Apache Way

那接下来我将就Apache的特点以及理念这两部分简单且系统地理解一下Apache

特点

人人平等

每个人都有机会参与项目,且获得的权限多少,全看你在项目中的贡献,可不就是人人平等的观念嘛。

社区化

应该是个人参与到ASF的项目中,而不是一个组织参与到。这其实进一步宣扬了公平开放的态度。

开放通信

所有的通信、决策均公开在开放网络上,采取邮件列表的形式,进行公开交流。

这其实有种约束的味道在里边,但其实辩证地来看,你也有更多的机会。如果你要为社区做贡献,假设你做了个错的决定,那么其他友好的开发者便可以在这上边对你进行一个battle,但要是你是对的呢,你可以在上边跟其他人进行一个激烈的讨论呢,这可是多么美好的一件事哟。当然如果你干了坏事,啧啧啧,好事不出门,坏事传千里了可能就hhhh。

邮件列表大致有以下的组

  • dev@(主要开发人员)
  • user@(用户们的讨论区)
  • commits@(源码更改了这边会有通知哦)
  • 偶然支持角色比如说市场营销@

!强烈申明,所有交谈必须公开呢!

共识决策(Consensus Decision)

均由志愿者团队进行监督决策,这边引用一下下面的内容。即接下来会讲到的“72小时懒人共识制”。

举一个例子哈。
如果我们有一个国内的开源项目要放入到Apache中进行孵化,那么会经过Apache mentor的投票环节。
Apache实行的是一票否决制。而这边投票的mentor全都是志愿者,受到Apache足够信任的志愿者们。

负责任的监督

ASF的治理模型是基于信任和委托监督的。基于一种约定通俗的原则。自治项目直接向董事会提供报告。Apache的committer通过进行peer 进行 code review ,采用强制性安全措施,确保许可合规性以及保护Apache的金字招牌不会被一些不正当的行为影响到。

理念

Community over Code

“社区高于代码”的这一句格言,相信被很多人熟知,在Apache社区中更是得到了淋漓尽致的体现。因为根据ASF的理念,健康的社区比良好的代码更重要。强大的社区总是可以纠正其代码的问题,而不健康的社区可能会努力以可持续的方式维护代码库,然后不一定得到一个很棒的结尾呢。

然后这一句话,我也可以这么来理解,举个通俗的例子哈。如果一串代码已经到了炉火纯青的地步,那么社区其实就起不到作用了(这里不经意间让我想起了Fabrice Bellard这位伟大的发过程序员,或许叫计算机科学家更确切呢)。Fabrice平生写的代码就极具完美性,ffmpeg好像就很少出现bug。但是Fabrice的项目一般都是那种超级基础性的项目,基本上属于写了之后就不再需要接下来的迭代开发了,这边就当我闲扯一番,么的事。不过也确实,想Fabrice的代码就压根不需要社区呢,可不就是相当于die了嘛社区。

那符合开源的项目呢,应该是那种需要随着时代的进步,逐渐发展的项目,比如咱APISIX,对应着kafka的出现,其实是需要进行可持续化的发展的。而且,在社区的帮助下,可能在许许多多有意思的想法的碰撞下出现更有意思的项目呢?这不就又离造福世界更近一步了嘛:P

团结就是力量~~~

好了,我想我暂时能领悟到的也就这些了,接下来我们开始看看一些有趣的关于开源的书籍知识。

行动:加入开源的具体准则

这边就拿之前标题"从’The Apache Way'开始说起"开始说起(套娃ing)

《大教堂与集市》

同行评审

同行评审是原文论述的重点,实际上,集市模式的核心价值就在于跨越组织边界的独立的同行评审验证设计和保证正确性。原文将其称为“Linus 定律”,即

如果有足够多的 beta 测试者和合作开发者,几乎所有问题都会很快显现,然后自然有人会把它解决。

不过针对这个定律有两点需要解释。

第一点

是它所强调的是独立的同行评审实施的简单性和有效性,而不是单纯的“人多力量大”。

举个例子

时至今日,传统的研发组织仍然把开发人员和测试人员区分成两个竖井,测试人员几乎只能完成黑盒测试。可想而知,缺乏分析的现象型 bug 报告往往需要耗费开发人员相当多的时间重新验证、复现和定位。如果让对源代码一无所知的测试人员为 bug 定级,则两类人员之间的冲突会更加尖锐。

......

原文引用《人月神话》[5]的 Brook 定律,提到随着开发人员数目的增长,项目复杂度和沟通成本按人数的平方增加,而工作成果只会呈线性增长。对于这个论点,原文作者是认同的。但是,开源项目所采用的沟通方式,区分成少部分核心开发人员与由 beta 测试者和潜在的贡献者组成的外围人员。外围开发者实际工作在分散而并行的子任务上,他们之间几乎不交流;代码修改和bug报告都会流向核心团队,只有在那个小的核心团队里才会有 Brooks 开销。

​ ——《大教堂与集市》

这边提到了对于开源项目贡献者的区分——部分核心开发人员与由beta测试者和潜在的贡献者组成的外围人员。这揭示了开源开发的精英领导制内核,也解释了 Linus 定律虽然常被简化成“只要眼睛多,bug 容易捉”,但是却不是简单的“人多力量大”。

第二点

是开源软件当中出现 bug 是正常的。这一点过于天经地义以至于当我发现我需要强调它的时候有些震惊。前几天的 Log4Shell 漏洞,导致部分声音认为开源项目的使用是有风险的。但其实想说的是,这是应该完全有可能存在的情况呀,毕竟开源项目出现bug是很正常的事情。但是尽管如此,开发者还是会尽自己一切可能去保护开源的声誉的。

此外,开源软件一般都附有免责声明,也即这个软件的源代码就这样(AS IS)给你了,没有任何保证(WITHOUT WARRANTIES)。

集市模式

什么是集市模式? 看过这篇文章,大概知道这个概念,这是来自于一本关于开源社区的书《大教堂与集市》

其中很多原则和技巧不是开源特有的,并通过敏捷等理念渗透到商业公司的软件开发当中。例如,“好的软件作品,往往源自开发者的个人需要”,“早发布,常发布,倾听用户的反馈”,以及“想出好主意是好事,从你的用户那里发现好主意也是好事”等等。

其中最重要的一点是关于发布的。开发者在需求列表不能调整和最后期限不能拖延的双重要求下,会完全顾不上质量,整个工作很可能会变成一团乱麻。Linux 通过发布两种不同类型的版本,各自宽松其中一个要求来保证软件质量和进度的协调。

一种办法是保持最后期限不变而让需求列表灵活一些,允许某些到最后期限时仍未完成的需求被舍弃,这基本上就是“稳定版”核心采取的策略。Alan Cox(稳定版核心的维护人)以相当规律的时间间隔将核心发布,但并不保证某个特定bug何时被修复,也不保证实验版中的某个特性何时会搬到稳定版中。

另一个办法是设定好想要的需求列表,并在其完成时发布,这基本上是“实验版”核心的策略。De Marco 和 Lister 引用研究结果,指出这个进度策略即是“好了告诉我”,这不仅能够保证最高质量,而且就平均而言,与“保守”或“激进”的进度安排相比,它的交付时间更短。

​ ——《 大教堂与集市》

概括地说,开源的方式给予开发者足够的自由,以吸引高水平的黑客自发地创造价值。这种超越了对安全需要乃至生理需要的追求的模式,激发的是参与者对社会需要和自我实现需要的热忱。

文章中很赞同的地方

在这里,没有预设的团队和资源,不需要在办公室环境下吞并其他团队的资源或者对其他团队的进攻做出防守。开源开发者是志愿者,是因为兴趣和能力自主选择的,他们会把自己的资源带到工作中,而不需要关心团队之间的领土争端和倾轧。

在这里,参与者凭借其创造的价值赢得权威。也就是说,最有才华的人能够对项目的发展做出最合适的决定。这不同于雇佣关系下被强制调配的人与项目之间的关系,而是对于特定的人,自由选择适合自己的项目,对于特定的项目,自然筛选出最合适的人。

原文还提到一种观点,即传统开发管理能保证艰苦和乏味的工作总能落实。我想这点毫无疑问是错误的。Linux 和 Kubernetes 的文档充足到令人难以置信,反过来只为了领工资才上班的人往往消极对抗撰写文档和测试或调试问题等工作。

开源共同体的目的是制造高质量的软件,在这个共同目标的引领下,不同方面的人才聚拢起来发挥自己的价值,反而是能够找到对传统开发管理认为艰苦和乏味的工作甘之如饴的人才。对于项目维护者来说,认识到这些所谓“无聊”部分的价值,协同参与者完成它们,是项目能够脱颖而出的必要条件。经过二十年来的经验积累,这逐渐成为最有才华的黑客当中的共识。

最后,对于想要实行集市模式的人,这里转述原文提到的“集市模式的必要条件”。

集市从成立伊始,就需要一个可以运行和测试的东西。当开始建设开源共同体的时候,你需要拿出一个像样的承诺。程序此时并不需要特别好,它可以简陋、有错、不完整,文档可以少得可怜。但它至少要做到能运行,且让潜在的合作开发者相信,这个软件在可预见的未来,能演变成一个非常棒的东西。

项目领导人需要能识别出别人的优秀创意,掌握一定水准的设计和编码能力,并且必须具备很好的人际交往和沟通能力。最后一点应该是显而易见的,为了建立一个开源开发共同体,你需要吸引人们,让他们对你做的事感兴趣,让他们乐于看到自己的贡献。一些技巧可能有助于实现这些,但远远不是全部,你的人格特征也很重要。

原文确实写得太好了,给个传送门,一定要去读读看呢!然后我再把这一部分完全写完了,消化为自己的内力。

原文在此

同,这篇极其优秀的文章列出在这里

优质开源公众号ACL

Apache community local(北京&深圳) 这俩公众号发的文章都还挺不错的。 有一说一,这个公众号里介绍的全都是国内参与开源,或者更准确来说,是Apache项目中来自中国的开发者们的经历。 https://mp.weixin.qq.com/s/u9zZq5kU4uYiXCJXFkmRyg 可以通过这个链接里边的专题介绍链接去进一步了解。

瞎捉摸自个的

中的开放通信,以下截图是我grpc和tuna两个我有了解的开源社区的mail list。

mail list图示

grpc

tuna社区

我们可以像这样在社区中混脸熟ing :)

然后就是正常的PR咯,目前暂时就这些叭。

最新的好消息!!!祝贺SeaTunnel 成功进入 Apache 孵化器

当然这好消息跟咱没太大关系,帮其稍稍免费宣传叭现在,以后等咱火了,再去要宣传费啊哈哈哈哈哈。

SeaTunnel加入Apache孵化器

人物访谈节目

https://www.infoq.cn/album/10

这边很多都是开源人物的访谈视频,需要回顾参考视频可能。

Apache顶级项目Core Committer的养成日志——伍翀

个人简介

身份&头衔

Apache Flink Committer 阿里巴巴高级开发工程师

任务经历&简介

北京理工大学硕士毕业,2015年加入阿里巴巴,参与阿里巴巴实时计算引擎JStorm的开发与设计。2016年开始从事阿里新一代实时计算引擎Flink SQL的开发与优化,并活跃于Flink社区,于2017年2月成为Apache Flink Committer, 是国内早期Flink Committer之一。目前主要专注于分布式处理和实时计算,热爱开源,热爱分享。

开源经历

大学的课程

最早接触开源是在大学里的一门课“Open source”

第一次commit

提交的第一个patch:打印的日志里某一个单词出错了。

第一次提交很顺利,中间一年提交了五六十次代码,最大的一个有五六千行。

对开源的理解

  • 成为committer,是承认了你的贡献,承认了你的能力。

  • 当你的想法和社区有出入的时候,需要你去说服社区,这是最困难的一件事情,但克服了就会很有成就感。

  • “把写代码做开源当做一种人生的热爱“

  • 开源更多的是一种责任。社区对你的认可,你需要能够有一种责任感,去帮助社区发展。

  • 几年前,国内不看好开源,最近几年好很多。Apache现在国内开源的项目已经数不过来了一只手。

  • 在开源里提交代码,就是在跟各路大神切磋技术,在切磋的时候自己的内力也得到了一定的提升。

内容来源

2020/03/18

https://www.infoq.cn/video/siugcqRy7sKJtVLwRu8F?utm_source=album_info&utm_medium=video

老刘与他的开源联盟(经历)

个人简介

老刘并非典型的黑客。1999 年,老刘初次接触开源,当时的他已经是一位 Oracle 的高管。连接他与开源之间的第一道桥梁叫做 TurboLinux,是当时“全球最领先的 Linux 发行版“之一,在 IT 界的火爆程度恐怕不亚于今天的区块链。 然而到了今天,知道的人可能不太多了。百花齐放的 Linux 发行版们从未迎来自己最好的时代,就早早被扫入了历史的角落。

开源联盟

创办理由

开源讲的是社区文化、氛围,

为什么中国没有想Apache,Gnome一样顶级的基金会呢?

创办过程

2014年创立了开源社(CSDN、优麒麟)

16年走到了一个时间点,在17年初改制变成了个人会员制。

创办感想

2000到2018年,十八年的职业生涯里,没有脱离开源的领域。

对个人意义,在跟开源接触以来,对个人的三观影响很大,“Community over code”。需要强调社区的氛围呢。你贡献越多,你收获越多,你成长越多。

对Apache开源中Consensus的理解

consensus,共识。

Apache尽量不投票,投票就一定有赢家和输家,不投票就意味着不反对。投票加一就意味着你赞成并愿意帮助他 。

一票否决。减一就是我不赞成,如果我不赞成的话,那我应当提出相应的理由,以及可替代方案。不是为了反对而反对。

老刘的所得(其实跟上面的创办感想应该是一致的)

一个代码如果完美的话,那这个社区就死掉了,因为烂烂的代码如果有很多人愿意修改,那项目就好起来了。与国内技术唯尊正好相反。

“虽然我已经很牛了,但我需要别人来帮我”

Don't be a jerk。社区大于代码。

能帮助别人才能成为英雄!

内容来源

2020/03/17

https://www.infoq.cn/video/RVDarvYYczMLw5FwNcds?utm_source=album_info&utm_medium=video

开源社理事——庄表伟的个人杂想

并不认为开源是理想是手段,

好玩就够了。其实我也觉得开源很好玩。

86、87年代码都是开源的。

两个很有意思的事情

1. 报纸上会有趣味小程序

学生计算机报,就会有趣味小程序,拿回家

周琦(Python大妈)

2. Opensource概念——这一点可以去看周琦的文章。

先去社区混熟、混脸面。交朋友

Apache的理念,Community over code,社区比代码更重要。

中国的开源社区最大的问题缺乏基金会

好像有政治壁垒,现在一般都把社区先搞起来。

16年到17年发现企业参与开源,很多时候是非常难以持久的比如git咖啡被收购、微软开放技术被微软收回去了,整个公司都没有了。

剩下的就是必须要进行开源的人。是非常有兴趣做开源的人。虽然我进了不同的公司,但我个人一直有这个兴趣在这里。

进行大改组

是把所有的企业请出去,所有的顾问委员会在企业里,所有的开源社成员全是个人成员。

问题

1. 你自己的和全世界的

有些人喜欢标榜国界

如果把一些东西标榜你自己的,那东西不会有更多的发展。开源理论上应该是没有国界的。

所谓的标榜误解了技术发展的本质,所谓的你自己的,不是在提升你自己的荣誉感,而是在限制它的发展的潜力。

2. 声音太多

对年轻人的建议

现在的软件编程领域太大了,需要一个判断,进入哪一个领域,然后有一个稳定的节奏。

有一个自我认知和方向性的话,无论是哪个方向都很不错。d

但有趣的事情太多了,很容易就会忽悠到其他事情去了。

Boring is great.

枯燥的一种工作状态,其实是一种很好的事情。

内容来源

2020/03/15

https://www.infoq.cn/video/8XN2zyhSCJtr7yNucsWQ?utm_source=album_info&utm_medium=video

褚霸(这个应该就算是我个人的学习啦

不要被其他人的标签束缚,你不能阻碍其他人的标签,但你可以决定自己要做的事情。

https://www.infoq.cn/video/pX6OqyEuu0HlkBb1XQzp

赵鹏王旭de开源理想

人物简介

赵鹏(Gnep):音速神童创始人

王旭:音速神童创始人

经历

赵鹏:上学的时候搞所谓的cloud

王旭:2000前后玩linux

想法

有些人娱乐方式不一样,我们玩电脑就是娱乐。

开源使得不同公司甚至没有公司的人做一个项目。是社会发展趋势,会火起来的。

开源经历

王旭:移动最早开始做云计算是在google的几篇论文下,2009开始做大数据相关,Hadoop相关的东西。然后进入到aws弹性计算。最早用的开源项目OpenNebula管理。后边引进了OpenStack。

对未来的技术设想

总结一下,将来的基础设施底层,不需要虚拟化指令集,不需要虚拟化,可以在没有虚拟化的情况下,做出类似于虚拟机的隔离性。性能接近物理机,隔离性又达到云的标准。

性能越高越好,隔离性越强越好,开销越低越好——标准。

坚持软件研发的信念是什么

喜欢做软件,赚到快乐,做点不一样的,做点有趣的事情。

内容来源

2020/03/28

https://www.infoq.cn/video/pX6OqyEuu0HlkBb1XQzp

OpenStack基金会前董事程辉——开源的四个阶段

2020年3月27日

第一个阶段:

纯粹的开源用户消费者转变到开发者

2011年发生在OpenStack这个项目上。

第二个阶段:

带团队从开源的开发者变成创业者

第三个阶段:

在前三年一个技术工程师纯粹理想主义者的创业的前三年。

第四个阶段

创业第四年到第五年,更多的精力在前端、销售、客户。

你眼中的OpenStack是怎样的

OpenStack11年开始,基本可用,写技术文章,被互联网和传统IT很多新型部门感兴趣。

云计算这东西一直不知道长啥样,从06开始,直到11年OpenStack出现,国内才知道到底是什么样子的。

so创始人从亚马逊的S3服务发布开始知道,知道公有云的云计算长啥样,当时创始人对亚马逊的内部各种技术非常憧憬。

so创始人加入了OpenStack,在OpenStak下终于可以做自己的云计算了,做像AWS类似的服务了。

亚马逊,高可用、云计算、

走上创业

开源软件和互联网的工具用到传统企业,这一个问题,刚开始创始人想不到具体怎么做,于是走上了创业的路。

当时认为只要我的产品有技术先进性、只要我公开出去,市场就会买单的,相信工程师能够改变这个世界。并没有意识到企业To B这个领域可能面临的艰难险阻。

15年下半年的时候,技术负责人带着一个存储研发的工程师成立一家公司,专门做存储一块的工作,然后拿到国内投资。这个对创始人打击很大。

12到15年,市场观念的转变期,到15年之后发现客户能够接受开源啦。

创业的目标

并不认为上市就是终点,真正引领一个行业的变迁,真正能够把企业级开源软件这个行当,做出一个可持续发展的模式,对这个生态里的客户厂商包括其他的参与者,有利。

如何看待开源代码的传播

认为非常重要对国内的发展。

从目前来看,开始有一些互联网公司开始成为开源代码主宰。开始引导行业发展。这是一个必然的趋势。

一句话总结

感激时代,感激影响到自己的人。

内容来源

2020/03/27

https://www.infoq.cn/video/ixxhRXLUYRgdrCk6Wih2?utm_source=album_info&utm_medium=video

半数以上国产手游曾使用过他开源的引擎:Cocos和王哲

个人简介

王哲/ Cocos引擎创始人、雅基软件CEO

小学四年级,93年学logo语言,小海龟作图

10年接触Cocos

三四月份开始评估,七月份开始动手,十一月份发布第一个版本,当时在联通沃phone操作系统的团队,当时和现在的合伙人林顺(负责底层驱动硬件),王负责上面的多媒体和娱乐。

一点点焊代码。

应该有一个跨平台的游戏引擎

把IOS开发完后能编译一个安卓版的,然后做着做着发现价值竟比沃phone还高。

看了好多书,Cocos,Lua。

开源商业化经历

由于地基没打牢,15年遇上了门槛,对技术太乐观,15年比较惨,没有经费做研究,而且要投入商业,就惨咯15年

不过确实,当时走到哪里都很受欢迎,资本市场不认可你,没钱就招不到牛人。

商业化与开源多多少少是有矛盾的。

可以靠Redhat的技术支持技术顾问一类的方式谋生。

国内把软件一部分包起来,卖license。这就很不行。

王哲设计的Cocos为三层,最底下一层仍然是Cocos2d-x,是开源的framework,整个开发者能完全掌握。

第二层就是在这个基础上做了一层编辑器,免费但是不开源,编辑器很多是给美术策划用的,

第三层是收费服务,编辑器实际上也算是ToBe的流量入口。平台厂商需要你的引擎支持他的平臺,嵌入它的某种服务的SDK。这一块收费。

认为开源成功的要素

在正确的技术革新做正确的事情。

技术更新是大机会。

给其他引擎挖坑

刚开始想到Cocos会有商业的一天。

所以刚开始就开源了。

所以Egret和laya上来也必须要开源

Unreal也基本上等于开源了。

Unity也开放了越来越多的代码。

Cocos引擎推动了整个游戏引擎的开源进程。

内容来源

2020/03/25

https://www.infoq.cn/video/X3fhujZr6Lr2MG1FoJCq?utm_source=album_info&utm_medium=video

Apache mentor之路——姜宁

个人经历

2017年1月到华为做开源相关的项目,去做华为的微服务框架——ServiceComb。

Comb蜂巢,服务拼在一起就像蜂巢一样。

刚开始比较轻松的成了一个初始的committer。

但是影响最大的是在08年参与到一个叫ApacheCamel的项目中时,不断做贡献的同时,别人觉得你是一个合格的或者有潜质的参与者,于是被vote成committer。意义相当大!会有人关注到你哦!

突然有一天收到一封信,邀请你成为Apache member,这意味着你可以mentor一个项目。(ps,我也想体验这种快乐呢)

Apache基金会一个重要的一点:For the public good

从人类的角度,为了公众的利益去做事情,在这个角度,公司的利益就渺小了。

作为Maintainer的话,看项目会有很多人给你做贡献,一般来说会提一些PR,然后作为一个非常了解项目的人来说,可以进行一个帮助性的指导,也可以理解为培养新人?培养apache开源文化?!

对于开源项目,大家集思广益,去攻克问题,实现改变世界。

分享以及协作

开源很大程度上基于分享以及协作。

不能一味索取。其实分享的时候,你在给予社会会收获更多**很大感悟!!!留意

Apache不会被商业公司控制。草根,这也就是它能够不断发展的原因。for the user,公信力提高,也能够让不同的商业公司站在一个角度去解决问题。

从全人类的角度,很多问题都很容易解决。迎刃而解。

内容来源

2020/03/24

https://www.infoq.cn/video/5sSYPKOl11EC3XiGJW5s?utm_source=album_info&utm_medium=video

Apache邮箱开始的顶级项目创始人——Kylin意味着我的一切

我叫韩卿,更多被叫做Luke,职位是Kyligence的联合创始人和CEO。同时更多人知道是因为也兼任着Apache麒麟的创始人和项目管理委员会的主席(chair)

14年10月份开源的,刚开始收到质疑(西方人),也很少有华人站出来说话,只能不断证明。

Apache Kylin代表了亚洲国家尤其是中国在开源界的参与和贡献。

可以用一句话来描述,中国的开源已经从国内社区进化到国际社区。

三个阶段的转变

  1. 只会白嫖,不贡献
  2. 不仅仅会用,还会贡献
  3. 不仅仅参与进去,还能贡献出去

15年毕业成为Apache顶级项目。中国第一个

团队凝聚力

一个团队在的话,信心就来咯。坚持一帮人能克服技术困难,搞定问题。如果一个人,很可能就放弃了。

麒麟对自己意味着什么

意味着一切,

一方面,通过开源醒目影响到全世界

二,探索的开源模式去做商业化的模式,基于开源项目的商业化的探索。

巨头的开源项目

有创业公司在后边支撑的开源项目更可能成功。

意义影响

大家都在用,靠技术影响了一波人

沮丧的时候

在ebay的时候,项目得到重组,自己做的事情无法得到更好的优先级。公司变故会令人沮丧。

找到几个场景,解决业务痛点。

Kylin是否成功

远远达不到成功,只能说到了一个很好的出发点。over

内容来源

2020/03/22

https://www.infoq.cn/video/6OCu2YwmK2oXXK79805j?utm_source=album_info&utm_medium=video

Dubbo的故事——梁飞

个人简介

梁飞 / 淘宝技术部 资深技术专家

开源经历

当时想写个模板引擎,写个开源软件发上去。

Dubbo

09年开始做

09年底有用户了

10年初发现架构不堪重负,于是重新Dubbo2.0

10年底,当时公司觉得要做开源事情,于是拿Dubbo开始。当时在github上放了源码,只做了文档网站。

文档网站:code.alibabatech.org

然后吉利、京东就开始请教。

12年阿里开始One Company战略,打算将HSF和Dubbo合起来。合了以后对集团的利益会更大。

最终决定将Dubbo合进HSF,两边的设计理念整合在一起,就特别好。

去年开始以公司层面推动事情,捐献给了Apache。整个工作北纬操刀。

感觉

开源的精神就是能够让智慧共同成长。开源可以加速过程。

大家都能探寻代码背后的东西。都提高后去传播理想的东西。

感觉Dubbo演化太慢了

开源社区要更新下去,跟上时代潮流,需要最开始的作者关注开原作品的生命力,这个是作者比较烦恼的事情。

因为大家的需求变多了,但是也需要开发者进行一个版本更新,才能够得到更进一步的生命力。

(个人感受,其实就是没时间继续搞啦,如果社区里有人能够提供代码的话,那岂不是更棒?)

内容来源

2020/03/21

https://www.infoq.cn/video/sS9GQdmhm2MKGls169GR?utm_source=album_info&utm_medium=video

写完的时候发现姜宁大佬的一篇文章,很重要哦

https://willemjiang.github.io/opensource/2018/10/21/asf-introduction.html#%E7%A4%BE%E5%8C%BA%E5%A4%A7%E4%BA%8E%E4%BB%A3%E7%A0%81-community-over-code

突然感觉自己白瞎了,唉。姜宁大佬很权威啊。

有用的文章汇总

《腾讯的开源之道:基于Apache之道的开源实践与探索》

· 2 min read
CheverJohn

小知识点(未进行总结)

  1. 新安装的debian系统,root用户无法远程登录。

网络配置方面

网络配置一般是通过修改

/etc/network

路径的

interfaces文件的路径

interfaces文件,进行对网络的进一步配置的。

interfaces文件内容

配置完成后,要进行更新,更新命令如下

sudo ifdown wlan0 && sudo ifup wlan0

https://askubuntu.com/questions/333063/restart-network-interface-after-editing-etc-network-interfaces

可以查看上面链接进一步了解。

查看系统版本

root@DESKTOP-8VUVO1M:~# lsb_release -d
Description: Debian GNU/Linux 11 (bullseye)
root@DESKTOP-8VUVO1M:~# lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description: Debian GNU/Linux 11 (bullseye)
Release: 11
Codename: bullseye
root@DESKTOP-8VUVO1M:~# cat /etc/issue
Debian GNU/Linux 11 \n \l

root@DESKTOP-8VUVO1M:~# cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 11 (bullseye)"
NAME="Debian GNU/Linux"
VERSION_ID="11"
VERSION="11 (bullseye)"
VERSION_CODENAME=bullseye
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"

以上大概就是熟知的几种方法咯,写个blog记录一下。

终于还是暂时放弃了Raspberry Pi4B

先暂时用wsl叭

wsl-debian

· 4 min read
CheverJohn

入门

三大特性

OpenResty的发展

基于成熟的开源组件——Nginx和LuaJIT。OpenResty诞生于2007年,第一个版本用的是Perl,原因是这跟作者章亦春的技术偏好有很大关系。

详尽的文档和测试用例

OpenResty的文档非常详细,作者把每一个需要注意的点都写在了文档中。

OpenResty还自带了一个命令行工具restydoc,专门用来帮助你通过shell查看文档,避免编码过程被打断。

同步非阻塞

什么是同步非阻塞。

阻塞:特质阻塞操作系统的线程。

动态

我理解为热部署呢,动态加载配置文件,就很棒!跟Nginx相比棒多了!

主要原因是OpenResty是由脚本语言Lua来控制逻辑的,动态是Lua的特性。

列出OpenResty的8重点,才能学好OpenRest

  • 同步非阻塞的编程模式;
  • 不同阶段的作用;
  • LuaJIT和Lua的不同之处;
  • OpenResty API和周边库;
  • 协程和cosocket;
  • 单元测试框架和性能测试工具;
  • 火焰图和周边工具链;
  • 性能优化。

test for github.

写一个helloworld

首先应该配置好环境,我倒是没有想到的是,居然好像不支持windows(emmmmm,当然是我扫了一眼得出的结论啦,不当真不当真)。

这边我看《极客时间》温铭老师提出了两个值得思考的问题 问题

  • 为什么不推荐源码编译安装呢?

    • 在我们日常操作中,其实就有这么一种操作,比如nginx,我们就自行编译打包运行,甚至也会使用一些额外的小命令-g 啦之类的,做一些很细致化的操作。
    • official 回答:老师给出的建议是,不是很建议是因为我们的日常目标是在生产环境中快速部署,所以理应使用更稳妥的方法。
    • 我的回答:淦,这不是明摆着的嘛,具体问题具体分析,亘古不变的道理,如果是玩票,随便你咋安装(事实上我刚开始肯定自己编译安装:) ,想好好了解这个东西呢!)
  • 为什么官方不接受第三方维护的包呢?

    • 这个问题我要小小解释一下,说不定我亲爱的读者们连题目都没有读得懂呢?第三方维护的包,一般是指为了加快源库的下载安装速度(网速为啥会变慢,就不由我多说了哈),国内会有一些公益性质的组织自行维护一些常见的包库,通过定时从国外的官方源库中下载下来,发布在国内的服务器上,这样国内用户自然而然就可以有很快的下载速度啦。此处可以举例清华tuna的清华源,就是这么个道理。

      official回答:为了避免第三方和官方之间的冲突,导致后期的项目

· 7 min read
CheverJohn

今天是版本第一次上线的日子,值得庆祝!然后我想就我第一次上线做一下记录工作。

项目简介

本项目就是个博客系统,主要功能就是每天记录下我的个人博客、技术心得。其中加入了一个原生的评论功能、侧边栏系统、热评系统、基本的博客系统。
利用的是拿手的Django(3.2.3)框架,前端是用了Django模板引擎,后边会改进成vue的框架。

项目部署

使用的是一台阿里云的轻量应用服务器。 基本部署思路是: 本地

  • 1.本地将代码上传到github仓库中去。

  • 2.本地将项目进行打包,使用python setup.py 命令,本来是准备上线到私有pypiserver的,但是后来还是直接把打包好的项目(mr8god_blog_website-0.1-py3-none-any.whl)通过ftp工具(mobaxterm)上传到了服务器。在服务器中使用pip install mr8god_blog_website-0.1-py3-none-any.whl命令将其安装,对了对了,前提是激活了虚拟环境哦。 服务器端

    • 2.1.使用root账户部署代码不够安全,所以创建了一个blog用户,将用户加入到超级用户组,然后开始部署项目。
    • 2.2.因为centos7系统自带的sqlite版本低于django所要求的最低版本,所以首先来更新sqlite3的版本。
    • 2.3.安装python3,这边选择python3.6,安装方法就不多介绍了,这个不难。
  • 3.使用blog账号,在/home/blog中创建文件夹blogsrc/website/website/settings/base.py(我相信这样进行设置,大家应该都能明白是什么意思了)。很清楚的就可以看到我的文件夹是怎么样子的。在/blogsrc这个文件夹里git clone 云端github仓库中的代码。

  • 4.部署代码的时候,需要在settings文件中修改ALLOWED_HOSTS值,可以修改为ALLOWED_HOSTS=['127.0.0.1','localhost','.mr8god.cn','101.132.184.191']指定了 ALLOWED_HOSTS 的值后,django 将只允许通过指定的域名访问我们的应用,比如这里只允许通过 127.0.0.1,localhost 以及 zmrenwu.com 和其任意子域名(域名前加一个点表示允许访问该域名下的子域名)访问(即 HTTP 报文头部中 Host 的值必须是以上指定的域名,通常你在浏览器输入域名访问网站时,Host 的值就会被设置为网站的域名),这样可以避免 HTTP Host 头攻击。

  • 5.还需要做的一件事是collectstatic,顾名思义,就是收集静态文件,这个需要打开设置文件中的STATIC_ROOT=os.path.join(BASE_DIR,'static') 意思就是自动生成静态文件在BASE_DIR下会有一个static的文件夹,里边全都是静态文件。 注意!这个文件夹不会被上传到github上去,这就意味着,你在服务器中还需要输入manage.py collectstatic这个命令。 对了,你还得在nginx服务器配置中配置好这个static文件夹。

  • 6.因为数据库文件没有带下来(没有上传到github上去)所以,还是得运行makemigration和migrate,还有createsuperuser。这个时候,可以通过manage.py runserver 进行一个测试开发服务器是否能正常启动。

  • 7.使用Gunicorn,在生产环境中,使用流行的Gunicorn来其启动可以用于线上环境的服务器。当然这里边要涉及一个Gunicorn的安装,安装很简单,以虚拟环境身份进行一个安装即可,同样,setup也是以虚拟环境进行安装。 gunicorn website.wsgi -w 2 -k gthread -b 0.0.0.0:8000 先进行一个这么的启动,待会再和nginx一起进行supervisor的后台管理哈。

  • 8.安装配置Nginx 以最简单的方法安装好nginx, nginx自己的配置文件在/etc/nginx/nginx.conf 配置文件中有这么一句话,include /etc/nginx/default.d/*.conf 意思就是在/etc/nginx/conf.d文件夹中只要是以.conf结尾的文件,都会识破并进行一个解析。 所以我们就得好好配置/etc/nginx/conf.d文件夹下的文件,比如说我们这个项目,我在里边的配置文件是hellomyblog.conf,该文件里有两个参数我进行了配置,server_name和location /static{ alias xxxx},前者决定了什么样的域名可以访问本项目,后者决定了nginx进行拦截解析的static文件位置。

  • 9.使用Supervisor进行管理进程,重点 现在Gunicorn和我们手工启动的,如果我们推出shell,服务器就关闭了,博客就无法访问了,就算在后台启动Gunicorn,万一哪天服务器崩溃重启了又得重新登录服务器去进行一个Gunicorn的启动,这就很不舒服了。为此,使用Supervisor来管理Gunicorn进程。这样当服务器重新启动或者Gunicorn进程意外崩溃后,Supervisor会帮我们自动重启Gunicorn。 首先还是使用我们的虚拟环境安装一个Supervisor。关于这个软件的配置文件,据我的目前理解就是,当我们运行完pip install supervisor之后,在/etc文件夹里会有supervisord.d文件夹和supervisord.conf。前者里边包含了supervisor需要启动的应用的配置文件,后者是supervisor本身的配置文件。 这边拿我写的一个pypiserver的配置文件做示范: [program:pypi-server] directory=/home/pypiserver/ command=/home/pypiserver/.venv/bin/pypi-server -p 18080 -P /home/pypiserver/.htaccess /home/pypiserver/packages autostart=true autorestart=true redirect_stderr=true 里边有我的命令(command)实际上也就这个命令需要进行一个配置。

    这边还需要配置的就是gunicorn了
    首先从github git clone本项目下来。
    2.创建虚拟环境,

    gunicorn website.wsgi -w 2 -k gthread -b 0.0.0.0:8000

· 10 min read
CheverJohn

本博文受BiliBili网站up主CodeSheep的视频《项目下载、运行、配置、构建、打包、部署:全步骤实战演示。前后端分离式项目实战部署(含nginx、tomcat部署配置)视频教程》的影响而完成的。

这个是视频的地址:知识野生技术协会

平台简介

这是一个基于SpringBoot,Spring Security,JWT,Vue & Element 的前后端分离权限管理系统

一直想做一款后台管理系统,看了很多优秀的开源项目但是发现没有合适的。于是利用空闲休息时间开始自己写了一套后台系统。如此有了若依。她可以用于所有的Web应用程序,如网站管理后台,网站会员中心,CMS,CRM,OA。所有前端后台代码封装过后十分精简易上手,出错概率低。同时支持移动客户端访问。系统会陆续更新一些实用功能。

若依是给还没有出生女儿取的名字(寓意:你若不离不弃,我必生死相依)

成功搭建平台的截图

若依登录页面

ruoyi-1

ruoyi-2

ruoyi-3

![ruoyi-4](D:\blog's new house\blog\source\我博客所有的图片文件备份\网站开发\若依前后端分离项目的小小试探\ruoyi-4.jpg)

ruoyi-5

ruoyi-6

开始搭建

虚拟机上先安装Centos

简介

本次项目是使用前后端开发的思想开发的,所以我们也以前后端的思想部署项目。我们将准备三个Centos服务器用于搭建,一个服务器作为运行前端项目的服务器,另外两个服务器制作成一个集群,存放后端项目。

若依服务器部署图示

开始制作虚拟机

我使用的配置如下 CentOS-7-x86_64-DVD-2003 VMwareWorkstation15

遇到的第一个问题:Centos 7的镜像下载

以下是解决方法

官网下载链接:http://isoredirect.centos.org/centos/7/isos/x86_64/

step1: 进入下载页,选择阿里云站点进行下载

Actual Country 国内资源 Nearby Countries 周边国家资源

阿里云站点:http://mirrors.aliyun.com/centos/7/isos/x86_64/

每个链接都包括了镜像文件的地址、类型及版本号等信息

选择当前国家资源区站点下载,获取资源速度比较快

step2: 进入阿里云站点,选择 CentOS-7-x86_64-DVD-1804.iso下载

centos7各类镜像

各个版本的ISO镜像文件说明:

CentOS-7-x86_64-DVD-1708.iso 标准安装版(推荐)

CentOS-7-x86_64-Everything-1708.iso 完整版,集成所有软件(以用来补充系统的软件或者填充本地镜像)

CentOS-7-x86_64-LiveGNOME-1708.iso GNOME桌面版

CentOS-7-x86_64-LiveKDE-1708.iso KDE桌面版

CentOS-7-x86_64-Minimal-1708.iso 精简版,自带的软件最少

CentOS-7-x86_64-NetInstall-1708.iso 网络安装版(从网络安装或者救援系统)

遇到的第二个问题:虚拟机的网卡配置

将镜像安装到虚拟机中的操作,应该是不难的,网上也有很多教材,这边也给出一个例子

虚拟机一

虚拟机二

虚拟机三

虚拟机四

虚拟机五

虚拟机六

7虚拟机

8虚拟机

9虚拟机

10虚拟机

11虚拟机

12虚拟机

13虚拟机

14虚拟机

但是我们在使用网络,配置网络的时候,还是要非常注意了,网络的类型有四种

8虚拟机

这四种,建议好好去了解一下为什么

我们选择的是NAT

网卡配置细讲

首先我们先看一下编辑->虚拟机网络编辑器下VMnet8中NAT设置里的网关和DHCP设置里的起始/结束ip地址,这里尤其要记住ip地址范围哦。

15虚拟机

16虚拟机

记住网关(Gateway)

17虚拟机——记住网关

记住这里边的起始IP地址和结束IP地址

18虚拟机——起始地址和结束地址

然后我们打开虚拟机上的Centos服务器,先拿一台做示范

Step1:在虚拟机中打开了一台Centos服务器

3配置网卡之开启服务器

Step2:使用MobaXterm工具中的SSH连接方式,连接了服务器

1MobaXterm

2配置网卡之便捷配置文件ens33

4444配置网卡之打开配置文件

5555配置网卡之便捷咯

编辑成上面这个样子就差不多啦,要注意的是:

  1. IPADDR后边填的是你要设置的,在初始IP地址和结束IP地址中间的任一处IP地址。可以看到 原本我的初始IP地址和结束IP地址分别为192.168.242.128和192.168.242.254,于是我给我第一个服务器设置的是192.168.242.129 。然后接下来的第二台第三台依次就成
  2. 然后上边要改两个点,总之上面改成跟我一样的就是了
  3. 网关Gateway,就填我刚刚记下的就行了
  4. 子网掩码也是
  5. DNS1这个是可以选择的,去百度上搜一个就成,我这边的是谷歌的
Step3:输入ping命令测试一下

6666配置网卡之成功了

当你整完上面的所有之后,便可以算作服务器已经安装好了

开始配置服务器上的编程环境和必要软件的安装

这边给必要的东西列个表

  1. Git工具安装
  2. JDK(Java环境)安装
  3. Node环境安装
  4. Python环境安装
  5. Maven项目构建和管理工具安装
  6. MySQL数据库部署和安装
  7. Redis缓存安装部署
  8. 消息队列RabbitMQ安装部署
  9. 应用型服务器Tomcat安装部署
  10. Web服务器Nginx安装部署
  11. Docker环境安装
  12. Kubernetes集群部署
  13. ElasticSearch集群部署
  14. ZooKeeper安装部署
  15. 消息队列Kafka安装部署

以上的东西只要按照我下面给出的github(https://github.com/hansonwang99/JavaCollection)上项目手册的说明来走,一般都不会有问题

但是我还是想要说一下,我踩过的坑

Git工具安装

按照手册来说,是有两种方法可以安装的,第一种是通过包管理器安装,第二种是通过源码编译安装。

区别就是,前者简单、但是安装的不是最新的。后者复杂一点、但是安装的可以是任意版本,能最新。

JDK(java环境)安装

这个没难度

Node环境安装

这个也太简单了,我表示无话可说

Python环境安装

也无话可说

Maven项目构建和管理工具安装

配置加速镜像源难了一点,但是也可以接受

MySQL数据库部署和安装

这个如果整错了就重新来过,这边我想说一点,VMwareWordstation15的快照功能超好用,一键恢复到之前的状态

redis缓存安装部署

很简单,过

消息队列RabbitMQ安装部署

在安装erlang环境的时候会遇到一个不常见的知识点——curl命令

这一命令可用的范围很广,可以用于配置安装的仓库、可以用于在前端即时编写脚本回调后端的接口进行测试。这边把本次所用到的命令写一遍

curl -s https://packagecloud.io/install/repositories/rabbitmq/erlang/script.rpm.sh | sudo bash

意思是安装erlang环境对应的包仓库

· 4 min read
CheverJohn

端口转发是安全壳(ssh)为了网络安全通信而使用的一种方法。

SSH可以利用端口转发技术来传输其他TCP/IP协议的报文

当使用这种方法的时候,SSH就为其他服务在客户端服务器建立一条安全的传输管道

端口转发利用本地客户机端口映射到服务器端口来工作

SSH可以映射所有的服务器端口到本地端口,但是1024以下的端口需要根用户权限。

在使用防火墙的网络中,如果设置了允许SSH服务通过(即开启了22端口),从而阻断了其他服务,则被阻断了的服务仍然可以通过端口转发技术转发数据包

简介

端口转发服务是由一组端口转发规则定义的策略。一个端口转发服务可以应用到一个或更多的虚拟机。然后虚拟机的入站网络访问就根据端口转发服务所定义的策略进行管理。可以根据需要指定一个或多个CIDR来过滤源lP地址,以允许来自特定IP地址的请求被转发 。

虚拟机可以应用任意数量的端口转发服务。端口转发服务也可以先定义好,但暂时不应用到虚拟机上。如果虚拟机属于多个网络,则只有在默认网络中定义的端口转发规则才会生效 。

不能使用端口转发打开弹性lP地址的端口。当使用弹性IP时,外部访问通过使用安全组来控制 。

区分端口映射和端口转发

端口映射场景: 外网主机A想访问内网主机B上的服务 端口转发场景: 外网主机A已经可以任意内网主机B上的端口,但是无法访问内网主机C上的端口 此时可以将C主机的端口到B主机的端口,那么外网主机A访问B主机的某某端口就相当于访问了C主机的某某 总结: 端口转发和端口映射原理是一样的只不过是应用场景不一样,假如我们将本机的端口转发到远程主机端口,我们可以叫端口映射,也可以叫端口转发,看下图【注意图上文字】 图一

我们如果把本机可以访问到的任意 IP 的端口转发到另外一台服务器的端口,我们叫他端口转发,看下图【注意图上文字】

图二

端口转发和代理工具

Lcx Htran Netcat frp ngrok

· 67 min read
CheverJohn

来自于我协会的朱学长哈!

来自于我协会的朱学长哈!

1. Java 基本功

1.1. Java 入门(基础概念与常识)

1.1.1. Java 语言有哪些特点?

  1. 简单易学;
  2. 面向对象(封装,继承,多态);
  3. 平台无关性( Java 虚拟机实现平台无关性);
  4. 可靠性;
  5. 安全性;
  6. 支持多线程( C++ 语言没有内置的多线程机制,因此必须调用操作系统的多线程功能来进行多线程程序设计,而 Java 语言却提供了多线程支持);
  7. 支持网络编程并且很方便( Java 语言诞生本身就是为简化网络编程设计的,因此 Java 语言不仅支持网络编程而且很方便);
  8. 编译与解释并存;

修正(参见: issue#544):C++11 开始(2011 年的时候),C++就引入了多线程库,在 windows、linux、macos 都可以使用std::threadstd::async来创建线程。参考链接:http://www.cplusplus.com/reference/thread/thread/?kw=thread

1.1.2. 关于 JVM JDK 和 JRE 最详细通俗的解答

1.1.2.1. JVM

Java 虚拟机(JVM)是运行 Java 字节码的虚拟机。JVM 有针对不同系统的特定实现(Windows,Linux,macOS),目的是使用相同的字节码,它们都会给出相同的结果。

什么是字节码?采用字节码的好处是什么?

在 Java 中,JVM 可以理解的代码就叫做字节码(即扩展名为 .class 的文件),它不面向任何特定的处理器,只面向虚拟机。Java 语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。所以 Java 程序运行时比较高效,而且,由于字节码并不针对一种特定的机器,因此,Java 程序无须重新编译便可在多种不同操作系统的计算机上运行。

Java 程序从源代码到运行一般有下面 3 步:

Java程序运行过程

我们需要格外注意的是 .class->机器码 这一步。在这一步 JVM 类加载器首先加载字节码文件,然后通过解释器逐行解释执行,这种方式的执行速度会相对比较慢。而且,有些方法和代码块是经常需要被调用的(也就是所谓的热点代码),所以后面引进了 JIT 编译器,而 JIT 属于运行时编译。当 JIT 编译器完成第一次编译后,其会将字节码对应的机器码保存下来,下次可以直接使用。而我们知道,机器码的运行效率肯定是高于 Java 解释器的。这也解释了我们为什么经常会说 Java 是编译与解释共存的语言。

HotSpot 采用了惰性评估(Lazy Evaluation)的做法,根据二八定律,消耗大部分系统资源的只有那一小部分的代码(热点代码),而这也就是 JIT 所需要编译的部分。JVM 会根据代码每次被执行的情况收集信息并相应地做出一些优化,因此执行的次数越多,它的速度就越快。JDK 9 引入了一种新的编译模式 AOT(Ahead of Time Compilation),它是直接将字节码编译成机器码,这样就避免了 JIT 预热等各方面的开销。JDK 支持分层编译和 AOT 协作使用。但是 ,AOT 编译器的编译质量是肯定比不上 JIT 编译器的。

总结:

Java 虚拟机(JVM)是运行 Java 字节码的虚拟机。JVM 有针对不同系统的特定实现(Windows,Linux,macOS),目的是使用相同的字节码,它们都会给出相同的结果。字节码和不同系统的 JVM 实现是 Java 语言“一次编译,随处可以运行”的关键所在。

1.1.2.2. JDK 和 JRE

JDK 是 Java Development Kit,它是功能齐全的 Java SDK。它拥有 JRE 所拥有的一切,还有编译器(javac)和工具(如 javadoc 和 jdb)。它能够创建和编译程序。

JRE 是 Java 运行时环境。它是运行已编译 Java 程序所需的所有内容的集合,包括 Java 虚拟机(JVM),Java 类库,java 命令和其他的一些基础构件。但是,它不能用于创建新程序。

如果你只是为了运行一下 Java 程序的话,那么你只需要安装 JRE 就可以了。如果你需要进行一些 Java 编程方面的工作,那么你就需要安装 JDK 了。但是,这不是绝对的。有时,即使您不打算在计算机上进行任何 Java 开发,仍然需要安装 JDK。例如,如果要使用 JSP 部署 Web 应用程序,那么从技术上讲,您只是在应用程序服务器中运行 Java 程序。那你为什么需要 JDK 呢?因为应用程序服务器会将 JSP 转换为 Java servlet,并且需要使用 JDK 来编译 servlet。

1.1.3. Oracle JDK 和 OpenJDK 的对比

可能在看这个问题之前很多人和我一样并没有接触和使用过 OpenJDK 。那么 Oracle 和 OpenJDK 之间是否存在重大差异?下面我通过收集到的一些资料,为你解答这个被很多人忽视的问题。

对于 Java 7,没什么关键的地方。OpenJDK 项目主要基于 Sun 捐赠的 HotSpot 源代码。此外,OpenJDK 被选为 Java 7 的参考实现,由 Oracle 工程师维护。关于 JVM,JDK,JRE 和 OpenJDK 之间的区别,Oracle 博客帖子在 2012 年有一个更详细的答案:

问:OpenJDK 存储库中的源代码与用于构建 Oracle JDK 的代码之间有什么区别?

答:非常接近 - 我们的 Oracle JDK 版本构建过程基于 OpenJDK 7 构建,只添加了几个部分,例如部署代码,其中包括 Oracle 的 Java 插件和 Java WebStart 的实现,以及一些封闭的源代码派对组件,如图形光栅化器,一些开源的第三方组件,如 Rhino,以及一些零碎的东西,如附加文档或第三方字体。展望未来,我们的目的是开源 Oracle JDK 的所有部分,除了我们考虑商业功能的部分。

总结:

  1. Oracle JDK 大概每 6 个月发一次主要版本,而 OpenJDK 版本大概每三个月发布一次。但这不是固定的,我觉得了解这个没啥用处。详情参见:https://blogs.oracle.com/java-platform-group/update-and-faq-on-the-java-se-release-cadence
  2. OpenJDK 是一个参考模型并且是完全开源的,而 Oracle JDK 是 OpenJDK 的一个实现,并不是完全开源的;
  3. Oracle JDK 比 OpenJDK 更稳定。OpenJDK 和 Oracle JDK 的代码几乎相同,但 Oracle JDK 有更多的类和一些错误修复。因此,如果您想开发企业/商业软件,我建议您选择 Oracle JDK,因为它经过了彻底的测试和稳定。某些情况下,有些人提到在使用 OpenJDK 可能会遇到了许多应用程序崩溃的问题,但是,只需切换到 Oracle JDK 就可以解决问题;
  4. 在响应性和 JVM 性能方面,Oracle JDK 与 OpenJDK 相比提供了更好的性能;
  5. Oracle JDK 不会为即将发布的版本提供长期支持,用户每次都必须通过更新到最新版本获得支持来获取最新版本;
  6. Oracle JDK 根据二进制代码许可协议获得许可,而 OpenJDK 根据 GPL v2 许可获得许可。

1.1.4. Java 和 C++的区别?

我知道很多人没学过 C++,但是面试官就是没事喜欢拿咱们 Java 和 C++ 比呀!没办法!!!就算没学过 C++,也要记下来!

  • 都是面向对象的语言,都支持封装、继承和多态
  • Java 不提供指针来直接访问内存,程序内存更加安全
  • Java 的类是单继承的,C++ 支持多重继承;虽然 Java 的类不可以多继承,但是接口可以多继承。
  • Java 有自动内存管理机制,不需要程序员手动释放无用内存
  • 在 C 语言中,字符串或字符数组最后都会有一个额外的字符‘\0’来表示结束。但是,Java 语言中没有结束符这一概念。 这是一个值得深度思考的问题,具体原因推荐看这篇文章: https://blog.csdn.net/sszgg2006/article/details/49148189

1.1.5. 什么是 Java 程序的主类 应用程序和小程序的主类有何不同?

一个程序中可以有多个类,但只能有一个类是主类。在 Java 应用程序中,这个主类是指包含 main()方法的类。而在 Java 小程序中,这个主类是一个继承自系统类 JApplet 或 Applet 的子类。应用程序的主类不一定要求是 public 类,但小程序的主类要求必须是 public 类。主类是 Java 程序执行的入口点。

1.1.6. Java 应用程序与小程序之间有哪些差别?

简单说应用程序是从主线程启动(也就是 main() 方法)。applet 小程序没有 main() 方法,主要是嵌在浏览器页面上运行(调用init()或者run()来启动),嵌入浏览器这点跟 flash 的小游戏类似。

1.1.7. import java 和 javax 有什么区别?

刚开始的时候 JavaAPI 所必需的包是 java 开头的包,javax 当时只是扩展 API 包来使用。然而随着时间的推移,javax 逐渐地扩展成为 Java API 的组成部分。但是,将扩展从 javax 包移动到 java 包确实太麻烦了,最终会破坏一堆现有的代码。因此,最终决定 javax 包将成为标准 API 的一部分。

所以,实际上 java 和 javax 没有区别。这都是一个名字。

1.1.8. 为什么说 Java 语言“编译与解释并存”?

高级编程语言按照程序的执行方式分为编译型和解释型两种。简单来说,编译型语言是指编译器针对特定的操作系统将源代码一次性翻译成可被该平台执行的机器码;解释型语言是指解释器对源程序逐行解释成特定平台的机器码并立即执行。比如,你想阅读一本英文名著,你可以找一个英文翻译人员帮助你阅读, 有两种选择方式,你可以先等翻译人员将全本的英文名著(也就是源码)都翻译成汉语,再去阅读,也可以让翻译人员翻译一段,你在旁边阅读一段,慢慢把书读完。

Java 语言既具有编译型语言的特征,也具有解释型语言的特征,因为 Java 程序要经过先编译,后解释两个步骤,由 Java 编写的程序需要先经过编译步骤,生成字节码(*.class 文件),这种字节码必须由 Java 解释器来解释执行。因此,我们可以认为 Java 语言编译与解释并存。

1.2. Java 语法

1.2.1. 字符型常量和字符串常量的区别?

  1. 形式上: 字符常量是单引号引起的一个字符; 字符串常量是双引号引起的若干个字符
  2. 含义上: 字符常量相当于一个整型值( ASCII 值),可以参加表达式运算; 字符串常量代表一个地址值(该字符串在内存中存放位置)
  3. 占内存大小 字符常量只占 2 个字节; 字符串常量占若干个字节 (注意: char 在 Java 中占两个字节)

java 编程思想第四版:2.2.2 节

1.2.2. 关于注释?

Java 中的注释有三种:

  1. 单行注释

  2. 多行注释

  3. 文档注释。

在我们编写代码的时候,如果代码量比较少,我们自己或者团队其他成员还可以很轻易地看懂代码,但是当项目结构一旦复杂起来,我们就需要用到注释了。注释并不会执行,是我们程序员写给自己看的,注释是你的代码说明书,能够帮助看代码的人快速地理清代码之间的逻辑关系。因此,在写程序的时候随手加上注释是一个非常好的习惯。

《Clean Code》这本书明确指出:

代码的注释不是越详细越好。实际上好的代码本身就是注释,我们要尽量规范和美化自己的代码来减少不必要的注释。

若编程语言足够有表达力,就不需要注释,尽量通过代码来阐述。

举个例子:

去掉下面复杂的注释,只需要创建一个与注释所言同一事物的函数即可

// check to see if the employee is eligible for full benefits
if ((employee.falgs & HOURLY_FLAG) && (employee.age > 65))

应替换为

if (employee.isEligibleForFullBenefits())

1.2.3. 标识符和关键字的区别是什么?

在我们编写程序的时候,需要大量地为程序、类、变量、方法等取名字,于是就有了标识符,简单来说,标识符就是一个名字。但是有一些标识符,Java 语言已经赋予了其特殊的含义,只能用于特定的地方,这种特殊的标识符就是关键字。因此,关键字是被赋予特殊含义的标识符。比如,在我们的日常生活中 ,“警察局”这个名字已经被赋予了特殊的含义,所以如果你开一家店,店的名字不能叫“警察局”,“警察局”就是我们日常生活中的关键字。

1.2.4. 自增自减运算符

在写代码的过程中,常见的一种情况是需要某个整数类型变量增加 1 或减少 1,Java 提供了一种特殊的运算符,用于这种表达式,叫做自增运算符(++)和自减运算符(--)。

++和--运算符可以放在操作数之前,也可以放在操作数之后,当运算符放在操作数之前时,先自增/减,再赋值;当运算符放在操作数之后时,先赋值,再自增/减。例如,当“b=++a”时,先自增(自己增加 1),再赋值(赋值给 b);当“b=a++”时,先赋值(赋值给 b),再自增(自己增加 1)。也就是,++a 输出的是 a+1 的值,a++输出的是 a 值。用一句口诀就是:“符号在前就先加/减,符号在后就后加/减”。

1.2.5. Java中的几种基本数据类型是什么,对应的,各自占用多少字节呢?

Java有8种基本数据类型,分别为:

  1. 6种数字类型 :byte、short、int、long、float、double
  2. 1种字符类型:char
  3. 1中布尔型:boolean。

这八种基本类型都有对应的包装类分别为:Byte、Short、Integer、Long、Float、Double、Character、Boolean

基本类型位数字节默认值
int3240
short1620
long6480L
byte810
char162'u0000'
float3240f
double6480d
boolean1false

对于boolean,官方文档未明确定义,它依赖于 JVM 厂商的具体实现。逻辑上理解是占用 1位,但是实际中会考虑计算机高效存储因素。

注意:

  1. Java 里使用 long 类型的数据一定要在数值后面加上 L,否则将作为整型解析:
  2. char a = 'h'char :单引号,String a = "hello" :双引号

1.2.6. 自动装箱与拆箱

  • 装箱:将基本类型用它们对应的引用类型包装起来;
  • 拆箱:将包装类型转换为基本数据类型;

更多内容见:深入剖析 Java 中的装箱和拆箱

1.2.7. continue、break、和return的区别是什么?

在循环结构中,当循环条件不满足或者循环次数达到要求时,循环会正常结束。但是,有时候可能需要在循环的过程中,当发生了某种条件之后 ,提前终止循环,这就需要用到下面几个关键词:

  1. continue :指跳出当前的这一次循环,继续下一次循环。
  2. break :指跳出整个循环体,继续执行循环下面的语句。

return 用于跳出所在方法,结束该方法的运行。return 一般有两种用法:

  1. return; :直接使用 return 结束方法执行,用于没有返回值函数的方法
  2. return value; :return 一个特定值,用于有返回值函数的方法

1.3. 方法(函数)

1.3.1. 什么是方法的返回值?返回值在类的方法里的作用是什么?

方法的返回值是指我们获取到的某个方法体中的代码执行后产生的结果!(前提是该方法可能产生结果)。返回值的作用是接收出结果,使得它可以用于其他的操作!

1.3.2. 为什么 Java 中只有值传递?

为什么 Java 中只有值传递?

1.3.3. 重载和重写的区别

重载就是同样的一个方法能够根据输入数据的不同,做出不同的处理

重写就是当子类继承自父类的相同方法,输入数据一样,但要做出有别于父类的响应时,你就要覆盖父类方法

1.3.3.1. 重载

发生在同一个类中,方法名必须相同,参数类型不同、个数不同、顺序不同,方法返回值和访问修饰符可以不同。

下面是《Java 核心技术》对重载这个概念的介绍:

综上:重载就是同一个类中多个同名方法根据不同的传参来执行不同的逻辑处理。

1.3.3.2. 重写

重写发生在运行期,是子类对父类的允许访问的方法的实现过程进行重新编写。

  1. 返回值类型、方法名、参数列表必须相同,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类。
  2. 如果父类方法访问修饰符为 private/final/static 则子类就不能重写该方法,但是被 static 修饰的方法能够被再次声明。
  3. 构造方法无法被重写

综上:重写就是子类对父类方法的重新改造,外部样子不能改变,内部逻辑可以改变

暖心的 Guide 哥最后再来个图标总结一下!

区别点重载方法重写方法
发生范围同一个类子类 中
参数列表必须修改一定不能修改
返回类型可修改一定不能修改
异常可修改可以减少或删除,一定不能抛出新的或者更广的异常
访问修饰符可修改一定不能做更严格的限制(可以降低限制)
发生阶段编译期运行期

1.3.4. 深拷贝 vs 浅拷贝

  1. 浅拷贝:对基本数据类型进行值传递,对引用数据类型进行引用传递般的拷贝,此为浅拷贝。
  2. 深拷贝:对基本数据类型进行值传递,对引用数据类型,创建一个新的对象,并复制其内容,此为深拷贝。

deep and shallow copy

1.3.5. 方法的四种类型

1、无参数无返回值的方法

// 无参数无返回值的方法(如果方法没有返回值,不能不写,必须写void,表示没有返回值)
public void f1() {
System.out.println("无参数无返回值的方法");
}

2、有参数无返回值的方法

/**
* 有参数无返回值的方法
* 参数列表由零组到多组“参数类型+形参名”组合而成,多组参数之间以英文逗号(,)隔开,形参类型和形参名之间以英文空格隔开
*/
public void f2(int a, String b, int c) {
System.out.println(a + "-->" + b + "-->" + c);
}

3、有返回值无参数的方法

// 有返回值无参数的方法(返回值可以是任意的类型,在函数里面必须有return关键字返回对应的类型)
public int f3() {
System.out.println("有返回值无参数的方法");
return 2;
}

4、有返回值有参数的方法

// 有返回值有参数的方法
public int f4(int a, int b) {
return a * b;
}

5、return 在无返回值方法的特殊使用

// return在无返回值方法的特殊使用
public void f5(int a) {
if (a>10) {
return;//表示结束所在方法 (f5方法)的执行,下方的输出语句不会执行
}
System.out.println(a);
}

2. Java 面向对象

2.1. 类和对象

2.1.1. 面向对象和面向过程的区别

  • 面向过程面向过程性能比面向对象高。 因为类调用时需要实例化,开销比较大,比较消耗资源,所以当性能是最重要的考量因素的时候,比如单片机、嵌入式开发、Linux/Unix 等一般采用面向过程开发。但是,面向过程没有面向对象易维护、易复用、易扩展。
  • 面向对象面向对象易维护、易复用、易扩展。 因为面向对象有封装、继承、多态性的特性,所以可以设计出低耦合的系统,使系统更加灵活、更加易于维护。但是,面向对象性能比面向过程低

参见 issue : 面向过程 :面向过程性能比面向对象高??

这个并不是根本原因,面向过程也需要分配内存,计算内存偏移量,Java 性能差的主要原因并不是因为它是面向对象语言,而是 Java 是半编译语言,最终的执行代码并不是可以直接被 CPU 执行的二进制机械码。

而面向过程语言大多都是直接编译成机械码在电脑上执行,并且其它一些面向过程的脚本语言性能也并不一定比 Java 好。

2.1.2. 构造器 Constructor 是否可被 override?

Constructor 不能被 override(重写),但是可以 overload(重载),所以你可以看到一个类中有多个构造函数的情况。

2.1.3. 在 Java 中定义一个不做事且没有参数的构造方法的作用

Java 程序在执行子类的构造方法之前,如果没有用 super()来调用父类特定的构造方法,则会调用父类中“没有参数的构造方法”。因此,如果父类中只定义了有参数的构造方法,而在子类的构造方法中又没有用 super()来调用父类中特定的构造方法,则编译时将发生错误,因为 Java 程序在父类中找不到没有参数的构造方法可供执行。解决办法是在父类里加上一个不做事且没有参数的构造方法。

2.1.4. 成员变量与局部变量的区别有哪些?

  1. 从语法形式上看:成员变量是属于类的,而局部变量是在方法中定义的变量或是方法的参数;成员变量可以被 public,private,static 等修饰符所修饰,而局部变量不能被访问控制修饰符及 static 所修饰;但是,成员变量和局部变量都能被 final 所修饰。
  2. 从变量在内存中的存储方式来看:如果成员变量是使用static修饰的,那么这个成员变量是属于类的,如果没有使用static修饰,这个成员变量是属于实例的。而对象存在于堆内存,局部变量则存在于栈内存。
  3. 从变量在内存中的生存时间上看:成员变量是对象的一部分,它随着对象的创建而存在,而局部变量随着方法的调用而自动消失。
  4. 成员变量如果没有被赋初值:则会自动以类型的默认值而赋值(一种情况例外:被 final 修饰的成员变量也必须显式地赋值),而局部变量则不会自动赋值。

2.1.5. 创建一个对象用什么运算符?对象实体与对象引用有何不同?

new 运算符,new 创建对象实例(对象实例在堆内存中),对象引用指向对象实例(对象引用存放在栈内存中)。一个对象引用可以指向 0 个或 1 个对象(一根绳子可以不系气球,也可以系一个气球);一个对象可以有 n 个引用指向它(可以用 n 条绳子系住一个气球)。

2.1.6. 一个类的构造方法的作用是什么? 若一个类没有声明构造方法,该程序能正确执行吗? 为什么?

主要作用是完成对类对象的初始化工作。可以执行。因为一个类即使没有声明构造方法也会有默认的不带参数的构造方法。如果我们自己添加了类的构造方法(无论是否有参),Java 就不会再添加默认的无参数的构造方法了,这时候,就不能直接 new 一个对象而不传递参数了,所以我们一直在不知不觉地使用构造方法,这也是为什么我们在创建对象的时候后面要加一个括号(因为要调用无参的构造方法)。如果我们重载了有参的构造方法,记得都要把无参的构造方法也写出来(无论是否用到),因为这可以帮助我们在创建对象的时候少踩坑。

2.1.7. 构造方法有哪些特性?

  1. 名字与类名相同。
  2. 没有返回值,但不能用 void 声明构造函数。
  3. 生成类的对象时自动执行,无需调用。

2.1.8. 在调用子类构造方法之前会先调用父类没有参数的构造方法,其目的是?

帮助子类做初始化工作。

2.1.9. 对象的相等与指向他们的引用相等,两者有什么不同?

对象的相等,比的是内存中存放的内容是否相等。而引用相等,比较的是他们指向的内存地址是否相等。

2.2. 面向对象三大特征

2.2.1. 封装

封装是指把一个对象的状态信息(也就是属性)隐藏在对象内部,不允许外部对象直接访问对象的内部信息。但是可以提供一些可以被外界访问的方法来操作属性。就好像我们看不到挂在墙上的空调的内部的零件信息(也就是属性),但是可以通过遥控器(方法)来控制空调。如果属性不想被外界访问,我们大可不必提供方法给外界访问。但是如果一个类没有提供给外界访问的方法,那么这个类也没有什么意义了。就好像如果没有空调遥控器,那么我们就无法操控空凋制冷,空调本身就没有意义了(当然现在还有很多其他方法 ,这里只是为了举例子)。

public class Student {
private int id;//id属性私有化
private String name;//name属性私有化

//获取id的方法
public int getId() {
return id;
}

//设置id的方法
public void setId(int id) {
this.id = id;
}

//获取name的方法
public String getName() {
return name;
}

//设置name的方法
public void setName(String name) {
this.name = name;
}
}

2.2.2. 继承

不同类型的对象,相互之间经常有一定数量的共同点。例如,小明同学、小红同学、小李同学,都共享学生的特性(班级、学号等)。同时,每一个对象还定义了额外的特性使得他们与众不同。例如小明的数学比较好,小红的性格惹人喜爱;小李的力气比较大。继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。通过使用继承,可以快速地创建新的类,可以提高代码的重用,程序的可维护性,节省大量创建新类的时间 ,提高我们的开发效率。

关于继承如下 3 点请记住:

  1. 子类拥有父类对象所有的属性和方法(包括私有属性和私有方法),但是父类中的私有属性和方法子类是无法访问,只是拥有
  2. 子类可以拥有自己属性和方法,即子类可以对父类进行扩展。
  3. 子类可以用自己的方式实现父类的方法。(以后介绍)。

2.2.3. 多态

多态,顾名思义,表示一个对象具有多种的状态。具体表现为父类的引用指向子类的实例。

多态的特点:

  • 对象类型和引用类型之间具有继承(类)/实现(接口)的关系;
  • 对象类型不可变,引用类型可变;
  • 方法具有多态性,属性不具有多态性;
  • 引用类型变量发出的方法调用的到底是哪个类中的方法,必须在程序运行期间才能确定;
  • 多态不能调用“只在子类存在但在父类不存在”的方法;
  • 如果子类重写了父类的方法,真正执行的是子类覆盖的方法,如果子类没有覆盖父类的方法,执行的是父类的方法。

2.3. 修饰符

2.3.1. 在一个静态方法内调用一个非静态成员为什么是非法的?

由于静态方法可以不通过对象进行调用,因此在静态方法里,不能调用其他非静态变量,也不可以访问非静态变量成员。

2.3.2. 静态方法和实例方法有何不同

  1. 在外部调用静态方法时,可以使用"类名.方法名"的方式,也可以使用"对象名.方法名"的方式。而实例方法只有后面这种方式。也就是说,调用静态方法可以无需创建对象。

  2. 静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),而不允许访问实例成员变量和实例方法;实例方法则无此限制。

2.3.3. 常见关键字总结:static,final,this,super

详见笔主的这篇文章: https://snailclimb.gitee.io/javaguide/#/docs/java/basic/final,static,this,super

2.4. 接口和抽象类

2.4.1. 接口和抽象类的区别是什么?

  1. 接口的方法默认是 public,所有方法在接口中不能有实现(Java 8 开始接口方法可以有默认实现),而抽象类可以有非抽象的方法。
  2. 接口中除了 static、final 变量,不能有其他变量,而抽象类中则不一定。
  3. 一个类可以实现多个接口,但只能实现一个抽象类。接口自己本身可以通过 extends 关键字扩展多个接口。
  4. 接口方法默认修饰符是 public,抽象方法可以有 public、protected 和 default 这些修饰符(抽象方法就是为了被重写所以不能使用 private 关键字修饰!)。
  5. 从设计层面来说,抽象是对类的抽象,是一种模板设计,而接口是对行为的抽象,是一种行为的规范。

备注:

  1. 在 JDK8 中,接口也可以定义静态方法,可以直接用接口名调用。实现类和实现是不可以调用的。如果同时实现两个接口,接口中定义了一样的默认方法,则必须重写,不然会报错。(详见 issue:https://github.com/Snailclimb/JavaGuide/issues/146
  2. jdk9 的接口被允许定义私有方法 。

总结一下 jdk7~jdk9 Java 中接口概念的变化(相关阅读):

  1. 在 jdk 7 或更早版本中,接口里面只能有常量变量和抽象方法。这些接口方法必须由选择实现接口的类实现。
  2. jdk8 的时候接口可以有默认方法和静态方法功能。
  3. Jdk 9 在接口中引入了私有方法和私有静态方法。

2.5. 其它重要知识点

2.5.1. String StringBuffer 和 StringBuilder 的区别是什么? String 为什么是不可变的?

简单的来说:String 类中使用 final 关键字修饰字符数组来保存字符串,private final char value[],所以 String 对象是不可变的。

补充(来自issue 675):在 Java 9 之后,String 类的实现改用 byte 数组存储字符串 private final byte[] value;

StringBuilderStringBuffer 都继承自 AbstractStringBuilder 类,在 AbstractStringBuilder 中也是使用字符数组保存字符串char[]value 但是没有用 final 关键字修饰,所以这两种对象都是可变的。

StringBuilderStringBuffer 的构造方法都是调用父类构造方法也就是AbstractStringBuilder 实现的,大家可以自行查阅源码。

AbstractStringBuilder.java

abstract class AbstractStringBuilder implements Appendable, CharSequence {
/**
* The value is used for character storage.
*/
char[] value;

/**
* The count is the number of characters used.
*/
int count;

AbstractStringBuilder(int capacity) {
value = new char[capacity];
}}

线程安全性

String 中的对象是不可变的,也就可以理解为常量,线程安全。AbstractStringBuilderStringBuilderStringBuffer 的公共父类,定义了一些字符串的基本操作,如 expandCapacityappendinsertindexOf 等公共方法。StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder 并没有对方法进行加同步锁,所以是非线程安全的。

性能

每次对 String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String 对象。StringBuffer 每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用。相同情况下使用 StringBuilder 相比使用 StringBuffer 仅能获得 10%~15% 左右的性能提升,但却要冒多线程不安全的风险。

对于三者使用的总结:

  1. 操作少量的数据: 适用 String
  2. 单线程操作字符串缓冲区下操作大量数据: 适用 StringBuilder
  3. 多线程操作字符串缓冲区下操作大量数据: 适用 StringBuffer

2.5.2. Object 类的常见方法总结

Object 类是一个特殊的类,是所有类的父类。它主要提供了以下 11 个方法:


public final native Class<?> getClass()//native方法,用于返回当前运行时对象的Class对象,使用了final关键字修饰,故不允许子类重写。

public native int hashCode() //native方法,用于返回对象的哈希码,主要使用在哈希表中,比如JDK中的HashMap。
public boolean equals(Object obj)//用于比较2个对象的内存地址是否相等,String类对该方法进行了重写用户比较字符串的值是否相等。

protected native Object clone() throws CloneNotSupportedException//naitive方法,用于创建并返回当前对象的一份拷贝。一般情况下,对于任何对象 x,表达式 x.clone() != x 为true,x.clone().getClass() == x.getClass() 为true。Object本身没有实现Cloneable接口,所以不重写clone方法并且进行调用的话会发生CloneNotSupportedException异常。

public String toString()//返回类的名字@实例的哈希码的16进制的字符串。建议Object所有的子类都重写这个方法。

public final native void notify()//native方法,并且不能重写。唤醒一个在此对象监视器上等待的线程(监视器相当于就是锁的概念)。如果有多个线程在等待只会任意唤醒一个。

public final native void notifyAll()//native方法,并且不能重写。跟notify一样,唯一的区别就是会唤醒在此对象监视器上等待的所有线程,而不是一个线程。

public final native void wait(long timeout) throws InterruptedException//native方法,并且不能重写。暂停线程的执行。注意:sleep方法没有释放锁,而wait方法释放了锁 。timeout是等待时间。

public final void wait(long timeout, int nanos) throws InterruptedException//多了nanos参数,这个参数表示额外时间(以毫微秒为单位,范围是 0-999999)。 所以超时的时间还需要加上nanos毫秒。

public final void wait() throws InterruptedException//跟之前的2个wait方法一样,只不过该方法一直等待,没有超时时间这个概念

protected void finalize() throws Throwable { }//实例被垃圾回收器回收的时候触发的操作

2.5.3. == 与 equals(重要)

== : 它的作用是判断两个对象的地址是不是相等。即,判断两个对象是不是同一个对象(基本数据类型==比较的是值,引用数据类型==比较的是内存地址)。

equals() : 它的作用也是判断两个对象是否相等。但它一般有两种使用情况:

  • 情况 1:类没有覆盖 equals() 方法。则通过 equals() 比较该类的两个对象时,等价于通过“==”比较这两个对象。
  • 情况 2:类覆盖了 equals() 方法。一般,我们都覆盖 equals() 方法来比较两个对象的内容是否相等;若它们的内容相等,则返回 true (即,认为这两个对象相等)。

举个例子:

public class test1 {
public static void main(String[] args) {
String a = new String("ab"); // a 为一个引用
String b = new String("ab"); // b为另一个引用,对象的内容一样
String aa = "ab"; // 放在常量池中
String bb = "ab"; // 从常量池中查找
if (aa == bb) // true
System.out.println("aa==bb");
if (a == b) // false,非同一对象
System.out.println("a==b");
if (a.equals(b)) // true
System.out.println("aEQb");
if (42 == 42.0) { // true
System.out.println("true");
}
}
}

说明:

  • String 中的 equals 方法是被重写过的,因为 object 的 equals 方法是比较的对象的内存地址,而 String 的 equals 方法比较的是对象的值。
  • 当创建 String 类型的对象时,虚拟机会在常量池中查找有没有已经存在的值和要创建的值相同的对象,如果有就把它赋给当前引用。如果没有就在常量池中重新创建一个 String 对象。

2.5.4. hashCode 与 equals (重要)

面试官可能会问你:“你重写过 hashcode 和 equals 么,为什么重写 equals 时必须重写 hashCode 方法?”

2.5.4.1. hashCode()介绍

hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返回一个 int 整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。hashCode() 定义在 JDK 的 Object.java 中,这就意味着 Java 中的任何类都包含有 hashCode() 函数。

散列表存储的是键值对(key-value),它的特点是:能根据“键”快速的检索出对应的“值”。这其中就利用到了散列码!(可以快速找到所需要的对象)

2.5.4.2. 为什么要有 hashCode

我们先以“HashSet 如何检查重复”为例子来说明为什么要有 hashCode: 当你把对象加入 HashSet 时,HashSet 会先计算对象的 hashcode 值来判断对象加入的位置,同时也会与该位置其他已经加入的对象的 hashcode 值作比较,如果没有相符的 hashcode,HashSet 会假设对象没有重复出现。但是如果发现有相同 hashcode 值的对象,这时会调用 equals()方法来检查 hashcode 相等的对象是否真的相同。如果两者相同,HashSet 就不会让其加入操作成功。如果不同的话,就会重新散列到其他位置。(摘自我的 Java 启蒙书《Head first java》第二版)。这样我们就大大减少了 equals 的次数,相应就大大提高了执行速度。

通过我们可以看出:hashCode() 的作用就是获取哈希码,也称为散列码;它实际上是返回一个 int 整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。hashCode()在散列表中才有用,在其它情况下没用。在散列表中 hashCode() 的作用是获取对象的散列码,进而确定该对象在散列表中的位置。

2.5.4.3. hashCode()与 equals()的相关规定
  1. 如果两个对象相等,则 hashcode 一定也是相同的
  2. 两个对象相等,对两个对象分别调用 equals 方法都返回 true
  3. 两个对象有相同的 hashcode 值,它们也不一定是相等的
  4. 因此,equals 方法被覆盖过,则 hashCode 方法也必须被覆盖
  5. hashCode() 的默认行为是对堆上的对象产生独特值。如果没有重写 hashCode(),则该 class 的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)

推荐阅读:Java hashCode() 和 equals()的若干问题解答

2.5.5. Java 序列化中如果有些字段不想进行序列化,怎么办?

对于不想进行序列化的变量,使用 transient 关键字修饰。

transient 关键字的作用是:阻止实例中那些用此关键字修饰的的变量序列化;当对象被反序列化时,被 transient 修饰的变量值不会被持久化和恢复。transient 只能修饰变量,不能修饰类和方法。

2.5.6. 获取用键盘输入常用的两种方法

方法 1:通过 Scanner

Scanner input = new Scanner(System.in);
String s = input.nextLine();
input.close();

方法 2:通过 BufferedReader

BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
String s = input.readLine();

3. Java 核心技术

3.1. 集合

3.1.1. Collections 工具类和 Arrays 工具类常见方法总结

详见笔主的这篇文章: https://gitee.com/SnailClimb/JavaGuide/blob/master/docs/java/basic/Arrays,CollectionsCommonMethods.md

3.2. 异常

3.2.1. Java 异常类层次结构图

因为有一些错误,所以这边省略了一大段话,还请查看原文

3.2.2. Throwable 类常用方法

  • public string getMessage():返回异常发生时的简要描述
  • public string toString():返回异常发生时的详细信息
  • public string getLocalizedMessage():返回异常对象的本地化信息。使用 Throwable 的子类覆盖这个方法,可以生成本地化信息。如果子类没有覆盖该方法,则该方法返回的信息与 getMessage()返回的结果相同
  • public void printStackTrace():在控制台上打印 Throwable 对象封装的异常信息

3.2.3. try-catch-finally

  • try 块: 用于捕获异常。其后可接零个或多个 catch 块,如果没有 catch 块,则必须跟一个 finally 块。
  • catch 块: 用于处理 try 捕获到的异常。
  • finally 块: 无论是否捕获或处理异常,finally 块里的语句都会被执行。当在 try 块或 catch 块中遇到 return 语句时,finally 语句块将在方法返回之前被执行。

在以下 4 种特殊情况下,finally 块不会被执行:

  1. 在 finally 语句块第一行发生了异常。 因为在其他行,finally 块还是会得到执行
  2. 在前面的代码中用了 System.exit(int)已退出程序。 exit 是带参函数 ;若该语句在异常语句之后,finally 会执行
  3. 程序所在的线程死亡。
  4. 关闭 CPU。

下面这部分内容来自 issue:https://github.com/Snailclimb/JavaGuide/issues/190

注意: 当 try 语句和 finally 语句中都有 return 语句时,在方法返回之前,finally 语句的内容将被执行,并且 finally 语句的返回值将会覆盖原始的返回值。如下:

public class Test {
public static int f(int value) {
try {
return value * value;
} finally {
if (value == 2) {
return 0;
}
}
}
}

如果调用 f(2),返回值将是 0,因为 finally 语句的返回值覆盖了 try 语句块的返回值。

3.2.4.使用 try-with-resources 来代替try-catch-finally

《Effecitve Java》中明确指出:

面对必须要关闭的资源,我们总是应该优先使用try-with-resources而不是try-finally。随之产生的代码更简短,更清晰,产生的异常对我们也更有用。try-with-resources语句让我们更容易编写必须要关闭的资源的代码,若采用try-finally则几乎做不到这点。

Java 中类似于InputStreamOutputStreamScannerPrintWriter等的资源都需要我们调用close()方法来手动关闭,一般情况下我们都是通过try-catch-finally语句来实现这个需求,如下:

        //读取文本文件的内容
Scanner scanner = null;
try {
scanner = new Scanner(new File("D://read.txt"));
while (scanner.hasNext()) {
System.out.println(scanner.nextLine());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (scanner != null) {
scanner.close();
}
}

使用Java 7之后的 try-with-resources 语句改造上面的代码:

try (Scanner scanner = new Scanner(new File("test.txt"))) {
while (scanner.hasNext()) {
System.out.println(scanner.nextLine());
}
} catch (FileNotFoundException fnfe) {
fnfe.printStackTrace();
}

当然多个资源需要关闭的时候,使用 try-with-resources 实现起来也非常简单,如果你还是用try-catch-finally可能会带来很多问题。

通过使用分号分隔,可以在try-with-resources块中声明多个资源:

3.3. 多线程

3.3.1. 简述线程、程序、进程的基本概念。以及他们之间关系是什么?

线程与进程相似,但线程是一个比进程更小的执行单位。一个进程在其执行的过程中可以产生多个线程。与进程不同的是同类的多个线程共享同一块内存空间和一组系统资源,所以系统在产生一个线程,或是在各个线程之间作切换工作时,负担要比进程小得多,也正因为如此,线程也被称为轻量级进程。

程序是含有指令和数据的文件,被存储在磁盘或其他的数据存储设备中,也就是说程序是静态的代码。

进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的。系统运行一个程序即是一个进程从创建,运行到消亡的过程。简单来说,一个进程就是一个执行中的程序,它在计算机中一个指令接着一个指令地执行着,同时,每个进程还占有某些系统资源如 CPU 时间,内存空间,文件,输入输出设备的使用权等等。换句话说,当程序在执行时,将会被操作系统载入内存中。 线程是进程划分成的更小的运行单位。线程和进程最大的不同在于基本上各进程是独立的,而各线程则不一定,因为同一进程中的线程极有可能会相互影响。从另一角度来说,进程属于操作系统的范畴,主要是同一段时间内,可以同时执行一个以上的程序,而线程则是在同一程序内几乎同时执行一个以上的程序段。

3.3.2. 线程有哪些基本状态?

Java 线程在运行的生命周期中的指定时刻只可能处于下面 6 种不同状态的其中一个状态(图源《Java 并发编程艺术》4.1.4 节)。

Java线程的状态

线程在生命周期中并不是固定处于某一个状态而是随着代码的执行在不同状态之间切换。Java 线程状态变迁如下图所示(图源《Java 并发编程艺术》4.1.4 节):

Java线程状态变迁

由上图可以看出:

线程创建之后它将处于 NEW(新建) 状态,调用 start() 方法后开始运行,线程这时候处于 READY(可运行) 状态。可运行状态的线程获得了 cpu 时间片(timeslice)后就处于 RUNNING(运行) 状态。

操作系统隐藏 Java 虚拟机(JVM)中的 READY 和 RUNNING 状态,它只能看到 RUNNABLE 状态(图源:HowToDoInJavaJava Thread Life Cycle and Thread States),所以 Java 系统一般将这两个状态统称为 RUNNABLE(运行中) 状态 。

RUNNABLE-VS-RUNNING

当线程执行 wait()方法之后,线程进入 WAITING(等待)状态。进入等待状态的线程需要依靠其他线程的通知才能够返回到运行状态,而 TIME_WAITING(超时等待) 状态相当于在等待状态的基础上增加了超时限制,比如通过 sleep(long millis)方法或 wait(long millis)方法可以将 Java 线程置于 TIMED WAITING 状态。当超时时间到达后 Java 线程将会返回到 RUNNABLE 状态。当线程调用同步方法时,在没有获取到锁的情况下,线程将会进入到 BLOCKED(阻塞) 状态。线程在执行 Runnable 的run()方法之后将会进入到 TERMINATED(终止) 状态。

3.4. 文件与 I\O 流

3.4.1. Java 中 IO 流分为几种?

  • 按照流的流向分,可以分为输入流和输出流;
  • 按照操作单元划分,可以划分为字节流和字符流;
  • 按照流的角色划分为节点流和处理流。

Java Io 流共涉及 40 多个类,这些类看上去很杂乱,但实际上很有规则,而且彼此之间存在非常紧密的联系, Java I0 流的 40 多个类都是从如下 4 个抽象类基类中派生出来的。

  • InputStream/Reader: 所有的输入流的基类,前者是字节输入流,后者是字符输入流。
  • OutputStream/Writer: 所有输出流的基类,前者是字节输出流,后者是字符输出流。

按操作方式分类结构图:

IO-操作方式分类

按操作对象分类结构图:

IO-操作对象分类

3.4.1.1. 既然有了字节流,为什么还要有字符流?

问题本质想问:不管是文件读写还是网络发送接收,信息的最小存储单元都是字节,那为什么 I/O 流操作要分为字节流操作和字符流操作呢?

回答:字符流是由 Java 虚拟机将字节转换得到的,问题就出在这个过程还算是非常耗时,并且,如果我们不知道编码类型就很容易出现乱码问题。所以, I/O 流就干脆提供了一个直接操作字符的接口,方便我们平时对字符进行流操作。如果音频文件、图片等媒体文件用字节流比较好,如果涉及到字符的话使用字符流比较好。

3.4.1.2. BIO,NIO,AIO 有什么区别?
  • BIO (Blocking I/O): 同步阻塞 I/O 模式,数据的读取写入必须阻塞在一个线程内等待其完成。在活动连接数不是特别高(小于单机 1000)的情况下,这种模型是比较不错的,可以让每一个连接专注于自己的 I/O 并且编程模型简单,也不用过多考虑系统的过载、限流等问题。线程池本身就是一个天然的漏斗,可以缓冲一些系统处理不了的连接或请求。但是,当面对十万甚至百万级连接的时候,传统的 BIO 模型是无能为力的。因此,我们需要一种更高效的 I/O 处理模型来应对更高的并发量。
  • NIO (Non-blocking/New I/O): NIO 是一种同步非阻塞的 I/O 模型,在 Java 1.4 中引入了 NIO 框架,对应 java.nio 包,提供了 Channel , Selector,Buffer 等抽象。NIO 中的 N 可以理解为 Non-blocking,不单纯是 New。它支持面向缓冲的,基于通道的 I/O 操作方法。 NIO 提供了与传统 BIO 模型中的 SocketServerSocket 相对应的 SocketChannelServerSocketChannel 两种不同的套接字通道实现,两种通道都支持阻塞和非阻塞两种模式。阻塞模式使用就像传统中的支持一样,比较简单,但是性能和可靠性都不好;非阻塞模式正好与之相反。对于低负载、低并发的应用程序,可以使用同步阻塞 I/O 来提升开发速率和更好的维护性;对于高负载、高并发的(网络)应用,应使用 NIO 的非阻塞模式来开发
  • AIO (Asynchronous I/O): AIO 也就是 NIO 2。在 Java 7 中引入了 NIO 的改进版 NIO 2,它是异步非阻塞的 IO 模型。异步 IO 是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。AIO 是异步 IO 的缩写,虽然 NIO 在网络操作中,提供了非阻塞的方法,但是 NIO 的 IO 行为还是同步的。对于 NIO 来说,我们的业务线程是在 IO 操作准备好时,得到通知,接着就由这个线程自行进行 IO 操作,IO 操作本身是同步的。查阅网上相关资料,我发现就目前来说 AIO 的应用还不是很广泛,Netty 之前也尝试使用过 AIO,不过又放弃了。

4. 参考

· 8 min read
CheverJohn

Maven项目对象模型(POM), 可以通过一小段描述信息来管理项目的构建、报告和文档的项目管理工具软件。 ​ Maven除了以程序构建能力为特色之外,还提供高级项目管理工具。由于Maven的缺省构建规则有较高的可重用性能,所以常常用两三行Maven构建脚本就可以构建简单的项目。由于Maven的面向项目的属性,很多项目发布时都会使用Maven,所以目前使用Maven技术的比例在持续增长。 ​ 总而言之,Maven是一个可以用来构建和管理任何基于Java的项目的工具,主要目标是让开发人员在最短的时间内了解开发工作的完整状态。

emmmm

Maven的优点如下

简化构建过程 提供统一的构建系统 提供优质的项目信息 提供最佳实践开发指南 允许透明迁移新功能

简化构建过程

虽然使用Maven时偶尔也需要你对底层细节有所了解!但是,Maven 确实屏蔽了很多细节,它已经大大简化了开发人员的工作。

提供统一的构建系统

Maven 使用项目对象模型(POM)和一组所有项目共享的插件来构建项目,从而提供统一的构建系统。开发人员使用 Maven 构建项目的话,后期维护项目会节省大量时间。

提供优质的项目信息

Maven 提供了大量有用的项目信息,这些信息部分来自您的POM,部分来自项目源。例如,Maven可以提供:

更改从源代码控制直接创建的日志文档 交叉引用的来源 邮件列表 依赖列表 单元测试报告包括报道

由于 Maven 改进了提供的信息,所有这些信息对 Maven 用户都是透明的。 通过 Maven 插件,其他产品可以将自己的项目信息兼容 Maven 的标准信息,所有信息同样基于POM

提供最佳实践开发指南

Maven 会汇总当前最佳开发实践的原则,并通过 Maven 影响其他项目。

例如,Maven 的正常构建周期中的单元测试的规范,执行和报告。

当前的单元测试最佳实践被用作指导原则:

将测试源代码保存在独立的、并行的源代码树中;

规范测试用例命名,便于来定位和执行测试;

为测试用例设置的环境,不依赖与客户化的定制构建和测试准备。

Maven还旨在工作流程中协助项目开发,如发布管理和问题跟踪。

允许透明迁移到新功能

Maven 为 Maven 客户端提供了一种安装更新的简单方法,开发人员可以简单便捷的利用 Maven 的最新特性。

从第三方或 Maven 安装新的插件变得非常的简单。

在Java中Maven项目跟Web项目的区别(distinction)

定义不同:

Web项目是网页的编码,像

jsp(https://baike.baidu.com/item/JSP/141543) servlet(https://baike.baidu.com/item/servlet) struts(https://baike.baidu.com/item/struts)

Java Maven项目是 AWT(https://baike.baidu.com/item/AWT)、**SWING**(https://baike.baidu.com/item/Swing/3286527) 这类的编码

举例说明:

Java不仅是一门编程语言,还是一个平台,通过JRuby和Jython,我们可以在Java平台上编写和运行Ruby和Python程序;

Maven不仅是构建工具,还是一个依赖管理工具和项目信息管理工具;

web项目是网页的编码项目,需要在服务器上运行。

作用不同:

Java可以用来编写桌面应用程序、Web应用程序、分布式系统和嵌入式系统应用程序等 ;

Maven由项目对象模型、标准集合、项目生命周期和依赖关系管理系统构成,可以经过项目对象模型描述信息来管理项目的构建、报告和文档,还可以生成站点和管理JAR文件;

web是建立在Internet上的一种网络服务,包含了超文本、超媒体和超文本传输协议,可以提供图形化的直观的网页浏览界面,信息可以实时更新。

特点不同

Java是一门面向对象编程语言,Java具有简单性、面向对象、分布式、健壮性、安全性、平台独立与可移植性、多线程、动态性等特点。

Maven 有一个生命周期,当你运行 mvn install 的时候被调用,这条命令告诉 Maven 执行一系列的有序的步骤,直到到达你指定的生命周期。遍历生命周期旅途中的一个影响就是,Maven 运行了许多默认的插件目标,这些目标完成了像编译和创建一个 JAR 文件这样的工作。

web即全球广域网,也称为万维网,它是一种基于超文本和HTTP的、全球性的、动态交互的、跨平台的分布式图形信息系统。是建立在Internet上的一种网络服务,为浏览者在Internet上查找和浏览信息提供了图形化的、易于访问的直观界面。

Maven常用命令

mvn archetype:generate 创建Maven项目

mvn compile 编译源代码

mvn deploy 发布项目

mvn test-compile 编译测试源代码

mvn test 运行应用程序中的单元测试

mvn site 生成项目相关信息的网站

mvn clean 清除项目目录中的生成结果

mvn package 根据项目生成的jar

mvn install 在本地Repository中安装jar

mvn eclipse:eclipse 生成eclipse项目文件

mvnjetty:run 启动jetty服务

mvntomcat:run 启动tomcat服务