nohup

nohup 查看完整档案

北京编辑  |  填写毕业院校知名互联网公司  |  高级工程师 编辑填写个人主网站
编辑
_ | |__ _ _ __ _ | '_ \| | | |/ _` | | |_) | |_| | (_| | |_.__/ \__,_|\__, | |___/ 该用户太懒什么也没留下

个人动态

nohup 发布了文章 · 6月10日

springboot重新获取配置文件参数

springboot重写配置参数要实现 EnvironmentPostProcessor方法

重写springboot中rocketmq.name-server 这个参数,从其他地方获取

因为我们这面有个变量是根据环境来确定的,所以需要重写

@Component
public class MQConfigProperty implements
    EnvironmentPostProcessor {


    private static final String PROPERTY_SOURCE_NAME = "applicationConfig: [classpath:/application.properties]";


    public static final String nameServer = EnvironmentAddress.getConfig(EnvironmentAddress.MQ);

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment,
        SpringApplication springApplication) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("rocketmq.name-server", this.nameServer);
        addOrReplace(environment.getPropertySources(), map);
    }

    private void addOrReplace(MutablePropertySources propertySources,
        Map<String, Object> map) {
        MapPropertySource target = null;
        if (propertySources.contains(PROPERTY_SOURCE_NAME)) {
            PropertySource<?> source = propertySources.get(PROPERTY_SOURCE_NAME);
            if (source instanceof MapPropertySource) {
                target = (MapPropertySource) source;
                for (String key : map.keySet()) {
                    if (target.containsProperty(key)) {
                        System.out.printf("reload properties key:%s,value:%s \n",key,map.get(key));
                        target.getSource().put(key, map.get(key));
                    }
                }
            }
        }
        if (target == null) {
            target = new MapPropertySource(PROPERTY_SOURCE_NAME, map);
        }
        if (!propertySources.contains(PROPERTY_SOURCE_NAME)) {
            propertySources.addLast(target);
        }
    }
}

编写完这个类需要创建src/main/resources/META-INF/spring.factories

里面填写

org.springframework.boot.env.EnvironmentPostProcessor=
MQConfigProperty

这样的话springboot就可使用最新的值了

查看原文

赞 0 收藏 0 评论 0

nohup 发布了文章 · 2019-12-17

mybatis-log-plugin 把mybatis生成的PreparedStatement语句恢复成原始完整的sql语句

这是一个Intellij的插件,主要作用是把mybatis生成的PreparedStatement语句恢复成原始完整的sql语句。
它将用真实的参数值替换PreparedStatement语句的问号占位符。
通过 "Tools -> MyBatis Log Plugin" 这个菜单可以实时输出sql日志。
点击窗口左边的 "Filter" 按钮,可以过滤不想要输出的sql语句。
点击窗口左边的 "Format Sql" 按钮,可以格式化输出的sql语句。
解析配置:输出的sql日志必须包含可识别的前缀才能正常解析,如:"Preparing:"和"Parameters:"

左边几个按钮的作用:

  • Sql Text: 从文本还原语句
  • Filter: 过滤语句配置
  • Rerun: 重新启动
  • Stop: 停止输出
  • Format Sql: 格式化后续输出的Sql语句
  • Close: 关闭该窗口

支持mybatis的输出格式如下:

2016-11-11 16:46:29.316 DEBUG selectSql1 - ==> Preparing: select * from t_table where name = ?
2016-11-11 16:46:29.343 DEBUG selectSql1 - ==> Parameters: hello(String)

以 "Preparing:" 和 "Parameters:" 作为分割符进行解析。
接着输出的完成sql语句如下:
select * from t_table where name = 'hello';

具体项目github地址:https://github.com/kookob/mybatis-log-plugin

查看原文

赞 0 收藏 0 评论 0

nohup 发布了文章 · 2019-09-23

mapstruct 使用jenkins打包遇到的一个问题

mapstruct 使用jenkins打包遇到的一个问题:

java.lang.NoClassDefFoundError: org/mapstruct/ap/spi/AstModifyingAnnotationProcessor
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:468)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:74)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:369)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:363)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:362)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:411)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:348)
    at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:370)
    at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:404)
    at java.util.ServiceLoader$1.next(ServiceLoader.java:480)
    at 

如何找到这个问题的解决办法呢,先分析一下mapstruct实现机制,
是使用注解的方式生成对应的实现类,需要在编译阶段进行生成。

最终使用

    <!-- compiler插件, 设定JDK版本 -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.6.2</version>
                    <configuration>
                        <source>1.7</source>
                        <target>1.7</target>
                        <showWarnings>true</showWarnings>
                        <annotationProcessorPaths>
                            <path>
                                <groupId>org.projectlombok</groupId>
                                <artifactId>lombok</artifactId>
                                <version>1.16.18</version>
                            </path>
                            <path>
                                <groupId>org.mapstruct</groupId>
                                <artifactId>mapstruct-processor</artifactId>
                                <version>1.3.0.Final</version>
                            </path>
                        </annotationProcessorPaths>
                    </configuration>
                </plugin>

在打包插件阶段进行配置即可。

查看原文

赞 0 收藏 0 评论 0

nohup 发布了文章 · 2019-09-09

Fast-object-diff 对象对比工具

Fast-object-diff

我们经常要打一些日志记录,然而手动记录是比价困难的,
也是不方便的,非常需要一个对比java相同对象内不同值的方法
Fast-object-diff就这样诞生.

https://github.com/colincatsu...

  1. 支持基本对象 和 Collection集合
  2. 日期可按照自定义格式输出
  3. 注解方法输出日志,配置简单
  4. 忽略不需要的值
  5. 提供基础方法 generateDiff 和扩展方法
  6. 集合中可根据某个key进行对应diff记录,方便乱序中使用diff对比某个Object

使用方法很简单:

    public class BeanA {
    
        //使用注解标记列
        @DiffLog(name = "测试a")
        private String a;
    
        //忽略这个
        @DiffLog(name = "测试b", ignore = true)
        private String b;
        
        //集合递归支持
        @DiffLog(name = "BList集合")
        private List<BeanB> bList;
    
        //日期格式转换
        @DiffLog(name = "开始时间",dateFormat = "yyyy-dd-MM hh:mm:ss")
        private Date start;
    
        @DiffLog(name = "价格")
        private BigDecimal price;
    }
    public class BeanB {

        @DiffLogKey(name = "订单编号")//标记集合中对应的key,根据这个key来比对输出
        @DiffLog(name = "主键")
        private Long id ;

        @DiffLog(name = "机场")
        private String name;
    }
            BeanB a1b = new BeanB(1L,"北京");
            BeanB a1b3 = new BeanB(3L,"3");
            BeanB a1b2 = new BeanB(2L,"1");
    
            ArrayList<BeanB> list = new ArrayList<>();
            list.add(a1b);
            list.add(a1b3);
            list.add(a1b2);
            BeanA a1 = new BeanA("1","1",list);
            a1.setStart(new Date());
            //        a1.setPrice(new BigDecimal("10.23"));
    
    
            BeanB a2b = new BeanB(1L,"上海");
            BeanB a2b2 = new BeanB(2L,"2");
    
            ArrayList<BeanB> list2 = new ArrayList<>();
            list2.add(a2b);
            list2.add(a2b2);
            final BeanA a2 = new BeanA("2","2",list2);
            a2.setPrice(new BigDecimal("50.852236"));
            List<DiffWapper> diffWappers = AbstractObjectDiff.generateDiff(a1, a2);

结果Json格式:

[
    {
        "diffValue":{
            "newValue":"2",
            "oldValue":"1"
        },
        "logName":"测试a",
        "op":"CHANGE",
        "path":"/a"
    },
    {
        "diffValue":{
            "newValue":"上海",
            "oldValue":"北京"
        },
        "logName":"BList集合.订单编号[1].机场",
        "op":"CHANGE",
        "path":"/bList/1/name"
    },
    {
        "diffValue":{
            "newValue":"2",
            "oldValue":"1"
        },
        "logName":"BList集合.订单编号[2].机场",
        "op":"CHANGE",
        "path":"/bList/2/name"
    },
    {
        "diffValue":{
            "newValue":null,
            "oldValue":"[主键]=3 ,[机场]=3 "
        },
        "logName":"BList集合.订单编号[3]",
        "op":"REMOVE",
        "path":"/bList/3"
    },
    {
        "diffValue":{
            "newValue":null,
            "oldValue":"2019-09-09 02:16:30"
        },
        "logName":"开始时间",
        "op":"REMOVE",
        "path":"/start"
    },
    {
        "diffValue":{
            "newValue":50.852236,
            "oldValue":null
        },
        "logName":"价格",
        "op":"ADD",
        "path":"/price"
    }
]

也可以直接输出中文日志格式:

  String s = ChineseObjectDiff.genChineseDiffStr(a1, a2);

结果直接输出:

「测试a」由[1]修改为[2]
「BList集合.订单编号[1].机场」由[北京]修改为[上海]
「BList集合.订单编号[2].机场」由[1]修改为[2]
「BList集合.订单编号[3]」由[[主键]=3 ,[机场]=3 ]被删除
「开始时间」由[2019-09-09 02:01:54]被删除
「价格」被添加成[50.852236]

也可以使用AbstractObjectDiff+DiffWapper扩展自己的格式输出.

public class ChineseObjectDiff extends AbstractObjectDiff {
    @Override
    protected String genDiffStr(Object sourceObject, Object targetObject) throws Exception {
        List<DiffWapper> diffWappers = generateDiff(sourceObject, targetObject);
        return DiffUtils.genDiffStr(diffWappers);
    }

}
查看原文

赞 0 收藏 0 评论 0

nohup 发布了文章 · 2019-08-23

MAC下最好用的Mysql工具Sequel Pro扩展(bundle)单行显示工具

一直在寻找一个比较好用的mac下的Mysql工具
试过一下几个:
Navicat 实在是卡
tableplus 还算是好用吧,但是比较蛋疼的是收费
Sequel Pro 刚开始觉得不好用,现在觉得比较完美,需要调教

直入主题:
1.Sequel Pro 设置提示延迟为0.5s 这个我之前一直用默认的,提示超级慢,非常难受,调整过后非常流畅
2.单行按列显示,这个功能tableplus的非常好用,我一直希望能有一个这样的功能
3.SQL语句格式化 https://www.jianshu.com/p/bbf...
说搞就搞,先看一下最终效果:
已经非常完美了,可以展示出表格和按照关键字进行过滤

clipboard.png

起源:
先是本来要搞一个SQL格式化工具,查到下面这两个文章,受官方导出JSON的启发吧,查阅官方文档
https://www.jianshu.com/p/bbf...
https://sequelpro.com/docs/bu...

1.配置Sequel Pro bundle选项 Bundles -> Bundle Editor -> Date table 点击show -> 然后点击左下角+号 ,添加一个新的,按下图设置即可

bundle scope : Date Table
Input: select rows(csv)
output: show as HTML
也可以选择 SHOW AS HTML TOOLTIP 进行直接提示

clipboard.png

1.使用Python解析出相应的内容csv格式的,代码比较简单,主要是python不熟
2.按照table固定格式输出HTML即可
3.通过js进行过滤table中的元素

#!/usr/bin/python
#coding=utf-8

import urllib2, urllib

import json

import sys

reload(sys)

sys.setdefaultencoding('utf-8')


data = sys.stdin.readlines()

#过滤掉没数据表格
if len(data) > 0 :
    print '<input type="text" id="filterName"  style="width:140px;height:30px"/> <button id="filterBtn">filter</button>'
    print '<button id="resetBtn">reset</button><br>'
else:
    exit(0)

header = data[0].strip('\n');
headers = header.split(",")

rowdata = data[1];
rowdatas = rowdata.split(",")
content_tab_row = '<table border="1" cellspacing="0">  '
row_tr  = ""
for index in range(len(headers)):
    row_tr = row_tr  +  "  <tr><th>" +headers[index].strip('"') +" </th><th>" +rowdatas[index].strip('"') +"</th> " + "</tr>"

content_tab_row = content_tab_row + row_tr + "</table>"
print content_tab_row

#引入jQuery
print '<script type="text/javascript" data-original="http://code.jquery.com/jquery-1.4.1.min.js"></script>'
print '<script type="text/javascript">'
print 'jQuery.expr[":"].contains=function(a,i,m){return jQuery(a).text().toUpperCase().indexOf(m[3].toUpperCase())>=0};'
print '$("#filterBtn").click(function(){var keyword=$("#filterName").val();if(keyword==undefined||keyword==""){return}$("table tbody tr").hide().filter(":contains(\'"+(keyword)+"\')").show()});'
print '$("#resetBtn").click(function(){window.location.reload()});'
print '</script>'

这样就算是大功告成了。

遇到问题:
刚开始觉得实现了展示即可,但是还是非常想实现过滤功能的,这个功能很常用,
查看文档发现可以支持SHOW AS HTML 是支持JavaScript的
但是一直尝试不成功,后来发现其实页面导出的就是HTML,那按理说就可以执行js代码,然后进行简单测试发现真的可以实现这个功能。
所以后来又添加上了filter功能。
Github :https://github.com/colincatsu...

你也可以直接下载 :https://github.com/colincatsu...

查看原文

赞 1 收藏 0 评论 3

nohup 评论了文章 · 2018-10-18

入职三天,公司给了100块钱叫我走人

十月,金秋季节,本是丰收之时,却因为陆续有同事离职,心中多少有些悲凉之意,顿然想起从参加工作到现在,五年已过,当年青涩懵懂的小年轻,如今出街招摇过市时,被小孩子看到都会喊声大叔。回想这五年,有心酸和无奈、有快乐和期待、也有不断的蜕变和成长。趁着国庆长假,写下这一路的心路历程,于己,是一个总结和督促,于读者,是一个故事,兼听则明,希望对你们有些许启发,足矣。

1. 毕业=失业?有可能的

2013年6月底,虽然此前早已被某软(国内最大的软件开发商)的政府事业部录用并被寄以厚望要培养成核心人员,但出于对乡土的眷恋和对南方的热爱,还没领到毕业证的我,怀着极大的憧憬,拖着一个行李箱,兜里怀揣着几百块钱,坐了三十多个小时的绿皮从山东回到广州。

“初来乍到,请多多指教”,踏入广州那一刻,我满怀热情的对广州说。

本以为,作为985/211大学毕业的我,在国内最大的软件服务商被寄予厚望的我,在广州应该也是个热饽饽,不愁吃不愁穿不愁offer的。
然而现实是广州的公司对我并没有多多指教,而是多多抛弃。

到广州第二天,我就开始海投简历,可能是985的原因,我得到了不少的面试通知,忙的不亦乐乎,可结果却是事与愿违,有些是嫌弃没经验,有些是因为基础还不够好,有些是因为技术要求高...林林总总,总而言之就是offer一个都没拿到,以致到后面自己信心都丧失了,一再降低标准,修改简历,改成实习生、甚至跟着舍友学了几天AS3,投一些游戏公司的简历,可惜都没用。

每次回到住处,舍友就关切的问“还没拿到offer吗?”
每次打电话回家,家里人都问“找到工作了吗?待遇怎样?”
甚至到最后,家人已经对我失去了信心,打电话来说“我们想去旅游,要不你回来看一下家,反正你也找不到工作的”。
....
各种打击,内心充满了伤
毕业前满满的希望,想要凭借自己的实力,掌控一切,至少,至少也能找到一份很好的工作,
如今现实摆在眼前,毕业=失业,对于我来说,这不是假设,而是真命题。
住处是个只有10平米的单间,却住着三个人,两个人睡床上,我睡在床边的地铺上,每当夜深人静的时候,总能感觉到地板里传来的寒气,直接渗入体内,刺骨的凉让我彻夜难眠,我想挣脱这一切,我想摆脱这样的困境,更加努力的准备面试笔试,无论待遇的高低、无论公司的大小、无论距离的远近,只要给发我面试通知,我都会去面试。

记得最困难的时候,几乎身无分文,没有能力办信用卡,也不敢问家里要,每天的中午饭都是舍友从公司带回来的盒饭,晚饭就去住处旁边一家三个菜8块钱、饭和刷锅水免费随便吃喝的小店解决。有一次和大学舍友聊天,说到此事,舍友说我给你打500块钱来吧,因为异地异行取款要收10块钱手续费,为省下这10块钱我走到三公里外的银行才把钱取回来(那时候还没有摩拜、ofo之类的共享单车)。

最终功夫不负有心人,7月的尾巴,中山大学旁边的一家小型外包公司给我发来了offer,那一刻,感觉出人头地了,一切都变得那么亲切,天是那么的蓝,空气是那么的清新,地沟油是那么的香,就连我睡的地板,传来的都是凉爽。

笔者建议:

  1. 作为一名毕业生,千万不要高估自己的实力,过去的辉煌代表着过去,对于每一次面试,都必须抱着谦虚的心认真的去对待。
  2. 不同城市对毕业生的需求不一样,北方的公司(北京、大连、济南等)更看重985学校的身份,认为你是一个潜力股,因此在北方公司的简历,多写些在学校获得荣誉能对面试加不少分。而南方的公司(广州、深圳等)则更注重你当前能为公司做些什么具体的工作,产生多少的效益,因此在南方的公司的简历里,多写你的项目经验、实习经验,会对面试加分。当然这只是个人经历总结,不能以偏概全,权当是一个参考吧,笔者更加倾向于针对每个公司都有不同的简历内容,摸清公司的招聘喜好,有助于你找到心仪的工作。
  3. 一定要坚定自己的方向,不要因为工作不好找,就转向其它方向,这样只会让你浪费更多的时间更多的精力,得不偿失。

2. offer=工作?不一定!

我迫不及待的告知亲友,仿佛这件事值得举国同庆一般。
可能太开心的缘故:

上班第一天: 我就迟到了几分钟,我的上级见到我,也没说什么,就交给了一个任务:“用ssh写个简易博客”,看字面是个非常简单的任务,但由于只给了一句话,其它什么都没有,连要有什么功能、界面大概做成什么样都没有,这就增加了难度,于是我先到网站找一些管理系统的前端模板,过程非常犹豫不决,感觉bootstrap的兼容性不好、感觉easyUI又太大材小用、感觉...

上班第二天:没有迟到,但惊慌地发现:上级比我早到,我赶紧跑到座位,这时上级也转过身来
“进展怎样了?”,
我赶紧说:嗯,框架搭建好了,已经实现了部分功能。
说完自己都心虚,还想着今天再花点时间找个好模板呢,真慌,赶紧随便找了个模板,就开始搭建开发环境,下载eclipse、下载jdk...发现网络特差,于是等待等待等待,直到下午终于弄好了,草草建了个ssh项目,就开始编码,没多久就下班了,我也没加班,想着来日方长呢。

上班第三天:一到公司,上级就说进展怎样,给我演示一下吧,顿时心慌,只能硬着头皮把项目跑起来,他把我做的仅有的一点点功能看了一遍之后,就走了,没过多久,hr走过来,递给我100元:

**“不好意思,三天的考察期到了,你不符合我们的预期,这是公司给你三天工作的一点补偿”
“为什么?为什么?具体什么原因?我不要这钱,请相关的人给我说明一下”
我愤愤不平的说,
“这是领导的意思,我也不是很清楚,你看就先把钱拿着吧收拾收拾回去吧”。
她把钱放到我桌面上就走了。**

我伤心到了极点,坐在我前面座位的已经成为“前上级”的那位他也没有回头跟我说一句话,也没有说任何原因,我更加愤怒,直接到经理办公室敲门进去问总经理为什么这样对我。

经理示意我坐下来,不要生气:
“小X啊,你不要伤心啊,三百六十行,行行出状元,你长得又高,身材挺拔,外表也阳光,其实你去做保险业务员会很有前途,写代码这个工作并不是很适合你啊,我跟你讲个故事,我大学一个宿舍的同学,毕业之后,我写代码,他跑业务,现在已经做到大区经理,开保时捷了...”

听到这些,我的心已经凉凉,再讨公道已经没有意义,在一家不被老板认同的公司,注定是不会长久了,我说了句“谢谢老板这3天的照顾,希望公司早日上市(当然后来我每年都去查一下这家公司的经营状况,终于在第三年的时候倒闭了)”,就回到我的座位上默默的收拾东西,关电脑,临走时决定把那100块钱带了。

笔者建议:

  1. 千万不要认为offer拿到手就是铁饭碗了,每个新员工都会有几天的考察期和3~6个月的试用期,只有过了这两个期,你才是真正的受到《合同法》保护的,除此之外,两期之内,公司要开除你,也不需要付出什么代价的。
  2. 作为一名新员工,初来乍到,一定要谦虚地和老同事多打交道,多请教,如果我拿到任务之后,不是自己闷头做,而是多请教老同事怎么做;开发软件的下载,公司一般都会有相应的ftp工具库,省去很多搭建时间,提高开发效率。
  3. 对于新员工来说,你的上级就是你两期内的神,如果不讨好他,你会为此付出代价的。
  4. 一些常识不能少:比如不要迟到,比如进度慢了要主动加班...

3. 困境=绝境?只有努力

怀揣着100元巨款,我回到住处附近,点了份平时舍不得吃的最贵的猪脚饭,一点味道都没有,回到住处,舍友问我怎么中午就回来了,我说“我被开了”,鼻子有点酸,差点哭了,舍友不敢多问,赶紧让我先休息会。
我躺在地板上,脑子一片空白。

我该怎么对我的父母说我被开了。
我该怎么面对那些关心我的人。
我该怎么找工作。
我真的那么差劲吗。
我真的不适合写代码吗。
也许...

没有过不去的坎,只有过不去的自己;再伤心也得努力,躺了一会地板之后,起来继续投简历,这次我注重所投公司的专注的行业,挑选一些自己喜欢的行业去投,比如做体育、电商类的公司,第二天就得到了一个面试通知,我把一切都准备的好好的,还提前半个小时到面试公司楼下,是在小区里的一个公司,进门那一瞬间,有点小失望,一个家庭作坊的样子,大厅摆着几台电脑,两个员工在那盯着屏幕,我说来面试的,一个hr样子的女生就起来进去,一会带出来一个高个子领导样子的中年男子,笑眯眯的叫我进他办公室,问了一些基础问题之后,就给我讲了现在公司的状况(我进来就是二号员工)、公司业务(体育彩票类,我喜欢)、福利待遇(实习工资2.5k😢)、还有我进来之后要做的事情...讲完之后,就让我回去等通知。

两天之后,就顺利收到了offer,虽然工资很低,但因为是我喜欢的行业,再者目前找工作困难,我没多想,就答应了。

经过了前一份工作的洗礼之后,我对这份工作特别珍惜,每天提前半小时到办公室,不懂的东西就缠着仅有的一位同事给我讲,以前没学过的知识晚上回来加班加点学习(至今还记得舍友睡了我还趴在地上敲着电脑,中秋那一夜,月亮特别亮),老板让我做的东西,我主动每天下班前都发一份邮件附上今天所做的内容给老板,以此坚持了一个月,到后面,老板说你不用写那么认真,大概列一下工作内容告诉我就行。

第一个月,拿了1.6k的工资,虽然少的可怜,还不如一个端盘子的拿得多,但收到短信的那一刻,有种热泪盈眶的感觉,我终于可以靠自己的本事拿到第一份薪水了(上次的100块钱更像是耻辱,而不是薪水),为了不让家里担心,我打电话跟爸妈说我领了4k工资。

到实习期满,老板给我开了5k的工资,对我说之前给你这么低的薪水,是故意考察你的,想不到你能坚持下来并且把事情做得很好,现在这个工资才是符合你的工作能力和态度。

笔者建议:

  1. 毕业生找工作是一件很困难的事情,尤其是在准备不周到的情况下,你需要对自己的能力、兴趣做一个评估,投简历也要圈一个行业、公司实力的范围,这样你才更有胜算。
  2. 工作是一件持久的事情,你需要有持续的付出,领导才会看得到,才会得到回报。
  3. 人生本来就是困难,困境之下,你依然需要努力,再坚持一下,说不定就是出路了。

4. 工作=薪水?太肤浅

经过实习期之后,一切步入正轨,对于领导安排的一切事情,我都充满兴趣的去做。

  1. 一开始的工作是做iOS APP,此前我都是做Java,没办法,我花了两个通宵装了个黑苹果学了一周之后,领导就给我Mac Air开始开发iOS,压力和动力并存,那时心无旁骛,只想着怎么把事情做好,那时候公司甚至还没有UI,我就求着那位会UI的全栈同事给我切图,写代码时遇到难题我就骚扰大学舍友(有两个舍友做iOS)解答,历时三个半月终于完成了第一版本,上线那晚上,我们出去庆祝了一番。通过这个项目,我学会了iOS(虽然现在已经忘得差不多了)。
  2. 2014年初,那时候H5刚刚火起来,领导让我尝试把APP的内容做到H5中,仅仅在大学学过一点HTML+CSS的我,接受了这个项目,花了一个月我才开发出第一个业务,之后几乎每周就能增加一个业务,通过做这个项目,我学会了PHP,同时加强了前端的技术能力以及势头很猛的H5开发。
  3. 公司接到一个集成的项目,需要去A城对接,说到要安排人出差时,我想到这也是一个很不错的学习机会,于是很快就举手申请出差,出差一个月,我负责web项目的对接,当时有个非常困难的问题摆在眼前,那就是有一些非常复杂的涉及到较多算法的业务以前根本没开发,现在甲方要求有,我硬着头皮研究,领导天天打电话来问有没有头绪,甲方也在问,最终一周多的时间之后,终于解决,因为这次任务的完美完成,出差回来之后,领导直接把我的工资提到7k,当然不仅仅是薪水,通过这次出差,我不仅学会了项目对接的一些流程,还学了一些高深的算法,还趁这个机会把A城中的所有大学同学见了个遍。
  4. 甚至有一次,领导让我帮忙去投标,我也跟着去见识了一番,往后的日子了,说到项目投标,我都知道大概是怎么个回事了。

就这样,时间过得很快,转眼来到了2014年的夏天,从毕业到现在快一年的时间里,我从来没在意过自己的钱有多少,也没想过有什么假期,基本上就是朝九晚十一并且每周六天班,我只是不断的努力,不断的学习,不断地的汲取一切能学习到的知识,不知不觉地,我的知识库中已经增加了iOS、PHP、HTML、CSS、JavaScript等语言,而我的待遇也大幅度的提高,到了我之前没想过的高度。

笔者建议:

  1. 作为刚入行的你,薪水对你来说并不意味着更多,放下那该死的薪水吧,好好沉淀自己,如果你盯着薪水工作,那就太肤浅了。
  2. 要抓住一切机会学习,只有不断的学习,才会不断的提高,你的努力,随着时间迁移,一切会回馈给你的。

5. 编程=工作?多挖掘潜能

当我逐渐的掌握更多技能和得到更好的待遇的时候,我的心态也发生了改变,一年前闷头闷脑写代码的我,因为渐渐的成熟以及公司的转变,得到了其他方面的锻炼,比如面试、带新人、带小团队。

有些人说我是技术宅,我只想钻研技术,做其他的事情会浪费我的时间,而且我也不喜欢

其实这种想法是不对的,无论你以后的路子是要成为技术大咖还是进入管理层,首先有要技术,这确实是永恒不变的先决条件,但与人交往,并不是一种浪费时间的行为,而是另一种方式让你汲取知识和技术的途径,比如这些年,我面试过的人,少说有三五百了,最疯狂的一天面试了6个人(作为技术人员,当然不能和hr比啦)。

面试者的群体中,有还没毕业的、有刚毕业一年的、也有毕业十多年的,不管哪个层次的面试者,与之交谈,是一种自我回顾和自我提升的途径,与年幼者(技术层面)面试,会使我的基础知识得到一次回顾和巩固,与年长者(技术层面)面试,会使我的知识深度和广度得到一次拓展和加深。记得在我工作的第三年就面试过好几个工作十多年的老程序员,那时候初生牛犊不怕虎,我拿着简历就冲进面试室,让大牛先来个自我介绍,当听到他提到自己有多少开源项目,GitHub有多少star,在什么开源论坛上写过博客时,顿时感觉自己渺小到无地自容,幸好大牛面善心不恶,不但没有拆穿我,把我提的问题回答的通通透透,还顺便把知识点延伸出去,那些我根本没听过的技术,知道但是不了解的技术,都给我理了一遍,顿时觉得免费听了一节高级技术课,抵得上自己学习一个星期了。

因此技术固然重要,但一个人的力量太单薄,无论你的同事、朋友还是面试者,只要你肯与之交流、探讨,有时候会比自己一个人闭关苦读效率要高得多。

我发现有那么一批老程序员群体,他们年纪都在30多岁,地中海就不说了,在公司属于技术骨干,平时露面不多,但一露面给我们讲课,都是口吃很严重的,一个spring都要分开发音s~s~s~pring,虽然我不确定是不是天生如此,但是有那么一段时间,需要我破解一个难题,大约有一个月的时间吧,我都是处于一种思考~敲代码~思考~敲代码的状态,一天下来,除了上厕所和打水,就没动过,更别说说话了,后来任务完成后放松下来,想和同事唠唠嗑,却发现发言有点吃力,总感觉讲不出话来,只能断断续续的说一些..h~h~h~tml,瞬间感觉自己要完了。

因此你不能认为工作就是写代码,其它与你无关,当你把面向外界的窗户关上的时候,你就会渐渐地于外界脱节,你所有的潜能和时间,也仅换成那些可能有用也可能没用的代码和一点点薪水而已。

说实话的,我很喜欢技术,但技术不是终点;我喜欢和PM谈需求,喜欢和技术聊代码,喜欢和hr规划招人,也喜欢参与集体活动,因为这些都能让我学到很多东西,技术的、产品的、运营的、行政的...当你投入去做好每一件事的背后,收获都是超乎你想象的,有些同事来公司两年了,可能还有不少运营的同事不认识的,有些同事明明对公司做了很大的贡献,可老板都叫不出姓名来,这就显得有点悲凉了。

因此不要抗拒和外界接触,你需要与外界交流,方能知自己的潜力和兴趣,你过去的爱好是写代码,或许仅仅是因为你觉得玩游戏很酷,想自己造一款游戏呢;又或许是因为你发现淘宝很赚钱,想自己写个网页出来卖东西呢;又或许是你哥哥在你面前炫耀那看起来很恐怖的控制台输出把你迷倒了呢;过去不等于现在,当你涉足的东西越多的时候,就越容易摸清自己更喜欢什么,就像我有朋友从游戏转到产品,也有从戏剧转到游戏,甚至还有从写代码转到了空少的...

笔者建议:

  1. 工作不能仅仅是工作,它也不是仅仅为了你的技术有长进和获得更多的薪水,实际上,再多的薪水,你也是打工的,也有被老板炒掉的风险,有失业的可能,只有在工作中,学习更多的技术和技术之外的知识,以后的道路才会更宽广,也更平坦。
  2. 技术成长有很多种方式,我们往往会选择闭关修行的方式,但实际上,如果你懂得怎么学习,任何场合下,都会让你学到更多的技术和其它的能力。
  3. 技多不压身,只有经历更多多元化的工作内容,你才知道自己的真爱是那一行,只有做自己喜欢的工作,才能做得快乐、长久。

6. 编程=未来?身体第一

时间来到了第四年,我依然喜欢写代码、经常加班、甚至有时候通宵达旦的编码,然而,身体素质相比五年前已经差了很多,记得刚毕业时,压力动力都有,每天几乎都是十一点过后才打车回家,睡一觉第二天照样精神抖擞的上班去,如今身体渐渐地变得不经折腾,加班一次回来累得不想动,早上睡到醒不来,爬个楼梯都气喘不止。

<又一程序员996加班猝死>、《又一个程序员倒下》、《34岁程序员猝死:年轻人,谁为你的过劳死买单?》、《又一名程序员倒下,内心悲哀:我们只是新时代农民工》、《华为程序员跳楼,难道这就是我的 35 岁?》....程序员死亡这种新闻在网上已经是屡见不鲜了,有人可能认为我吃得好睡的香身体棒棒的,猝死离我还很远,其实不然,程序员长期与电脑作伴,一天坐在电脑前脑力风暴十几个小时,对身心的摧残都是极大的,刚开始工作可能感觉没什么,但是随着年龄的慢慢增大以及久坐不动,地中海、啤酒肚、四眼仔、鼠标手...等就不知不觉的伤身了。

因此不要认为年轻就是资本,如果不注意劳逸结合,不注意休息,不注意经常运动,用不了几年,麻烦就找上门了。

可能是压力大的原因,从上个月开始,每天中午休息的时候都觉得头脑发胀、睡不着,到了下午就变成了偏头痛,整个右脑处于瘫痪状态,时不时还出现心悸的现象,那时候顿时感觉人生已经没有什么意义了,连身体都照顾不好,写再多代码,赚更多钱又有什么用,后来狠心决定每天早起半个小时去公园跑步,坚持了半个月之后,之前那些不舒服,都慢慢地恢复正常,工作起来效率更高了。

因此,健身绝对不能成为浪费时间的理由,一副好的身心,能帮你提高不少的工作效率,事半功倍。

笔者建议:

  1. 不要像我这等到身体出问题才去健身,一定要坚持坚持再坚持,去健身!!!
  2. 身体是革命的本钱,你要超越别人,不仅仅是技术,还要时间,还要有一个好身体,有一个健康的躯体,是你成功的强大后盾。

7. 附上一份技术清单

在毕业之前,很多学生都很迷茫但也很好奇,那些炫酷复杂的商城网站,那些硕果累累的技术博客,要是我也想做出一个来,都需要学那些知识呀,下面,我就做一个简单的Javaweb项目所需的技术列出一个技术清单,仅限我个人的经验,列举一些比较常见的技术而已,希望对大家有帮助。

1.前端:

语言:HTML+CSS+JavaScript
开发工具:webstorm/vscode
调试器:Chrome

  1. 学会HTML的常用标签、元素、以及它们的属性。
  2. 学会CSS的基本语法、各种样式的使用,理解CSS的盒子模型、文档流,会用定位、浮动和清除等常见的知识点。
  3. 学会js的基础(变量、函数、数组、字符串等)、理解JavaScript的面向对象思想;会用一些常用的js库(如jQuery、bootstrap等);能用js写出一些常用的插件(轮播组件、选项卡等)。
  4. 能用HTML+CSS编写网页,实现基本的网页布局,能用JavaScript+CSS编写常用的动效,能用ajax实现和后台接口的数据交互。
  5. 会用Chrome做开发调试以及简单的性能调试。

2. 后台:

语言:spring、SpringMVC/springboot
开发工具:eclipse/idea
调试工具:Chrome

  1. 了解Java起源和发展史以及语言特性,理解jdk和jre,学会配置Java开发环境。
  2. 学会Java基础,包括标识符、常量变量、关键字、标识符、数据类型、运算符、流程控制语句、数组、方法等。
  3. 理解Java面向对象的思想,理解类和对象的概念,理解面向对象的三大特性(封装、继承、多态),理解this和super的区别和使用,理解Java的接口、内部类、抽象类等。
  4. 会用一些常用的Java类(Object、String、Arrays、Math、Date、SystemDateFormate、Calendar以及一些包装类等)。
  5. 学会一些Java的高级特性,集合、多线程、IO等,还有反射的原理和使用。
  6. 学会至少一种Javaweb的开发框架(spring、springmvc、springboot等)
  7. 学会使用eclipse或idea创建web项目以及常用的开发流程、还有一些快捷键的使用。

3. 数据库

  1. 数据库:Oracle/MySQL、Redis/mongdb
  2. 开发工具:Navicat、Redis命令行
  1. 学会至少一种关系型数据库(Oracle、MySQL等),和一种非关系型数据库(Redis、mongdb等)
  2. 学会关系型数据库相关的理论和基础知识,学会非关系型数据的原理以及优势。
  3. 学会SQL的基本操作如数据库表、视图、索引的增删改查操作。
  4. 学会SQL的一些高级特性如锁、函数、触发器等。
  5. 会用Navicat等SQL客户端连接工具进行数据库的操作。
  6. 具备一些SQL性能优化的能力。

4. 版本控制:

git/svn/Cornerstone

  1. 理解版本控制的原理和应用场景,理解数据仓库中各个库的作用和使用方式。
  2. 熟悉git常用的操作命令(创建本地/远程分支、查看本地/远程分支、切换分支、提交版本、回滚、合并版本、拉取和推送分支等)。

5. 项目构建工具:

gradle/maven

这个就不多说了,项目开发必备的工具,至少得学会其中一种。

6. 运行环境:

Tomcat、nginx

  1. 了解Tomcat的组成和运行原理,理解server.xml各个熟悉的配置
  2. 学会查看和分析Tomcat的项目运行日志
  3. 学会在Tomcat中部署Java项目
  4. 了解nginx的原理和作用,学会安装nginx
  5. 学会nginx的项目配置

7. 服务器环境:

Linux

  1. 了解Linux的基本原理和一些常用的命令
  2. 能在Linux是安装jdk、Tomcat、nginx等web程序必备的软件
  3. 学会一些服务器性能调优的命令

一念之下发此文,不为名不为利,只愿与君共勉。


觉得本文对你有帮助?请分享给更多人
关注「编程无界」,提升装逼技能

查看原文

nohup 赞了文章 · 2018-10-18

入职三天,公司给了100块钱叫我走人

十月,金秋季节,本是丰收之时,却因为陆续有同事离职,心中多少有些悲凉之意,顿然想起从参加工作到现在,五年已过,当年青涩懵懂的小年轻,如今出街招摇过市时,被小孩子看到都会喊声大叔。回想这五年,有心酸和无奈、有快乐和期待、也有不断的蜕变和成长。趁着国庆长假,写下这一路的心路历程,于己,是一个总结和督促,于读者,是一个故事,兼听则明,希望对你们有些许启发,足矣。

1. 毕业=失业?有可能的

2013年6月底,虽然此前早已被某软(国内最大的软件开发商)的政府事业部录用并被寄以厚望要培养成核心人员,但出于对乡土的眷恋和对南方的热爱,还没领到毕业证的我,怀着极大的憧憬,拖着一个行李箱,兜里怀揣着几百块钱,坐了三十多个小时的绿皮从山东回到广州。

“初来乍到,请多多指教”,踏入广州那一刻,我满怀热情的对广州说。

本以为,作为985/211大学毕业的我,在国内最大的软件服务商被寄予厚望的我,在广州应该也是个热饽饽,不愁吃不愁穿不愁offer的。
然而现实是广州的公司对我并没有多多指教,而是多多抛弃。

到广州第二天,我就开始海投简历,可能是985的原因,我得到了不少的面试通知,忙的不亦乐乎,可结果却是事与愿违,有些是嫌弃没经验,有些是因为基础还不够好,有些是因为技术要求高...林林总总,总而言之就是offer一个都没拿到,以致到后面自己信心都丧失了,一再降低标准,修改简历,改成实习生、甚至跟着舍友学了几天AS3,投一些游戏公司的简历,可惜都没用。

每次回到住处,舍友就关切的问“还没拿到offer吗?”
每次打电话回家,家里人都问“找到工作了吗?待遇怎样?”
甚至到最后,家人已经对我失去了信心,打电话来说“我们想去旅游,要不你回来看一下家,反正你也找不到工作的”。
....
各种打击,内心充满了伤
毕业前满满的希望,想要凭借自己的实力,掌控一切,至少,至少也能找到一份很好的工作,
如今现实摆在眼前,毕业=失业,对于我来说,这不是假设,而是真命题。
住处是个只有10平米的单间,却住着三个人,两个人睡床上,我睡在床边的地铺上,每当夜深人静的时候,总能感觉到地板里传来的寒气,直接渗入体内,刺骨的凉让我彻夜难眠,我想挣脱这一切,我想摆脱这样的困境,更加努力的准备面试笔试,无论待遇的高低、无论公司的大小、无论距离的远近,只要给发我面试通知,我都会去面试。

记得最困难的时候,几乎身无分文,没有能力办信用卡,也不敢问家里要,每天的中午饭都是舍友从公司带回来的盒饭,晚饭就去住处旁边一家三个菜8块钱、饭和刷锅水免费随便吃喝的小店解决。有一次和大学舍友聊天,说到此事,舍友说我给你打500块钱来吧,因为异地异行取款要收10块钱手续费,为省下这10块钱我走到三公里外的银行才把钱取回来(那时候还没有摩拜、ofo之类的共享单车)。

最终功夫不负有心人,7月的尾巴,中山大学旁边的一家小型外包公司给我发来了offer,那一刻,感觉出人头地了,一切都变得那么亲切,天是那么的蓝,空气是那么的清新,地沟油是那么的香,就连我睡的地板,传来的都是凉爽。

笔者建议:

  1. 作为一名毕业生,千万不要高估自己的实力,过去的辉煌代表着过去,对于每一次面试,都必须抱着谦虚的心认真的去对待。
  2. 不同城市对毕业生的需求不一样,北方的公司(北京、大连、济南等)更看重985学校的身份,认为你是一个潜力股,因此在北方公司的简历,多写些在学校获得荣誉能对面试加不少分。而南方的公司(广州、深圳等)则更注重你当前能为公司做些什么具体的工作,产生多少的效益,因此在南方的公司的简历里,多写你的项目经验、实习经验,会对面试加分。当然这只是个人经历总结,不能以偏概全,权当是一个参考吧,笔者更加倾向于针对每个公司都有不同的简历内容,摸清公司的招聘喜好,有助于你找到心仪的工作。
  3. 一定要坚定自己的方向,不要因为工作不好找,就转向其它方向,这样只会让你浪费更多的时间更多的精力,得不偿失。

2. offer=工作?不一定!

我迫不及待的告知亲友,仿佛这件事值得举国同庆一般。
可能太开心的缘故:

上班第一天: 我就迟到了几分钟,我的上级见到我,也没说什么,就交给了一个任务:“用ssh写个简易博客”,看字面是个非常简单的任务,但由于只给了一句话,其它什么都没有,连要有什么功能、界面大概做成什么样都没有,这就增加了难度,于是我先到网站找一些管理系统的前端模板,过程非常犹豫不决,感觉bootstrap的兼容性不好、感觉easyUI又太大材小用、感觉...

上班第二天:没有迟到,但惊慌地发现:上级比我早到,我赶紧跑到座位,这时上级也转过身来
“进展怎样了?”,
我赶紧说:嗯,框架搭建好了,已经实现了部分功能。
说完自己都心虚,还想着今天再花点时间找个好模板呢,真慌,赶紧随便找了个模板,就开始搭建开发环境,下载eclipse、下载jdk...发现网络特差,于是等待等待等待,直到下午终于弄好了,草草建了个ssh项目,就开始编码,没多久就下班了,我也没加班,想着来日方长呢。

上班第三天:一到公司,上级就说进展怎样,给我演示一下吧,顿时心慌,只能硬着头皮把项目跑起来,他把我做的仅有的一点点功能看了一遍之后,就走了,没过多久,hr走过来,递给我100元:

**“不好意思,三天的考察期到了,你不符合我们的预期,这是公司给你三天工作的一点补偿”
“为什么?为什么?具体什么原因?我不要这钱,请相关的人给我说明一下”
我愤愤不平的说,
“这是领导的意思,我也不是很清楚,你看就先把钱拿着吧收拾收拾回去吧”。
她把钱放到我桌面上就走了。**

我伤心到了极点,坐在我前面座位的已经成为“前上级”的那位他也没有回头跟我说一句话,也没有说任何原因,我更加愤怒,直接到经理办公室敲门进去问总经理为什么这样对我。

经理示意我坐下来,不要生气:
“小X啊,你不要伤心啊,三百六十行,行行出状元,你长得又高,身材挺拔,外表也阳光,其实你去做保险业务员会很有前途,写代码这个工作并不是很适合你啊,我跟你讲个故事,我大学一个宿舍的同学,毕业之后,我写代码,他跑业务,现在已经做到大区经理,开保时捷了...”

听到这些,我的心已经凉凉,再讨公道已经没有意义,在一家不被老板认同的公司,注定是不会长久了,我说了句“谢谢老板这3天的照顾,希望公司早日上市(当然后来我每年都去查一下这家公司的经营状况,终于在第三年的时候倒闭了)”,就回到我的座位上默默的收拾东西,关电脑,临走时决定把那100块钱带了。

笔者建议:

  1. 千万不要认为offer拿到手就是铁饭碗了,每个新员工都会有几天的考察期和3~6个月的试用期,只有过了这两个期,你才是真正的受到《合同法》保护的,除此之外,两期之内,公司要开除你,也不需要付出什么代价的。
  2. 作为一名新员工,初来乍到,一定要谦虚地和老同事多打交道,多请教,如果我拿到任务之后,不是自己闷头做,而是多请教老同事怎么做;开发软件的下载,公司一般都会有相应的ftp工具库,省去很多搭建时间,提高开发效率。
  3. 对于新员工来说,你的上级就是你两期内的神,如果不讨好他,你会为此付出代价的。
  4. 一些常识不能少:比如不要迟到,比如进度慢了要主动加班...

3. 困境=绝境?只有努力

怀揣着100元巨款,我回到住处附近,点了份平时舍不得吃的最贵的猪脚饭,一点味道都没有,回到住处,舍友问我怎么中午就回来了,我说“我被开了”,鼻子有点酸,差点哭了,舍友不敢多问,赶紧让我先休息会。
我躺在地板上,脑子一片空白。

我该怎么对我的父母说我被开了。
我该怎么面对那些关心我的人。
我该怎么找工作。
我真的那么差劲吗。
我真的不适合写代码吗。
也许...

没有过不去的坎,只有过不去的自己;再伤心也得努力,躺了一会地板之后,起来继续投简历,这次我注重所投公司的专注的行业,挑选一些自己喜欢的行业去投,比如做体育、电商类的公司,第二天就得到了一个面试通知,我把一切都准备的好好的,还提前半个小时到面试公司楼下,是在小区里的一个公司,进门那一瞬间,有点小失望,一个家庭作坊的样子,大厅摆着几台电脑,两个员工在那盯着屏幕,我说来面试的,一个hr样子的女生就起来进去,一会带出来一个高个子领导样子的中年男子,笑眯眯的叫我进他办公室,问了一些基础问题之后,就给我讲了现在公司的状况(我进来就是二号员工)、公司业务(体育彩票类,我喜欢)、福利待遇(实习工资2.5k😢)、还有我进来之后要做的事情...讲完之后,就让我回去等通知。

两天之后,就顺利收到了offer,虽然工资很低,但因为是我喜欢的行业,再者目前找工作困难,我没多想,就答应了。

经过了前一份工作的洗礼之后,我对这份工作特别珍惜,每天提前半小时到办公室,不懂的东西就缠着仅有的一位同事给我讲,以前没学过的知识晚上回来加班加点学习(至今还记得舍友睡了我还趴在地上敲着电脑,中秋那一夜,月亮特别亮),老板让我做的东西,我主动每天下班前都发一份邮件附上今天所做的内容给老板,以此坚持了一个月,到后面,老板说你不用写那么认真,大概列一下工作内容告诉我就行。

第一个月,拿了1.6k的工资,虽然少的可怜,还不如一个端盘子的拿得多,但收到短信的那一刻,有种热泪盈眶的感觉,我终于可以靠自己的本事拿到第一份薪水了(上次的100块钱更像是耻辱,而不是薪水),为了不让家里担心,我打电话跟爸妈说我领了4k工资。

到实习期满,老板给我开了5k的工资,对我说之前给你这么低的薪水,是故意考察你的,想不到你能坚持下来并且把事情做得很好,现在这个工资才是符合你的工作能力和态度。

笔者建议:

  1. 毕业生找工作是一件很困难的事情,尤其是在准备不周到的情况下,你需要对自己的能力、兴趣做一个评估,投简历也要圈一个行业、公司实力的范围,这样你才更有胜算。
  2. 工作是一件持久的事情,你需要有持续的付出,领导才会看得到,才会得到回报。
  3. 人生本来就是困难,困境之下,你依然需要努力,再坚持一下,说不定就是出路了。

4. 工作=薪水?太肤浅

经过实习期之后,一切步入正轨,对于领导安排的一切事情,我都充满兴趣的去做。

  1. 一开始的工作是做iOS APP,此前我都是做Java,没办法,我花了两个通宵装了个黑苹果学了一周之后,领导就给我Mac Air开始开发iOS,压力和动力并存,那时心无旁骛,只想着怎么把事情做好,那时候公司甚至还没有UI,我就求着那位会UI的全栈同事给我切图,写代码时遇到难题我就骚扰大学舍友(有两个舍友做iOS)解答,历时三个半月终于完成了第一版本,上线那晚上,我们出去庆祝了一番。通过这个项目,我学会了iOS(虽然现在已经忘得差不多了)。
  2. 2014年初,那时候H5刚刚火起来,领导让我尝试把APP的内容做到H5中,仅仅在大学学过一点HTML+CSS的我,接受了这个项目,花了一个月我才开发出第一个业务,之后几乎每周就能增加一个业务,通过做这个项目,我学会了PHP,同时加强了前端的技术能力以及势头很猛的H5开发。
  3. 公司接到一个集成的项目,需要去A城对接,说到要安排人出差时,我想到这也是一个很不错的学习机会,于是很快就举手申请出差,出差一个月,我负责web项目的对接,当时有个非常困难的问题摆在眼前,那就是有一些非常复杂的涉及到较多算法的业务以前根本没开发,现在甲方要求有,我硬着头皮研究,领导天天打电话来问有没有头绪,甲方也在问,最终一周多的时间之后,终于解决,因为这次任务的完美完成,出差回来之后,领导直接把我的工资提到7k,当然不仅仅是薪水,通过这次出差,我不仅学会了项目对接的一些流程,还学了一些高深的算法,还趁这个机会把A城中的所有大学同学见了个遍。
  4. 甚至有一次,领导让我帮忙去投标,我也跟着去见识了一番,往后的日子了,说到项目投标,我都知道大概是怎么个回事了。

就这样,时间过得很快,转眼来到了2014年的夏天,从毕业到现在快一年的时间里,我从来没在意过自己的钱有多少,也没想过有什么假期,基本上就是朝九晚十一并且每周六天班,我只是不断的努力,不断的学习,不断地的汲取一切能学习到的知识,不知不觉地,我的知识库中已经增加了iOS、PHP、HTML、CSS、JavaScript等语言,而我的待遇也大幅度的提高,到了我之前没想过的高度。

笔者建议:

  1. 作为刚入行的你,薪水对你来说并不意味着更多,放下那该死的薪水吧,好好沉淀自己,如果你盯着薪水工作,那就太肤浅了。
  2. 要抓住一切机会学习,只有不断的学习,才会不断的提高,你的努力,随着时间迁移,一切会回馈给你的。

5. 编程=工作?多挖掘潜能

当我逐渐的掌握更多技能和得到更好的待遇的时候,我的心态也发生了改变,一年前闷头闷脑写代码的我,因为渐渐的成熟以及公司的转变,得到了其他方面的锻炼,比如面试、带新人、带小团队。

有些人说我是技术宅,我只想钻研技术,做其他的事情会浪费我的时间,而且我也不喜欢

其实这种想法是不对的,无论你以后的路子是要成为技术大咖还是进入管理层,首先有要技术,这确实是永恒不变的先决条件,但与人交往,并不是一种浪费时间的行为,而是另一种方式让你汲取知识和技术的途径,比如这些年,我面试过的人,少说有三五百了,最疯狂的一天面试了6个人(作为技术人员,当然不能和hr比啦)。

面试者的群体中,有还没毕业的、有刚毕业一年的、也有毕业十多年的,不管哪个层次的面试者,与之交谈,是一种自我回顾和自我提升的途径,与年幼者(技术层面)面试,会使我的基础知识得到一次回顾和巩固,与年长者(技术层面)面试,会使我的知识深度和广度得到一次拓展和加深。记得在我工作的第三年就面试过好几个工作十多年的老程序员,那时候初生牛犊不怕虎,我拿着简历就冲进面试室,让大牛先来个自我介绍,当听到他提到自己有多少开源项目,GitHub有多少star,在什么开源论坛上写过博客时,顿时感觉自己渺小到无地自容,幸好大牛面善心不恶,不但没有拆穿我,把我提的问题回答的通通透透,还顺便把知识点延伸出去,那些我根本没听过的技术,知道但是不了解的技术,都给我理了一遍,顿时觉得免费听了一节高级技术课,抵得上自己学习一个星期了。

因此技术固然重要,但一个人的力量太单薄,无论你的同事、朋友还是面试者,只要你肯与之交流、探讨,有时候会比自己一个人闭关苦读效率要高得多。

我发现有那么一批老程序员群体,他们年纪都在30多岁,地中海就不说了,在公司属于技术骨干,平时露面不多,但一露面给我们讲课,都是口吃很严重的,一个spring都要分开发音s~s~s~pring,虽然我不确定是不是天生如此,但是有那么一段时间,需要我破解一个难题,大约有一个月的时间吧,我都是处于一种思考~敲代码~思考~敲代码的状态,一天下来,除了上厕所和打水,就没动过,更别说说话了,后来任务完成后放松下来,想和同事唠唠嗑,却发现发言有点吃力,总感觉讲不出话来,只能断断续续的说一些..h~h~h~tml,瞬间感觉自己要完了。

因此你不能认为工作就是写代码,其它与你无关,当你把面向外界的窗户关上的时候,你就会渐渐地于外界脱节,你所有的潜能和时间,也仅换成那些可能有用也可能没用的代码和一点点薪水而已。

说实话的,我很喜欢技术,但技术不是终点;我喜欢和PM谈需求,喜欢和技术聊代码,喜欢和hr规划招人,也喜欢参与集体活动,因为这些都能让我学到很多东西,技术的、产品的、运营的、行政的...当你投入去做好每一件事的背后,收获都是超乎你想象的,有些同事来公司两年了,可能还有不少运营的同事不认识的,有些同事明明对公司做了很大的贡献,可老板都叫不出姓名来,这就显得有点悲凉了。

因此不要抗拒和外界接触,你需要与外界交流,方能知自己的潜力和兴趣,你过去的爱好是写代码,或许仅仅是因为你觉得玩游戏很酷,想自己造一款游戏呢;又或许是因为你发现淘宝很赚钱,想自己写个网页出来卖东西呢;又或许是你哥哥在你面前炫耀那看起来很恐怖的控制台输出把你迷倒了呢;过去不等于现在,当你涉足的东西越多的时候,就越容易摸清自己更喜欢什么,就像我有朋友从游戏转到产品,也有从戏剧转到游戏,甚至还有从写代码转到了空少的...

笔者建议:

  1. 工作不能仅仅是工作,它也不是仅仅为了你的技术有长进和获得更多的薪水,实际上,再多的薪水,你也是打工的,也有被老板炒掉的风险,有失业的可能,只有在工作中,学习更多的技术和技术之外的知识,以后的道路才会更宽广,也更平坦。
  2. 技术成长有很多种方式,我们往往会选择闭关修行的方式,但实际上,如果你懂得怎么学习,任何场合下,都会让你学到更多的技术和其它的能力。
  3. 技多不压身,只有经历更多多元化的工作内容,你才知道自己的真爱是那一行,只有做自己喜欢的工作,才能做得快乐、长久。

6. 编程=未来?身体第一

时间来到了第四年,我依然喜欢写代码、经常加班、甚至有时候通宵达旦的编码,然而,身体素质相比五年前已经差了很多,记得刚毕业时,压力动力都有,每天几乎都是十一点过后才打车回家,睡一觉第二天照样精神抖擞的上班去,如今身体渐渐地变得不经折腾,加班一次回来累得不想动,早上睡到醒不来,爬个楼梯都气喘不止。

<又一程序员996加班猝死>、《又一个程序员倒下》、《34岁程序员猝死:年轻人,谁为你的过劳死买单?》、《又一名程序员倒下,内心悲哀:我们只是新时代农民工》、《华为程序员跳楼,难道这就是我的 35 岁?》....程序员死亡这种新闻在网上已经是屡见不鲜了,有人可能认为我吃得好睡的香身体棒棒的,猝死离我还很远,其实不然,程序员长期与电脑作伴,一天坐在电脑前脑力风暴十几个小时,对身心的摧残都是极大的,刚开始工作可能感觉没什么,但是随着年龄的慢慢增大以及久坐不动,地中海、啤酒肚、四眼仔、鼠标手...等就不知不觉的伤身了。

因此不要认为年轻就是资本,如果不注意劳逸结合,不注意休息,不注意经常运动,用不了几年,麻烦就找上门了。

可能是压力大的原因,从上个月开始,每天中午休息的时候都觉得头脑发胀、睡不着,到了下午就变成了偏头痛,整个右脑处于瘫痪状态,时不时还出现心悸的现象,那时候顿时感觉人生已经没有什么意义了,连身体都照顾不好,写再多代码,赚更多钱又有什么用,后来狠心决定每天早起半个小时去公园跑步,坚持了半个月之后,之前那些不舒服,都慢慢地恢复正常,工作起来效率更高了。

因此,健身绝对不能成为浪费时间的理由,一副好的身心,能帮你提高不少的工作效率,事半功倍。

笔者建议:

  1. 不要像我这等到身体出问题才去健身,一定要坚持坚持再坚持,去健身!!!
  2. 身体是革命的本钱,你要超越别人,不仅仅是技术,还要时间,还要有一个好身体,有一个健康的躯体,是你成功的强大后盾。

7. 附上一份技术清单

在毕业之前,很多学生都很迷茫但也很好奇,那些炫酷复杂的商城网站,那些硕果累累的技术博客,要是我也想做出一个来,都需要学那些知识呀,下面,我就做一个简单的Javaweb项目所需的技术列出一个技术清单,仅限我个人的经验,列举一些比较常见的技术而已,希望对大家有帮助。

1.前端:

语言:HTML+CSS+JavaScript
开发工具:webstorm/vscode
调试器:Chrome

  1. 学会HTML的常用标签、元素、以及它们的属性。
  2. 学会CSS的基本语法、各种样式的使用,理解CSS的盒子模型、文档流,会用定位、浮动和清除等常见的知识点。
  3. 学会js的基础(变量、函数、数组、字符串等)、理解JavaScript的面向对象思想;会用一些常用的js库(如jQuery、bootstrap等);能用js写出一些常用的插件(轮播组件、选项卡等)。
  4. 能用HTML+CSS编写网页,实现基本的网页布局,能用JavaScript+CSS编写常用的动效,能用ajax实现和后台接口的数据交互。
  5. 会用Chrome做开发调试以及简单的性能调试。

2. 后台:

语言:spring、SpringMVC/springboot
开发工具:eclipse/idea
调试工具:Chrome

  1. 了解Java起源和发展史以及语言特性,理解jdk和jre,学会配置Java开发环境。
  2. 学会Java基础,包括标识符、常量变量、关键字、标识符、数据类型、运算符、流程控制语句、数组、方法等。
  3. 理解Java面向对象的思想,理解类和对象的概念,理解面向对象的三大特性(封装、继承、多态),理解this和super的区别和使用,理解Java的接口、内部类、抽象类等。
  4. 会用一些常用的Java类(Object、String、Arrays、Math、Date、SystemDateFormate、Calendar以及一些包装类等)。
  5. 学会一些Java的高级特性,集合、多线程、IO等,还有反射的原理和使用。
  6. 学会至少一种Javaweb的开发框架(spring、springmvc、springboot等)
  7. 学会使用eclipse或idea创建web项目以及常用的开发流程、还有一些快捷键的使用。

3. 数据库

  1. 数据库:Oracle/MySQL、Redis/mongdb
  2. 开发工具:Navicat、Redis命令行
  1. 学会至少一种关系型数据库(Oracle、MySQL等),和一种非关系型数据库(Redis、mongdb等)
  2. 学会关系型数据库相关的理论和基础知识,学会非关系型数据的原理以及优势。
  3. 学会SQL的基本操作如数据库表、视图、索引的增删改查操作。
  4. 学会SQL的一些高级特性如锁、函数、触发器等。
  5. 会用Navicat等SQL客户端连接工具进行数据库的操作。
  6. 具备一些SQL性能优化的能力。

4. 版本控制:

git/svn/Cornerstone

  1. 理解版本控制的原理和应用场景,理解数据仓库中各个库的作用和使用方式。
  2. 熟悉git常用的操作命令(创建本地/远程分支、查看本地/远程分支、切换分支、提交版本、回滚、合并版本、拉取和推送分支等)。

5. 项目构建工具:

gradle/maven

这个就不多说了,项目开发必备的工具,至少得学会其中一种。

6. 运行环境:

Tomcat、nginx

  1. 了解Tomcat的组成和运行原理,理解server.xml各个熟悉的配置
  2. 学会查看和分析Tomcat的项目运行日志
  3. 学会在Tomcat中部署Java项目
  4. 了解nginx的原理和作用,学会安装nginx
  5. 学会nginx的项目配置

7. 服务器环境:

Linux

  1. 了解Linux的基本原理和一些常用的命令
  2. 能在Linux是安装jdk、Tomcat、nginx等web程序必备的软件
  3. 学会一些服务器性能调优的命令

一念之下发此文,不为名不为利,只愿与君共勉。


觉得本文对你有帮助?请分享给更多人
关注「编程无界」,提升装逼技能

查看原文

赞 91 收藏 46 评论 47

nohup 评论了文章 · 2018-09-30

RocketMq使用过程的那些小事

在使用rocketmq之前使用了rabbitmq,会出现丢消息的情况,进而果断放弃,继续投入到大Java的怀抱,不过也遇到了一些问题,这里总结一下:

  1. 使用过程中新加节点需要手动创建topic

  2. 消费者处理不合理,不能实现负载均衡

针对第二点:我之前一直使用的是pull方式,按顺序来消费,一旦程序重启则从头一个一个消费,显然这种效率很低,
而且因为一个代码问题,如果我在offsize = 0的情况获取不了数据,则min offsize不增长,这种情况导致如果数据隔天了则不能消费,这时候消费者相当于在空跑。

          List<MessageVo> msgList = new ArrayList<MessageVo>();
            try {
                Set<MessageQueue> mqs = consumer.fetchSubscribeMessageQueues(queueName);
                for (MessageQueue mq : mqs) {
                    System.out.printf("Consume from the queue: " + mq + "%n");
                    try {
                        PullResult pullResult =
                                consumer.pullBlockIfNotFound(mq, null, getMessageQueueOffset(mq), 32);
                        if (pullResult != null) {
                            putMessageQueueOffset(mq, pullResult.getNextBeginOffset());
                            switch (pullResult.getPullStatus()) {
                                case FOUND:
                                    if (pullResult.getMsgFoundList() != null && pullResult.getMsgFoundList().size() > 0) {
                                        for (MessageExt messageExt : pullResult.getMsgFoundList()) {
                                            msgList.add(new MessageVo(messageExt.getMsgId(), messageExt.getBody()));
                                        }
                                    }
                                    break;
                                case NO_MATCHED_MSG:
                                    break;
                                case NO_NEW_MSG:
                                    break;
                                case OFFSET_ILLEGAL:
                                    break;
                                default:
                                    break;
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

使用这种方法可以稳定的pull出数据,但是这种情况效率很低。

使用多线程方式:

            private Queue<List<MessageVo>> messageQueue = new LinkedBlockingQueue<List<MessageVo>>();
            
           DefaultMQPullConsumer consumer = new DefaultMQPullConsumer(groupName);
            consumer.setNamesrvAddr(url);
            scheduleService = new MQPullConsumerScheduleService(groupName);
            scheduleService.setMessageModel(MessageModel.CLUSTERING);
            scheduleService.setDefaultMQPullConsumer(consumer);
            
          List<MessageVo> msgList = new ArrayList<MessageVo>();
            try {
                Set<MessageQueue> mqs = consumer.fetchSubscribeMessageQueues(queueName);
                for (MessageQueue mq : mqs) {
                    System.out.printf("Consume from the queue: " + mq + "%n");
                    try {
                        PullResult pullResult =
                                consumer.pullBlockIfNotFound(mq, null, getMessageQueueOffset(mq), 32);
                        if (pullResult != null) {
                            putMessageQueueOffset(mq, pullResult.getNextBeginOffset());
                            switch (pullResult.getPullStatus()) {
                                case FOUND:
                                    if (pullResult.getMsgFoundList() != null && pullResult.getMsgFoundList().size() > 0) {
                                        for (MessageExt messageExt : pullResult.getMsgFoundList()) {
                                            msgList.add(new MessageVo(messageExt.getMsgId(), messageExt.getBody()));
                                        }
                                    }
                                    break;
                                case NO_MATCHED_MSG:
                                    break;
                                case NO_NEW_MSG:
                                    break;
                                case OFFSET_ILLEGAL:
                                    break;
                                default:
                                    break;
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
          List<MessageVo> msgList = new ArrayList<MessageVo>();
            try {
                Set<MessageQueue> mqs = consumer.fetchSubscribeMessageQueues(queueName);
                for (MessageQueue mq : mqs) {
                    System.out.printf("Consume from the queue: " + mq + "%n");
                    try {
                        PullResult pullResult =
                                consumer.pullBlockIfNotFound(mq, null, getMessageQueueOffset(mq), 32);
                        if (pullResult != null) {
                            putMessageQueueOffset(mq, pullResult.getNextBeginOffset());
                            switch (pullResult.getPullStatus()) {
                                case FOUND:
                                    if (pullResult.getMsgFoundList() != null && pullResult.getMsgFoundList().size() > 0) {
                                        for (MessageExt messageExt : pullResult.getMsgFoundList()) {
                                            msgList.add(new MessageVo(messageExt.getMsgId(), messageExt.getBody()));
                                        }
                                    }
                                    break;
                                case NO_MATCHED_MSG:
                                    break;
                                case NO_NEW_MSG:
                                    break;
                                case OFFSET_ILLEGAL:
                                    break;
                                default:
                                    break;
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

通过回调的方式来定时调用。这种方式是多线程来实现的。

使用这种方式不能部署两个程序,因为会导致groupName冲突

查看原文

nohup 收藏了文章 · 2018-09-19

vue-cli3.x 新特性及踩坑记

webpack.png

前言

vue-cli 都到 3.0.3 了,所以是时候玩转一下 vue-cli 3 的新特性了。

1. vue-cli 3.0.3

以下的安装都是在 macOS 的环境下进行的,当然在 windows 和 linus 下也同理。

1.1 安装

vue cli 的包名称由 vue-cli 改成了 @vue/cli。 如果你已经全局安装了旧版本的 vue-cli (1.x 或 2.x),你需要先通过 npm uninstall vue-cli -g 或 yarn global remove vue-cli 卸载它。

可以使用下列任一命令安装这个新 vue-cli 3.0.3 的包:

npm install -g @vue/cli
# OR
yarn global add @vue/cli

你还可以用这个命令来检查其版本是否正确 (3.x):

vue --version

或者:

vue -V

1.2使用图形化界面

你也可以通过 vue ui 命令以图形化界面创建和管理项目:

vue ui

上述命令会打开一个浏览器窗口,并以图形化界面将你引导至项目创建的流程。

1.3 创建项目

1.3.1 默认型
  • 新建文件夹,在该文件夹下打开命令窗口,输入以下命令进行新建项目,当然我起的项目名字叫 vue-webpack-demo
vue create vue-webpack-demo
  • 会让你选择默认(default)还是手动(Manually),(注:现在vue-cli3.0默认使用yarn下载)。

  • 先是默认的,一路回车后的项目目录如下:

  • 再来手动的,我起的项目名字叫 vue-webpack-demo2,如下图,让你选择那些选项,按 空格键 是选择单个,a 键 是全选。

  • 我选择了常用的如下选项:

  • vue-router 默认 hash 模式,所以我选择默认的,选择了 n ,而不是 history 模式:

  • 下一步之后问询问你安装哪一种 CSS 预处理语言,我是选择了用的 less。

  • 这个是问你选择哪个自动化代码格式化检测,配合 vscode 编辑器的,Prettier - Code formatter插件,我选的随后一个。

  • 第一个是保存就检测,第二个是 fix 和 commit 的时候检查。

  • 选择单元测试解决方案,Mocha是流行的JavaScript测试框架之一,通过它添加和运行测试,从而保证代码质量,chai 是断言库,我两个都选择了。

  • 上边这俩意思问你像,babel, postcss, eslint 这些配置文件放哪?第一个是:放独立文件放置,第二个是:放package.json里,这里小汪选择放单独配置文件,选第一个

image.png

  • 下面倒数第二行问你是否将以上这些将此保存为未来项目的预配置吗 ?选择是的时候,下次创建项目时,可以选择刚刚配置好的配置,不用再每个都配置一遍。最后一个是选择的名字,你随意选择,点击确定就开始下载模板了。

  • 再创建项目的时候,刚刚配置好的选择的名字 vue-webpack4 会这样子出现:

  • 启动命令
// 1. 进入项目
cd vue-webpack-demo 
// 或者 cd vue-webpack-demo2
// 2. 安装依赖
npm i
// 3. 启动
npm run serve

1.4 项目改变
  1. 相比 vue-cli 2.X 创建的目录,vue-cli 3.0 创建的目录看不见 webpack 的配置

image.png

  1. 启动命令行由:
npm run dev 或者 npm start

改变为:

npm run serve
  1. 安装过程也发生了一些变化,配置可以保存,下次可以再用,像前面的 vue-webpack4。
  2. 手动配置 webpack:在根目录下新建一个 vue.config.js 文件,进行你的配置 :
const path = require('path');

module.exports = {
    // 基本路径
    baseUrl: './',
    // 输出文件目录
    outputDir: 'dist',
    // eslint-loader 是否在保存的时候检查
    lintOnSave: true,
    // webpack配置
    // see https://github.com/vuejs/vue-cli/blob/dev/docs/webpack.md
    chainWebpack: () => {},
    configureWebpack: (config) => {
        if (process.env.NODE_ENV === 'production') {
            // 为生产环境修改配置...
            config.mode = 'production';
        } else {
            // 为开发环境修改配置...
            config.mode = 'development';
        }

        Object.assign(config, {
            // 开发生产共同配置
            resolve: {
                alias: {
                    '@': path.resolve(__dirname, './src'),
                    '@c': path.resolve(__dirname, './src/components')
                }
            }
        });
    },
    // 生产环境是否生成 sourceMap 文件
    productionSourceMap: true,
    // css相关配置
    css: {
        // 是否使用css分离插件 ExtractTextPlugin
        extract: true,
        // 开启 CSS source maps?
        sourceMap: false,
        // css预设器配置项
        loaderOptions: {},
        // 启用 CSS modules for all css / pre-processor files.
        modules: false
    },
    // use thread-loader for babel & TS in production build
    // enabled by default if the machine has more than 1 cores
    parallel: require('os').cpus().length > 1,
    // PWA 插件相关配置
    // see https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-pwa
    pwa: {},
    // webpack-dev-server 相关配置
    devServer: {
        open: process.platform === 'darwin',
        host: '0.0.0.0',
        port: 8080,
        https: false,
        hotOnly: false,
        // proxy: {
        //     // 设置代理
        //     // proxy all requests starting with /api to jsonplaceholder
        //     'http://localhost:8080/': {
        //         target: 'http://baidu.com:8080', //真实请求的目标地址
        //         changeOrigin: true,
        //         pathRewrite: {
        //             '^http://localhost:8080/': ''
        //         }
        //     }
        // },
        before: (app) => {}
    },
    // 第三方插件配置
    pluginOptions: {
        // ...
    }
};
  1. 当然如果你不想用3.0的话,还是可以继续使用2.0的, 官方文档是这样说的:

具体配置看官方文档:
vue-cli 3.0
简单的配置方式

踩坑记

1. npm 的全局路径被修改了

我都不记得在装什么包的时候修改了 mac 中 npm 的全局路径了,平时 npm 运行各种命令不报错。

全局卸载 vue-cli 命令行:

npm uninstall vue-cli -g;

但是今天全局卸载 vue-cli 的时候一直不成功,搞了一个小时,结果看了一下 npm 的全局路径,才发现路径不对!!!

如果你的 npm 的全局路径也变了,请按如下步骤修改加默认的。

方法一:

原因:npmr 的配置改变了,导致正确的 npmr 不能用。

  • 打开终端,切换到根路径
cd 
open .npmrc 
  • 文件里面修改为 prefix=/usr/local

方法二:

npm config set prefix /usr/local  //是默认路径 修改了路径会出现错误。

按上面的方法修改完,再全局卸载 vue-cli 果然就成功了。

最后

你以为本文就这么结束了 ? 精彩在后面 !!!

全栈修炼 有兴趣的朋友可以扫下方二维码关注我的公众号

我会不定期更新有价值的内容,长期运营。

关注公众号并回复 福利 可领取免费学习资料,福利详情请猛戳: Python、Java、Linux、Go、node、vue、react、javaScript

图片描述

查看原文

nohup 赞了文章 · 2018-09-19

vue-cli3.x 新特性及踩坑记

webpack.png

前言

vue-cli 都到 3.0.3 了,所以是时候玩转一下 vue-cli 3 的新特性了。

1. vue-cli 3.0.3

以下的安装都是在 macOS 的环境下进行的,当然在 windows 和 linus 下也同理。

1.1 安装

vue cli 的包名称由 vue-cli 改成了 @vue/cli。 如果你已经全局安装了旧版本的 vue-cli (1.x 或 2.x),你需要先通过 npm uninstall vue-cli -g 或 yarn global remove vue-cli 卸载它。

可以使用下列任一命令安装这个新 vue-cli 3.0.3 的包:

npm install -g @vue/cli
# OR
yarn global add @vue/cli

你还可以用这个命令来检查其版本是否正确 (3.x):

vue --version

或者:

vue -V

1.2使用图形化界面

你也可以通过 vue ui 命令以图形化界面创建和管理项目:

vue ui

上述命令会打开一个浏览器窗口,并以图形化界面将你引导至项目创建的流程。

1.3 创建项目

1.3.1 默认型
  • 新建文件夹,在该文件夹下打开命令窗口,输入以下命令进行新建项目,当然我起的项目名字叫 vue-webpack-demo
vue create vue-webpack-demo
  • 会让你选择默认(default)还是手动(Manually),(注:现在vue-cli3.0默认使用yarn下载)。

  • 先是默认的,一路回车后的项目目录如下:

  • 再来手动的,我起的项目名字叫 vue-webpack-demo2,如下图,让你选择那些选项,按 空格键 是选择单个,a 键 是全选。

  • 我选择了常用的如下选项:

  • vue-router 默认 hash 模式,所以我选择默认的,选择了 n ,而不是 history 模式:

  • 下一步之后问询问你安装哪一种 CSS 预处理语言,我是选择了用的 less。

  • 这个是问你选择哪个自动化代码格式化检测,配合 vscode 编辑器的,Prettier - Code formatter插件,我选的随后一个。

  • 第一个是保存就检测,第二个是 fix 和 commit 的时候检查。

  • 选择单元测试解决方案,Mocha是流行的JavaScript测试框架之一,通过它添加和运行测试,从而保证代码质量,chai 是断言库,我两个都选择了。

  • 上边这俩意思问你像,babel, postcss, eslint 这些配置文件放哪?第一个是:放独立文件放置,第二个是:放package.json里,这里小汪选择放单独配置文件,选第一个

image.png

  • 下面倒数第二行问你是否将以上这些将此保存为未来项目的预配置吗 ?选择是的时候,下次创建项目时,可以选择刚刚配置好的配置,不用再每个都配置一遍。最后一个是选择的名字,你随意选择,点击确定就开始下载模板了。

  • 再创建项目的时候,刚刚配置好的选择的名字 vue-webpack4 会这样子出现:

  • 启动命令
// 1. 进入项目
cd vue-webpack-demo 
// 或者 cd vue-webpack-demo2
// 2. 安装依赖
npm i
// 3. 启动
npm run serve

1.4 项目改变
  1. 相比 vue-cli 2.X 创建的目录,vue-cli 3.0 创建的目录看不见 webpack 的配置

image.png

  1. 启动命令行由:
npm run dev 或者 npm start

改变为:

npm run serve
  1. 安装过程也发生了一些变化,配置可以保存,下次可以再用,像前面的 vue-webpack4。
  2. 手动配置 webpack:在根目录下新建一个 vue.config.js 文件,进行你的配置 :
const path = require('path');

module.exports = {
    // 基本路径
    baseUrl: './',
    // 输出文件目录
    outputDir: 'dist',
    // eslint-loader 是否在保存的时候检查
    lintOnSave: true,
    // webpack配置
    // see https://github.com/vuejs/vue-cli/blob/dev/docs/webpack.md
    chainWebpack: () => {},
    configureWebpack: (config) => {
        if (process.env.NODE_ENV === 'production') {
            // 为生产环境修改配置...
            config.mode = 'production';
        } else {
            // 为开发环境修改配置...
            config.mode = 'development';
        }

        Object.assign(config, {
            // 开发生产共同配置
            resolve: {
                alias: {
                    '@': path.resolve(__dirname, './src'),
                    '@c': path.resolve(__dirname, './src/components')
                }
            }
        });
    },
    // 生产环境是否生成 sourceMap 文件
    productionSourceMap: true,
    // css相关配置
    css: {
        // 是否使用css分离插件 ExtractTextPlugin
        extract: true,
        // 开启 CSS source maps?
        sourceMap: false,
        // css预设器配置项
        loaderOptions: {},
        // 启用 CSS modules for all css / pre-processor files.
        modules: false
    },
    // use thread-loader for babel & TS in production build
    // enabled by default if the machine has more than 1 cores
    parallel: require('os').cpus().length > 1,
    // PWA 插件相关配置
    // see https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-pwa
    pwa: {},
    // webpack-dev-server 相关配置
    devServer: {
        open: process.platform === 'darwin',
        host: '0.0.0.0',
        port: 8080,
        https: false,
        hotOnly: false,
        // proxy: {
        //     // 设置代理
        //     // proxy all requests starting with /api to jsonplaceholder
        //     'http://localhost:8080/': {
        //         target: 'http://baidu.com:8080', //真实请求的目标地址
        //         changeOrigin: true,
        //         pathRewrite: {
        //             '^http://localhost:8080/': ''
        //         }
        //     }
        // },
        before: (app) => {}
    },
    // 第三方插件配置
    pluginOptions: {
        // ...
    }
};
  1. 当然如果你不想用3.0的话,还是可以继续使用2.0的, 官方文档是这样说的:

具体配置看官方文档:
vue-cli 3.0
简单的配置方式

踩坑记

1. npm 的全局路径被修改了

我都不记得在装什么包的时候修改了 mac 中 npm 的全局路径了,平时 npm 运行各种命令不报错。

全局卸载 vue-cli 命令行:

npm uninstall vue-cli -g;

但是今天全局卸载 vue-cli 的时候一直不成功,搞了一个小时,结果看了一下 npm 的全局路径,才发现路径不对!!!

如果你的 npm 的全局路径也变了,请按如下步骤修改加默认的。

方法一:

原因:npmr 的配置改变了,导致正确的 npmr 不能用。

  • 打开终端,切换到根路径
cd 
open .npmrc 
  • 文件里面修改为 prefix=/usr/local

方法二:

npm config set prefix /usr/local  //是默认路径 修改了路径会出现错误。

按上面的方法修改完,再全局卸载 vue-cli 果然就成功了。

最后

你以为本文就这么结束了 ? 精彩在后面 !!!

全栈修炼 有兴趣的朋友可以扫下方二维码关注我的公众号

我会不定期更新有价值的内容,长期运营。

关注公众号并回复 福利 可领取免费学习资料,福利详情请猛戳: Python、Java、Linux、Go、node、vue、react、javaScript

图片描述

查看原文

赞 85 收藏 67 评论 18

认证与成就

  • 获得 20 次点赞
  • 获得 2 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 2 枚铜徽章

擅长技能
编辑

(゚∀゚ )
暂时没有

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2016-02-16
个人主页被 781 人浏览