沉默王二

沉默王二 查看完整档案

洛阳编辑  |  填写毕业院校原创公号「沉默王二」  |  作者 编辑 www.itwanger.com 编辑
编辑

《Web全栈开发进阶之路》作者
公众号:沉默王二
微信:qing_geee
专注于有趣的Java技术,有益的程序人生

个人动态

沉默王二 发布了文章 · 3月1日

Vim,牛逼

思否的小伙伴们,大家好,我是周一就在装逼学习的沉默王二。

写完 Shell 那篇后就想写 Vim 了,因为人类史上最好的文本编辑器就是 Vim,不赞同的请自觉持有保留意见,哈哈哈。

Better, Stronger, Faster.

用这三个单词来赞美 Vim,一点都不为过。只不过,Vim 的学习曲线相当的大,这是一个连我都不得不承认的事实。就好像弹一把吉他,一开始学起来非常痛苦,简直想摔了它,但学会后,就能感受到乐器的无限魅力,以及学妹崇拜的小眼神。

来吧,下定决心拥抱它,没有比它更好的文本编辑器了,非常地难学,但却不可思议地好用。

01、初识 Vim

Vim 有着悠久的历史。80 年代末,布莱姆·米勒在一个开源的 vi(更早的一种计算机文本编辑器,我记得有个读者的网名就叫这个)基础上开发了 Vim 1.0 版本。

1994 年,Vim 3.0 中加入了里程碑式的多窗口编辑模式。

1996 年,Vim 4.0 中加入了图形化界面的版本。

1998 年,Vim 5.0 中加入了语法高亮的功能。

。。。。。。

总之是,越来越强!最新的版本是 8.0,启动界面里会显示一句非常暖心的话——「Help poor children in Uganda」,翻译过来就是「请帮助乌干达的可怜孩童」。这让我想起来我最喜欢的一支乐队——Beyond 的一首歌《Amani》。

打开终端,键入「vim」,就可以进入启动界面了,如下图所示。

Vim 有很多聪明的设计,所以很多其他工具也支持 Vim 模式,比如说 Visual Studio Code。很牛掰的一点是,Vim 逃离了鼠标的“魔掌”,只通过键盘就可以肆意地操作文本。

键入 :help 就可以查看 Vim 的帮助文档,尽管文档是英文的,但这的确是最权威的 Vim 学习资料了,听我一句劝,耐着性子读一读吧!

键入 :q 可以退出帮助文档。当然了,如果英文读起来确实痛苦了些,我还为你准备了在线的中文翻译文档,看这里:

https://yianwillis.github.io/...

02、实操 Vim

俗话说,“光说不练假把戏。”咱们直接上手来体验一把。键入 vim xxx 命令。如下图所示。

随后敲回车键,就进入 xxx 文件的阅读模式了。如下图所示。

在阅读模式下,你需要尝试下面这些命令。

  • 上下左右移动:对应上下左右键
  • 按照词移动:w(下一个词),b(单词的第一个字母),e(单词的最后一个字母),不适合中文
  • 按照行移动:0(第一行),$(行尾),:+行数直接跳转到指定的行(此处的+意味着按下 : 后,再输入行数,比如 10)
  • 按照屏幕移动:H(屏幕顶部),M(屏幕中间),L(屏幕底部)
  • 翻页:不同的键盘有所不懂,比如说 Mac 的巧克力键盘,fn+↑ 键向上翻,fn+↓键向下翻(此处的+意味着组合键)
  • gg(移动到文件开头),G(移动到文件末尾)
  • /+关键词(此处的+意味着按下反斜杠后,再输入关键词)进行搜索,n/N 用于向下或者向上匹配

除此之外,阅读模式下,你还可以:

  • 键入 i 进入插入模式,此时会在窗口底部出现 -- INSERT -- 的字样。

在插入模式下按 esc 键退回到阅读模式。郑重其事的提醒:如果你不知道现在处于什么模式,就狂按 esc 键

除了 i 键可以进入插入模式,还有其他几个键可以进入插入模式,比如说 a 键可以在光标后插入;o 键可以在当前行后插入;0 键可以在当前行前插入。

  • 键入 dd 删除当前行,并把删除的行存到剪贴板里。
  • 键入 x 删除当前光标所在的一个字符。
  • 键入 p 可用于粘贴上一次复制的内容。
  • 键入 yy 可以复制当前行的内容。
  • 键入 u 可用于撤销当前操作。
  • 键入 :w 可以保存当前修改后的内容。
  • 键入 :q! 可以在不保存内容的情况下退出 Vim。
  • 键入 :wq 可以在保存内容的情况下退出 Vim。

温馨提醒:如果你是在插入模式,想要退出或者保存内容的话,一定要先按 esc 键退出到阅读模式。

好了,到此为止,你已经算是入门级的 Vim 用户了,真的,掌握了这些命令,其他编辑器能干的事,你都可以通过 Vim 完成了。

03、进阶

孙悟空成为花果山水帘洞的大王之后,感到了空前的寂寞,他想要进阶,于是撑了一叶扁舟拜师学艺去了。同样的,当我们熟练掌握了上述这些命令之后,也会感到空前的寂寞,因为 Vim 的强大绝不止于此。

来看一下,Vim 是怎么重复自己的。

  • 键入 . 可以重复上一次的命令。这意味着什么呢?意味着如果我们键入 dd 删除了一行内容,如果我们还想删除一行的话,不需要再按下两次 d 键了,只需要按下一次 . 键就可以了。
  • 键入 N+命令可以重复某个命令 N 次。(此处的+意味着按下次数后,再输入命令)。这意味着什么呢?意味着生产力的大幅度提升啊!

比如说,在阅读模式下,键入 3dd 可以一次性删除 3 行内容;键入 10p 可以粘贴 10 次文本。

来个带劲的哈。

通过 vim hello.txt 打开一个新的文本文件。然后键入 10+i+hello world+回车键+esc(此处的+意味着按下次数后,再键入 i 键进入插入模式,再敲下 hello world,再按下回车键换行,再按下 esc 键退出到阅读模式),奇妙的事情发生了,见下图。

想一下,键入 10. 会发生什么?相信我,试玩之后,你会“哇”的。

妙,实在是妙。除此之外,你还可以键入:

  • % 匹配括号来移动,包括 {[(,前提条件是你需要把光标移动到括号上。
  • * 匹配单词来向下一个移动。(中文就无法使用了)
  • # 匹配单词来向上一个移动。(同上)

记住光标的移动就可以脱离鼠标的束缚了。大多数命令都可以按照下面的方式来干:

光标开始的位置+命令+光标结束的位置

比如 0y$ 意味着:

  • 0,光标移动到行首
  • y,从这里开始复制
  • $,直到行尾

如果你想看到光标选中了哪些文本,可以先按下 v 键进入可视化视图,然后再操作光标,如下图所示。

更强大的操作,可以看看耗子叔翻译的一篇《简明 Vim 练级攻略》:

https://coolshell.cn/articles...

在阅读模式下,键入 :sp 可以横向分割窗口,键入 :vsp 可以竖向分割窗口,见下图。

舒服吧?原来一边编辑,一遍预览,在 Vim 下,只需要键入三四个字符!

04、结语

如果你想在手头备一份 Vim 的帮助手册,免得在用 Vim 的时候四处搜索,实话告诉你,我替你准备了,就是这么贴心。真的,花了 2 天的时间呢,整理了一份《Vim 中文用户手册》,310 页,内容非常全面。

Vim 中文用户手册下载

最后,多说几句。作为程序员,我们大部分的时间都花费在摸鱼上,不不不,代码编辑器上,因此,花点时间来掌握一个适合自己的编辑器还是非常值得的。很多大佬都直接使用 Vim 来作为代码编辑器,虽然我还没达到这种高逼格,但使用 Vim 来操作日志和配置文件的频率还是非常高的。

要想熟练掌握 Vim,你需要这样做:

  • 认真阅读这篇内容;
  • 坚持使用 Vim 来完成所有的文本编辑工作,即使一开始会很痛苦;
  • 随时查阅帮助文档,强化肌肉记忆;
  • 两周时间的苦练后,你会发现,工作和学习效率有了大幅度的提升。
  • 一个月过后,你跑过来感谢我,“二哥,你丫的,牛逼”!

好了,我是沉默王二,希望这篇文章能够帮到你!下期见。

查看原文

赞 1 收藏 1 评论 2

沉默王二 发布了文章 · 2月24日

狂补计算机基础知识,让我上了瘾,从此不再是一名 curd boy

思否的小伙伴们,大家好,我是沉默王二。最近我在狂补计算机基础知识,感觉有点上瘾!以前觉得很枯燥的知识,现在竟然有点香!不知道为什么。

我算是科班出身,大学的专业就是计算机网络,不过老实说,在实际的开发中,大学的很多课程,要么“用处”不大,要么可以换个方式,更高效的学习。

其中的原因,一方面是实际开发更关注知识的“实用”,另外一方面,大学的教学确实和产业有些脱钩。所以我就从实际应用的角度出发,重新来梳理一下计算机基础方面的知识。

01、数据结构

毫无疑问,数据结构对一名程序员来说非常重要,还是那句话程序=数据结构+算法,这种说法无论放在什么时候都是成立的。

大部分的数据结构课程,关注的重点都在如何从数学上实现一个数据结构,但在实际开发中,大部分主流语言都已经内置了常见的数据结构,比如说 Java。也就是说,对于大部分程序员来说,实际开发中,很难有需求要从零开始实现一个数据结构。因此我们只需要做到下面几点。

1、熟悉常见数据结构的概念,比如说数组、堆栈、链表、哈希表等。

2、了解常用数据结构之间的差异,比如说 ArrayList 和 LinkedList,我在之前的文章中有详细说明过,可以点击链接去查看下。

3、关注常用数据结构的外围算法,比如说如何对 List 和 Map 进行查找。

4、关注数据结构使用中容易出错的地方,比如说线程是否安全等。

...

B 站上浙江大学的一个数据结构的课还不错,很系统很经典,适合小白入门。

视频地址如下。

https://www.bilibili.com/vide...

02、算法

以我接触的领域来说,大部分普通的业务系统都不会涉及到太复杂的算法,因此我没有在算法上投入过多时间。

但如果你在一些特殊的领域,如果算法跟不上,可以说是“寸步难行”,比如说图形处理领域,无论是图像的变化还是增强,无一例外都要用到矩阵变换,因此就必然涉及到线性代数的内容,再往深处学的话,必然会牵扯出更多的知识。

所以学习算法要视情况而定,如果想走算法岗,那么《算法第4版》、《算法导论》、《数学之美》、《编程珠玑》、《剑指offer》这些书都要耐着性子啃一啃。电子书可以在下面这个 GitHub 仓库上找得到。

https://github.com/itwanger/JavaBooks

顺带再推荐一份阿里大佬的算法刷题笔记吧,在 GitHub 上已经有 13.3k 的 star 了。里面的每道题都写了解题思路,是通过 GO 语言实现的,每道题都 runtime beats 100% 了。

在线阅读地址如下所示:

https://books.halfrost.com/le...

03、设计模式

我认为设计模式是初中级程序员迈向高级程序员的必经之路。有不少程序员,前期冲劲十足,但后继乏力,都是吃了设计模式的亏。

在工作的前几年,大部分程序员都处于熟悉编程语言的阶段,也就是处于“技”的阶段,随后就要进入“术”的阶段了。在编程领域,“术”的典型代表就是“设计模式”。

我自己推荐的一本书是《设计模式之禅》,代码是用 Java 实现的,读起来比较轻松,也更符合国内程序员的阅读习惯。

另外就是我上次推荐的 Refactoring Guru 网站,里面附带的图片非常精美,阅读起来的视觉效果会比较丰富。

在线阅读地址如下所示:

https://refactoring.guru

离线版可以通过下面这个链接下载(无套路,不需要解压密码):

设计模式,牛逼!

04、软件工程

实现一个软件系统的过程,不仅只有编码,还涉及到项目安排,团队协调等一系列非技术因素,如果想从一名程序员走向管理岗,成为 team leader 或者开发经理,软件工程方面的知识就必须得跟得上。

这里我推荐几本不错的经典书,其中有一本邹欣老师的书,他刚出任 CSDN 副总裁,希望 CSDN 能在他的入驻后变得更好一些。他这本书的书名叫做《构建之法》,我看过,还是很不错的。

另外还有两本必读,就是《人月神话》和《人件》,虽然有了岁月的痕迹,但依然值得深读。当然,关于软件工程,最好的学习方法是观察,观察你所在的团队是如何处理工程问题的,然后思考,最终形成自己的方法观。

电子书可以在下面这个 GitHub 仓库上找得到。

https://github.com/itwanger/JavaBooks

05、架构 & 设计

要想写出一个好而美的程序,需要经过三个阶段。

第一阶段,有扎实的基本功,简单点说,就是要做到语法熟练、框架熟练,成为一名能够完成开发任务的“码农”。

第二阶段,从“码农”到“工程师”,在局部上,不仅要能够实现功能,还能关注功能之外的维度,比如健壮性、低耦合、可扩展等指标。

第三阶段,从“工程师”到“架构师”,不仅在局部上追求一个模块的好坏,而且还要从整个系统层面去掌控,合理安排资源的优先级,保证整个系统不会出现腐败等等。

要想成为一名优秀的架构师,除了自身的努力,也需要一点点运气,但靠读书可能不够,但这些经典书籍还是要阅读的,能给日常的工作带来巨大的帮助。

  • 《代码大全》
  • 《重构:改善既有代码的设计》
  • 《设计原本》
  • 《大型网站技术架构核心原理与案例分析》

电子书可以在下面这个 GitHub 仓库上找得到。

https://github.com/itwanger/JavaBooks

最后

技术这条道路并不好走,不仅要学习很多新技术、新框架,还要及时补充必要的计算机基础知识,底子硬的同时还要学会拥抱变化。

学习的过程,就好像登山一样,大概有 80% 的人在这个过程中会掉队。那么请相信我,只要目标明确,努力加上坚持,再加上一点点好运气,你就能登顶!

好了,我是沉默王二,希望这篇文章能够帮到你!下期见。

查看原文

赞 0 收藏 0 评论 0

沉默王二 发布了文章 · 2月24日

狂补计算机基础知识,让我上了瘾,从此不再是一名被人歧视的 CURD boy

思否的小伙伴们,大家好,我是沉默王二。最近我在狂补计算机基础知识,感觉有点上瘾!以前觉得很枯燥的知识,现在竟然有点香!不知道为什么。

我算是科班出身,大学的专业就是计算机网络,不过老实说,在实际的开发中,大学的很多课程,要么“用处”不大,要么可以换个方式,更高效的学习。

其中的原因,一方面是实际开发更关注知识的“实用”,另外一方面,大学的教学确实和产业有些脱钩。所以我就从实际应用的角度出发,重新来梳理一下计算机基础方面的知识。

01、数据结构

毫无疑问,数据结构对一名程序员来说非常重要,还是那句话程序=数据结构+算法,这种说法无论放在什么时候都是成立的。

大部分的数据结构课程,关注的重点都在如何从数学上实现一个数据结构,但在实际开发中,大部分主流语言都已经内置了常见的数据结构,比如说 Java。也就是说,对于大部分程序员来说,实际开发中,很难有需求要从零开始实现一个数据结构。因此我们只需要做到下面几点。

1、熟悉常见数据结构的概念,比如说数组、堆栈、链表、哈希表等。

2、了解常用数据结构之间的差异,比如说 ArrayList 和 LinkedList,我在之前的文章中有详细说明过,可以点击链接去查看下。

3、关注常用数据结构的外围算法,比如说如何对 List 和 Map 进行查找。

4、关注数据结构使用中容易出错的地方,比如说线程是否安全等。

...

B 站上浙江大学的一个数据结构的课还不错,很系统很经典,适合小白入门。

视频地址如下。

https://www.bilibili.com/vide...

02、算法

以我接触的领域来说,大部分普通的业务系统都不会涉及到太复杂的算法,因此我没有在算法上投入过多时间。

但如果你在一些特殊的领域,如果算法跟不上,可以说是“寸步难行”,比如说图形处理领域,无论是图像的变化还是增强,无一例外都要用到矩阵变换,因此就必然涉及到线性代数的内容,再往深处学的话,必然会牵扯出更多的知识。

所以学习算法要视情况而定,如果想走算法岗,那么《算法第4版》、《算法导论》、《数学之美》、《编程珠玑》、《剑指offer》这些书都要耐着性子啃一啃。

顺带再推荐一份阿里大佬的算法刷题笔记吧,在 GitHub 上已经有 13.3k 的 star 了。里面的每道题都写了解题思路,是通过 GO 语言实现的,每道题都 runtime beats 100% 了。

在线阅读地址如下所示:

https://books.halfrost.com/le...

03、设计模式

我认为设计模式是初中级程序员迈向高级程序员的必经之路。有不少程序员,前期冲劲十足,但后继乏力,都是吃了设计模式的亏。

在工作的前几年,大部分程序员都处于熟悉编程语言的阶段,也就是处于“技”的阶段,随后就要进入“术”的阶段了。在编程领域,“术”的典型代表就是“设计模式”。

我自己推荐的一本书是《设计模式之禅》,代码是用 Java 实现的,读起来比较轻松,也更符合国内程序员的阅读习惯。

另外就是我上次推荐的 Refactoring Guru 网站,里面附带的图片非常精美,阅读起来的视觉效果会比较丰富。

在线阅读地址如下所示:

https://refactoring.guru

离线版可以通过下面这个链接下载(无套路,不需要解压密码):

设计模式,牛逼!

04、软件工程

实现一个软件系统的过程,不仅只有编码,还涉及到项目安排,团队协调等一系列非技术因素,如果想从一名程序员走向管理岗,成为 team leader 或者开发经理,软件工程方面的知识就必须得跟得上。

这里我推荐几本不错的经典书,其中有一本邹欣老师的书,他刚出任 CSDN 副总裁,希望 CSDN 能在他的入驻后变得更好一些。他这本书的书名叫做《构建之法》,我看过,还是很不错的。

另外还有两本必读,就是《人月神话》和《人件》,虽然有了岁月的痕迹,但依然值得深读。当然,关于软件工程,最好的学习方法是观察,观察你所在的团队是如何处理工程问题的,然后思考,最终形成自己的方法观。

05、架构 & 设计

要想写出一个好而美的程序,需要经过三个阶段。

第一阶段,有扎实的基本功,简单点说,就是要做到语法熟练、框架熟练,成为一名能够完成开发任务的“码农”。

第二阶段,从“码农”到“工程师”,在局部上,不仅要能够实现功能,还能关注功能之外的维度,比如健壮性、低耦合、可扩展等指标。

第三阶段,从“工程师”到“架构师”,不仅在局部上追求一个模块的好坏,而且还要从整个系统层面去掌控,合理安排资源的优先级,保证整个系统不会出现腐败等等。

要想成为一名优秀的架构师,除了自身的努力,也需要一点点运气,但靠读书可能不够,但这些经典书籍还是要阅读的,能给日常的工作带来巨大的帮助。

  • 《代码大全》
  • 《重构:改善既有代码的设计》
  • 《设计原本》
  • 《大型网站技术架构核心原理与案例分析》

最后

技术这条道路并不好走,不仅要学习很多新技术、新框架,还要及时补充必要的计算机基础知识,底子硬的同时还要学会拥抱变化。

学习的过程,就好像登山一样,大概有 80% 的人在这个过程中会掉队。那么请相信我,只要目标明确,努力加上坚持,再加上一点点好运气,你就能登顶!

好了,我是沉默王二,希望这篇文章能够帮到你!下期见。

查看原文

赞 13 收藏 11 评论 1

沉默王二 发布了文章 · 2月8日

大学寒假这样过,过完惊艳所有人,不只是你的宿友,还有千千万万个程序员同行们!!!

先来看这样一个计划:

6:30 起床洗漱
7:30 早餐
8:00 背英语单词
9:30 健身,简单运动
12:00 美味午饭
14:00 饭后午休/朋友谈心
16:00 看部电影/学计算机编程
18:00 舒心晚餐
20:00 读书
22:00 睡觉

瞧瞧,瞧瞧,同学们瞧瞧,这个计划整得怎么样?很充实很详细吧!but,如果你能这样坚持一个寒假,算我输,你不是人,你已经成仙了!

说句实在话,临近放假了,我自己都有点飘飘然,心不静,真的。工作上只求稳妥,不求表现,顺顺利利把这一周多的时间耗过去就是福啊,千万别出幺蛾子。

说个我身边的例子吧。我妹,真的身边人,已经放假二十多天了,电脑就没打开过,一行代码都没敲过,所以我得赶紧整个靠谱的方案给她规划一下。

PS:在此之前,我专门针对她写过一个回答:

计算机学院的学生该怎样提高自己的编程能力?

其实吧,我们也没必要自我欺骗,说要完成几个或者十几个目标,完成一两个目标就很不错了。毕竟,我们都是个平凡的人哪。

寒假一个半月的时间,我认为一名大学生可以从 4 个方面着手,个人提升、学习考证、额外技能、面试刷题。

01、个人提升

假期的时间是最连贯的,几乎零打扰。除了偶尔约同学出去逛个街、喝个小酒,剩下的时间大把大把,真的是这样,饭不用做,衣服不用洗,父母给安排的明明白白的。

时间这么充沛的情况下,通过视频来提升自己应该是最恰当的方式了,因为视频的整个体系都是非常完整的,比起白纸黑字,视频的观感也更符合大学生的诉求。

在我看来,B 站是一个非常牛逼的学习网站(真心的),上面的内容包罗万象,应有尽有。比如计算机网络、计算机组成原理、操作系统、数据库、算法与数据结构,以及各种编程语言的学习教程。

1)计算机网络

当今这个时代,没有网络简直无法生存,哪怕是在电梯里的一分钟,我都受不了那种手机没有网络的状态。我们所学的编程知识,如果脱离了网络,将变得毫无意义,因为没有哪个编程语言是要在单机环境下运行的。

计算机网络方面的视频我推荐湖科大教书匠的《计算机网络微课堂》,制作得非常用心,是一部不可多得的佳作。目前更新了 73 小节,每节 20 分钟左右,很适合在假期刷。

视频地址如下所示:

https://www.bilibili.com/vide...

2)计算机组成原理

众所周知,计算机是由 CPU、内存、显示器这些设备组成的硬件,但我们大学毕业后,往往从事的是软件方面的开发工作。那怎样才能在硬件和软件之间自由穿梭呢?答案就是学好计算机组成原理。

弄明白了计算机的组成原理,也就对整个软件开发有了一个系统的认知,不论是计算机的硬件原理,还是软件架构,都能很好的驾驭,随之而来的,我们的职业发展机会也就更多了。

如果想深入学习计算机组成原理的话,我推荐哈工大的这门视频课,整体评价非常高。一共 128 节,每节课差不多 10 分钟左右,建议 1.5 倍速食用。

视频地址如下所示:

https://www.bilibili.com/vide...

3)操作系统

为什么要学习操作系统呢?第一,面试要考;第二,无论学习哪门子编程语言,比如说 Java、C/C++,还是 D++(走错片场了),都需要和操作系统打交道,像 Java 中的多线程技术,其实是由操作系统来负责进程和线程管理的;第三,学习操作系统,还能学到内存分配方面的知识。

我推荐清华大学的《操作系统》课,虽然清华大学的校门进不去,清华大学的视频课还是可以白嫖的嘛。一共 98 小节,每节课差不多 15 分钟左右。

视频地址如下所示:

https://www.bilibili.com/vide...

关于计算机网络、计算机组成原理、操作系统之间的关系,我们可以用一幅图来表示下。

4) 数据库

数据库,其实是一种经常被我们忽略,但实际上相当重要的课程,尤其是在海量数据的信息化时代。使用数据库可以高效且条理分明地存储数据,方便我们进行有效的检索和访问。一个软件如果没有数据库的支撑,就相当于空有一副皮囊却没有灵魂。

要想学好数据,首先要学习一下 SQL,我推荐一个老外的视频课(中字版啦),内容制作得非常棒,所以完全不用担心听不懂。155 小节,但每节课大概只有 1 分钟或者 5 分钟的长度,真 10 个小时就能学完。

视频地址如下所示:

https://www.bilibili.com/vide...

然后再学习一下市场占有率非常高的 MySQL,视频我推荐尚硅谷的一个课程,女老师讲的。不得不承认,老师讲得很精彩,嗯,弹幕里也很精彩。350 集,内容量巨大。

视频地址如下所示:

https://www.bilibili.com/vide...

目前大多数公司的存储都是 MySQL + Redis,MySQL 作为主要的存储方式,Redis 作为缓存,用来加快热点数据的读写速度,从而提高性能。所以学完 MySQL,可以趁热打铁学一下 Redis。我推荐狂神说的 Redis 课程,一共 36 小节,每节课差不多 20 分钟

视频地址如下所示:

https://www.bilibili.com/vide...

5) 算法与数据结构

无论什么时候,程序=数据结构+算法这种说法都是成立的。浙江大学的一个的课还是挺不错的(我推荐过很多次了),很系统很经典,适合小白入门。143 小节,每节课五六分钟,男女老师混合讲,不同的台风,学习起来也会轻松一些。

视频地址如下所示:

https://www.bilibili.com/vide...

6)编程语言

学完基础课,就要学编程语言了,也只有学了编程语言,我们程序员才能写出有应用价值的程序,才能在毕业后找到一份称心如意的工作。如果时间充足的话,我建议先学习 C 语言打好基础,然后再学 C++ 或者 Java 作为工作语言。

学习 C 语言的话,我推荐浙江大学的翁恺教授的课程,讲得非常棒,我已经是第 3 次推荐了吧。132 小节,每节课差不多 10 分钟,学习起来很轻松。老师背后的书是真的多,有不少是英文原版的,我偷偷地买了好几本,哈哈。

视频地址如下所示:

https://www.bilibili.com/vide...

学习 C++ 的话,推荐侯捷老师的全家桶。不过,由于版权问题,B 站上已经全部下架了,很可惜。不过,油管上还可以看,直接搜「侯捷」就可以了。基本上看过的人都说好,强烈推荐。

学习 Java 的话,推荐尚硅谷的一个课程,717 小节,我天呐,必须 2.0 倍速食用!

视频地址如下所示:

https://www.bilibili.com/vide...

02、学习考证

考证方面,我认为大学最重要的就是四六级了,对于我们程序员来说,英语功底好一些,优势还是非常大的。四六级早点考的话,还可以吃一吃高中时候的老本。

温馨提示,千万不要把四六级考试当做是走流程,报名费虽然不贵,但还是要心疼一下的。要想一次性过四级,难度应该不大,一次性过六级的话,可能有点难度,但重要的是,一定要多做真题,多做真题,多做真题。考试前的一个月,最好每天做 2 套真题。

考试考的就是阅读理解,单词如果都不认识的话,上下文的意思就不可能读的懂。所以单词还是要背的,就像学习古诗词一样,如果背不会的,装文化人的时候会吃亏啊。

然后就是听力,多刷刷美剧还是有好处的,推荐《绝望的主妇》、《老友记》、《生活大爆炸》。

再然后是写作,这玩意必须多练,把近十年的真题全部过一遍,分门别类下,找出适合自己的套路。

对了,除了四六级,还有个驾照,这个我之前也提到过,还是要趁大学的时候考一下。

如果想考公务员或者考研,假期的时间一定要利用起来,提前规划好。

03、额外技能

现如今,我认为这 3 个额外技能非常非常非常重要:

1、PS

2、视频剪辑

3、PPT

先说 PS。

我这个头像大家也看到了,很佛,像个四五十岁的大叔。一直想换一个年轻态点的头像,又怕这个头像形成了品牌文化,换一个后大家需要重新去记忆。

一开始就迫切想要一张个性化的头像,但没找到合适的,就用的迈克尔杰克逊,后来掏了 36 块钱请一个专业设计师 PS 了一个(就是目前这个),虽然不太满意,但奈何自己不会 P。

我大学那会是有 PS 这门课的,只不过那时候没有好好学,导致工作后 PS 个背景图了,或者搞个二维码了,还得找人 PS,很麻烦。想学 PS 的话,我推荐《敬伟 PS 教程全集》,202 集,制作非常精良。

视频地址如下所示:

https://www.bilibili.com/vide...

再说视频剪辑。

啊,这篇内容已经推荐了好多好多视频了,可想而知,视频剪辑的重要性多么的不言而喻。不论是刷 B 站,还是刷抖音,每个视频都是经过精心处理的,如果不是精心处理过的,那基本上不会进入我们的视野,因为视频实在是太能喝了——海量啊。

视频的商业价值就不用我再赘言了吧,瞧瞧 B 站的股价就能明白,瞧瞧张小龙对视频号的重视程度就知道。如果能够剪得一手好视频,大学就能自己养活自己。

我推荐 vikk 的视频剪辑教学,一共就 8 节课,可以说是寓教于乐,干货满满。

最后说说 PPT。

这么说吧,如果能够写得一手好 PPT,不光能像贾跃亭那样揽财无数,还能在公开演讲、述职报告、年终总结、季度汇报上大放异彩。记得之前某个明星的危机公关都上的 PPT,嘿嘿嘿。

至于 PPT 方面的视频,我就不再推荐了,算是留给同学们的作业题。

04、面试刷题

经常有同学问我刷题重不重要,这个问题真的不需要多问了,如果不重要的话,就不叫面试刷题了。公司怎么考核你,最简单的方法就是通过面试题,你平常学那么多,用了那么多功,到头来,怎么证明自己有能力,就是面试题。

那有些同学可能要问了,我才大一,要刷题吗?

当然要啊,提前做准备,把刷题的道路摸清楚它不香吗?临时抱佛脚可能有用,但长期的积累才是根本,对吧?

提前就刷起来,到时候绝不会吃亏!我问了身边很多大佬,他们给我推荐一份刷题笔记,真心不错呀!来自一位 BAT 的大佬,真踏马强啊,不服不行。

可通过下面的链接获取这份 PDF。

https://zhuanlan.zhihu.com/p/348106459

05、总结

寒假是个沉淀期,利用得好,开学后就会焕然一新;利用得不好,开学后就会感觉身上附了一层灰,还要花一点时间去适应,才能进入学习状态。

每个人的喜好都是不同的,所以寒假到底怎么过没有标准的答案。但有一点很清楚,寒假绝不是让我们整天追剧打游戏的,也绝不是每天睡到太阳晒到屁股的。

我不建议大家做什么天衣无缝的计划表,因为一旦落实不了反而背负上沉甸甸的愧疚感。该玩的时候尽情的玩,放松完了切记还有习要学,就对了。

最后,希望大家在寒假的时候多陪陪父母吧,毕竟工作后可能就天南海北了,一年见不上几次面了。我当时就这样,毕业的时候去了苏州,每年回洛阳最多两次,有时候真的特别想家,但又不能想回就回。

好了,就说这么多吧,加油!同学们

看完两件事:

如果你觉得这篇内容对你挺有帮助,我想邀请你帮我两个忙~

1、点赞,让更多的人也能看到这篇内容(收藏不点赞,都是耍流氓啊)

2、年关将近,码字不易,记得关注 

@沉默王二

 哟,让我们成为长期关系。

查看原文

赞 11 收藏 10 评论 0

沉默王二 发布了文章 · 2月3日

GitHub 标星 167k!你要的优质书籍这都有,还开源!


主题列表:juejin, github, smartblue, cyanosis, channing-cyan, fancy, hydrogen, condensed-night-purple, greenwillow, v-green, vue-pro, healer-readable, mk-cute, jzman, geek-black, awesome-green, qklhk-chocolate

贡献主题:https://github.com/xitu/jueji...

theme: juejin

highlight:

马克西姆·高尔基曾说过,“书籍是人类进步的阶梯。”不服不行,这句话放在任何时候都是成立的。

以前,书籍少,人们获取知识的途径少,那基本上只要有书读的,都能在短时间内领先于其他人。

现在,我们再也不愁没有书读了,获取知识的信息源越来越多。但这又造成了另外一种困扰,就是我们不知道哪些书是好书,哪些书是烂书。

我家里屯有 3000 多本纸质书,但实话实说,有不少烂书,读的时候让我懊恼不已。要知道,浪费买书的钱是小事,浪费读书的时间。。。。。。听,那是 money 在碎钞机中的声音。

信息时代,生活的节奏越来越快,快到我们似乎没有时间去读书。但更确切地说,应该是我们没有时间去书籍的海洋中筛选出值得读的书,或者说我们不知道读书的顺序是什么。

我之前在知乎上回答过一个提问:“Java 书籍的最佳阅读顺序”,已经累计 1872 个赞,10600 次收藏,145 万阅读量。这个数据还是非常可观的,这说明我的经验帮助到了不少人。

地址我这里贴一下,感兴趣的小伙伴可以去围观下,如果阅读后感觉还不错,就顺带点个赞,让更多需要的小伙伴看得到——赠人玫瑰,手留余香。

https://www.zhihu.com/question/269505829/answer/933582331

除此之外,我还有一个珍藏了很久很久的开源书库推荐给大家,GitHub 上标星 167k,多达 6045 次提交,可以说非常的宝藏了。

来看一下详细的目录:

基本上与我们程序员相关的主题都包含在内了,有编程语言无关的 IDE、分布式、大数据、操作系统、数据库、编译原理、设计模式等等,还有编程语言相关的 Java、C、C++、C#、MySQL、JavaScript、Swift、Golang 等等,应有具有,包罗万象。

比如我们要学习操作系统、版本控制,按图索骥,就可以找到下面这些优质的书单。

每一本书都有对应的在线阅读地址,比如说这本《Docker 从入门到实践》。

这些都是开源的,没有版权问题,所以大家不需要担心。有些小伙伴可能会问,“二哥,有没有离线版的啊?有时候信号不好,在线阅读起来比较费劲。”我只能说,我替大家考虑周全了,离线版也帮大家准备了一些,通过下面的地址就可以获取。

GitHub:https://github.com/itwanger/JavaBooks

码云:https://gitee.com/itwanger/JavaBooks

小伙伴们方便的话,可以给 free-programming-books 的作者点个 Star 鼓励一下。我自己也是 https://github.com/itwanger/JavaBooks 项目的作者,深知开源的不易,需要耗费大量的心血。大家一个小小的鼓励,也许就是开源作者们创作的最强动力(逃。

说实话,快过年了,心有点静不下来。但是,我还是希望思否上的小伙伴们能在假期多读几本书吧,悄悄惊艳,悄悄膨胀,哈哈

查看原文

赞 8 收藏 7 评论 1

沉默王二 发布了文章 · 1月29日

Guava - 拯救垃圾代码,写出优雅高效,效率提升N倍

01、前世今生

你好呀,我是 Guava。

1995 年的时候,我的“公明”哥哥——Java 出生了。经过 20 年的发展,他已经成为世界上最流行的编程语言了,请允许我有失公允的把“之一”给去了。

虽然他时常遭受着各种各样的吐槽,但他始终没有停下前进的脚步。除了他本身的不断进化,围绕着他的大大小小的兄弟们也在不断地更新迭代。我正是在这样的背景下应运而生的,我简单易用,对我大哥是一个非常好的补充,可以说,只要你有使用我哥作为开发语言的项目,几乎都能看到我的身影。

我由 Google 公司开源,目前在 GitHub 上已经有 39.9k 的铁粉了,由此可以证明我的受欢迎程度。

我的身体里主要包含有这些常用的模块:集合 [collections] 、缓存 [caching] 、原生类型支持 [primitives support] 、并发库 [concurrency libraries] 、通用注解 [common annotations] 、字符串处理 [string processing] 、I/O 等。新版的 JDK 中已经直接把我引入了,可想而知我有多优秀,忍不住骄傲了。

这么说吧,学好如何使用我,能让你在编程中变得更快乐,写出更优雅的代码!

02、引入 Guava

如果你要在 Maven 项目使用我的话,需要先在 pom.xml 文件中引入我的依赖。

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>30.1-jre</version>
</dependency>

一点要求,JDK 版本需要在 8 以上。

03、基本工具

Doug Lea,java.util.concurrent 包的作者,曾说过一句话:“null 真糟糕”。Tony Hoare,图灵奖得主、快速排序算法的作者,当然也是 null 的创建者,也曾说过类似的话:“null 的使用,让我损失了十亿美元。”鉴于此,我用 Optional 来表示可能为 null 的对象。

代码示例如下所示。

Optional<Integer> possible = Optional.of(5);
possible.isPresent(); // returns true
possible.get(); // returns 5

我大哥在 JDK 8 中新增了 Optional 类,显然是从我这借鉴过去的,不过他的和我的有些不同。

  • 我的 Optional 是 abstract 的,意味着我可以有子类对象;我大哥的是 final 的,意味着没有子类对象。
  • 我的 Optional 实现了 Serializable 接口,可以序列化;我大哥的没有。
  • 我的一些方法和我大哥的也不尽相同。

使用 Optional 除了赋予 null 语义,增加了可读性,最大的优点在于它是一种傻瓜式的防护。Optional 迫使你积极思考引用缺失的情况,因为你必须显式地从 Optional 获取引用。

除了 Optional 之外,我还提供了:

  • 参数校验
  • 常见的 Object 方法,比如说 Objects.equals、Objects.hashCode,JDK 7 引入的 Objects 类提供同样的方法,当然也是从我这借鉴的灵感。
  • 更强大的比较器

04、集合

首先我来说一下,为什么需要不可变集合。

  • 保证线程安全。在并发程序中,使用不可变集合既保证线程的安全性,也大大地增强了并发时的效率(跟并发锁方式相比)。
  • 如果一个对象不需要支持修改操作,不可变的集合将会节省空间和时间的开销。
  • 可以当作一个常量来对待,并且集合中的对象在以后也不会被改变。

与 JDK 中提供的不可变集合相比,我提供的 Immutable 才是真正的不可变,我为什么这么说呢?来看下面这个示例。

下面的代码利用 JDK 的 Collections.unmodifiableList(list) 得到一个不可修改的集合 unmodifiableList。

List list = new ArrayList();
list.add("雷军");
list.add("乔布斯");

List unmodifiableList = Collections.unmodifiableList(list);
unmodifiableList.add("马云");

运行代码将会出现以下异常:

Exception in thread "main" java.lang.UnsupportedOperationException
    at java.base/java.util.Collections$UnmodifiableCollection.add(Collections.java:1060)
    at com.itwanger.guava.NullTest.main(NullTest.java:29)

很好,执行 unmodifiableList.add() 的时候抛出了 UnsupportedOperationException 异常,说明 Collections.unmodifiableList() 返回了一个不可变集合。但真的是这样吗?

你可以把 unmodifiableList.add() 换成 list.add()

List list = new ArrayList();
list.add("雷军");
list.add("乔布斯");

List unmodifiableList = Collections.unmodifiableList(list);
list.add("马云");

再次执行的话,程序并没有报错,并且你会发现 unmodifiableList 中真的多了一个元素。说明什么呢?

Collections.unmodifiableList(…) 实现的不是真正的不可变集合,当原始集合被修改后,不可变集合里面的元素也是跟着发生变化。

我就不会犯这种错,来看下面的代码。

List<String> stringArrayList = Lists.newArrayList("雷军","乔布斯");
ImmutableList<String> immutableList = ImmutableList.copyOf(stringArrayList);
immutableList.add("马云");

尝试 immutableList.add() 的时候会抛出 UnsupportedOperationException。我在源码中已经把 add() 方法废弃了。

  /**
   * Guaranteed to throw an exception and leave the collection unmodified.
   *
   * @throws UnsupportedOperationException always
   * @deprecated Unsupported operation.
   */
  @CanIgnoreReturnValue
  @Deprecated
  @Override
  public final boolean add(E e) {
    throw new UnsupportedOperationException();
  }

尝试 stringArrayList.add() 修改原集合的时候 immutableList 并不会因此而发生改变。

除了不可变集合以外,我还提供了新的集合类型,比如说:

  • Multiset,可以多次添加相等的元素。当把 Multiset 看成普通的 Collection 时,它表现得就像无序的 ArrayList;当把 Multiset 看作 Map<E, Integer> 时,它也提供了符合性能期望的查询操作。
  • Multimap,可以很容易地把一个键映射到多个值。
  • BiMap,一种特殊的 Map,可以用 inverse() 反转
    BiMap<K, V> 的键值映射;保证值是唯一的,因此 values() 返回 Set 而不是普通的 Collection。

05、字符串处理

字符串表示字符的不可变序列,创建后就不能更改。在我们日常的工作中,字符串的使用非常频繁,熟练的对其操作可以极大的提升我们的工作效率。

我提供了连接器——Joiner,可以用分隔符把字符串序列连接起来。下面的代码将会返回“雷军; 乔布斯”,你可以使用 useForNull(String) 方法用某个字符串来替换 null,而不像 skipNulls() 方法那样直接忽略 null。

Joiner joiner = Joiner.on("; ").skipNulls();
return joiner.join("雷军", null, "乔布斯");

我还提供了拆分器—— Splitter,可以按照指定的分隔符把字符串序列进行拆分。

Splitter.on(',')
        .trimResults()
        .omitEmptyStrings()
        .split("雷军,乔布斯,,   沉默王二");

06、缓存

缓存在很多场景下都是相当有用的。你应该知道,检索一个值的代价很高,尤其是需要不止一次获取值的时候,就应当考虑使用缓存。

我提供的 Cache 和 ConcurrentMap 很相似,但也不完全一样。最基本的区别是 ConcurrentMap 会一直保存所有添加的元素,直到显式地移除。相对地,我提供的 Cache 为了限制内存占用,通常都设定为自动回收元素。

如果你愿意消耗一些内存空间来提升速度,你能预料到某些键会被查询一次以上,缓存中存放的数据总量不会超出内存容量,就可以使用 Cache。

来个示例你感受下吧。

@Test
public void testCache() throws ExecutionException, InterruptedException {

    CacheLoader cacheLoader = new CacheLoader<String, Animal>() {
        // 如果找不到元素,会调用这里
        @Override
        public Animal load(String s) {
            return null;
        }
    };
    LoadingCache<String, Animal> loadingCache = CacheBuilder.newBuilder()
        .maximumSize(1000) // 容量
        .expireAfterWrite(3, TimeUnit.SECONDS) // 过期时间
        .removalListener(new MyRemovalListener()) // 失效监听器
        .build(cacheLoader); //
    loadingCache.put("狗", new Animal("旺财", 1));
    loadingCache.put("猫", new Animal("汤姆", 3));
    loadingCache.put("狼", new Animal("灰太狼", 4));

    loadingCache.invalidate("猫"); // 手动失效

    Animal animal = loadingCache.get("狼");
    System.out.println(animal);
    Thread.sleep(4 * 1000);
    // 狼已经自动过去,获取为 null 值报错
    System.out.println(loadingCache.get("狼"));
}

/**
 * 缓存移除监听器
 */
class MyRemovalListener implements RemovalListener<String, Animal> {

    @Override
    public void onRemoval(RemovalNotification<String, Animal> notification) {
        String reason = String.format("key=%s,value=%s,reason=%s", notification.getKey(), notification.getValue(), notification.getCause());
        System.out.println(reason);
    }
}

class Animal {
    private String name;
    private Integer age;

    public Animal(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
}

CacheLoader 中重写了 load 方法,这个方法会在查询缓存没有命中时被调用,我这里直接返回了 null,其实这样会在没有命中时抛出 CacheLoader returned null for key 异常信息。

MyRemovalListener 作为缓存元素失效时的监听类,在有元素缓存失效时会自动调用 onRemoval 方法,这里需要注意的是这个方法是同步方法,如果这里耗时较长,会阻塞直到处理完成。

LoadingCache 就是缓存的主要操作对象了,常用的就是其中的 put 和 get 方法了。

07、尾声

上面介绍了我认为最常用的功能,作为 Google 公司开源的 Java 开发核心库,个人觉得实用性还是很高的(不然呢?嘿嘿嘿)。引入到你的项目后不仅能快速的实现一些开发中常用的功能,而且还可以让代码更加的优雅简洁。

我觉得适用于每一个 Java 项目,至于其他的一些功能,比如说散列、事件总线、数学运算、反射,就等待你去发掘了。

另外,我为你准备了一份中文版的官方文档(部分目录见上图),一共 190 页,写得非常详细,强烈建议你通过下面的方式下载一份放在桌面上!

链接:https://pan.baidu.com/s/1hrfaArC3UH6_ZNZEWCKzXA 密码:684a

推荐阅读:

自学java,学多久可以自己找到工作?

看完谷歌学长的刷题笔记,我决定 2021 年手撕这101道 Leetcode 算法题

如果内容对你有所帮助的话,请给我点个赞吧,笔芯~,你最美你最帅,你 2021 年发大财。

查看原文

赞 4 收藏 2 评论 1

沉默王二 发布了文章 · 1月14日

2020总结文章|乘风破浪的一年

前言

你好呀,我是沉默王二。放在一年前,打死我也不相信,这四个平淡无奇的字组合在一起竟然充满了魔力!估计你也想不到。

还有十多天,2020 年就过去了,这一年,我经历了很多,成长了很多,也收获了很多。多的是,你不知道的事(无厘头的竟然接了一首王力宏的歌,你笑还是不笑)。

2019 年的时候,我看过一本书,名叫《影响力》,应该有不少读者也看过。但说实在的,这本书我就看了几页,就看不下去了,不是这书不好,而是我觉得它不适合我,因为我那时候没什么影响力(谦虚点)。

没有影响力的时候想着怎么扩大影响力,我就觉得有点扯淡。就像没有财的时候想着理财一样,有点白日做梦。

与其白日做梦,不如脚踏实地,换一句浅显易懂的话,就是,与其想着理财,不如想想怎么攒钱。如果连原始资本都“攒”不住的话,“理”就无从谈起,对吧?

同样的,影响力这东西,需要有一定量的作品,需要时间的积累,还需要个人魅力、运气和时机,缺哪样都不行。

但讲良心话,这年头,影响力真的非常非常非常重要。

你应该知道王一博吧,很火的一个新生代偶像。我一个程序员,为什么要提一个流量明星?没错,我想蹭他的热度,因为他是洛阳人(裂开),更关键的是,他和我都住在涧西区,名字里还带个王字,我笔名,他艺名。

假如让王一博和我同时站台为洛阳带盐的话,估计我应该在台下,不应该在台上(女粉给我踹下去的)。

这就是影响力的体现。同样一件事,不同影响力的人去做,效果是完全不同的。由此可见,影响力的重要性和稀缺性,说得裸露一点就是,影响力还可以兑换成 money。

至于如何兑换成 money?我猜你一定很感兴趣,但是,任性的我选择略过,因为我们先要解决的是,如何打造你的技术影响力,这方面,我还是有些经验的。

如何打造呢?说起来,也挺简单,就是在各大平台上贡献有价值的内容。落实到操作层面,无非就两样,写作和视频。

视频

2020 年,视频行业呈现出前所未有的爆棚式发展。B 站成了技术人的第一选择,能露脸的,敢露脸的,都在上面尝试了一把,并且有些做得还不错。

视频方面我是个菜逼,拍了六个短视频,发在微信视频号上,播放量加起来不到 3 万,于是就草率地放弃了。

我感觉啊,这视频号除了能曝光我的盛世美颜,别的效果是一点没看到。虽然张小龙和各种大 V 都在吹捧视频号的发展潜力,但我就是鼠目寸光,实在是感受不到。

我还拍了两个长点的视频,大约十分钟,放在 B 站、知乎和 CSDN 上,但播放量加起来也就不到一万。为什么没有火呢?答案显而易见,视频的质量有待提升——有实力的人还有自知之明,这事你怎么能忍?

是个人都在说,视频是未来。但鞋子合不合脚,只有自己知道(我怎么联想到了郭天王)。

总之呢,视频这块我没有话语权,保持沉默,不再多比比,就只说写作吧!

写作

先说说我身边的几个朋友吧,他们无一例外,都是通过写作建立起来的影响力。

第一个,我想到的就是纯洁的微笑。我在写作方面之所以能突飞猛进,除了源于我自身的努力,微笑哥在初期给了我不少无私的帮助。

微笑哥是通过分享 Spring Boot 方面的技术文章起家的,这方面的成就至今应该无人超越。Spring Boot 刚开始流行的时候,微笑哥就开始在博客园分享这方面的技术文章了。

如果我没记错的话,他分享的一篇 Spring Boot 入门的文章,阅读量就有一百多万,随着时间的推移,这个数目也会不断的攀升。要说这篇文章,文采上肯定没什么特色,就是一个“早”字。

但是,绝大多数的技术人,当然包括我在内,缺的就是这种眼力见,说得优雅点就是对技术的敏锐嗅觉。微笑哥就有,所以他的影响力有目共睹。

如果你恰好就有这种洞察力,那甭管在什么平台,都能够取得瞩目的成绩。因为生意经里有一句话,真的非常经典,放在写文章方面也是再适合不过了。

人无我有,人有我好,人好我早,人多我早。

第二个,我的好朋友,江南一点雨。我俩差不多在相同的时间段起步,但他跑得更快一些。

松哥(小朋友,你是不是有很多问号,为什么不叫雨哥)步了微笑哥的“后尘”(必须得加双引号),也是通过 Spring Boot 起家的,虽然比微笑哥晚一些,但仍然吸引了一大批忠实的读者。

你在写作的时候,会不会也有这样的疑惑,“这个技术点别人已经写过了呀,我还有写的必要吗?”

瞧,这个问题的答案松哥就给出了。微笑哥写了 Spring Boot,松哥写的仍然有很多读者喜欢看呀!只要你能写出新意,写出自己的风格,就会有受众,所以完全没必要担心这个问题。

退一万步说,即便是写不出新意,写不出自己的风格,要知道这个世界上的人非常非常多,互联网是没有这个屏障的,总会有人“躲”在某个隐秘的角落里看到你辛苦的付出。

我和松哥平常交流得比较多,他在 GitHub 上开源的 vhr,已经接近 20k 星标了,很强!我是这个项目唯一的 contributor,就说牛逼不牛逼?反正混的。

经常有读者傻傻分不清我俩谁是谁,今天松哥还截图发我,我的回答干脆直接——你就说我俩是 CP。

这个名单如果就这样列下去的话,恐怕会很长很长,长得就像老奶奶的裹脚布。总之,他们俩都是通过写作,建立起了强大的技术影响力,影响了百万级别的读者。

写作秘诀

接下来,再来说说我自己的写作秘诀吧!

我本身是一个很普通很普通的程序员,放在人堆里,除了与生俱来的盛世美颜,就只剩下 173 的大个了。我既没有高学历,又没有大厂背书,靠得就是坚韧不拔的意志力,以及与时俱进的自驱力。

就是我这样的一个废柴,也有着自己与众不同的影响力。随便放几张截图凡尔赛一下。

所以,我的写作秘诀,可能更具有普适性。我相信,只要你努努力,假以时日,就能让我看见你的背影。如果上面这些文字成功地激发了你的写作欲望,那就别再犹豫了,搞起来!

一开始,写什么好呢

ladies and gentlemen,这真的是一个难以起笔的好问题啊。

我认为最好是工作中或者学习中遇到的 bug,噢,不,bug 的解决方案。为什么这么说呢?

第一,bug 的解决方案对搜索引擎非常友好,你不需要标题党,也不需要多充实的内容,就能够获得足够多的浏览量!一旦你的解决方案被搜索引擎收录,那基本上就是源源不断的流量。

第二,同一个问题,可能会被无数人遇到。说得惊悚点就是,韭菜一波又一波。著名的 Stack Overflow 就是靠此为生的呀,光一个 NullPointerException 就足足有 300 万的浏览量。

你敢说你没有遇到过 bug?如果有的话,你过来捶我,我保证不还手,别打脸就行,毕竟我靠脸吃饭,不,靠才华吃饭,用力捶。

写 bug 的解决方案太 low 了,还什么可写的吗?

太多了,我给你说。每个程序员都逃不过面试这一关吧,甭管你是学生还是打工人,总要刷一波面试题或者算法题的,刷 Leecode,或者牛客网,都行。

这些面试题或者算法题,不 low 吧?刷起来是不是就带劲多了?毕竟关系到你以后的薪资和福利待遇。你把解题的思路,以及心得体会记录下来,分享出来,梳理自己的同时也能够帮助更多的小伙伴,两全其美,有木有?

如果可以的话,你甚至可以把解题思路同步到 GitHub 上,一定能俘获不少“芳心”——star 了。如果你的解题思路是最优解,那完了,膜拜你的学弟学妹就多了去了。

不想刷 Leecode?就喜欢读书学习?

也行啊,把读书心得、学习笔记分享出来也可以啊,如果你觉得不好意思,怕写得不好,拿不出手,怕被骂,起个不像样的笔名就行了啊!

网络上的那些键盘侠天不怕地不怕的,你怕啥?别怕,怕来哥保护你,反正我已经被喷得更强大了。

我想翻译,可以吗?

perfect 啊!如果说英语功底比较扎实,翻译可以说是写作道路上的助推器!

对于绝大多数的人来说,“我就是写不出来啊......”是个老生常谈的话题,即便是一个写作了很久的作者来说,也有写不出来的那一天。反正我知道村上春树就曾在他的书里吐露过这样的心声,人家可是一个常年陪跑诺贝尔文学奖的人。

如果你能翻译的话,那岂不是天大的优势?尤其是对于我们技术人员来说,绝大多数的一手资料,都是英文版的。

只要是成熟的技术,都有自己的官网,说明文档特别详细。如果能够在第一时间把这些文档翻译成中文的话,你的影响力能够很快地建立起来,我保证!

不要担心文笔不好,就拿《Effective Java》 这本书来说吧,这本书的译者在豆瓣上都被喷成渣了,但是肯第一个吃螃蟹的人,才是真正的勇士啊!

说白了,我们要的是影响力,不是那些徒有其表的文笔。

解决了不知道写什么的后,我就要送你一句话糙理不糙的至理名言了:

伟大的牛逼之前都是傻逼式的坚持。

偷偷地告诉你,我已经把这句话悄悄地刻在了桌面上,就像小学课桌上的那道 38 线一样清晰可见。每次我想偷懒的时候,这句话就像同桌的她一样,在我胳膊上掐出一个爱心。

三线城市

很多读者知道我在三线城市洛阳的时候,都很惊讶,这片互联网的荒漠里,竟然还有程序员?竟然还有程序员能建立起不错的影响力,去帮助了那么多读者。

我还认识一个朋友,macrozheng,GitHub 上很火的一个项目 mall 的作者,他也经常在掘金上发文章,可能你也认识他。他其实也不在一线大厂,也做出应有的成绩。

站在我的角度来看,刚毕业参加工作的时候,最好的选择当然是去一线城市,因为一线城市的机会更多,无论你的学历怎样,技术功底怎样,总能找到一份工作。

只要自己肯下功夫,自然也能够不断地晋升,最终成为技术大牛,即便成为不了,也能够安身立命,养家糊口。

当你觉得大城市容纳不下灵魂和身体的时候,考虑回到二线城市或者三线城市,也不是不可选。

很多科学家都是奋不顾身的从国外回到国内,参与到国家的建设,做出了非凡的成就,也在历史的足迹当中留下了自己华丽的身影。

如果能从一线城市回到二三线城市,本身对家乡的互联网也是一种补充。虽然一开始会比较难,比如说工资低,技术不够新,不够成熟,但从长远来看,是有利的。

技术成长

在我的十年程序人生当中,技术成长最快的阶段有两次。

第一次,是毕业后去苏州参加工作。公司规模不算大,也就三四百人,是一家日企。整个工作流程是很完善的,并且对代码质量和文档要求很高,所以在高要求的环境中,成长是飞速的。

第二次,就是 2020 年了。这一年我基本上保持了日更(有时候一天两篇)的节奏,创作的文章达到了 400 篇。所谓输出倒逼输入,我就是一个印证。

我本身是一个很普普通通的程序员,没有高学历,没有大厂背景,没有在一线城市过,但正是这样,我的一步一个脚印,才显得更加弥足珍贵。

技术上,我补了 Redis、Spring Boot、RabbitMQ 等方面的知识,学习了数据结构与算法,巩固了 Java 基础。

每学习到一点知识,我就会输出一篇文章,甭管我是不是已经掌握了。

自己会用是一个层次,教会别人才是更高的一个层次。从内心上讲,对于我来说,2020 年真的是在技术上有了肉眼可见的成长。

https://www.zhihu.com/question/267403723/answer/1520053322

我在知乎上的这个学习路线,更是帮助了很多很多读者。因为我知道,这个世界上,有很厉害很厉害的程序员,也有迷茫,不知所措的程序员,他们需要帮助,在这一点上,我是无私的。

可能很多大厂的程序员,或者薪资很高的,技术很厉害的程序员不屑于来做这些事,但我愿意。因为,这也让我成长了很多!

生活

做技术的同时,千万别忘了,我们还是一个社会的打工人。

该调整心态的时候,就去玩,就去疯,就去肆无忌惮。不要把所有都扎根到工作上面,以为公司是自己家的,身体是公司的,技术就是全部。

去思考,去想未来的路,去活在当下的每一天。

如果你是学生的话,大学最快乐的事,就是学习、玩和谈恋爱,三件事情要能不偏不倚,不能只玩不学习,也最好不要只学习不玩,不谈恋爱。

如果你是刚毕业的新人,职场上是很残酷的一件事,领导批评了,不要玻璃心,同事甩锅了,不要去骂,去争,真正该争的,是你的职位,你的薪水,你在团队的影响力。不要太去计较一时的得失,要学会包容。包容不是忍气吞声,而是大度的据理力争。

如果你已经工作三五年了,职场上遇到瓶颈了,可以去想一想,总结回顾一下,看看自己那些方面还需要提升,还需要进步,还需要去改善。

可以做一个技术专家,也可以走向管理层,当然也可以思考一下副业。

买房、结婚、买车,这些生活中的事情也需要在对应的年纪考虑到。

沉默王二

我不是一个十全十美的人,也有着很多的缺点。我来自农村,我的父母都是面朝黄土背朝天的农民,我自己呢,虽然小学,初中,高中的成绩都不错,但高考却没考好,所以很长一段时间里,我是个很自卑的人。

我害怕做错事情,我不敢承担责任,我在技术上没有优势。我已经三十一岁了,我以为自己错过了最佳的学习时期。

但 2020 年,让我改头换面,我通过自己的努力,逐渐成为了一个自己喜欢的人,自己认可自己的人,甚至是读者认可的人。

我还是曾经那个少年,没有一丝丝改变,18 岁。即便是再多的非议,我仍然会我行我素,做一个普普通通的程序员,带着一颗有趣的灵魂。

收入

可能你会想知道,我在三线城市的收入情况,我也可以大方的告诉你。

大致和一个在一线城市工作了五六年,技术功底还不错的程序员的年收入相当。

没有大富大贵,也没有贫穷到一日三餐吃不上。

不羡慕他人,不卑不亢!

2021 期许

有人说,2020 年是之前十年最差的一年,但可能是未来十年最好的一年。我是不信这个的。

我相信的,只有自己的本领,个体肯定会受到大环境的影响,但个体也会在悄无声息地影响着大环境。

如果你像我一样,是个普通的程序员,那么对于思否这个平台来说,就是发文章,然后一步步积攒声望值。

我希望 2021 年,我没有放弃写作,家庭和谐,老读者都在,新读者更多,重要的是,我能陪在你身边!

就这吧,干!能和 思否 一起成长,是我最开心的一件事。

我是沉默王二,see you!

本文参与了 SegmentFault 思否征文「2020 总结」,欢迎正在阅读的你也加入。
查看原文

赞 2 收藏 0 评论 1

沉默王二 赞了文章 · 1月14日

思否年度有奖征文丨你的 2020 留下了哪些印记?

中奖名单来咯~

2020年思否有奖征文获奖名单公布,快来领奖!
戳链接领取奖:https://segmentfault.com/a/11...

image.png

2020年已经结束,这一年过的太快,让人产生了一种虚幻而错乱的穿越感,仿佛上一秒还在年初,下一秒就临近年尾。

但实际上这一年我们经历了太多,其中有恐慌、焦虑、辛酸和艰难,当然也有收获、快乐与感动。

回顾 2020 年,你最大的感受是什么?

作为一名开发者,你在 2020 又留下了哪些印记?

年底了,让我们一起回顾 2020,展望 2021,参加 SegmentFault 思否的年度有奖征文活动,来对自己的 2020年 做个总结吧~

如何参与?

一、活动规则

在思否社区写下你的「2020总结文章」,添加「2020总结」标签,并在文章注明超链接:

本文参与了 SegmentFault 思否征文「2020 总结」,欢迎正在阅读的你也加入。
二、文章内容

写下属于你的 2020 年 故事:标题不限,文体不限,语言不限,字数不限,自由发挥。

三、活动时间

自本篇文章发布始到 2021 年 1 月 31 日

有什么奖励 ?

image

实物奖品大合影

感谢融云RongCloud、青云QingCloud、京东智联云开发者社区、AWS、ARM中国 等对本次活动的赞助

编程课程8折劵(会在现有的折扣价上再打 8 折):

视频课程
图文课程

如何获奖?

当然,这些丰富礼品,要拿下以下这四个大奖才能得到~

  • 2020 人气顶流奖

    评选规则:社区文章互动数多的(基于点赞、评论等)
    评选人数:【3人】
    💗奖励: 融云鼠标垫 + ARM 蓝牙音箱 + 京东玩偶 + 编程课程 8 折劵 各一份

  • 2020 凡尔赛文学奖

    评选规则:文笔超赞/分享硬核干货内容最多的
    评选人数:【3人】
    💗奖励: 青云定制包 + AWS 玩偶 + 技术书籍 + 编程课程 8 折劵 各一份

  • 2020 搞笑担当奖

    评选规则:内容最有趣的
    评选人数:【3人】
    💗奖励: 京东鼠标垫 + AWS 玩偶 + ARM 蓝牙音箱 + 编程课程 8 折劵 各一份

  • 2020 人间真爱奖

    评选规则:前【50人】(自本篇文章发布至1月31日)参与活动且文章符合要求被收录的征文作者即可获得奖励
    💗 奖励:1-20 可获得 SegmentFault 思否定制马克杯+ 编程课程 8 折劵, 21-50 可获得重启世界限量版手办 + 编程课程 8 折劵


2020 已经结束,2021 欣然赴约;凛冬过后,春天还会远吗?我们努力把 2021 过成梦想的样子...

温馨提示:

发布后在此帖下面留言,小姐姐会更快发现你的文章,获奖机会更大。
② 思否小姐姐会把优质文章汇总收录并发出,参与征文活动的优质文章内容会被推荐到社区首页技术交流群,分享给更多的开发者。
③ 除了以上的「四大奖」以外,还有神秘礼品,大家要积极参与哦~


扫码下方二维码,添加 SF 思否小姐姐 了解更多活动信息

思否小姐姐微信号

最终解释权归 SegmentFault 思否所有

参选文章汇总

  1. axuebin:一个小小前端的 2020 年流水账
  2. 欧雷属于我的三年·第一年
  3. Kevinwan一个20年技术老兵的 2020 年度技术总结
  4. 小傅哥2020总结 | 作为技术号主的一年!
  5. pingan87872020 总结 | 21 张图总结我的 2020 年
  6. 民工哥我的 2020 年是这样的。。你的呢?
  7. 沈唁今天,告别 2020 年。
  8. masonli“措手不及”的2020 | 2020总结
  9. 敲键盘的猫我的2020,在非常时期的非常努力
  10. 皮小蛋2020 年终总结
  11. Why技术2020,我这一年。
  12. xuexiangjys年终总结 | 在开源、博客和搬砖的路上砥砺前行「2020」
  13. codecraft2020年终总结
  14. 公丕昊再见,2020
  15. robin2020,再见
  16. 死月死月的二零二零总结
  17. linong2020总结😊我想混个奖品
  18. YourbatmanYourBatman 2020年感悟关键词:科比、裁员、管理层、活着
  19. 边城边城客栈的 2020
  20. Fw恶龙2020 年终盘点
  21. CrazyCodes2021 PHP程序员修炼秘籍
  22. 波波Nadia我的 2020 个人成长回顾:花足够长的时间,有智慧地做“无用功”
  23. 折腾不止的追梦人我的2020,啪啪打脸
  24. Kense2020 年终总结
  25. 一个优秀的废人来年,做个俗人!
  26. formulahendry我的 2020:出书、办签售会、发展 VS Code 中文社区、成为开源先锋、全网 10 万粉丝、10 场演讲、内推 21 人
  27. 程序员哆啦A梦2020回顾-个人web分享JavaScript面试题附加回答
  28. Shenfq:普普通通打工人的2020
  29. HLQ_Struggle静心,未来可期 | 告别 2020
  30. 蒋鹏飞工作都是公司的,技术才是自己的!| 底层技术人的2020年度总结
  31. Raymond懒人的2020
  32. xindooXINDOO的2020总结
  33. tina6662020 疫情下湖北人的生活(只谈生活)
  34. 张喜硕度光阴的人
  35. JerryWang_汪子熙一个SAP成都研究院开发工程师的2020年度总结:未知生,焉知死
  36. 夜尽天明前端工程师的 2020 年终总结 - 成长不及预期的 3 年之痒
  37. 张晋涛2020 小回顾 | 新晋程序员奶爸的云原生之路
  38. JamesGoodbye 2020 wassup 2021 | 2020 总结
  39. howie梦想开始的地方
  40. 运维汪回顾2020,展望202,确定三个关键字:自我成长、打地基、过男人关
  41. zangecizangeci的2020年度报告
  42. Meathill2020 年知识分享与学习总结
  43. 寒雁2021,一个长期主义者的年度计划
  44. 程序员cxuan:坚持并活下去!cxuan 在思否的 2020 年终总结。
  45. 芋头芒果小龙虾再见2020,再见口罩,再见所有的不愉快
  46. thinkwei全面建设小康社会的2020年
  47. Java中文社群大龄程序员10年编程生涯的转型之旅,2020年新的开始
  48. kumfo写在2020年结尾——2020总结
  49. qqxx6661阔别2020 | 我的年度总结
  50. 沉默王二2020总结文章|乘风破浪的一年
  51. joking_zhang2020 总结 | 张兜兜 - 神奇的一年
  52. Chor Chor 的 2020 年度总结 | 2020,再见;2021,你好
  53. 0xBoo二零二零年终总结
  54. 风中有php做的云洪光光的2020年
  55. 陆陆通通「2020总结」一个老程序员的 2020 年总结回顾,2021 年如何变的更牛逼
  56. By无邪2020年度总结
  57. 三掌柜2020年年度关于前端学习与工作的心得体会
  58. TianSong2020感谢每一天的陪伴
  59. Gopal:Gopal 的 2020 年度总结
  60. Mondo平凡的 2020 年
  61. 我是开发者FTD2020,再见;2021,我来了!
  62. 敖丙一年40W粉,小小程序员的2020年终总结
  63. 木易杨:我的 2020 总结,我在蚂蚁成长的这一年
  64. 蔚蓝2020 一个少年大厂梦的陨落与wlui的诞生
  65. 良许万万没想到,良许也开挂了
  66. mar112020年,得与失,汗水和泪水
  67. 依然饭特稀西2020年总结!翻过这座山,他们就会听到你的故事!
  68. 卡颂:大佬那么多,为什么不能是我 | 卡颂2020年终总结
  69. 起风了Zzzz24岁, 接触前端的这三年
  70. dreamapplehappy:2020年,我第一次很正式地写年终总结
  71. 书旅:2020年终总结:回顾、反思、期待
  72. phodal2020 结点:平凡 & 重新出发
  73. BWH_Steven二十一岁的九局下半,希望能将结局逆转 | 年度总结
  74. 暖暖日记🍂文艺逗比的2020
  75. 画星星高手我的2020回顾——技术篇
  76. Lpyexplore 迟来的2020年度总结,顺带附上被鸽了很久的自我介绍「2020总结文章」
  77. 澹台宇鹏平凡而精彩的2020,期待的2021
  78. 提莫找蘑菇我去前面探路了,2020!

划重点

不要忘记在你的文章下添加「2020总结」标签,并在文章末尾处注明超链接 ——

本文参与了 SegmentFault 思否征文「2020 总结」,欢迎正在阅读的你也加入。
查看原文

赞 29 收藏 3 评论 69

沉默王二 赞了文章 · 1月11日

命令行界面 (CLI)、终端 (Terminal)、Shell、TTY,傻傻分不清楚?

原文发表在我的 博客 上,欢迎订阅。;)

为什么突然想写这样一篇文章呢?其实是因为在最近计划发布的一篇关于 WSL (Windows Subsystem for Linux) 的博文中,我打算对终端模拟器、Shell 的选择与配置进行一些说明。不过对于刚接触 Linux 或者刚接触命令行界面的同学,可能会有些难以理解它们之间的区别(事实上我当初也是这样)。

虽然这个话题已是老生常谈,搜索一下应该也能找到大把的相关文章。不过难得提到了这方面,就趁此机会把我的理解写下来,一来看看我是不是真正理解了,二来看看我能不能把它们之间的区别讲得更加简明易懂。

0. 太长不看 TL;DR

  • 命令行界面 (CLI) = 使用文本命令进行交互的用户界面
  • 终端 (Terminal) = TTY = 文本输入/输出环境
  • 控制台 (Console) = 一种特殊的终端
  • Shell = 命令行解释器,执行用户输入的命令并返回结果

1. 什么是命令行界面?

命令行界面,通俗来讲,就是你看过的那种满屏幕都是字符的界面。

命令行界面(英语:Command-line Interface,缩写:CLI)是在图形用户界面得到普及之前使用最为广泛的用户界面,它通常不支持鼠标,用户通过键盘输入指令,计算机接收到指令后,予以执行。

—— 摘自 Wikipedia

相信大家对于影视作品中出现的那种,某黑客/程序员/安全专家坐在电脑前猛敲键盘、屏幕上放眼望去全是滚动的字符的场景不会感到陌生。这种靠一行行命令的输入输出进行交互的用户界面,就叫做命令行界面。

the_matrix_screenshot.jpg

▲ 电影「黑客帝国」剧照

在图形用户界面 (GUI) 已经完全普及的今天,普通用户在日常使用电脑的过程中几乎不用手动输入任何命令,大部分操作都是点点鼠标就能完成,而熟练使用命令行操作似乎已经成为高逼格的代名词。

但事实上,现在依然有着很多的软件开发者、系统管理员,或者是高级用户在使用命令行界面操作计算机。其中很大一个原因,就是效率:在熟记命令的前提下,使用命令行界面往往要比使用图形用户界面来得快。

举个栗子,我要把当前目录下的(包括嵌套的子目录)所有 *.tpl 文件的后缀名修改为 *.blade.php,如果不使用命令行,该怎么做?手动修改肯定不至于,但也得去网上找找相关软件,得要注意下载来源是否靠谱(像我这样有点洁癖的选手还得去找绿色版),下载后还要手动指定文件路径、重命名模板……

而使用命令行的话(这里以 Ubuntu 上的 Bash 为例),只需运行这么一句:

rename 's/\.tpl$/\.blade.php/' ./**/*.tpl

命令行操作的高效率等优点,也是现在许多图形化的计算机系统依然没有放弃提供命令行操作方式的原因。就连 Windows 都有自带 cmd.exe 和 PowerShell 等命令行程序(事实上你在搜索「批量重命名」时,可以看到很多方案都是通过「Windows 命令提示符」实现的)。

2. 终端 —— 人与机器交互的接口

终端 (Terminal),其词汇本身的意义为「终点站;末端;(电路)的端子,线接头」。而在计算机领域,终端则是一种用来让用户输入数据至计算机,以及显示其计算结果的机器。

也就是说,终端只是一种用于与计算机进行交互的输入输出设备,其本身并不提供运算处理功能。

想要充分理解终端,我们得回溯历史,去看看终端的起源。

2.1 历史上的终端

在大型机 (Mainframe) 和小型机 (Minicomputer) 的时代里,计算机曾经非常昂贵且巨大,不像现在这样人手一台。这些笨重的计算机通常被安置在单独的房间内,而操作计算机的人们坐在另外的房间里,通过某些设备与计算机进行交互。这种设备就叫做 终端 (Terminal),也叫终端机。

ASR-33_2.jpg

▲ ASR-33 电传打字机(图片来源:Flickr - Marcin Wichary,CC-BY-2.0)

早期的终端一般是一种叫做 电传打字机 (Teletype) 的设备。为啥呢?因为 Unix 的创始人 Ken Thompson 和 Dennis Ritchie 想让 Unix 成为一个多用户系统。多用户系统就意味着要给每个用户配置一个终端,每个用户都要有一个显示器、一个键盘。但当时所有的计算机设备都非常昂贵(包括显示器),而且键盘和主机是集成在一起的,根本没有独立的键盘。

后来他们机智地找到了一样东西,那就是 ASR-33 电传打字机。虽然电传打字机原本的用途是在电报线路上收发电报,但是它既有可以发送信号的键盘,又能把接收到的信号打印在纸带上,完全可以作为人机交互设备使用。

而且最重要的是,价格低廉。:P

于是,他们把很多台 ASR-33 连接到计算机上,让每个用户都可以在终端登录并操作主机。就这样,他们创造了计算机历史上第一个真正的多用户操作系统 Unix,而电传打字机就成为了第一个 Unix 终端。

想知道用电传打字机做终端是一种怎样的体验?这里有一个 很炫酷的演示视频

2.2. 控制台 (Console) 是什么?

上面我们说过,在历史上,终端是连接到计算机上的一种带输入输出功能的外设。但是有一个终端与众不同,它与计算机主机是一体的,是计算机的一个组成部分。这个特殊的终端就叫做 控制台 (Console)。

顾名思义,控制台是用于管理主机的,只能给系统管理员使用,有着比普通终端更大的权限。一台计算机上一般只有一个控制台,但是可以连接很多个终端。

console_and_terminal.jpg

▲ 左边的是 Console,右边的是 Terminal(图片来源:带你逛西雅图活电脑博物馆

放在现在我们可能难以理解为什么会有控制台和终端的区分,不过就像上一节所说的,当时都是很多个用户通过终端去访问一台计算机,而专门管理那些大块头机器的系统管理员另有其人。普通用户用的就是普通的终端,而系统管理员用的终端比较牛逼,所以就被叫做控制台啦(笑)。

不过随着个人计算机的普及,控制台 (Console) 与终端 (Terminal) 的概念已经逐渐模糊。在现代,我们的键盘与显示器既可以认为是控制台,也可以认为是普通的终端。当你在管理系统时,它们是控制台;当你在做一般的工作时(浏览网页、编辑文档等),它们就是终端。我们自己既是一般用户,也是系统管理员。

因此,现在 Console 与 Terminal 基本被看作是同义词。

2.3 字符终端与图形终端

终端也有不同的种类。

字符终端 (Character Terminal) 也叫文本终端 (Text Terminal),是只能接收和显示文本信息的终端。早期的终端全部是字符终端。字符终端也分为 哑终端 (Dumb Terminal) 和所谓的 智能终端 (Intelligent Terminal),因为后者可以理解转义序列、定位光标和显示位置,比较聪明,而哑终端不行。

DEC_VT100_terminal.jpg

▲ DEC VT100 终端(图片来源:Flickr - Jason Scott,CC-BY-2.0)

DEC 公司在 1978 年制造的 VT100,由于其设计良好并且是第一批支持 ANSI 转义序列与光标控制的智能终端,获得了空前的成功。VT100 不仅是史上最流行的字符终端,更是成为了字符终端事实上的标准。

随着技术的进步,图形终端 (Graphical Terminal) 也开始出现在公众的视野中。图形终端不但可以接收和显示文本信息,也可以显示图形与图像。著名的图形终端有 Tektronix 4010 系列。

不过现在专门的图形终端已经极为少见,他们基本上已经被全功能显示器所取代。

2.3. 终端模拟器 (Terminal Emulator)

随着计算机的进化,我们已经见不到专门的终端硬件了,取而代之的则是键盘与显示器。

但是没有了终端,我们要怎么与那些传统的、不兼容图形接口的命令行程序(比如说 GNU 工具集里的大部分命令)交互呢?这些程序并不能直接读取我们的键盘输入,也没办法把计算结果显示在我们的显示器上……(图形界面的原理我这里就不多说了,它们编程的时候图形接口还在娘胎里呢!)

这时候我们就需要一个程序来模拟传统终端的行为,即 终端模拟器 (Terminal Emulator)。

严格来讲,Terminal Emulator 的译名应该是「终端仿真器」。

对于那些命令行 (CLI) 程序,终端模拟器会「假装」成一个传统终端设备;而对于现代的图形接口,终端模拟器会「假装」成一个 GUI 程序。一个终端模拟器的标准工作流程是这样的:

  1. 捕获你的键盘输入;
  2. 将输入发送给命令行程序(程序会认为这是从一个真正的终端设备输入的);
  3. 拿到命令行程序的输出结果(STDOUT 以及 STDERR);
  4. 调用图形接口(比如 X11),将输出结果渲染至显示器。

终端模拟器有很多,这里就举几个经典的例子:

  • GNU/Linux:gnome-terminal、Konsole;
  • macOS:Terminal.app、iTerm2;
  • Windows:Win32 控制台、ConEmu 等。

my-terminals.png

▲ 我正在使用的终端模拟器:Hyperwsl-terminal

在专门的终端硬件已经基本上仅存于计算机博物馆的现代,人们通常图省事儿,直接称呼终端模拟器为「终端」。

2.4 终端窗口 (Terminal Window) 与虚拟控制台 (Virtual Console)

大部分终端模拟器都是在图形用户界面 (GUI) 中运行的,但是也有例外。

比如在 GNU/Linux 操作系统中,按下 Ctrl + Alt + F1,F2...F6 等组合键可以切换出好几个黑不溜秋的全屏终端界面,而按下 Ctrl + Alt + F7 才是切换回图形界面。不过不要被它们唬着了,虽然它们并不运行在图形界面中,但其实它们也是终端模拟器的一种。

KNOPPIX_booting.png

▲ 一个正在显示系统启动信息的虚拟控制台(图片来源:hacktolive.org,GPLv2)

这些全屏的终端界面与那些运行在 GUI 下的终端模拟器的唯一区别就是它们是 由操作系统内核直接提供的。这些由内核直接提供的终端界面被叫做 虚拟控制台 (Virtual Console),而上面提到的那些运行在图形界面上的终端模拟器则被叫做 终端窗口 (Terminal Window)。除此之外并没有什么差别。

当然了,因为终端窗口是跑在图形界面上的,所有如果图形界面宕掉了那它们也就跟着完蛋了。这时候你至少还可以切换到 Virtual Console 去救火,因为它们由内核直接提供,只要系统本身不出问题一般都可用(笑)。

3. 那么 TTY 又是什么?

简单来说,tty 就是终端的统称。

为什么呢?看了上面的 2.1 节的同学应该知道,最早的 Unix 终端是 ASR-33 电传打字机。而电传打字机 (Teletype / Teletypewriter) 的英文缩写就是 tty,即 tty 这个名称的来源。

由于 Unix 被设计为一个多用户操作系统,所以人们会在计算机上连接多个终端(在当时,这些终端全都是电传打字机)。Unix 系统为了支持这些电传打字机,就设计了名为 tty 的子系统(没错,因为当时的终端全都是 tty,所以这个系统也被命名为了 tty,就是这么简单粗暴),将具体的硬件设备抽象为操作系统内部位于 /dev/tty* 的设备文件。

为什么要把电传打字机这个硬件设备抽象成「tty 设备」文件呢?有兴趣的同学可以去了解一下 Unix 操作系统中 Everything is a file 的概念。

tty_device_files.png

▲ 还记得上面我们说过的特殊的终端,也就是通过 Ctrl + Alt + F1-6 呼出的那些虚拟控制台 (Virtual Console) 吗?其对应的就是上图中的 tty1tty6

随着计算机的发展,终端设备已经不再限制于电传打字机,但是 tty 这个名称还是就这么留了下来。久而久之,它们的概念就混淆在了一起。所以在现代,tty 设备就是终端设备,终端设备就是 tty 设备,无需区分。

由于早期计算机上的 串行端口 (Serial Port) 最大的用途就是连接终端设备,所以当时的 Unix 会把串口上的设备也同样抽象为 tty 设备(位于 /dev/ttyS*)。因此,现在人们也经常将串口设备称呼为 tty 设备。

在 tty 子系统中后来还衍生出了 pty、ptmx、pts 等概念,这里就不详细展开了。有兴趣的同学可以参考一下这篇文章:Linux TTY/PTS 概述

4. Shell —— 提供用户界面的程序

大家都知道,操作系统有一个叫做 内核 (Kernel) 的东西,它管理着整台计算机的硬件,是现代操作系统中最基本的部分。但是,内核处于系统的底层,是不能让普通用户随意操作的,不然一个不小心系统就崩溃啦!

但我们总还是要让用户操作系统的,怎么办呢?这就需要一个专门的程序,它接受用户输入的命令,然后帮我们与内核沟通,最后让内核完成我们的任务。这个提供用户界面的程序被叫做 Shell (壳层)。

其实 Shell 只是提供了一个用户操作系统的入口,我们一般是通过 Shell 去调用其他各种各样的应用程序,最后来达成我们的目的。比如说我们想要知道一个文件的内容,我们会在 Shell 中输入命令 cat foo.txt,然后 Shell 会帮我们运行 cat 这个程序,cat 再去调用内核提供的 open 等系统调用来获取文件的内容。虽然并不是 Shell 直接去与内核交互,但广义上可以认为是 Shell 提供了与内核交互的用户界面。

至于为什么叫做 Shell,看下图就知道啦。是不是很像一层壳呢?

computer_system.jpg

Shell 通常可以分为两种:命令行 Shell图形 Shell。顾名思义,前者提供一个命令行界面 (CLI),后者提供一个图形用户界面 (GUI)。Windows 下的 explorer.exe 就是一个典型的图形 Shell(没错,它确实是,因为它接受来自你的指令,并且会帮你与内核交互完成你的指令)。

常见或历史上知名的命令行 Shell 有:

  • 适用于 Unix 及类 Unix 系统:

    • sh (Bourne shell),最经典的 Unix shell;
    • bash (Bourne-Again shell),目前绝大多数 Linux 发行版的默认 shell;
    • zsh (Z shell),我个人最喜欢的 shell;
    • fish (Friendly interactive shell),专注于易用性与友好用户体验的 shell;
  • Windows 下的 cmd.exe (命令提示符) 与 PowerShell

还有其他各种五花八门的 Shell 程序,这里就不一一列举了,有兴趣的自己去搜一搜吧。:P

5. Shell 与终端的分工

现在我们知道,终端干的活儿是从用户这里接收输入(键盘、鼠标等输入设备),扔给 Shell,然后把 Shell 返回的结果展示给用户(比如通过显示器)。而 Shell 干的活儿是从终端那里拿到用户输入的命令,解析后交给操作系统内核去执行,并把执行结果返回给终端。

不过 Shell 与终端的分工有一些容易混淆的地方,这里以例子进行说明:

  • 终端将用户的键盘输入转换为控制序列(除了字符以外的按键,比如 左方向键^[[D),Shell 则解析并执行收到的控制序列(比如 ^[[D将光标向左移动);
  • 不过也有例外,比如终端在接收到 Ctrl + C 组合键时,不会把这个按键转发给当前的程序,而是会发送一个 SIGINT 信号(默认情况下,这会导致进程终止)。其他类似的特殊组合键有 Ctrl-ZCtrl-\ 等,可以通过 stty -a 命令查看当前终端的设置。

shell_control_sequences.png

  • Shell 发出类似「把前景色改为红色(控制序列为 \033[31m)」「显示 foo」等指令;
  • 终端接收这些指令,并且照着 Shell 说的做,于是你就看到了终端上输出了一行红色的 foo

terminal_control_sequences.png

  • 除非被重定向,否则 Shell 永远不会知道它所执行命令的输出结果。我们可以在终端窗口中上下翻页查看过去的输出内容,这完全是终端提供的 feature,与 Shell 没有半毛钱关系;
  • 命令提示符 (Prompt) 是一个完全的 Shell 概念,与终端无关;
  • 行编辑、输入历史与自动补全等功能是由 Shell 提供的(比如 fish 这个 Shell 就有着很好用的历史命令与命令自动补全功能)。不过终端也能自己实现这些功能,比如说 XShell 这个终端模拟器就可以在本地写完一行命令,然后整条发送给远程服务器中的 Shell(在连接状况不佳时很有用,不然打个字都要卡半天);
  • 终端中的复制粘贴功能(Shift + Insert 或者鼠标右键等)基本上都是由终端提供的。举个例子,Windows 默认的终端对于复制粘贴的支持很屎,而换一个终端(例如 ConEmu)后就可以很好地支持复制粘贴。不过 Shell 以及其他命令行程序也可以提供自己的复制粘贴机制(例如 vim)。

6. 总结

计算机史这玩意,有趣是挺有趣的,就是查起资料来太费脑子。

为了不误人子弟,在这篇博文写作的过程中我也查阅了各种各样的文档和史料,力求内容的准确性。不过能力所限,如果文章中仍有出现谬误,欢迎在下方评论区批评指正。

7. 参考链接

查看原文

赞 146 收藏 100 评论 20

沉默王二 发布了文章 · 2020-12-28

Gson:Google 出品的 Java JSON 解析器,GitHub 上标星 18K

01、前世今生

我叫 Gson,是一款开源的 Java 库,主要用途为序列化 Java 对象为 JSON 字符串,或反序列化 JSON 字符串成 Java 对象。从我的名字上,就可以看得出一些端倪,我并非籍籍无名,我出身贵族,我爸就是 Google,市值富可敌国。

当然了,作为一个聪明人,我是有自知之明的,我在我爸眼里,我并不是最闪耀的那颗星。

我来到这个世上,纯属一次意外,反正我爸是这样对我说的,他总说我是从河边捡回来的,虽然我一直不太相信。对于这件事,我向我妈确认过,她听完笑得合不拢嘴,说我太天真。

长大后,我喜欢四处闯荡,因此结识了不少同行,其中就有 JacksonFastjson

说起 Jackson,我总能第一时间想到 MJ,那个被上帝带走的流行天王。Jackson 在 GitHub 上有 6.1k 的 star,虽然他的粉丝数没我多,但作为 Spring Boot 的默认 JSON 解析器,我非常地尊重他。

Fastjson 来自神秘的东方,虽然爆出过一些严重的漏洞,但这并不妨碍他成为最受欢迎的 JSON 解析器,他的粉丝数比我还要多,尽管我已经有超过 18K 的 star。

外人总说我们是竞争对手,但我必须得告诉他们,我们仨的关系,好到就差穿同一条内裤了。

我们各有优势,Jackson 在运行时占用的内存较少,Fastjson 的速度更快,而我,可以处理任意的 Java 对象,甚至在没有源代码的情况下。另外,我对泛型的支持也更加的友好。

02、添加依赖

在使用我的 API 之前,需要先把我添加到项目当中,推荐使用 Maven 和 Gradle 两种形式。

Maven:

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.6</version>
</dependency>

Gradle:

dependencies {
  implementation 'com.google.code.gson:gson:2.8.6'
}

PS:Gradle 是一个基于 Apache Ant 和 Apache Maven 概念的项目自动化建构工具。Gradle 构建脚本使用的是 Groovy 或 Kotlin 的特定领域语言来编写的,而不是传统的 XML。

03、性能表现

不是我觉得,是真的,通过大量的测试证明,我在处理 JSON 的时候性能还是很牛逼的。

测试环境:双核,8G 内存,64 位的 Ubuntu 操作系统(以桌面应用为主的 Linux 发行版)

测试结果:

1)在反序列化 25M 以上的字符串时没有出现过任何问题。

2)可以序列化 140 万个对象的集合。

3)可以反序列化包含 87000 个对象的集合。

4)将字节数组和集合的反序列化限制从 80K 提高到 11M 以上。

测试用例我已经帮你写好了,放在 GitHub 上,如果你不相信的话,可以验证一下。

https://github.com/google/gso...

04、使用指南

不是我自吹自擂,是真的,我还是挺好用的,上手难度几乎为零。如果你不相信话,可以来试试。

我有一个女朋友,她的名字和我一样,也叫 Gson,我的主要功能都由她来提供。你可以通过 new Gson() 的这种简单粗暴的方式创建她,也可以打电话给一个叫 GsonBuilder 的老板,让他邮寄一个复刻版过来,真的,我不骗你。

先来看一个序列化的例子。

Gson gson = new Gson();
System.out.println(gson.toJson(18));
System.out.println(gson.toJson("沉默"));
System.out.println(gson.toJson(new Integer(18)));
int[] values = { 18,20 };
System.out.println(gson.toJson(values));

在我女朋友的帮助下,你可以将基本数据类型 int、字符串类型 String、包装器类型 Integer、int 数组等等作为参数,传递给 toJson() 方法,该方法将会返回一个 JSON 形式的字符串。

来看一下输出结果:

18
"沉默"
18
[18,20]

再来看一下反序列化的例子。

Gson gson = new Gson();
int one = gson.fromJson("1", int.class);
Integer two = gson.fromJson("2", Integer.class);
Boolean false1 = gson.fromJson("false", Boolean.class);
String str = gson.fromJson("\"王二\"", String.class);
String[] anotherStr = gson.fromJson("[\"沉默\",\"王二\"]", String[].class);

System.out.println(one);
System.out.println(two);
System.out.println(false1);
System.out.println(str);
System.out.println(Arrays.toString(anotherStr));

toJson() 方法用于序列化,对应的,fromJson() 方法用于反序列化。不过,你需要在反序列化的时候,指定参数的类型,是 int 还是 Integer,是 Boolean 还是 String,或者 String 数组。

来看一下输出结果:

1
2
false
王二
[沉默, 王二]

上面的例子都比较简单,还体现不出来我的威力。

下面,我们来自定义一个类:

public class Writer {
    private int age = 18;
    private String name = "王二";
    private transient int sex = 1;
}

然后,我们来将其序列化:

Writer writer = new Writer();
Gson gson = new Gson();
String json = gson.toJson(writer);
System.out.println(json);

用法和之前一样简单,来看一下输出结果:

{"age":18,"name":"王二"}

同样,可以将结果反序列化:

Writer writer1 = gson.fromJson(json, Writer.class);

这里有一些注意事项,我需要提醒你。

1)推荐使用 private 修饰字段。

2)不需要使用任何的注解来表明哪些字段需要序列化,哪些字段不需要序列化。默认情况下,包括所有的字段,以及从父类继承过来的字段。

3)如果一个字段被 transient 关键字修饰的话,它将不参与序列化。

4)如果一个字段的值为 null,它不会在序列化后的结果中显示。

5)JSON 中缺少的字段将在反序列化后设置为默认值,引用数据类型的默认值为 null,数字类型的默认值为 0,布尔值默认为 false。

接下来,来看一个序列化集合的例子。

List<String> list =new ArrayList<>();
list.add("好好学习");
list.add("天天向上");
String json = gson.toJson(list);

结果如下所示:

["好好学习","天天向上"]

反序列化的时候,也很简单。

List<String> listResult = gson.fromJson(json,List.class);

结果如下所示:

[好好学习, 天天向上]

我女朋友是一个很细心也很贴心的人,在你调用 toJson() 方法进行序列化的时候,她会先判 null,防止抛出 NPE,再通过 getClass() 获取参数的类型,然后进行序列化。

public String toJson(Object src) {
    if (src == null) {
        return toJson(JsonNull.INSTANCE);
    }
    return toJson(src, src.getClass());
}

但是呢?对于泛型来说,getClass() 的时候会丢掉参数化类型。来看下面这个例子。

public class Foo<T> {
    T value;

    public void set(T value) {
        this.value = value;
    }

    public T get() {
        return value;
    }

    public static void main(String[] args) {
        Gson gson = new Gson();
        Foo<Bar> foo = new Foo<Bar>();
        Bar bar = new Bar();
        foo.set(bar);

        String json = gson.toJson(foo);
    }
}

class Bar{
    private int age = 10;
    private String name = "图灵";
}

假如你 debug 的时候,进入到 toJson() 方法的内部,就可以观察到。

foo 的实际类型为 Foo<Bar>,但我女朋友在调用 foo.getClass() 的时候,只会得到 Foo,这就意味着她并不知道 foo 的实际类型。

序列化的时候还好,反序列化的时候就无能为力了。

Foo<Bar> foo1 = gson.fromJson(json, foo.getClass());
Bar bar1 = foo1.get();

这段代码在运行的时候就报错了。

Exception in thread "main" java.lang.ClassCastException: class com.google.gson.internal.LinkedTreeMap cannot be cast to class com.itwanger.gson.Bar (com.google.gson.internal.LinkedTreeMap and com.itwanger.gson.Bar are in unnamed module of loader 'app')
    at com.itwanger.gson.Foo.main(Foo.java:36)

默认情况下,泛型的参数类型会被转成 LinkedTreeMap,这显然并不是我们预期的 Bar,女朋友对此表示很无奈。

作为 Google 的亲儿子,我的血液里流淌着“贵族”二字,我又怎能忍心女朋友无助时的落寞。

于是,我在女朋友的体内植入了另外两种方法,带 Type 类型参数的:

toJson(Object src, Type typeOfSrc);
<T> T fromJson(String json, Type typeOfT);

这样的话,你在进行泛型的序列化和反序列化时,就可以指定泛型的参数化类型了。

Type fooType = new TypeToken<Foo<Bar>>() {}.getType();
String json = gson.toJson(foo,fooType);
Foo<Bar> foo1 = gson.fromJson(json, fooType);
Bar bar1 = foo1.get();

debug 进入 toJson() 方法内部查看的话,就可以看到 foo 的真实类型了。

fromJson() 在反序列化的时候,和此类似。

这样的话,bar1 就可以通过 foo1.get() 到了。

瞧,我考虑得多周全,女朋友都忍不住夸我了!

05、处理混合类型

你知道的,Java 不建议使用混合类型,也就是下面这种情况。

List list = new ArrayList();
list.add("沉默王二");
list.add(18);
list.add(new Event("gson", "google"));

Event 的定义如下所示:

class Event {
    private String name;
    private String source;
    Event(String name, String source) {
        this.name = name;
        this.source = source;
    }
}

由于 list 没有指定具体的类型,因此它里面可以存放各种类型的数据。这样虽然省事,我女朋友在序列化的时候也没问题,但反序列化的时候就要麻烦多了。

Gson gson = new Gson();
String json = gson.toJson(list);
System.out.println(json);

输出结果如下所示:

["沉默王二",18,{"name":"gson","source":"google"}]

反序列化的时候,就需要花点心思才能拿到 Event 对象。

JsonParser parser = new JsonParser();
JsonArray array = parser.parse(json).getAsJsonArray();
String message = gson.fromJson(array.get(0), String.class);
int number = gson.fromJson(array.get(1), int.class);
Event event = gson.fromJson(array.get(2), Event.class);

承认了,JsonParser 是我的前任。希望你不要喷我渣男,真不是我花心,是因为我们性格上有些不太适合。但我们仍然保持着朋友的关系,因为我们谁都没有错,只是代码更加规范了,已经很少有开发者使用混合类型了。

06、个性化定制

考虑到你是一个追求时髦的人,我一直对自己要求很高,力争能够满足你的所有需求。这种高标准的要求,让我女朋友对我是又爱又恨。

爱的是,我这种追求完美的态度;恨的是,她有时候力不从心,帮不上忙。

使用 toJson() 序列化 Java 对象时,返回的 JSON 字符串中没有空格,很紧凑。如果你想要打印更漂亮的 JSON 格式,你需要打电话给一个叫 GsonBuilder 的老板,让他进行一些定制,然后再把复刻版邮寄给你,就像我在使用指南中提到的那样。

public class Writer {
    private int age = 18;
    private String name = "沉默王二";

    public static void main(String[] args) {
        Writer writer = new Writer();
        Gson gson = new Gson();
        String json = gson.toJson(writer);
        System.out.println(json);

        Gson gson1 = new GsonBuilder().setPrettyPrinting().create();
        String jsonOutput = gson1.toJson(writer);
        System.out.println(jsonOutput);
    }
}

来对比一下输出结果:

{"age":18,"name":"沉默王二"}
{
  "age": 18,
  "name": "沉默王二"
}

通过 setPrettyPrinting() 定制后,输出的格式更加层次化、立体化,字段与值之间有空格,每个不同的字段之间也会有换行。

之前提到了,默认情况下,我女朋友在序列化的时候会忽略 null 值的字段,如果不想这样的话,同样可以打电话给 GsonBuilder。

public class Writer {
    private int age = 18;
    private String name = null;

    public static void main(String[] args) {
        Writer writer = new Writer();
        Gson gson = new Gson();
        String json = gson.toJson(writer);
        System.out.println(json);

        Gson gson2 = new GsonBuilder().serializeNulls().create();
        String jsonOutput2 = gson2.toJson(writer);
        System.out.println(jsonOutput2);
    }
}

来对比一下输出结果:

{"age":18}
{"age":18,"name":null}

通过 serializeNulls() 定制后,序列化的时候就不会再忽略 null 值的字段。

也许,你在序列化和反序列化的时候想要筛选一些字段,我也考虑到这种需求了,特意为你准备了几种方案,你可以根据自己的口味挑选适合你的。

第一种,通过 Java 修饰符

你之前也看到了,使用 transient 关键字修饰的字段将不会参与序列化和反序列化。同样的,static 关键字修饰的字段也不会。如果你想保留这些关键字修饰的字段,可以这样做。

保留单种。

Gson gson = new GsonBuilder().excludeFieldsWithModifiers(Modifier.TRANSIENT).create();

保留多种。

Gson gson = new GsonBuilder()
    .excludeFieldsWithModifiers(Modifier.STATIC, Modifier.TRANSIENT, Modifier.VOLATILE)
    .create();

第二种,通过 @Expose 注解

要使用 @Expose 注解,你需要先这样做:

Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();

再在需要序列化和反序列化的字段上加上 @Expose 注解,如果没加的话,该字段将会被忽略。

@Expose
private int age = 18;

07、心声

如果你还想了解更多的话,请来参观我的 GitHub 主页:

https://github.com/google/gson

我会向你坦露我的一切,毫不保留的,除了我和女朋友之间的一些秘密,只为能够帮助到你。

如果你觉得我有点用的话,不妨点个赞,留个言,see you。

推荐阅读

拜托,别再问我怎么自学 Java 了!和盘托出

带妹入坑,她该怎样提高自己的编程能力?

查看原文

赞 3 收藏 2 评论 1

认证与成就

  • 获得 195 次点赞
  • 获得 1 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 1 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

  • 《Web 全栈开发进阶之路》

    全书一共7章,主要讲解了如何利用Maven快速地搭建SpringMVC的Web项目、jQuery的各种函数和方法调用、前端开发框架Bootstrap、如何对常见的jQuery和Bootstrap插件进行HTML扩展、关系型数据库MySQL及其连接方法、AdminLTE及其囊括的大量可直接投入项目使用的组件、From表单等内容。除此之外,本书包含大量源码实例,其均是完成的项目开发程序,并可在此之上进行二次开发,这样就能够帮助读者融会贯通,快速地完成一个企业级Web应用程序的设计,使读者在实战中学到技术的精髓。

注册于 2015-11-18
个人主页被 2.4k 人浏览