logo资料库

JAVA面试重点话术(张大大吐血整理).doc

第1页 / 共27页
第2页 / 共27页
第3页 / 共27页
第4页 / 共27页
第5页 / 共27页
第6页 / 共27页
第7页 / 共27页
第8页 / 共27页
资料共27页,剩余部分请下载后查看
1 springmvc工作原理:
2堆和栈
栈(数据结构):一种先进后出的数据结构。
3Java集合
Vector是一种老的动态数组,是线程同步的,效率很低,一般不赞成使用
ArrayList  实现一个动态数组,它的规模可变并且能像链表一样被访问。它提供的功能类似Vect
4锁机制:
4.1sql锁:
4.2方法锁:
5Reids
6Solr
7数据库比较
8dubbo
9Zookerpper
10Freemarker
11App接口开发
12第三方支付
13第三方登录
14单点登录
15订单管理
16购物车
17代码中事务是如何控制的?
脏读:
不可重复读:
幻觉读:
18mybatis缓存?
19Restful
20索引
21存储过程
22数据库优化应该从哪些方法考虑?
23有没有做过项目的重构,代码的优化?
24根据项目选择合适的web服务?
25工作中遇到的问题:
26多线程高并发问题:
27接口
28webservice
29httpclient
30权限
31Shiro
32项目文档
33B2B直接掉银行接口支付
34Mysql数据库引擎
35keepalive+nginx实现双机热备
36Redis 分片
37Java操作文件
38spring_boot和spring_cloud
39Nginx
40微信公众号
41MQ消息队列
42Angular.js
43工作流
44常用Linux命令
45如何给别人介绍自己会的知识点
1 springmvc 工作原理: tomcat 启动时,也是先加载 web.xml,找到 spring mvc 的前端总控制器 DispatcherServlet,并 且通过 DispatcherServlet 来加载相关的配置文件信息。 当浏览器发出一个请求之后,首先找到 DispatcherServlet,通过这个控制器和代码中的 requestMapping 注解找到对应的 controller 中的方法,参数直接通过方法参数接收就可以, 然后调用 service、dao 操作数据库,返回数据。如果页面跳转,controller 的方法可以返回 ModelAndView 和 string 类型,再通过 spring-mvc 配置文件中的视图解析器找到对应的页面。 数据可以用 request 或 ModelAndView 返回到页面。如果是 ajax 请求,可以直接返回 List 或 对象,加上 responseBody 注解,进行返回。 2 堆和栈  栈的空间比较小,存放函数的参数值,局部变量的值等。  堆的空间比较大,用于存放 new 的对象。  与 C++不同,Java 自动管理栈和堆,程序员不能直接地设置栈或堆。  堆(数据结构):堆可以被看成是一棵树,如:二叉树。  栈(数据结构):一种先进后出的数据结构。 3 Java 集合 Java 里边主要有两种集合,collection 接口和 map 接口,其中 collection 下又包含 list 和 set 两个子接口; List 子接口:有序,可以有重复元素。和数组类似,List 可以动态增长,查找 元素效率高,相对的插入删除元素效率低,因为会引起其他元素位置改变。 Set 子接口:无序,不允许重复。检索元素效率低下,删除和插入效率高,插入 和删除不会引起元素位置改变。set 集合中的元素不按特定方式排序,只是简单 的把对象加入集合中,就像往口袋里放东西。 List 接口下有三个实现类 ArrayList 、LinkedList 和 Vector Vector 是一种老的动态数组,是线程同步的,效率很低,一般不赞成使用 ArrayList 实现一个动态数组,它的规模可变并且能像链表一样被访问。它提供的功能 类似 Vector 类但不同步,它是以 Array 方式实现的 List,允许快速随机存取。特点是读 快改慢; LinkedList 实现一个链表,提供最佳顺序存取,适合插入和移除元素。由这个类定义的链 表也可以像栈或队列一样被使用。提供最佳顺序存取,适合插入和移除元素。特点是改快 读慢
Set 接口有 HashSet 和 TreeSet 两个实现类 HashSet 能够快速定位一个元素, 要注意的是:存入 HashSet 中的对象必须实现 HashCode()方法; TreeSet 将放入其中的元素按序存放。它实现的是 SortedSet 接口,也就是加入了对象 比较的方法。通过对集中的对象迭代,我们可以得到一个升序的对象集合。 Map 接口的实现类主要有 HashMap 、HashTable 和 TreeMap; 当 元 素 的 顺 序 很 重 要 时 选 用 TreeMap , 当 元 素 不 必 以 特 定 的 顺 序 进 行 存 储 时 , 使用 HashMap。HashMap 不是同步的,Hashtable 是同步的,但 Hashtable 不推荐使用,因 为 HashMap 提供了所有类似的功能,并且速度更快。当需要在多线程环境下使用时, HashMap 也可以转换为同步的。HashMap 没法保证映射的顺序一直不变,但是作为 HashMap 的子类 LinkedHashMap 可以。 HashMap 可以通过 Map m = Collections.synchronizedMap(hashMap)来达到同步的效 果。 4 锁机制: 4.1 sql 锁: id,nam from biao for update 悲观锁:就是考虑问题很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据 的时候都会上锁; 实现:sql 语句后边加上 for update 例子:Select 乐观锁:就是考虑问题很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁 实现:在表里边加一个 vesion 例子: Select max(nub) ,version from biao Update biao set nub=nub+1,version=vsersion+1 where id=id and version =version 4.2 方法锁: 方法锁主要包括:synchronized 锁和 lock 锁 区别: 1)Lock 是一个接口,而 synchronized 是 Java 中的关键字; 2)synchronized 当一个线程获取了对应的锁,并执行该代码块时,其他线程便只能一直等 待,等待获取锁的线程释放锁,不能够响应中断,(释放:1 执行完线程自动释放 2 发生异常 jvm 让线程释放)((比如调用 sleep 方法)),这样的好处是不会导致死锁现象发生。 Lock 锁,可以不让等待的线程一直无期限地等待下去,比如只等待一定的时间或者响应中断。
但 Lock 在发生异常时,如果没有主动通过 unLock()去释放锁,则很可能造成死锁现象,因此 使用 Lock 时必须在 try{}catch{}块中进行,需要在 finally 块中释放锁; 3)通过 Lock 可以知道有没有成功获取锁,而 synchronized 却无法办到。 在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时 (即有大量线程同时竞争),此时 Lock 的性能要远远优于 synchronized。所以说,在具体 使用时要根据适当情况选择。 在并发量比较小的情况下,使用 synchronized 是个不错的选择,但是在并发量比较高 的情况下,其性能下降很严重,此时 ReentrantLock(可重入锁,唯一实现了 Lock 接口 的类)是个不错的方案。 5 Reids Redis 是一个继 memcached 后的又一个第三方缓存数据库,他比 memcached 强大很多, 支持更多的数据类型(String、list、set、sort set、hash),支持持久化,支持集群; Redis 虽然支持持久化,但是他并不适合持久化的保存数据。因为他不是很稳定。但是由于他 是保存在内存中,读取速度非常快,所以在项目中一般都用它作为数据库和应用程序直接的中间 层来使用,已减轻数据库压力,提高运行效率。 我们项目中很多地方用到了 redis;比如商品的三级分类、省市县、关于我们、联系我们、 友情链接,常见问题等经常查询但是不经常改变的数据.redis 还可以在 tomcat 集群里边实现 session 的共享。由于他的单线程的,所以在电商平台里边也经常用他做“防止超卖”, 生成 规则的商品编号等。还有就是购物车也用到了 redis 代码中,我们一般都通过 spring 整合 redis 官方提供的 jedis 工具包来操作 redis。 可以是单机版,也可以是集群。Redis 本身就支持集群操作 redis_cluster,另外 redis 还 支持主从复杂,还有他独特的哨兵模式,在主服务器宕机时,从服务器可以自动转换为主服务器。 另外,他也有他的分片机制,就像 mysql 的水平分表设计,数据量大时,可以把数据存储到不 同的库中,来减轻 redis 负担。 Redis 的持久化方式主要有 2 种,RDB 和 AOF,RDB 是一种快照方式,默认每隔 5 分钟创 建一个快照副本,这种方式占用空间大,而且会丢失间隔时间 5 分钟之内的数据,但是他适合 做备份,恢复时,可以根据需要恢复任意间隔时间点的数据。AOF 是一种日志的持久化记录方 式,每秒钟,都把 redis 中新增的数据记录到日志文件中,这种方式只有一个文件,占用空间 少,最多丢失 1 秒内的数据。相对比较好,但是如果想要恢复 5 分钟或 10 分钟前某个时间点的 数据,就不行了。所以实际项目中,我们一般会两种方式同时使用。如果搭建集群的话,还可以 通过集群互相备份数据,只要集群不同时挂掉,单个 redis 就可以从集群中的其他服务器获取 到最新数据。 还有就是,由于 redis 不是很稳定,有时候会发生“穿透”和“雪崩”; redis,都是按照 key 去缓存查询,如果不存在对应的 value,就应该去数据库 查找。如果 key 对应的 value 是一定不存在的,并且对该 key 并发请求量很大, 就会对后端系统造成很大的压力。这就叫做缓存穿透。当缓存服务器重启或者大
量缓存集中在某一个时间段失效,这样在失效的时候,也会给后端系统(比如 DB) 带来很大压力,这就叫“缓存雪崩”。解决办法是,对查询结果为空的情况也进 行缓存,并且给缓存设置不同的有效期。当然 redis 容灾的最有效的方法还是搭 建集群。 6 Solr Solr 是一个基于 Lucene 开发的全文搜索引擎,项目中一般用它做首页的全文搜索或 者做文件管理系统中的文件检索,因为他提供了分词的支持,同时采用文件存储数据,所以 无论是查询速度还是匹配精确度方面,都比数据库的 like 查询方便了很多。比如:电商网站 上,用户想买手机,输入“苹果手机”,但是系统中录入的是 ipone 手机,那么用 like 查询就 很难匹配到,但 lucene 就可以解决这个问题。 使用时,Lucene 官方紧紧提供了核心实现的 jar 包,我们只能通过 api 文档,自己实现 创建索引和查询的逻辑,并进行优化处理,开发比较繁琐,但比较基础,更灵活,做文档的 检索时可能相对更好点。而 solr 是 Apache 开发的一个开源的 web 工程,他帮我们实现了创 建索引、查询等操作,经内部进行了一定的优化,然后以 restful 风格对外提供了接口。并且 提供了 solrj 的 sdk 工具包,方便 Java 开发者直接使用。一般做电商等网站的全文搜索,我 们使用时,只需要官方下载到 solr 工程的 war 包,根据我们的实际情况,修改 solrhome 、 solrconfig.xml 和 schema.xm 文件,简单配置一下使用的数据库和创建索引的 sql 和字段,然 后把 war 包进行部署就可以了。可以通过他提供的页面进行创建和查询索引的操作。也可以 在项目中集成 solrj 的 jar 包,直接调用他的方法,进行创建索引和查询的操作。 Solr 支持高亮显示搜索关键字,支持匹配权重配比(无特殊排序要求时,默认根据查询相关 度来进行排序,可以在配置文件中配置,通过权重配置相关度) 、支持分页,支持自动分词 等。我们一般都采用 IK 分词器,代替他默认的标准分词器。因为 IK 对中文的支持比较好。 如果想要支持拼音,还可以使用它的拼音分词器。Solr 也支持集群部署,官方提供了 SolrCloud 的部署方案,一般通过 solrcloud+zookeeper 实现,zookeeper 在 solr 集群中主要有两大作用: 1 负载均衡 2 集中式配置管理。需要注意的是:zookeeper 一般采用选举机制,所以一般都 是 2n+1(奇数)台。 另外由于 solr 查询时,不是直接查询数据库,而是开始时,先把数据库中的数据同步到索引 文件中,查询时,直接查询索引文件。索引数据库数据修改时,需要同时同步到 solr 的索引 文件中,也就是创建索引。创建索引分为全量创建和增量创建。可以通过配置文件实现自动 增量更新,自动增量更新可定时将数据库中的数据导入到 solr 索引库中,并可定时重建索引 库 , 合 并 小 索 引 文 件 为 大 的 索 引 文 件 。 除 了 solr 以 外 , 最 近 又 出 了 一 个 搜 索 引 擎 叫 ElasticSearch,我简单了解了一下,他和 solr 一样,也是一个基于 Lucene 的,rest 风格的, 分布式搜索引擎。Solr 特点是:查询快,但更新索引时慢(即插入删除慢),对用于电商等 提前录入好数据,之后查询特别多的应用;而 ElasticSearch 简称 ES 建立索引快、查询相对 慢点,但综合上表现为实时性查询快,用于新浪了,facebook 了等搜索。 1、zookerpper 的作用; 2、solr、Lucene、es 的区别; 3、solr 集群搭建主要步骤,和集群方案;
4、solr 高亮和分页 5、solr 权重配置; 6、索引创建;全局索引和增量索引; 7、solr 部署主要步骤; 8、solrhome 9、solrconfig.xml,主要定义 solr 的处理程序(handler)和一些扩展程序; solrconfig.xml 文件不仅指定了 Solr 如何处理索引、突出显示、分类、搜索以及其他请求, 还指定了用于指定缓存的处理方法的属性,以及用于指定 Lucene 管理索引的方法的属性。 10、schema.xml,主要定义索引的字段和字段类型。 fieldtype、Fields、copyField、dynamicField 7 数据库比较 1、 首先主要是关系型数据库、nosql 数据库和缓存数据库的区别;我觉的: 关系型数据库(mysql、Oracle)就想当于一个储物柜,里边分了各种小格子,把各种数据 有序的保存在里边,查询时非常方便;有比较完善的 sql 语句;  mysql 免费开源,自动提交事务,是基于表级别的一个事务,而 Oracle 不自动提交,是 基于行级别的事务;mysql 安装包小,使用简单,Oracle 安装包较大,还会收费,更适 合于大数据的处理、并发量高;  mysql 用 limit 进行分页,第一个参数表示启始数,第二个参数表示要查询的条数。  oracle 用伪列 rownum 来进行分页,因为伪列只能用小于,不能用大于,所以需要一个 两层的嵌套查询。  mysql 主键可以自增。Oracle 必须用序列(sequence); 字段类型有些区别;  mysql 一般都是先有用户,然后创建库、创建表。而 Oracle 一般是,先创建数据库,然 后创建临时表空间、物理表空间,再创建用户,创建表。 nosql 数据库(mongdb)就相当于一个仓库,比如把衣服放在一堆,书本放在一堆,这样他 的存储效率肯定很高,但是查找时,不方便精确查找。所以 nosql 更适合于数据量比较大, 但是数据之间关系不是特别强,或者不是特别重要的数据;比如:电商里边的评论数据; 他的 collection 相当于数据库,document 相当于表,document 中数据主要以 json 格式存储; 缓存数据库(redis、memcached):缓存数据库由于是保存在内存中的,所以他的存储效率 非常高;但是他不适合持久化存储数据,尽管 redis 支持持久化,但是他也仅仅是在一定程 度上保证了数据的安全性,还是有很多情况会造成数据丢失的,比如 redis 穿透、雪崩等。 所以他仅仅适合做为数据库和应用程序直接的中间层使用,不能作为真正的存储数据库使 用。即使使用,也只能是一些不是特别重要的数据,比如购物车,在 B2C 的项目中,用户 购物车一般都是临时存储,如果放入购物车长时间不提交,那么用户再购买的可能性很小了, 所以即使丢了,也不会造成太多的损失。以这个,来换取项目的运行效率非常划算; 8 dubbo dubbo 是一个分布式架构的服务框架,一般结合 maven 的模块试开发使用。传统
的单架构项目,不方便维护和升级;通过 maven 的模块式开发,就可以把一个单 架构的工程,拆封成一个一个的小模块,包括(jar 和 war);jar 包可以被 war 包直接应用。war 包可以分布式部署,但是这样不同的 war 之间的交互就成为了 问题。我们之前的做法是,两个 war 之间进行交互时,一般采用 webservice 或 httpclient。但是在这种分布式架构中,多个 war 之间的交互会特别频繁,如果 用 webservice 或 httpclient 架构师很多时候自己都搞不清楚他们之间的依赖关 系了。而 dubbo 解决了这个问题,有了 dubbo 架构以后,多个 war 之间不在直接 进行交互,而是统一和 dubbo 的注册中心 zookeeper 进行交互。无论是发布服务 还是调用服务,都通过 dubbo 实现,并且提供了 web 页面,来监控和管理各个接 口直接的调用。 使用时首先搭建 dubbo 的注册中心 zookeeper,然后下载 dubbo 的服务治 理工程 dubbo_admin.war,解压修改他的配置文件 dubbo.properties,设置用户 名、密码和注册中心 zookeeper 的 ip、端口。部署到 Tomcat 的 webapp 中,启 动 Tomcat,浏览器用 ip+端口访问,就可以看到 dubbo_admin 的 web 页面了。接 着在我们要发布或者调用服务的项目中,导入 dubbo 提供的相关 jar 包,加载配 置文件,把要发布的服务注册到 zookeeper 里边。或者从 zookeeper 里边调用服 务就可以了。dubbo_admin 的 web 页面中,可以监控和管理所有的服务提供者和 调用者。。 在 dubbo 架构中,service 接口和实体对象时各个工程共享的,service 实 现类是发布服务的工程独有的。只需要发布服务的工程把他的接口注册到 zookeeper 中,其他工程就可以从 zookeeper 中进行调用了。 用 dubbo 的好处是:把项目拆分成各个独立的小工程,通过接口调用方式,互相交互数据, 可以单独进行部署和升级,这样就减少了他们直接的耦合性和代码的复用性。还可以针对不 同模块采用不同的部署策略,比如订单模块并发比较高,所以可以把订单模块这个 war 包, 单独部署多套,都注册到同一个 zookeeper 中。当客户端调用时,zookeeper 会帮忙进行负 载处理。 9 Zookerpper zookerper 主要功能是为分布式系统提供一致性协调(Coordination)服务,主要有 两大功能:统一配置管理和集群负载均衡, 统一配置管理:分布式系统都有好多机器,这些机器上边的配置是一致的,正常情况 下需要修改好一个以后,然后 scp 到其他服务器,每次修改,就要把所有的配置都 修改一遍,Zookeeper 提供了这样的一种服务:一种集中管理配置的方法,我们在 这个集中的地方修改了配置,所有对这个配置感兴趣的都可以获得变更。这样就省 去手动拷贝配置了,还保证了可靠和一致性。 集群负载均衡:在分布式的集群中,经常会由于各种原因,比如硬件故障,软件故障, 网络问题,有些节点会进进出出。有新的节点加入进来,也有老的节点退出集群。
这个时候,集群中有些机器(比如 Master 节点)需要感知到这种变化,然后根据 这种变化做出对应的决策。Zookeeper 会对通过选举机制,选举一个主节点作为管 理者。选举一般都是奇数台,否则会选举失败。并且集群中,有半数以上宕机,则 会认为整个集群挂掉。 我们项目中用到 zookerpper 的地方主要有:solr 集群、redis 集群和 dubbo 注册 中心。 10 Freemarker freemarker 是一个模板化引擎语言,传统项目中,后台页面基本上都是 list 列表,页面都是 类似的,只是展示的数据不一样。这样我们就可以把他的样式做成一个 freemarker 模板,然 后传入数据就可以展示不同的页面。他的模板一般是以.ftl 结尾的。如果使用这个呢,可以 使我们开发人员不需要太关注前台。但是对于很多门户或商城类项目,每个页面都是不一样, 所以用他也不是很方便。另外,由于可以把 freemarker 模板直接转换成 html、jsp、java、xml、 word 等各种文档。所以我们经常使用他做代码生成、word 生成或者首页静态化等。我这里 就用到了首页静态化的功能。由于任何用户访问时,首先会访问到我们的首页,所以很多东 西都希望能在首页展示,但是放的东西多了,就会加载很慢。给用户的体验度很不好。所以 我们在项目启动时,直接把首页需要的数据查询出来,通过 freemarker 模板生成静态的 html 页面,之后用户访问时,都去访问这个静态页面,这样就不需要频繁访问数据库,减轻了数 据库压力,提高了用户体验度。但是缺点是,数据库数据数据变换了以后,数据无法实时更 新。我们一般通过定时器的方式,每天凌晨重新生成。 还有就是热销商品的商品详情页面也做了静态化处理,首页我们是通过定时器每天凌晨一 点,去重新生成;商品详情我们是在商品信息修改以后,给定时器表(id,业务 id、type,remark) 中推送一条信息,到第二天凌晨一点时,定时任务扫描表,发现有需要重新生成的页面,就 调用 freemarker 模板,重新生成 html 页面,以商品 id 作为 html 页面名称,然后删除任务表 中的数据。为了预防大量静态页面给服务器造成压力,我们把 html 页面直接生成到 Nginx 的静态页面服务器上。访问时,不用经过 Tomcat,直接通过 Nginx 访问。 和他类似的技术,我还知道一种 volicity,但是这个技术现在基本上用的很少了,主要是他 对 jsp 的兼容不是很好。 freemarker 主要语法用${}输出变量,$#等要用原样输出符${r"#"},空值会抛异常,<#list 做 循环,循环下标用变量_index ${book.name?if_exists } //用于判断如果存在,就输出这个值 ${book.name?default(‘xxx’)}//默认值 xxx ${book.name!"xxx"}//默认值 xxx ${book.date?string('yyyy-MM-dd')} //日期格式 ${book?string.number} 20 //三种不同的数字格式 ${book?string.currency}--<#-- $20.00 -->
${book?string.percent}—<#-- 20% --> 用 lt、lte、gt 和 gte 来替代<、<=、>和>= 如果存在特殊字符,可以使用${r"..."}进行过滤 11App 接口开发 1、 由于移动端 app 一般时不能直接访问数据库的,所以需要我们 Java 后台开发接口,供移 动端去调用; 2、 App 接口的开发一般都是 restful 分格的接口。就是不需要跳转页面,都是直接返回需要 的数据。所有的方法上都需要@ResponseBody 注解,把返回结果转换成 json。所以我们 一般用@RestController 代替@controller; 3、 因为 app 接口如果获取不到想要数据,就很可能发生闪退,所以我们需要在 controller 中的所有方法中,用 try catch 捕获异常,把异常也返回。 4、 为了让用户识别异常,我们一般需要定义一组错误编码。 5、 由于接口比较多,为了方便客户端处理接口返回数据,我们定义了一个统一的返回对象 类。里边主要包含三个参数:Boolean success,String code,Object data; 6、 安全方面考虑,接口最后都要把 http 协议转换成 https(http+CA 证书)协议。 7、 在接口的拦截器里边,采用对称加密的方式,进行签名认证。 对称加密就是服务端给 调用端一个 appid 和一个 appsecret; 8、 接口文档:接口说明、接口的 url,传入参数、响应参数。 9、 接口自己测试:一般在浏览器上安装一个 restclient 的插件,用这个插件就可以测试。 10、 接口的调试:方法一:手机连接公司的内外;方法二:通过 Nginx 把自己的 ip 代 理到外网。 12 第三方支付 B2C 电商的支付,一般由于支付金额比较小,支付比较频繁,所以一般采用第三方支付, 常用的第三方支付有:支付宝、微信、聚合支付、付钱啦等。他们的原理都差不多。都 是在点击支付时,直接调用第三方支付接口,传入 appid、appsecret、订单编号、订单金 额、回调 url,直接跳转到第三方支付页面,接下来的支付过程,我们都不需要管,支付 成功以后,第三方支付平台会直接回调我们的 url。给我们返回:状态码、订单编号、支 付流水号三个参数。我们首先根据订单编号,找到我们的订单,把支付流水号和状态码 更新到我们的订单里边。回调 url,一般有两种,一种用同步 get 方法回调,一种用异步 的类似 ajax 方法回调,同步方法回调,一般是成功以后才会回调,并且只回调一次,回 调成功以后我们可以直接跳转到我们的支付成功页面、异步方法回调,一般要求我们返 回一个 success 字符串,第三方平台如果没有接受到 success,就会认为没有调用成功,他 会重复多次调用。比如支付宝会在 25 小时之内,调用 8 次;一般情况下第三方支付都采 用第二种方式,因为比较安全,但支付宝是同时采用了两种。 我之前接触过一个 B2B 的电商,他们由于交易金额比较大,第三方支付无法实现, 所以是直接和银行对接。大体上是,首先平台和银行签订合同,银行为平台开设一个总
分享到:
收藏