推荐需要看的几本书:
《Spring源码深度解析》《大型网站技术架构 核心原理与案例分析》《大型网站系统与Java中间件实践》《Effective Java中文版》《HotSpot实战》
《从Paxos到ZooKeeper 分布式一致性原理与实践》《深入分析Java Web技术内幕》《java多线程编程核心技术》《实战Java高并发程序设计》
要求:
其次掌握的技能树主要有三个方面:
第一个是基础,比如对集合类,并发包,IO/NIO,JVM,内存模型,泛型,异常,反射,等有深入了解,最好是看过源码了解底层的设计。比如一般面试都会问ConcurrentHashMap,CopyOnWrite,线程池,CAS,AQS,虚拟机优化等知识点,因为这些对互联网的企业是绝对重要的。而且一般人这关都过不了,还发闹骚说这些没什么用,为什么要面试。举一例子,在使用线程池时,因为使用了无界队列,在远程服务异常情况下导致内层飙升,怎么去解决?你要是连线程池都不清楚,你怎么去玩?再举一例,由于对ThreadLocal理解出错,使用它做线程安全的控制,导致没能实现真的线程安全,你怪我哦?所以作为一个拿两万的JAVA程序员这点基础是必须的。
第二你需要有全面的互联网技术相关知识。从底层说起,你起码得深入了解mysql,redis,mongodb,nginx,tomcat,rpc,jms等方面的知识。你要问需要了解到什么程度,我可以给你说个大慨。首先对于MySQL,你要知道常见的参数设置,存储引擎怎么去选择,还需要了解常见的索引引擎,知道怎么去选择。知道怎么去设计表,怎么优化sql,怎么根据执行计划去调优。高级的你需要去做分库分表的设计和优化,一般互联网企业的数据库都是读写分离,还会垂直与水平拆分,所以这个也有经验的成分在里面。然后redis,mongodb都是需要了解原理,需要会调整参数的,而nginx和tomcat几乎都是JAVA互联网方面必配,其实很阿里的技术栈选择有点关系。至于rpc相关的就多的去,必须各种网络协议,序列化技术,SOA等等,你要有一个深入的理解。现在应用比较广的rpc框架,在国内就是dubbo了,可以自行搜索。至于jms相关的起码得了解原理吧,一般情况下不是专门开发中间件系统和支撑系统的不需要了解太多细节,国内企业常用的主要是activeMQ和kafka。你能对我说的都研究的比较深入,阿里p6我觉得是没问题的,当然这个还需要看你的架构能力方面的面试表现了。
第三就是编程能力,编程思想,算法能力,架构能力的考量。首先2W程序员对算法的要求我觉得还是比较低,再高级也最多红黑树吧,但是排序和查询的基本算法得会。编程思想是必须的,问你个AOP和IOC你起码的清清楚楚,设计模式不说每种都用过,但是也能深入理解个十四五种。编程能力这个我觉得不好去评价,但是拿一个2000W用户根据姓名年龄排序这种题目也能信手拈来。最后就是架构能力,这种不是说要你设计个多牛逼多高并发的系统,起码让你做一个秒杀系统,防重请求的设计能快速搞定而没有坑吧。
#深入理解Java虚拟机
#Java并发编程实战
#MongoDB权威指南
#Netty权威指南
Netty Mina框架源码
2016新兴互联网公司前300:http://www.askci.com/news/hlw/20160425/941447185.shtml
面试:
1.数据传入的安全性解决方案?认证 SSL HTTPS 原理(eg:游戏中数据传输给服务器,如何保证数据安全和完整,防止外挂?)
2.如何使用多线程处理同一个大的任务?
3.蹲坑算法(数据量大的时候,根据内存空间的有序性,为每个数找各自对应的内存空间地址)
4.如何防止内存被击穿,最大并发限制,降级策略?(eg:游戏服务器,并发最多5000,超过就回击穿服务器内存,如果玩家>5000,如何处理?)
百万级访问量网站架构:http://www.biaodianfu.com/thinking-before-building-site.html
http://www.wtoutiao.com/p/12aqbAi.html
初期架构一般比较简单,web负载均衡+数据库主从+缓存+分布式存储+队列。
大方向上也确实就这几样东西,细节上也无数文章都重复过了,按照将来会有N多WEB,N多主从关系,N多缓存,N多xxx设计就行,基本方案都是现成的,
只是您比其他人厉害之处就在于设计上考虑到缓存失效时的雪崩效应、主从同步的数据一致性和时间差、队列的稳定性和失败后的重试策略、文件存储的效率和备份方式等等意外情况。
缓存总有一天会失效,数据库复制总有一天会断掉,队列总有一天会写不进去,电源总有一天会烧坏。根据墨菲定律,如果不考虑这些,网站早晚会成为茶几
多线程推荐:
http://www.cnblogs.com/dolphin0520/category/602384.html
http://blog.csdn.net/qilixiang012/article/category/2857487
http://blog.csdn.net/column/details/java-dxc.html
1.Eclipse安装Activiti插件 http://activiti.org/designer/update/
2.Spring MVC 输出页面乱码 在mvc.xml中配置 StringHttpMessageConverter 编码格式
text/plain;charset=UTF-8
text/html;charset=UTF-8
3.Spring MVC注解式统一异常处理:
--- 可根据异常,返回数据或指定页面
BaseController中添加方法处理异常
@ExceptionHandler(RuntimeException.class)
public @ResponseBody ResponseVo runtimeExceptionHandler(RuntimeException ex) {
ResponseVo responseVo = new ResponseVo();
responseVo.setSuccess(false);
responseVo.setMsg(ex.getMessage());
responseVo.setData(ex);
return responseVo;
}
4.几个最常用的Eclipse快捷键
1. ctrl+shift+r:打开资源,在workspace中快速按文件名查找
2. ctrl+o:快速outline,查看代码结构,显示类中方法和属性,能快速定位类的方法和属性
3. ctrl+e:快速转换编辑器
4. ctrl+2,L:为本地变量赋值
5. alt+shift+r:重命名
6. Alt+左右方向键
我们经常会遇到看代码时Ctrl+左键,层层跟踪,然后迷失在代码中的情况,
这时只需要按“Alt+左方向键”就可以退回到上次阅读的位置,
同理,按“Alt+右方向键”会前进到刚才退回的阅读位置
7.ctrl+shift+x和ctrl+shift+y:英文字母大小写的转换
8.ctrl+shift+f:格式化代码
9.ctrl+m:当前编辑页面窗口最大/小化
10.ctrl+shift+o:自动引入包和删除无用包
11.Ctrl+T 快速显示当前类的继承结构
12.Ctrl+W 关闭当前窗口
13.Alt+Shift+R 重命名
14.Alt+Shift+M 抽取方法
15.【Ct rl+K】、【Ct rl++Shift +K】 快速向下和向上查找选定的内容,从此不再需要用鼠标单击查找对话框
16.Ctrl+Shift+G 查找类、方法和属性的引用
17.Alt+Shift+w 查找当前文件所在项目中的路径
18.Ctrl+Shift+w 关闭所有文件
最实用的:
【Alt + ← 】 查看代码时,返回上次查看位置 --- 后退上次代码记录
【Alt + → 】 查看代码时,跟踪,回到下次浏览位置
点中类名+F4 查看类的继承关系
5.常见的内存移除的3种情况
1.JVM Heap(堆)溢出 java.lang.OutOfMemoryError:Java heap space
JVM在启动的时候会自动设置JVM Heap的值, 可以利用JVM提供的-Xmn -Xms -Xmx等选项可进行设置。
Heap的大小是Young Generation 和Tenured Generaion 之和。在JVM中如果98%的时间是用于GC,且可用的Heap size 不足2%的时候将抛出此异常信息
解决方法:
设置JVM Heap(堆)大小
即:-Xmn -Xms -Xmx等选项,以及 年轻代与年老代的比例 ratio等参数
2.PermGen space溢出 java.lang.OutOfMemoryError:PermGen space
永久带溢出 --- 一般发生在程序启动阶段
永久带被JVM存放Class和Meta信息,如果载入很多Class,可能出现PermGen space溢出
解决方法:
通过-XX:PermSize和-XX:MaxPermSize设置永久代大小即可
3.栈溢出 java.lang.StackOverflowError : Thread Stack space
可能原因:递归层次太多,导致栈溢出
解决方法:
1.修改程序
2.通过 -Xss 设置每个线程的Stack大小
Server容器启动时,需要设置的几个JVM参数:
-Xms:java Heap 堆初始大小, 默认是物理内存的1/64。
-Xmx:java Heap 堆最大值,不可超过物理内存。
-Xmn:young generation的heap堆大小,一般设置为Xmx的3、4分之一 。增大年轻代后,将会减小年老代大小,可以根据监控合理设置。
-Xss:每个线程的Stack大小,而最佳值应该是128K,默认值好像是512k。
-XX:PermSize:设定内存的永久保存区初始大小,缺省值为64M。
-XX:MaxPermSize:设定内存的永久保存区最大大小,缺省值为64M。
-XX:SurvivorRatio:Eden区与Survivor区的大小比值,设置为8,则两个Survivor区与一个Eden区的比值为2:8,一个Survivor区占整个年轻代的1/10
-XX:+UseParallelGC:F年轻代使用并发收集,而年老代仍旧使用串行收集.
-XX:+UseParNewGC:设置年轻代为并行收集,JDK5.0以上,JVM会根据系统配置自行设置,所无需再设置此值。
-XX:ParallelGCThreads:并行收集器的线程数,值最好配置与处理器数目相等 同样适用于CMS。
-XX:+UseParallelOldGC:年老代垃圾收集方式为并行收集(Parallel Compacting)。
-XX:MaxGCPauseMillis:每次年轻代垃圾回收的最长时间(最大暂停时间),如果无法满足此时间,JVM会自动调整年轻代大小,以满足此值。
-XX:+ScavengeBeforeFullGC:Full GC前调用YGC,默认是true。
实例如:JAVA_OPTS=”-Xms4g -Xmx4g -Xmn1024m -XX:PermSize=320M -XX:MaxPermSize=320m -XX:SurvivorRatio=6″
6.Service或Dao层获取request和IP方法?
1.获取IP InetAddress.getLocalHost().getHostAddress()
2.获取request对象 http://my.oschina.net/u/2007041/blog/420956
7.JDK6在Linux下的安装
第一:用linux 的命令运行它: sh jdk-6u2-linux-i586-rpm.bin
第二:按多次回车后出现
Do you agree to the above license terms? [yes or no]
输入yes
第三:编辑环境变量
$gedit ~/.bashrc
加入如下五行:
JAVA_HOME=/usr/java/jdk1.6.0_02
JAVA_BIN=/usr/java/jdk1.6.0_02/bin
PATH=$PATH:$JAVA_HOME/bin
CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export JAVA_HOME JAVA_BIN PATH CLASSPATH
第四步是必须的,不然它总是调用FC6自带的jdk1.4
第四:创建链接
#cd /usr/bin
#ln -s -f /usr/local/jdk1.5.0_05/jre/bin/java
#ln -s -f /usr/local/jdk1.5.0_05/bin/javac
或 环境变量配置 vi /etc/profile
#for java
export JAVA_HOME=/home/hetiewei/software/java/jdk1.8.0_40
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
#for go
export GOROOT=/home/hetiewei/go/soft/go
export PATH=$GOROOT/bin:$PATH
export GOPATH=/home/hetiewei/go/soft/go/pkg
#for node
export NODE_HOME=/home/hetiewei/node/software/node-v6.2.0-linux-x64
export PATH=$PATH:$NODE_HOME/bin
export NODE_PATH=$NODE_HOME/lib/node_modules
PATH=/usr/local/ssl/bin:/sbin/:$PATH:/usr/sbin
export PATH
#for hadoop
export HADOOP_HOME=/home/hetiewei/software/bigdata/hadoop/hadoop-2.6.4
export PATH=.:$HADOOP_HOME/bin:$PATH
source /etc/profile
8.Tomcat启动时,在initialing Spring root context 卡死:
解决:
1.查看数据库连接
2.清除Tomcat下的work目录
9.Maven install时出现编码异常解决方法:
mvn clean install -Dmaven.javadoc.skip=true
10.Spring和Mybatis整合时无法读取properties的处理方案:
方法一:
修改
为
原理:使用sqlSessionFactoryBeanName注入,不会立即初始化sqlSessionFactory, 所以不会引发提前初始化问题。
方法二:
直接删掉
注意:在没有配置这一行时,必须配置一个以sqlSessionFactory命名的org.mybatis.spring.SqlSessionFactoryBean。
11.token,Session的区别?
服务器在生成表单的时候同时生成一个CSRF token,插入到表单的一个hidden field里面,并且把这个token记录在服务器端,通常是用户的Session数据里面。
客户端啥都不用干,照常提交表单。当表单被提交的时候,服务端检查一个表单里面的token跟自己之前记录下来的是否匹配,匹配才继续处理。
CSRF劫持的请求也会带上网站的cookie的,所以光验证session并不能避免CSRF
token的关键是在于你在发送请求的时候一定要保证你是读取了这个页面的。。 而不是凭空就发送请求
对于HTTP协议来说,就是url,header,body
对于WEB页面来说,就是url,form/post body,cookie
好了,现在有的就是这么多东西,要怎么用呢?
首先是第一个问题,HTTP请求是无状态的,我怎么知道谁是谁?
解:让用户每次访问的时候告诉你它叫什么,怎么告诉?url,form/post body,cookie
然后是第二个问题,用户访问的时候说他自己是张三,他骗你怎么办?
解:在服务器端保存张三的信息,给他一个id,让他下次用id访问。id保存在url,form/post body,cookie中。这叫做session
现在是第三个问题,用户提交了一笔订单,你怎么保证他是在你的订单页面提交的?(referer可能是一个办法)
解:在你订单页面中放入一个加密的信息,只有真正打开了订单页才能知道,提交的时候将这个信息返回回来。这个东西,可以被叫做token
Token实现防止表单重复提交?
表单重复提交的两种情形:
1.通过浏览器回退功能,回到原来页面重复提交表单,服务器端应避免用户重复注册
2.提交完成后,单击浏览器的“刷新”按钮,浏览器会弹出对话框,询问是否重新提交数据。单击“是”,浏览器会重新提交数据。
如何防止?
每次请求都生产一个token标识
1.表单提交后,先匹配(使用Aop做)token,判断当前用户会话中token令牌值与当前请求参数的token令牌值是否一致
2.每次请求都创建一个新的token令牌,将其保存在当前会话(session)范围内
3.token在服务器端匹配后,就把session中的toke令牌值删除
12.Java线程安全的本质:线程中并没有存放任何对象数据,而是在执行时,去主内存(堆)中去同步数据,所有的对象数据都存在JVM的堆中,因此需要对资源进行共享锁!!!
堆 --- JVM的核心数据存储区 --- 线程共享的主内存
堆中为JVM的所有对象分配了内存空间用以存储和维护变量值等
栈 --- 线程私有的内存区,由值栈(线程栈)组成,存放8中基本数据类型和对象引用
每个线程都会生成一个自有的线程栈,线程栈中用存储了该线程的基本数据常量,变量值,以及对象长变量的引用
每个线程执行时,根据代码顺序,压栈 值栈(栈内存)
对象变量在线程执行时的过程:!!! --- 由JVM内存模型决定
1.线程根据栈中的引用去堆上同步该对象数据下来,然后在线程自己的内存中进行操作
2.操作之后再将线程栈撒花姑娘的运算结果同步到堆(主内存)中
3.多线程时,因为每个线程都操作自己从主内存(JVM堆)中同步过来的数据,如果不加锁,会导致线程安全问题(数据提交到主内存时不一致)
13.堆 --- JVM中所有对象的内存空间 分为: Young Gen, Old Gen
Young Gen 又分为:Eden区和两个大小相同的Survivor区(from 和 to)
Eden和Survivor默认比例 8:1 由 -XX:SurvivorRation设置
堆大小 -Xmx -Xms 设置
Young Gen -Xmn 设置
-XX:NewSize和-XX:MaxNewSize
用于设置年轻代的大小,建议设为整个堆大小的1/3或者1/4,两个值设为一样大。
Minor GC --- 发生在新生代的垃圾回收,Java 对象大多都具备朝生夕灭的特性,所以 Minor GC 非常频繁,一般回收速度也比较快,
年轻代的GC使用复制算法(将内存分为两块,每次只用其中一块,当这块内存用完,就将还活着的对象复制到另外一块上面,复制算法不会产生内存碎片)
Full GC --- 发生在年老代的GC, Full GC比较慢,尽量避免
新创建对象都会被分配到Eden区(一些大对象特殊处理),当Eden区满则进行Minor GC,
这些对象经过第一次Minor GC后,如果仍然存活,将会被移到Survivor区, 对象在Survivor区中每熬过一次Minor GC,年龄增加1岁,
当年龄增加到一定程度后(默认15岁),会被移动到年老代中,
当年老代满时,经常Full GC
线程Stack 每个线程独有的操作数栈局部变量表方法入口 -Xss 设置
方法区 -XX:PermSize和-XX:MaxPermSize设置
JVM中的类加载机制: http://www.cnblogs.com/ITtangtang/p/3978102.html
14.Go,MongoDB,redis,node.js在Linux下的安全和配置
1.go
下载tar.gz后,
解压:tar -zxvf go1.6.2.linux-amd64.tar.gz
环境变量:
vi /etc/profile
在profile中添加一下内容:
GOPATH和GOROOT修改为你的路径即可!!!
export GOROOT=/home/forward/tools/go
export PATH=$GOROOT/bin:$PATH
export GOPATH=/home/forward/tools/gopkg
刷新环境变量:
source /etc/profile
验证:
go version
编译Go程序:
go build xx.go
直接运行Go程序:
go run xx.go
2.mongodb
解压:
tar -zxvf mongodb-linux-i686-3.2.6.tgz
环境变量:
--- (只当前用户有效)
export PATH=
/bin:$PATH
或
--- (全局有效)
vi /etc/profile
在profile中添加一下内容:
export PATH=/bin:$PATH
刷新环境变量:
source /etc/profile
3.node.js
下载解压:
wget --no-check-certificate https://nodejs.org/dist/v6.2.0/node-v6.2.0-linux-x64.tar.gz
环境变量:
NODE_HOME 是node.js安全目录
export NODE_HOME=/home/hetiewei/node/software/node-v6.2.0-linux-x64
export PATH=$PATH:$NODE_HOME/bin
export NODE_PATH=$NODE_HOME/lib/node_modules
刷新环境变量: 让环境变量生效
source /etc/profile
验证:
命令行输入:node -v,查看node.js的版本
4.redis
参考官方源码安装说明
15.通过Spring在工具类中获取HttpServletRequest对象:
/**
* 获取当前Request
* @return
*/
private HttpServletRequest getRequest() {
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
return requestAttributes.getRequest();
}
16.Spring mvc在redirect请求中传递数据 http://shmilyaw-hotmail-com.iteye.com/blog/2246344
3种方式:1.Session 2.url template 3. flash attribute
17.logback与ActiveMQ的slf4j jar包冲突解决??? --- MQ使用指定版本, 不使用用activemq-all
org.springframework
spring-jms
${org.springframework.version}
org.apache.activemq
activemq-core
5.7.0
org.apache.activemq
activemq-pool
5.7.0