2014年9月2号,收到华为的优先招聘面试邀请,让我第二天早上9:45去西安香格里拉大酒店参加面试。心里很没底,作为不是科班出身,但是软件硕士一枚,真心感觉心虚啊,好多东西没复习,想想网络,操作系统什么的都压根没看,简直要裸面的节奏。不过幸运的是,我的哥们下午已经面试回来,说华为面试的人很多,你把简历上的东西好好准备,着重讲一个最有难度,最能体现自己水平的项目就OK了,尽量多扯一会,时间也就差不多了,面试官也就没有时间让你写什么堆排,快排这些有点难度的东西(当然,如果你数据结构复习的很好,这些也不在话下)。这下心里有底了,着重准备了一个项目,准备第二天从这个项目展开。
9月3号早上七点起床,坐上车出发了,到了酒店,发现面试的人也不是太多,突然很巧的碰见一个西工大的高中同学,就跟他聊了一会,知道他不是学软件的,来应聘的华为的测试岗。呵呵,我两都是早上9点45分第二批的。一看离面试还有一个多小时,想想各种排序都忘得差不多了,就冒泡和选择等简单的还能写出来,快排,堆排都只知道思路,于是趁着在等候区等待的这些时间就手机上搜了一下实现,开始推导起来。结果到了10点20才叫到我去面试。本次优选会,华为共两面,一面技术面、二面BOSS面。通过的话就可以直接等Offer了。
第一面技术面。
面试官是一个有40多岁的人,看上去挺和蔼的,他让我先自我介绍一下,这个没咋准备,几句话了事。接着面试管看着我的简历,说你做了五六个项目,捡一个印象最深的一个项目介绍一下,我挑了其中的一个,他让我画一下项目的架构图,幸好昨天准备过了,就把自己的项目架构图草草的画了一下,然后面试官让我画出自己做的部分。按照提前构思的,我跟面试官说我准备从三个方面讲解,他表示同意。由于我做的都是Java Web的项目,所以第一点我说用AOP实现了权限拦截,登录验证,操作日志统计等。第二点是基于WebSocket实现了小组内的聊天室。第三点用Lucene构建了搜索引擎。
一、AOP
他问我你AOP是干什么的?我开始讲:AOP是叫面向切面编程,怎么理解呢?就是关注点分离,让某些类在执行某些方法中增加一些其他业务操作。举例说明,(一遍在纸上画一边讲)A方法在执行时候完自己的业务逻辑之后要打印日志,B方法也要打印日志,C方法也要打印日志。。。。。传统OOP的作法是:在A、B、C都要调用打印日志的类的打印日志的方法。现在有了AOP只要声明一个切面(Aspect),定义一下切入点(PointCut)从A、B、C切入,,然后加上一个后置通知(doAfter),这样只要在每个方法前加上注解声明一下,就可以使得执行A方法、B方法、C方法时候执行打印日志操作。然后我说为什么Spring AOP能实现这样的功能呢?这就用到了动态代理模式,我这里主要讲了一下JDK的动态代理(CGLIB动态代理自己也忘了),我先说静态代理:假如,B类实现了A接口,C要代理B类的时候,也需要实现A接口,但是在C类中,会加入一些其他的操作,所以只要是实现了B接口的类,在调用时都会被代理类所代理,并增强处理。问题是,每个代理类我们都要自己写,假如又有另一组的接口需要被代理的时候,又得再写一个代理类。能不能抽象更好的方法呢?这就需要动态代理,我开始从Java反射机制讲:JVM在类加载过程中会为每个类生成唯一的Class对象,这个Class对象是单例的,且封装了类的一些内部数据结构,程序在运行过程中就可以像一面镜子一样获取通过Class对象获取该类实例的Method,Field,构造方法,注解信息,父类等。JDK动态代理呢,就可以根据这种机制动态的为这些类生成代理类,这些代理类实现了和目标类同样的接口。当目标类调用目标方法的时候,代理类就可以完全代理目标类的方法,并且可以增加一些其他处理。
说到这里,他感觉我说的比较抽象,说差不多了。接着,他问我,你做权限时候有没有怎么做的?我画了一下RBAC的图,说用户在登录的时候,根据用户的角色,查出他所用的权限列表,存在Session中,然后用户在执行操作的时候,根据AOP对用户的执行方法的权限进行拦截。他说,你这样做,考没考虑过:假如用户在操作过程中,后台管理员对他的权限进行重新配置,也就是说你的权限此时有所变化,比如说取消了你的某项权限,本应说你已无权执行该方法,但是你的Session中存取的权限列表中依然存在该方法,你该怎么办? 哦哦,我说,管理员在配置权限的时候,要更新用户的Session中的权限列表。一想这样并对,管理员怎么能拿到用户Session中的变量呢,压根就不是同一个Session中。想到这,我说能不能在AOP执行拦截的时候该方法时再查询一下用户的权限,这样在用户在访问每个要进行权限判断的方法前,都要重新查询一次,这就能保证用户的权限列表时刻是最新的。他就问假如用户量很大,有百万用户同时访问该网站,那每个要拦截的方法被执行前都要查一下数据库中的权限表,考没考虑过对服务器的性能影响呢?怎么解决呢?嘿嘿,说到这里,原来他想问我并发问题,我想了一会,说用分布式,他一听挺高兴的,说分布式确实是一种解决并发问题的方案。那你就来说说分布式吧,晕,直接给自己挖坑了。我说我只是简单了解分布式,没开发经验,不太会,他也没再问。
等了一下,你说你刚才讲了动态代理中,接口的实现这些OOP的东西。那你讲一下private,public,protected的区别,子类能访问父类的私有方法么?很简单的问题,我突然不知道咋回答,想了一下,说子类要访问父类的成员变量,是要看这个父类的是否为这个成员变量提供了getter方法,如果只提供getter方法,说明是该变量是只读的,只能访问,不能修改。有些答非所问了,这是任何类之间访问的权限问题,并不是人家要听到的。感觉被鄙视了,让我回去再好好看看书。然后又问我多态是什么?我说比如:一个List有个add()方法,ArrayList通过数组实现,LinkedList通过链表实现。那么List list=new ArrayList(),然后调用list.add()。也可以List list=new LinkedList()。list.add(),接口List的引用指向了不同的实现类,这就是多态性的一种体现。他竟然说这只是继承,不是多态。我又说比如Animal类,有个run()方法,Tiger继承了Animal,并重写了run(),Sheep类也继承了Animal,也重写了run()方法,这样当我们使用Animal a=new Tiger();a.run();和Animal b=new Tiger();b.run(),同一个父类的引用指向了不同的子类实例。他好像不同意(也可能是我讲的不清楚),让我说一下,书上是怎么定义的,我说,我不喜欢背概念,我是这样理解的。他也没再问多少。
接着,他问我,对数据库了解多少,我说对MySQL熟悉,他就问我,存储过程讲一讲,我说这个没咋用过,以前学过,忘了,又被鄙视了。接着问我联合查询,我说是不是Jion,他说不是那个。。。我想起来,是多表查询吧?对,写一下SQL吧,我写成select * from a,b where a.x=b.x,他说你这*哪来的,我一看不对,就说要改成字段,也可以用as自己命名。接着又问我什么是事务,我讲了一下,他表示同意。
第二、WebSocket
到这里,他说,基本问完了,问我还有什么问题没有?我刚准备说,他说对了,讲一下你那个WebSocket聊天室(PS:华为公司是搞通信的,很多员工都用的C/C++进行网络编程,所以应该要认真复习网络编程,还有各种协议)。我开始讲:WebSocket和传统的Socket编程,有所不同,传统的Socket是要编写一个客户端和服务器端应用程序,进行端对端的通信。而WebSocket的客户端只需要有一个浏览器(必须支持HTML5),就可以直接将浏览器作为Socket客户端用,服务器端直接用Apache的Web服务器如Tomcat或者JBoss的那些实现了Websocket协议的版本作为容器。 这样我们就将传统的C/S架构改成了B/S的架构,很方便。接着我说为什么我做聊天室要用到这个,因为我以前也做过AJAX聊天室,各个客户端采用轮询的方式定时地向服务器发送HTTP请求,让服务器去查询数据库,是否有新的聊天记录产生,若有的话,将HTTP响应的数据显示在聊天窗口中。但这样做,会给服务器带来很大负载,即使很长时间没有新消息,但是每个客户端还是定时请求,这就对服务器资源产生了很大浪费。现在有了WebSocket,每个客户端浏览器都和服务器Tomcat建立了一个Socket连接,那么我们就可以实现客户端和服务器端的全双工通信,一旦有一个客户端发消息,服务器监听到以后呢,就可以对通过遍历存在服务器端的HashMap<User,Socket>中的所有Socket连接,通过每个Socket广播给所有客户端。接下来,我讲了一下Websocket的原理:WebSocket是在Http请求的时候,在Http报文中加入了如下报文:upgrade:websocket ; connection:upgrade。key:XXX。告诉服务器的Servlet(一种特殊的Servlet,继承自WebSocketServlet),要求协议升级到WebSocket,服务器收到这个特殊的HTTP报文段,经过对key进行Hash以后,返回给客户端,表示升级成功,同意建立Socket连接(这样应用层两次握手就完了,这和传输层TCP的三次握手不在一个层面),这样双方就可以进行全双工的通信。他感觉我讲的还不错,就开始问我传统的Socket怎么实现聊天。我说服务器端用ServerSocket ss=new ServerSocket(Port);监听某个端口,然后while(true){Socket s=ss.accept();}时刻可以接受客户端的Socket请求。然后客户端Socket s=new Socket(String IP,String port),底层调用connet()方法像服务器请求Soket连接,经过三次握手成功以后就建立了Socket连接。这样,客户端和服务器端就可以通过网络流进行数据传输。说到这里,他提出一个问题:假如客户端A向服务器发送a数据,若要再发送b数据之前,必须确认服务器收到数据,并且收到服务器响应以后才能发b数据,请问你怎么实现?我说我用的基于TCP的Socket,TCP本身就是可靠传输的,有数据重传机制,能保证服务器收到数据。他说不对,那是传输层的问题,现在讨论的是应用层的问题,你怎么能知道服务器端Socket收到消息没?我说客户端能不能再发送a以后开始一直在read,如果没有读到数据就不发b,感觉还是讲的不清楚,真不知道怎么回答了。他让我再回去好好想想。他有看了看我的简历,说学过C语言没?我说大一的时候学过,有五六年时间了,现在都忘得差不多了,我主要从事的还是Java开发。呵呵,他笑了一下,说他问完了,问我有木有什么问题?我就随便问了一下如果华为决定录用我,能不能让我选择我感兴趣的职位,我想从事比如网络编程方面的东西。他一笑,说这个你如果签协议时候再说吧。
三、Lucene构建搜素引擎
这个方面的问题,我准备讲一下倒排索引啊,Lucene搜索引擎的原理啥的,我技术面的时间比较长有40多分钟,周围的人有的才面试了十几分钟。所以也就没再让我讲,让我在等候区等待下一轮面试。技术面就这样结束了。
第二面Boss面。
在等候区等待了一段时间之后,一个MM带我进去面试。坐在面试官对面,这位Boss看到人挺精神的,有个30岁的样子。他在电脑里面输入我的信息之后,开始面试 。
首先,他说了一下我的名字,然后直接问我要成绩单,我说学校还没开学,教务处没开门,没法打印。我说我就前30%的水平。他看了一下我的身份证,说你是咸阳人,以后准备留西安吧。我说:这个必须的。哈哈,要表达出强烈的意愿才行。
其次,他在电脑上看我的信息,问我的机试为什么不理想,我说我发挥的有些失误。他问我都考得什么题目。我说:第一题是求字符串里的元音字母,他问怎么求,我说这很简单,元音字母也就5个,枚举一下就OK 了。第二题是有字符串A:“cpupucpu”和字符串B:“cpu”,删除A中包含的B,然后输出A中删除B以后的字符串。我说这个题目失误了,我都编写出来了,结果因为没把删除以后的字符串重新赋值给A,就直接调试打印A,发现还是原来的值怎么都不变,就蒙在这个题上了。当时忽略了一点:Java中String对象是永不可变。他说,那要是字符串可变,怎么办?我说用StringBuffer。他接着问:那你最后咋还是没做出来,我说当时忽略了这个细节,想想华为这个题目是不是考的很难,就自己用KMP算法去匹配,因为KMP算法以前学过,有些忘了,这个算法有些难,现场推导把时间耗费了,写了有几十行代码,最后快调试出来的时候,时间到了,以至于后面第三道题目都没看,最后机试回来做了一下也不难。他表示赞同(不过我确实说的是事实,当时机试完肠子都悔青了),说我以后遇到简单问题要好好分析,不要把简单问题复杂化。
再次,他在电脑上看到我的毕设题目是做主题爬虫,他很感兴趣的样子,问我这个是干什么的。我说主要是构建垂直搜索引擎,他问我什么是垂直搜索引擎,我说就是基于某个行业的搜索引擎,比如手机垂直搜索引擎,搜一个有关华为手机的,能显示给用户详细的产品信息。他说百度也是这样的啊,我说百度不一样啊,百度的爬虫尽可能多的爬取网页,什么信息都爬,他还是没听懂,我就要了一张纸,画了一下搜索引擎的架构图,说百度搜出来的手机,是因为他根据关键字匹配出了手机,手机垂直搜索引擎的爬虫在爬取的时候只爬取手机相关的。他到这是还是说比较固执地说百度也是这样的啊,不信你拿我的手机搜一下。我有点急了,笑着说,你先听我讲完么。百度这种通用搜索引擎能搜出手机是由于他的检索部分实现的,但是他的爬虫爬到的网页什么都有,他的网页库非常庞大,不光有手机的。而手机垂直搜索引擎的主题爬虫只爬手机相关的,网页库只要手机,你搜电脑搜索不到的。并且百度搜索引擎搜出来的只是一些超链接,你想知道详细信息还得自己点进去去看,而手机垂直搜索引擎已经将收据进行了结构化存取,能直接将搜索到的手机信息结构化展示给用户,什么型号啊,价格啊,参数啊一目了然。他很高兴的样子,问我这有什么前景没?我说垂直搜索引擎精度高,并且也很全,能直接在某个行业搜出来结构化的数据,而不像百度那样只是给个结果,用户还得再找。接着问主题爬虫的原理,我画图讲解了一下,他说,在选取种子的时候,为什么不用百度先搜出来,取前N条URL作为种子再去爬取。我一听,说他的想法很好啊,奉承了他一下,他嘿嘿一笑,说他也是站在巨人的肩膀上。
最后,他看我刚才和他激烈讨论,说感觉我思维挺敏捷的。问我如果在以后工作中我的想法别人没听懂,他们还是坚持己见,我会怎么办?我说我会耐心的给他们讲,直到他听懂为止。哈哈他问我想选云计算,大数据啊什么岗位,然后又说:你做的东西也是数据挖掘方面的,比较适合我们部门,接着给我一张纸条,写了一下2012实验室,大数据部门,让我签协议的时候写上这个。
三、面试总结
嘿嘿,面试到此彻底结束,总体来说,感觉发挥的还不错,虽然有个别简单问题没答上来,但是收获也很多,毕竟这是人生第一次正式的求职面试。加油。