java开发工程师面试题总结(适用于1-2年工作经验的人)
作者:不善言谈者
原文链接:https://blog.csdn.net/bushanyantanzhe/article/details/79858961
这些资料有的是自己在网上看到的,有的是自己亲身经历后整理的。
1.JAVA的垮平台原理
JVM也是一个软件,不同的平台有不同的版本。我们编写的Java源码,编译后会生成一种 .class 文件,称为字节码文件。Java虚拟机就是负责将字节码文件翻译成特定平台下的机器码然后运行。也就是说,只要在不同平台上安装对应的JVM,就可以运行字节码文件,运行我们编写的Java程序。
而这个过程中,我们编写的Java程序没有做任何改变,仅仅是通过JVM这一”中间层“,就能在不同平台上运行,真正实现了”一次编译,到处运行“的目的。
JVM是一个”桥梁“,是一个”中间件“,是实现跨平台的关键,Java代码首先被编译成字节码文件,再由JVM将字节码文件翻译成机器语言,从而达到运行Java程序的目的。
注意:编译的结果不是生成机器码,而是生成字节码,字节码不能直接运行,必须通过JVM翻译成机器码才能运行。不同平台下编译生成的字节码是一样的,但是由JVM翻译成的机器码却不一样。
所以,运行Java程序必须有JVM的支持,因为编译的结果不是机器码,必须要经过JVM的再次翻译才能执行。即使你将Java程序打包成可执行文件(例如 .exe),仍然需要JVM的支持。
注意:跨平台的是Java程序,不是JVM。JVM是用C/C++开发的,是编译后的机器码,不能跨平台,不同平台下需要安装不同版本的JVM。
2.JAVA中INT占几个字节
char 占2个字节
boolean 一个字节(1位)
3.JAVA面向对象的特征
封装、抽象、继承和多态。
封装:在面向对象语言中,封装特性是由类来体现的,我们将现实生活中的一类实体定义成类,其中包括属性和行为(在Java中就是方法).例如电脑,
抽象:抽象就是将一类实体的共同特性抽象出来,封装在一个抽象类中,所以抽象在面向对象语言是由抽象类来体现的。比如人.
class Person{}
继承:继承就像是我们现实生活中的父子关系,儿子可以遗传父亲的一些特性,在面向对象语言中,就是一个类可以继承另一个类的一些特性,从而可以代码重用.
eg:class Zhangsan extends Person{};
多态:多态就是通过传递给父类对象引用不同的子类对象从而表现出不同的行为
eg:Person person=new Zhangsan();
4.装箱和拆箱
为什么需要装箱和拆箱:是java早年设计缺陷。基础类型是数据,不是对象,也不是Object的子类。
装箱就是自动将基本数据类型转换为包装器类型;拆箱就是自动将包装器类型转换为基本数据类型。
1. Integer a = Integer.valueOf(123);//装箱
1. int b = a.intValue(); //拆箱
5.==和EQUALS的区别
关于==
1.基本数据类型,也称原始数据类型。byte,short,char,int,long,float,double,boolean 他们之间的比较,应用双等号(==),比较的是他们的值。
2.复合数据类型(类) 当他们用(==)进行比较的时候,比较的是他们在内存中的存放地
equals
Java 语言里的 equals方法其实是交给开发者去覆写的,让开发者自己去定义满足什么条件的两个Object是equal的。
6.String,StringBuilder,StringBuffer的区别
运行速度:StringBuilder >StringBuffer >String
String为字符串常量,而StringBuilder和StringBuffer均为字符串变量,即String对象一旦创建之后该对象是不可更改的,但后两者的对象是变量,是可以更改的。Java中对String对象进行的操作实际上是一个不断创建新的对象并且将旧的对象回收的一个过程,所以执行速度很慢。而StringBuilder和StringBuffer的对象是变量,对变量进行操作就是直接对该对象进行更改,而不进行创建和回收的操作,所以速度要比String快很多。
线程安全:StringBuilder是线程不安全的,而StringBuffer是线程安全的
如果一个StringBuffer对象在字符串缓冲区被多个线程使用时,StringBuffer中很多方法可以带有synchronized关键字,所以可以保证线程是安全的,但StringBuilder的方法则没有该关键字,所以不能保证线程安全,有可能会出现一些错误的操作。所以如果要进行的操作是多线程的,那么就要使用StringBuffer,但是在单线程的情况下,还是建议使用速度比较快的StringBuilder。
使用场景
String:适用于少量的字符串操作的情况
StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况
StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况
7.讲一下JAVA中的集合
java中的集合分为value(Collection),和key-value(Map)两种;
存储value的有list和set两种:
list是有序的,可重复的
set是无序的,不可重复的
存储为key-value是map:HashMap,Hashtable,CurrentHashMap
8.ARRAYLIST, Vector和LINKEDLIST的区别
1.区别
Vector、ArrayList都是以类似数组的形式存储在内存中,LinkedList则以链表的形式进行存储。
Vector线程同步,ArrayList、LinkedList线程不同步。
LinkedList适合指定位置插入、删除操作,不适合查找;ArrayList、Vector适合查找,不适合指定位置的插入、删除操作。
Vector默认扩充为原来的两倍,(每次扩充空间的大小是可以设置的),而ArratList默认扩充为原来的1.5倍(查看之前的文章),因此ArrayList更节省空间。
2.联系
ArrayList,Vector、LinkedList类均在java.util包中都是可改变大小的.
ArrayList和Vector都是基于存储元素的Object[ ] array 来实现的,他们会在内存中开辟一块连续的空间来存储,由于数据存储是连续的,因此,他们支持用索引来访问元素,同时索引数据的速度比较快。但是在插入元素时需要移动容器中的元素,所以对数据的插入操作执行的比较慢。ArrayList和Vector都有一个初始化的容量大小,当里边存储的元素超过这个大小时就需要动态地扩充他们的存储空间。
9.HASHMAP和HASHTABLE的区别
相同:HashMap和Hashtable都可以使用来存储key-value的数据
区别:
基类不同:HashTable基于Dictionary类,而HashMap是基于AbstractMap。Dictionary是什么?它是任何可将键映射到相应值的类的抽象父类,而AbstractMap是基于Map接口的骨干实现,它以最大限度地减少实现此接口所需的工作。
线程安全:HashMap时单线程安全的,Hashtable是多线程安全的。
遍历不同:HashMap仅支持Iterator的遍历方式,Hashtable支持Iterator和Enumeration两种遍历方式。
null不同:HashMap可以允许存在一个为null的key和任意个为null的value,但是HashTable中的key和value都不允许为null。
多线程时,如何保障线程安全的同时也能保证效率?ConcurrentHashMap
通过把整个Map分为N个segment(类似Hashtable),这样既可以保障线程安全,也能使效率提高N倍,默认是16倍.
ConcurrentHashMap当中每个Segment各自持有一把锁。在保证线程安全的同时降低了锁的粒度,让并发操作效率更高。
10.实现一个拷贝文件的工具类要使用字节流还是字符串
使用字节流,因为我们要拷贝的文件,不好确定里面是否全是字符,如果文件中包含图片之类的字节时,就需要使用字节流.所以,我们一般是用字节流拷贝文件.
11.线程的的实现方式?怎么启动线程?怎么区分线程?
1.继承Thread类,不推荐
1.实现Runnable 接口
1.实现java.util.concurrent下的Callable接口
线程启动:调用start()方法;(调用start()方法,是使得线程处于可运行状态,线程并不一定会执行.如果start()方法是在main方法中调用的话,run()会执行.如果是在junit4下的话,线程不一定会执行)
怎么区分线程:给线程设置名字
12.线程并发库和线程池的作用
简单了解过,JDK5中增加了并发库,java.util.concurrent中提供了对线程优化.管理的各项操作,该包提供了线程的运行,线程池的创建,线程生命周期的控制.
线程池:java.util.concurrent.Executors创建四种线程池
newCachedThreadPool 创建非固定数量,可缓存的线程池,若线程池超过处理需要,可灵活回收空线程,若没有线程可回收,则建新线程
newFixedThreadPool固定线程池,底层是无界队列,可控制最大并发数,超出的线程会在队列中等待
newScheduledThreadPool定时执行线程池,支持定时及周期性任务执行
newSingleThreadExecutor单线程化的线程池,只会用唯一的工作线程来执行任务,保证所有任务按照顺序执行
线程池的好处:
限定线程的个数,不会导致由于线程过多导致系统运行缓慢或崩溃
线程池每次都不需要去创建和销毁,节约了资源
线程池不需要每次都去创建,相应时间更快.
13.设计模式和常用的设计模式(选择自己熟悉的说,最好能手写)
设计过程中可以反复使用的、可以解决特定问题的通用模板.
创建型模式(5种):工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式。
结构型模式(7种):适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模式,享元模式。
行为型模式(11种):策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
14.HTTP GET POST请求的区别
1、GET请求,请求的数据会附加在URL之后,以?分割URL和传输数据,多个参数用&连接。URL的编码格式采用的是ASCII编码,而不是uniclde,即是说所有的非ASCII字符都要编码之后再传输。
POST请求:POST请求会把请求的数据放置在HTTP请求包的包体中。
因此,GET请求的数据会暴露在地址栏中,而POST请求则不会。
2、传输数据的大小
在HTTP规范中,没有对URL的长度和传输的数据大小进行限制。但是在实际开发过程中,对于GET,特定的浏览器和服务器对URL的长度有限制。因此,在使用GET请求时,传输数据会受到URL长度的限制。
对于POST,由于不是URL传值,理论上是不会受限制的,但是实际上各个服务器会规定对POST提交数据大小进行限制,Apache、IIS都有各自的配置。
3、安全性
POST的安全性比GET的高。这里的安全是指真正的安全,而不同于上面GET提到的安全方法中的安全,上面提到的安全仅仅是不修改服务器的数据。比如,在进行登录操作,通过GET请求,用户名和密码都会暴露再URL上,因为登录页面有可能被浏览器缓存以及其他人查看浏览器的历史记录的原因,此时的用户名和密码就很容易被他人拿到了。
15.说说你对SERVLET的理解
就是一个运行在WEB服务器上的小的Java程序,用来接收和响应从客户端发送过来的请求,通常使用HTTP协议.
使用:1、编写一个Java类,实现servlet接口。
2、把开发好的Java类部署到web服务器中。
按照一种约定俗成的称呼习惯,通常我们也把实现了servlet接口的java程序,称之为Servlet
Servlet :接口
|
GenericServlet :通用的Servlet
|
HttpServlet :HttpServlet
* 编写一个类继承HttpServlet,重写doGet和doPost方法.
* 配置
16.SERVLET的生命周期
用户第一次访问Servlet的时候,服务器会创建一个Servlet的实例,那么Servlet中init方法就会执行.任何一次请求服务器都会创建一个新的线程访问Servlet中的service的方法.在service方法内部根据请求的方式的不同调用doXXX的方法.(get请求调用doGet,post请求调用doPost).当Servlet中服务器中移除掉,或者关闭服务器,Servlet的实例就会被销毁,那么destroy方法就会执行.
17.SERVLET中FORWARD和REDIRECT的区别
重定向(redirect)其实是两次request,第一次,客户端request,A服务器响应,并response回来,告诉浏览器,你应该去B。这个时候IE可以看到地址变了,而且历史的回退按钮也亮了。重定向可以访问自己web应用以外的资源。在重定向的过程中,传输的信息会被丢失。
请求转发(forward)是服务器内部把对一个request/response的处理权,移交给另外一个.对于客户端而言,它只知道自己最早请求的那个A,而不知道中间的B,甚至C、D。传输的信息不会丢失。
18.JSP和SERVLET的相同点和不同点
联系:
JSP 是 Servlet 技术的扩展,本质上是 Servlet 的简易方式,更强调应用的外表表达。
JSP编译后是”类 servlet”。
不同点:
- Servlet 的应用逻辑是在Java文件中,并且完全从表示层中的HTML里分离开来。Servlet如果要实现html功能,必须使用Writer输出对应的html.
- JSP 的情况是Java和HTML可以组合成一个扩展名为.jsp 的文件。做界面展示比较方便,而嵌入逻辑复杂.
- JSP 侧重于视图,Servlet 主要用于控制逻辑
19.jsp内置对象和四大作用域和页面传值
内置对象名类型
requestHttpServletRequest
responseHttpServletResponse
configServletConfig
applicationServletContext
sessionHttpSession
exceptionThrowable
pageObject(this)
outJspWriter
pageContextPageContext
域范围
page域只能在当前jsp页面使用
request域只能在同一个请求中使用
session域只能在同一个会话(session对象)中使用
context域只能在同一个web应用中使用
20.SESSION和COOKIE的区别和使用场景
Session和cookie都是会话(session)跟踪技术.cookie通过在客户端记录信息确定用户身份,而session是通过在服务器端记录信息确定用户身份.但是session的实现依赖于cookie机制来保存JESESSIONID(session的唯一标识,需要存在客户端)
区别:
>
1. cookie的数据存储在客户端,session的数据存储在服务器上
1. cookie不是很安全,别人可以通过分析存放在本地的cookie并进行cookie欺骗,考虑到安全应该使用session
1. session会在一定时间内保存在服务器上,当访问增多时,会影响服务器的性能.考虑到服务器性能,应当使用cookie.
1. 单个cookie保存数据不能超过4k,很多浏览器显示一个站点最多保存20个cookie
2. 将重要信息保存在session中(登陆),将其他需要保留的信心存放在cookie中(购物车,cookie是可以在客户端禁用的,这时候要使用cookie+数据库的方式实现购物车,当cookie中不能取出数据,就从数据库中取)
21.MVC模式和MVC各部分的实现
MVC的全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,是一种软件设计典范.低耦合(m和v的分离)
struts2的mvc:jsp–>StrutsPrepareAndExecuteFilter(前端控制器,核心控制器)+action–>javabean–>result
22.数据库分类和常用数据库
>
- 关系型:MySQL、 ORACLE、SQL Server、IBM DB2、Sybase
- 非关系型:Redis,Memcached,MongoDB ,Hadoop
23.关系型数据库的三范式
范式就是规范,就是关系型数据库设计表时遵循的三个规范.要满足第二范式,必须先满足第一范式,要满足第三范式,必须先满足第二范式
第一范式(1NF)是指数据库表的每一列都是不可分割的基本数据项,同一列中不能有多个值,即实体中的某个属性不能有多个值或者不能有重复的属性。列数据的不可分割.
第二范式(2NF)要求数据库表中的每个实例或行必须可以被唯一地区分。为实现区分通常需要为表加上一个列,以存储各个实例的唯一标识.(主键)
第三范式(3NF)要求一个数据库表中不包含已在其它表中已包含的非主关键字信息。(外键)
反三范式:有时候为了效率,可以设置重复或者可推导出的字段.比如:订单(总价),订单项(单价)
24.事务的四大特征
事务是并发控制的单位,是用户定义的一个操作序列.这些操作要么都做,要么都不做,是一个不可分割的工作单位.例子:转账
事务的四大特性:ACID
原子性(Atomicity):表示事务内不可分割,要么都成功,要么都失败
一致性(Consistency):要么都成功,要么都失败.失败了,要对前面的操作进行回滚
隔离性(Isolation):一个事务开启了,不能受其它事务的影响
持久性(Durability):持续性,表示事务开始了,就不能终止.事务提交后,将数据序列化到数据库
25.MYSQL数据库最大连接数
数据库默认的最大连接数是100,在实际操作中,我们会去修改这个值:mysql安装文件–>my.ini文件
# The maximum amount of concurrent sessions the MySQL server will
# allow. One of these connections will be reserved for a user with
# SUPER privileges to allow the administrator to login even if the
# connection limit has been reached.
max_connections=100
26.MYSQL和ORACLE的分页语句
为什么要分页?很多数据不能完全展示出来,需要进行分段显示
mysql:是使用关键字limit来进行分页的.LIMIT [offset,] rows:offset指定要返回的第一行的偏移量(也就是从哪个索引开始),rows第二个指定返回行的最大数目。初始行的偏移量是0(不是1)
oracle:一般是使用rownum 加select 嵌套查询
27.触发器的使用场景?
触发器:触发器需要有触发条件,当条件满足后,做什么操作
应用场景:某些社交软件的日志更新,会通知好友; 一些论坛中,当插入新帖时,会更改当前帖子总数以及最后发帖时间.
CREATE [or REPLACE] TRIGGER 触发器名
BEFORE | AFTER
[DELETE ][[or] INSERT] [[or]UPDATE [OF 列名]]
ON 表名
[FOR EACH ROW ][WHEN(条件) ]
declare
……
begin
PLSQL 块
End ;
28.存储过程的优点
>
1. 存储过程只在创建时进行编译,以后每次执行它都不会再重新编译.一般SQL语句每次执行都会编译.所以存储过程会大大提高数据库执行速度
1. 通常复杂的业务逻辑需要多条SQL语句,这些语句要分别从客户机发送到服务器,当客户机和服务器之间的操作很多时,会产生大量的网络传输.如果将这些操作放在一个存储过程中,那么客户机和服务器之间的网络传输会大大减少,降低网络负载.
1. 存储过程是可重复使用的,能减少数据库开发人员的工作量.
1. 存储过程可以屏蔽对底层数据对象的直接访问,使用EXECUTE权限调用存储过程,无需拥有访问底层数据库对象的显示权限,安全性高.
CREATE [ OR REPLACE ] PROCEDURE 存储过程名称
(参数名 类型, 参数名 类型, 参数名 类型)
IS|AS
变量声明部分;
BEGIN
逻辑部分
[EXCEPTION
异常处理部分]
END;
29.JDBC调用存储过程
贾琏欲执事
加载驱
获取连接
设置参数
执行
释放连接
30.简单说一下你对JDBC的理解
Java database connection java数据库连接,数据库关系系统很多,每个数据库关系管理系统支持的命令是不一样的.
Java只定义接口,让数据库厂商自己实现接口,对于我们开发人员而言,只需要导入对应厂商开发的实现即可,然后以接口的方式进行调用(mysql+mysql驱动(实现)+jdbc)
31.写一个JDBC的访问ORACLE的列子
public class OracleUtils {
static {
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//获取连接
public static Connection getConnection() throws SQLException {
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@ip:1521:orcl", "username", "password");
return conn;
}
//关闭资源
public static void close(ResultSet rs, Statement stmt, Connection conn) {
}
}
.....
调用
Connection conn = OracleUtils.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql);
ResultSet rs = stmt.executeQuery();
OracleUtils.close(rs, stmt, conn);
32.JDBC中PREPAREDSTATEMENT比STATEMENT的好处
PreparedStatement可以防止sql注入攻击,它是预编译的,
33.数据库连接池的作用
限定数据库的连接个数,不会由于数据库连接过多导致系统运行缓慢或崩溃
数据库连接不需要每次都去创建或销毁,节约了资源
数据库连接不需要每次都去创建,响应时间更快.
34.简单说一下HTML,CSS,JAVASCRIPT在网页开发中的定位
Html 超文本标记语言,定义网页的结构
Css 层叠样式表,用来美化页面
Javascript 主要用来验证表单,做动态交互(其中ajax)
35.简单介绍了一下AJAX
什么是ajax?异步的javascript和xml
作用是什么?通过ajax与服务器进行数据交换,ajax可以使网页实现局部更新.这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新.
怎么实现?ajax xmlhttpRrqueset对象,使用这个对象可以异步向服务器发送请求,获取响应,完成局部更新,open send responseText/responseXml局部响应.
使用场景:登陆失败时不跳转页面,注册时提示用户名是否存在,二级联动等等.
36.JS和JQUERY的关系
JQuery是一个js框架,封装了js的属性和方法,并且增强了js的功能,让用户使用起来更加便利,并且增强了js的功能.
原来是使用js是要处理很多兼容性的问题(比如注册事件等),由JQuery封装了底层,就不用处理兼容性问题.
原生的js的dom和事件绑定和ajax等操作非常麻烦,JQuery封装了以后,操作非常方便.
37.JQUERY中的常用选择器
ID选择器
Class选择器
标签选择器
通用选择器
层次选择器
属性选择器
38.JQUERY中页面加载完毕事件
为什么需要页面加载事件?很多时候我们需要获取元素,但是必须等到该元素被加载后才能获取,我们可以把js代码放到该元素的后面,但是这样就会造成js在我们的body中存在不好管理.所有页面加载完毕后,所有的元素当然已经加载完毕,一般获取元素做操作都要在页面加载完毕后.
$(function{}表示的是页面结构被加载完毕
Window.onload表示的是页面被加载完毕
39.JQUERY中AJAX和原生JS实现AJAX的关系
JQuery中的ajax也是通过原生的js封装的,封装完成后让我们使用起来更加便利,不用考虑底层实现或兼容性等的处理.
如果采用原生js实现ajax是非常麻烦的,并且每次都是一样的.如果我们不适用JQuery,我们也要封装对象的方法和属性,有像JQuery这些已经封装完成,经过很多企业实践过的框架,比较可靠,我们不需要封装,直接使用成熟的框架(JQuery)即可.
40.BOOTSTRAP的是什么
Bootstrap是一个移动设备优先的UI框架.我们不用写任何的css和js代码就能实现比较漂亮的有交互性的页面.我们程序员对页面的编写是有硬伤的,所以要自己写页面的话,就要使用类似bootstrap这样的UI框架.
平时经常用的:
模态框
表单,表单项
布局
栅格系统
41.什么是框架
框架(Framework)是一个框子—–具有约束性,也是一个架子—-具有支撑性.
IT语境中的框架,特支为解决一个开放性问题而设计的具有一定约束性的支撑架构.在此结构上可以根据具体问题扩展.安插更多的组成部分.从而更迅速和更方便的构建完整的解决问题的方案.
框架本身一般不完整到可以解决特定问题,但是可以帮助我们快速解决特定问题
框架天生就是为了扩展而设计的
框架里面可以为后续扩展的组件提供很多辅助性,支撑性的方便易用的使用工具.也就是说框架时常配套; 一些帮助解决某类问题的库或工具.
42.简单介绍一下MVC模式
MVC全名是model view Controller,是模型(model)—视图(view)—控制器(Controller)的缩写,是一种软件设计典范.
最简单的,最经典的就是jsp(view)+servlet(Controller)+javabean(model)
1.当控制器收到来自用户的请求
2.控制器调用javabean完成业务
3.完成业务后通过控制器跳转jsp页面的方式给用户反馈信息
4.Jsp给用户做出响应
43.简单说一下对MVC框架的理解
是为了解决传统的MVC模式(jsp+servlet+javabean)问题而出现的框架.
传统MVC模式问题
1.所有的servlet和servlet映射都要配置在web.xml中,如果项目太大,web.xml就太庞大,并且不能实现模块化管理.
2.Servlet的主要功能就是接受参数,调用逻辑,跳转页面,比如像其他字符编码,文件上传等功能也要写在servlet中,不能让servlet功能单一.
3.接受参数比较麻烦,不能通过model接收,只能单个接收,接收完成后转换封装进model.
4.跳转页面方式比较单一(forward,redirect),并且当页面名称发生变化时,需要修改servlet源代码.
常用的MVC框架:struts2,springMVC
44.STRUTS2的执行流程或者STRUTS2的原理
1.浏览器发送请求,经过一系列的过filter,到达strutsPrepareAndExecuteFilter
2.strutsPrepareAndExecuteFilter通过ActionMapper判断当前的请求是否需要某个Action处理,如果不需要,则走原来的流程.如果需要,把请求交个ActionProxy来处理
3.ActionProxy通过Configuration Manager 询问框架的配置文件struts.xml,找到需要调用的Action类;
4.创建一个ActionInvocation实例,来调用Action的对应方法来获取结果集的name,在调用前后会执行相关拦截器
5/通过结果集的name找到对应的结果集来对浏览器进行响应
45.STRUTS2的拦截器是什么
通过动态配置方式,可以在执行Action的方法前后,加入相关逻辑,完成业务 .struts2中的功能, 都是通过系统拦截器实现的.比如:参数处理,文件上传,字符编码.当然,我们也可以自定义拦截器
使用场景:用户登陆判断,在执行Action的前面判断是否已经登陆,如果没有登陆则跳转到登陆页面;用户权限的判断,在执行Action的前面判断是否具有权限,如果没有给出提示信息;
46.SPRING MVC的执行流程
1.用户发送请求,被前端控制器(DispatcherServlet)捕获(捕获请求)
2.前端控制器进行解析,得到URI,通过URI调用HandlerMapping并获得该Handler配置的所有相关对象(查找Handler)
3.前端控制器根据得到的Handler,选择合适的HandlerAdapter,提取Request中的模型数据,填入Handler入参,开始执行Handler,最后返回一个ModelAndView对象.(执行Handler)
4.前端控制器根据返回的ModelAndViewm,选择合适的ViewResolver(选择ViewResolver)
5.通过ViewResolver结合Model和View来渲染视图,前端控制器将渲染结果返回给客户端(渲染并返回)
47.SPRINGMVC和STRUTS2的不同
核心控制器不同:springmvc是servlet,struts2是filter
控制器实例:springmvc会比struts快(理论上),springmvc是基于方法设计,struts是基于对象,每发一次请求都会实例一个action.springmvc只有一个实例,每次请求执行对应的方法即可,简单来说,springmvc是单例,是trust是多例
管理方式:springmvc是spring的一个模块,所以spring对于springmvc的控制管理更加简单方便.而struts需要使用xml配置很多参数来管理
参数传递:struts2中自身提供多种参数接收,其实都是通过valuestack进行传递和赋值.而springmvc是通过方法参数进行接收.
interceptor的实现机制:struts有自己的interceptor机制,springmvc用的是独立的aop方式.
Springmvc处理ajax请求,直接返回数据,方法中使用注解@ResponseBody,springmvc自动帮我们将数据转成json数据,而struts2是通过插件的方式进行处理
48.简单介绍一下SPRING或者SPRING的两大核心
Spring是什么?spring是j2ee应用程序框架,是轻量级的IOC和AOP的容器框架,主要针对javabean的生命周期进行管理的轻量级容器,可以单独使用,也可以跟其它框架组合使用.
IOC(inversion of control)或DI(dependency injection)控制反转
原来:我的service要调用Dao,我就在service中创建Dao对象,这时Dao对象的创建的控制权在我手中
Spring:spring发现我的service依赖于Dao,就给我的service注入Dao对象,这时Dao对象创建的控制权在spring手中
核心原理:工厂模式+反射+配置文件
AOP:面向切面编程
核心原理:使用动态代理的方式在执行前后或出现异常后做相关逻辑.
我们主要使用AOP来做:
事务处理
权限判断
日志记录
49.AOP是什么?都用它做什么?
AOP:面向切面编程
核心原理:使用动态代理的方式在执行前后或出现异常后做加入相关逻辑.
我们主要使用AOP来做:
事务处理 执行方法前,开启事务,执行方法后提交事务,出现异常后回滚事务
权限判断 在执行方法前,判断是否具有权限
日志记录 在执行方法前执行日志
50.SPRING事务的传播特性和隔离级别
事务的传播特性:多个事务存在是怎么处理的策略.
传播行为意义
PROPAGATION_MANDATORY表示该方法必须运行在一个事务中。如果当前没有事务正在发生,将抛出一个异常
PROPAGATION_NESTED表示如果当前正有一个事务在进行中,则该方法应当运行在一个嵌套式事务中。被嵌套的事务可以独立于封装事务进行提交或回滚。如果封装事务不存在,行为就像PROPAGATION_REQUIRES一样。
PROPAGATION_NEVER表示当前的方法不应该在一个事务中运行。如果一个事务正在进行,则会抛出一个异常。
PROPAGATION_NOT_SUPPORTED表示该方法不应该在一个事务中运行。如果一个现有事务正在进行中,它将在该方法的运行期间被挂起。
PROPAGATION_SUPPORTS表示当前方法不需要事务性上下文,但是如果有一个事务已经在运行的话,它也可以在这个事务里运行。
PROPAGATION_REQUIRES_NEW表示当前方法必须在它自己的事务里运行。一个新的事务将被启动,而且如果有一个现有事务在运行的话,则将在这个方法运行期间被挂起。
PROPAGATION_REQUIRES表示当前方法必须在一个事务中运行。如果一个现有事务正在进行中,该方法将在那个事务中运行,否则就要开始一个新事务。
隔离级别含义
ISOLATION_DEFAULT使用后端数据库默认的隔离级别。
ISOLATION_READ_UNCOMMITTED允许读取尚未提交的更改。可能导致脏读、幻影读或不可重复读。
ISOLATION_READ_COMMITTED允许从已经提交的并发事务读取。可防止脏读,但幻影读和不可重复读仍可能会发生。
ISOLATION_REPEATABLE_READ对相同字段的多次读取的结果是一致的,除非数据被当前事务本身改变。可防止脏读和不可重复读,但幻影读仍可能发生。
ISOLATION_SERIALIZABLE完全服从ACID的隔离级别,确保不发生脏读、不可重复读和幻影读。这在所有隔离级别中也是最慢的,因为它通常是通过完全锁定当前事务所涉及的数据表来完成的。
51.ORM是什么?ORM框架是什么?
对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。简单来说,将程序中的兑现自动持久化到关系数据库中。那么,到底如何实现持久化呢?一种简单的反感是采用硬编码的方式(jdbc操作sql方式),为每一种可能的数据库访问操作提供单独的方法。这种方法存在很多缺陷,所以使用ORM框架(为了解决面型对象与关系数据库存在的互不匹配的现象的框架)来解决。
Java典型的ORM框架有:Hibernate,mybatits
52.MYBATIS和HIBERNATE有什么不同
相同:都是java中的orm框架,屏蔽jdbc的api底层访问细节,使我们不用域jdbc的挨批打交道,就可以完成对数据的持久化操作.jdbc的api编程流程固定,还将sql与java代码混在在一起,经常需要拼凑sql语句,细节繁琐,开发不方便.
Mybatis的好处:屏蔽jdbc api的底层访问细节,将sql语句域java代码分离,提供将结果集自动封装为实体对象和对象的集合的功能,queryForList返回对象集合.用queryForObject返回单个对象.提供自动将实体对象的属性传递给sql语句的参数
Hibernate的好处:hibernate是一个全自动的偶人吗映射工具,它可以自动生成sql语句,执行并返回java结果.
不同点:
1. hibernate要比mybatis功能强大很多,因为hibernate自动生成sql语句.
2. Mybatis需要我们自己在xml配置文件中写sql语句,hibernate我们无法直接控制该语句,我们就无法去写特定的高效的sql,对于一些不太复杂的sql查询,hibernate可以很好帮我们完成.但是,对于特别复杂的查询,hibernate就很难适应了,这时候用mybatis就是不错的选择,因为mybatis还是由我们自己写sql语句.mybatis可以处理复杂语句,而hibernate不能.
3. Mybatis要比hibernate简单的多,mybatis是面向sql的,不用考虑对象间一些复杂的映射关系.
53.HIBERNATE对象状态及其转换
瞬时态:刚new的,没有持久化,不在session中
持久态:session中的持久化对象
脱管态:不在session中的持久化对象
54.HIBERNATE的缓存
缓存:为了提高访问速度,把磁盘或数据库访问变成内存访问.
一级缓存(session缓存):session缓存内置不能被卸载session:是事务范围的缓存(session对象的生命周期通常对应一个数据库事务或者一个应用事务).一级缓存中,持久化类的每个实例都具有唯一的oid
二级缓存(SessionFactory缓存):由于SessionFactory对象的生命周期和一个用程序的整个过程对应,因此hibernate二级缓存是进城范围或者集群范围的缓存,有可能出现并发问题,因此需要采用适当的并发访问策略,该策略为被缓存的数据提供了事务隔离级别.二级缓存是可选的,是一个可配置的插件,默认下SessionFactory不会启用这个插件.
概括:hibernate中的缓存分一级缓存和二级缓存
一级缓存就是session级别的缓存, 在事务范围内是有效的,是内置的不能被卸载.二级缓存是SessionFactory级别的缓存,从应用启动到应用结束有效,是可选的,默认没有二级缓存,需要手动开启
保存数据库后,在内存中保存一份,如果更新了数据库就要同步更新缓存
什么样的数据适合放到缓存中(访问频率,读写比例,数据一致性):
很少被修改的数据
经常被查询的数据
不是很重要的数据,允许出现偶尔并发的数据
不会被并发访问的数据
常量数据
Hibernate的二级缓存默认是不支持分布式缓存的,使用memcache,redis等重要缓存来代替二级缓存
55.WEBSERVICE的使用场景
Webservice是一个SOA(面向服务的编程)的架构,它是不依赖于语言,不依赖于平台,可以实现不同的语言间的相互调用,通过Internet进行基于http协议的网络应用间的交互.
异构系统(语言)的整合
不同客户端的整合,浏览器 手机端 pc端等终端的访问
例子:
天气预报:可以通过实现webservice客户端调用远程天气服务实现的.
单点登录:一个服务器实现所有系统的登陆
56.ACTIVITI的简单介绍
Activiti是一个业务流程管理(BPM)和工作流系统,适用于开发人员和系统管理人员,其核心是超快速,稳定的BPMN2流程引擎,它易与spring集成使用.
主要用在OA中,把线下流程放到线上,把现实生活中的一些流程固话定义到系统中,然后通过输入表单数据完成业务.
57.LINUX的使用场景
Linux是一个长时间运行比较稳定的操作系统,所以我们一般会拿它作为服务器(web,db.app等).
Linux本身具有c的编译环境.我们的一些软件是没有软件包的(redis,nginx),需要在linux编译得到软件包
58.LINUX常用命令
Cd跳转到目录
Pwd 获取当前路径
Su 切换用户
Ll 查看当前目录下文件和目录
Tail 查看文件
Rm –rf 删除文件
Vi 修改文件
Mv 移动/重命名 文件或文件夹
Mkdir 创建文件夹
Rm –f 删除文件夹
Tar 打包/解压
Grep 查找想要的信息
59.怎么操作LINUX服务器
需要依赖于linux服务器安装ssh服务端,一般这个ssh服务的端口为22,
需要依赖于linux服务器安装sftp服务端,一般这个sftp服务的端口为25,
使用ssh客户端连接linux服务器,通过命令操作linux服务器
使用sftp客户端来连接sftp服务端,来上传和下载文件(安装包,修改文件上传)
60.有没有使用过云主机
使用过阿里云
云主机:就是一些云服务运营商(阿里,华为,新浪等)提供的远程服务器功能,我们公司只要付费就可以租用对应的服务器.
61.数据库优化方面的事情
定位:查找,定位慢查询,并优化
优化
1.创建索引:创建合适的索引,我们就可以在索引中查询,查询到以后直接找对应的额记录
2,分表:当一张表的数据比较多或者一张表的某些字段的值比较多并且很少使用时,采用水平分表或垂直分表来优化,比如spu表
3,读写分离:当一台服务器不能满足需要时,采用将读写分离的方式进行集群
4.缓存:使用redis来进行缓存
62.如果查询和定位慢查询
在项目自验或项目转测之前,在启动mysql数据库时开启慢查询,并且把执行慢的语句写到日志中,在运行一定的时间后,通过查看日志,找到对应的慢查询信息.
使用EXPLAIN +慢查询语句,,来详细分析语句的问题.
63.数据库优化之数据库表设计遵循范式
三范式:首先符合1nf,才能满足2nf,进一步满足3nf
反三范式:没有冗余的数据库未必是最好的数据库,有事为了提高运行效率,就必须降低范式标准,适当保留冗余数据.具体做法是,在概念数据模型设计时遵守三范式,降低方式标准的工作放到物理数据模型设计时考虑,降低范式就是增加字段,允许冗余.订单和订单项,相册浏览次数和照片的浏览次数.
64.选择合适的数据库引擎
Myisam存储引擎:如果表对事物要求不高,同时是以查询和添加为主的,我们考虑使用myisam存储引擎,比如论坛中的发帖表,回复表
Innodb存储引擎:对事物要求高,保存的数据都是重要数据.我们建议使用innodb,比如订单表,账号表
Myisam和innodb的区别:
1. 事务安全,myisam不支持使用,而innodb支持
2. 查询和添加速度,myisam不用支持事务就不用考虑同步锁,查找和添加的速度快
3. 支持全文索引,myisam支持,innodb不支持
4. 锁机制:myisam支持表锁,innodb支持行锁
5. 外键:myisam不支持外键,innodb支持外键
65.选择合适的索引
索引是帮助DBMS高效获取数据的数据结构.
分类:普通索引,唯一索引,主键索引,全文索引
1.普通索引:允许重复的值出现
2.唯一索引:除了不能有重复的记录外,其它和普通索引一样.(用户名;用户身份证;手机号)
3.主键索引:是随着设定主键而创建的;也就是把某个列设为主键的时候,数据库就会给该列创建索引;唯一且没有null值
4.全文索引:用来对表中文本域(char,varchar,text)进行索引,全文索引针对myisam
66.使用索引的一些技巧
索引弊端:
1. 占用磁盘空间.
2. 对dml(插入,修改.删除)操作有影响,变慢
使用场景:
1. 肯定在where条件经常使用,如果不做查询就没有意义
2. 该字段的内容不是唯一的几个值(sex).
3. 字段内容不是频繁变化
具体技巧:
1. 对于创建的多列索引(复合索引),不是使用的第一部分就不会使用索引(最左匹配)
2. 对于使用like查询,查询如果是”%aaa”不会使用到索引,而”aaa%”会使用到索引
3. 如果条件中有or,有条件没有使用索引,即使其中有条件带索引,也不会使用.简单来说,就是要求使用的所有字段,都必须单独使用时才能使用索引.
4. 如果列类型是字符串,拿一定要在条件中将数据使用引号引用起来,否则索引失效
5. 如果mysql估计使用全表扫描要比索引快,则不适用索引.例子:表里只有一条记录
67.数据库优化之分表
分表分为水平分表(按行)和垂直分表(按列)
水平:在实际操作中,mysql表数据一般达到百万级别,查询效率会很低,容易造成表锁,甚至堆积很多连接,直接挂掉.水平分表能够很大程度的减少这些压力.
垂直:如果一张表中某个字段值非常多(长文本,二进制等),而且只有在很少的情况下会查询,比如商品的详情描述,这时候就可以把字段单个放到一个表,通过外键与原表关联起来
水平分表策略:
1. 按时间分表:这种分表方式有一定的局限性,当数据有较强的时效性.如微博发布纪录,微信消息纪录等,这种数据很少会有用户查询几个月前的数据,这时可以按月分表
2. 按区间范围分表:一般在有严格的自增id需求上,如按照user_id水平分表
3. Hash分表(用的多):通过一个原始目标的id或者名称通过一定的hash算法计算出数据库存储表的表名,然后访问相应的表.
68.数据库的读写分离
一台数据库支持的最大并发连接数是有限的,如果用户并发访问太多,一台服务器满足不了要求时,可以集群处理.mysql的集群处理技术最常用的是读写分离,
1.主从同步:数据库最终会把数据持久化到磁盘,如果集群必须确保每个数据库服务器的数据时一致的.能改变数据库数据的操作都往主数据库去写,而其他的数据库从主数据库上同步数据
2.读写分离:使用负载均衡来实现写的操作都往主数据.而读的操作都往从数据库去
69.数据库优化之缓存
在持久层(dao)和数据库(db)之间添加一个缓存层,如果用户访问的数据已经缓存起来时,在用户访问数据时从缓存中获取,不用访问数据库,而缓存是在操作内存,访问速度快
作用:减少数据库服务器压力,减少访问时间
Java中常用的缓存:
1. hibernate的二级缓存,这种缓存不支持分布式缓存
2. 可以使用redis来作为中央缓存,对缓存的数据进行集中处理
70.SQL语句优化小技巧
DDL优化:
1. 通过禁用索引来提供导入数据性能,这个操作主要针对有数据的表追加数据
2. 关闭唯一校验
3. 修改事务提交方式(导入)(变多次提交为一次)
DML优化: 把多条插入的语句合并为一条(变多次提交为一次)
DQL优化:
Order by 优化
多用索引排序
普通结果排序(非索引排序)
Group by 优化:如果对排序的结果没有排序的需求,可以考虑在其后面加上order by nul
子查询优化
Or优化:
1.or两边都是用索引字段做判读,性能好
2.or两边,有一边不用,性能差
3.如果name=”a” or name=”b”,这种方式,索引失效
Limit优化
71.批量插入几百万条数据
可以使用存储过程
72.有没有使用过REDIS
Redis是一个key-value的nosql数据库,先存到内存中,会根据一定的策略持久化到磁盘,即使断电也不会丢失数据,支持的数据类型比较多.
主要用来做缓存数据库的数据和web集群时当做中央缓存存放session
73.REDIS的使用场景
缓存:把经常需要查询很少修改的数据放到读速度很快的空间(内存),以便减少下次访问时间,减轻db压力,
计数器:redis中的计数器是原子性的内存操作,可以解决库存溢出问题,进销存,系统存溢出
Session缓存服务器:web集群时作为session的缓存服务器
74.REDIS存储对象的方式
Json字符串:需要把对象转换成json字符串,当做字符串处理,直接使用set和get来设置或获取/
优点:设置和获取比较简单
缺点:没有提供专门的方法,需要把对象转换成json
字节:需要做序列号,就是把对象序列化为字节保存.
如果是担心json转对象会消耗资源的情况,这个问题需要考量几个地方,
1. 使用的json转换lib是否就会存在性能问题
2. 数据的数据量级别,如果是存储百万级的大数据对象,建议采用存储序列化对象方式.如果是少量的数据级对象,或者是数据对象字段不多,还是建议采用json转换成string方式.毕竟redis对存储字符类型这部分优化的非常好.具体采用的方式与方法,还要看你所使用的场景
75.REDIS数据淘汰机制
在 redis 中,允许用户设置最大使用内存大小 server.maxmemory,在内存限定的情况下是很有用的。譬如,在一台 8G 机子上部署了 4 个 redis 服务点,每一个服务点分配 1.5G 的内存大小,减少内存紧张的情况,由此获取更为稳健的服务。
内存大小有限,需要保存有效的数据?
Redis内存数据集大小上升到一定大小的时候,就会施行平台策略.数据淘汰策略.redis提供6中数据淘汰策略:
1.volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
2.volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
3.volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
4.allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
5.allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
6.no-enviction(驱逐):禁止驱逐数据
。
76.JAVA访问REDIS级REDIS集群
Java访问redis:
1. 使用jedisjava客户端来访问redis服务器,优点类似jdbc访问db一样
2. 如果是spring进行集成时,可以使用springDataRedis来访问redis , springDataRedis 只是对jedis的二次封装
Redis集群:当一台数据无法满足要求,可以使用redis集群来出来,类似mysql的读写分离
77.项目的并发
1.需求:用户量,这个客户说了算,大概也就是1-5年内用户总量
2.根据pv(页面点击量,浏览量)和uv(ip数量)预估,大致能达到多大的并发量.我们的项目大概能达到1000-3000的并发量
3.确定我们的服务器数量,我们使用的是tomcat,tomcat的默认线程数150,我们可以将它优化调到400左右.而我们大致需要5台web服务器
4.重要的因素(硬件服务器水平—去IOE),我们没有做这个,因为我们没钱.
78.http协议
1.无状态,为了解决http无状态问题,引入cookie技术
2.http1.0是短连接,http1.1是长连接
3.http协议是基于B/S请求-应答模式
79.cookie和session
1.Cookie是由服务器创建的,通过response对象的addCookie(Cookie cookie)方法写回客户端,存储在客户端的会话技术.key-value的结构
2.session是基于cookie,session的创建是由服务器做,可以通过request.getSession()获取(要从你的请求中找一个cookie—Jessionid,如果能找到这个cookie,他会拿着这个cookie的值去跟服务器端的session的id比较,如果找到相应的session,就不创建session.如果找不到相应的session,会创建session).session一旦创建就会有一个id属性(唯一的),通过response以cookie的方式写回客户端(这个cookie就叫做就sessionid).
会话:会话就是简单的理解成打开浏览器(包含了一次请求或多次请求).
80.session共享的方案
1.广播:会造成内网网络风暴,大量占用内网宽带
2.IP_hash:在nginx中配置和,相同的ip找固定的同一台服务器,这种方案会造成服务能力差
3.使用第三方中间件(数据库,redis),我们是使用redis
81.solr相似度匹配原理(多关键字搜索)
solr将用户输入的内容使用分词器分词,然后将这些新词做成向量.
比如,用户输入:我是萝莉控
solr分词记过:我 , 萝莉 , 萝莉控
向量:向量a–我 ,向量b–萝莉, 向量c–萝莉控
接下来,solr会将索引库中所有包含这些关键字的记录数做成n维向量.这个时候,solr会根据n维向量夹角的余弦值的大小来判断相似度的大小.余弦值越低,相似度越大,排名越靠前.反之,余弦值越大,相似度越小,排名越靠后.
题外话:lucene的数据模型其实是n维向量.
82.高并发问题:索引库同步
1.硬编码:在相应的代码中增加索引库同步的代码。不过,这种方法耦合度太高,将原本不相关的系统耦合在了一起,容易造成不可预估的错误,是电商项目的大忌。
2.spring的aop:编写一个索引库同步的方法,利用aop的形式,将它和数据库数据更新的方法联系起来。这种方式也会造成耦合。
3.消息队列:不过,这个方法会造成一个问题,那就是消息消费失败问题。
:解决两个系统间的通信问题。
消息消费失败:集中同步索引库,做一个定时任务。在消息队列所在的服务器上加一个数据库,我们使用的是redis缓存。消息队列中每发一条信息,就将这条信息持久化进redis中。接着定时(我们是在晚上,用户量少的时候)从redis中将消息列表取出来,批量同步索引库。
83.页面静态化问题
当商品规格出现不同组合时,它的价格势必会不一样,这时怎么在静态页面中处理价格这样的数据?
像价格这样的数据,只有我们在生成静态页面时才会和数据库交互一次,查出所有的sku,将这些sku存进集合中。接着,我们在前端js中定义一个变量来存储集合的值,当以后用户每一次来访问我们的静态页面时,他都是从静态页面的js变量中自动获取价格这样的数据。
84.与app端对接时需要注意什么
和app端对接,需要知道对方需要什么样的数据,以及接口的请求方式,返回值类型等
。
85.为什么服务层之间调用的activeMq会是在controller层发消息?
因为事务!如果是在controller层发送消息,那么controller层调用的service一定是完成了事务提交操作的。如果是在service层发送消息,那么事务可能会没有提交,会造成空指针异常。
86.索引库同步时为什么使用activemq的queue方式?(使用queue的好处)
1.不需要考虑消息没有被消费问题
2.queue方式,自带持久化机制
3.业务更加单一,相对来说比较安全
87.消息队列问题:同步索引库时,传输的内容为什么是商品信息,而不适用商品id?
传送商品id:
好处:传送的是商品id,传输的内容少,效率相对较高,不会产生消息阻塞。
缺点:消费方需要再次查询数据库取出商品信息,和数据库多了一次交互。
传送商品信息:
好处:这样消费者就不需要再次从数据库中查询商品信息数据,减少了与数据库的交互。
缺点:传输的是商品信息,传输内容相对较少(原因:文本信息在网络传输中占用的网络资源最少),可能会产生消息阻塞的问题,但是由于我们的消息的发送不是连续的,不会有太高的并发量(原因:消息的发送时需要运营商平台审核通过后才发送的。)
88.秒杀
秒杀业务最主要的操作:减库存和添加订单
1.第一种方式:数据库(中小型网站)
Update goods set num=num-1 where id=id;
Insert orders values() where goods.id=goodsid
为了保持数据的一致性,需要使用事务
优化:
①数据库服务器和秒杀服务器在同一个机房
②避免使用事务,使用数据库的存储过程来完成业务单元
存储过程逻辑:避免使用事务
(1)判断库存(num)
(2)如果num>0,执行update和insert操作
(3)如果num<0,秒杀结束
2.第二种方式:缓存(redis)(中大型网站)
将秒杀商品和订单都存在redis中,用户下单时,num>0?下单(num-1):秒杀结束;
89.HashMap中链表长度大于8时,会怎么样(优化hashMap)
HashMap在JDK1.8及以后的版本中引入了红黑树结构,若桶中链表元素个数大于等于8时,链表转换成树结构;若桶中链表元素个数小于等于6时,树结构还原成链表。因为红黑树的平均查找长度是log(n),长度为8的时候,平均查找长度为3,如果继续使用链表,平均查找长度为8/2=4,这才有转换为树的必要。链表长度如果是小于等于6,6/2=3,虽然速度也很快的,但是转化为树结构和生成树的时间并不会太短。
还有选择6和8,中间有个差值7可以有效防止链表和树频繁转换。假设一下,如果设计成链表个数超过8则链表转换成树结构,链表个数小于8则树结构转换成链表,如果一个HashMap不停的插入、删除元素,链表个数在8左右徘徊,就会频繁的发生树转链表、链表转树,效率会很低
90.JSP中动态INCLUDE与静态INCLUDE的区别
动态INCLUDE用jsp:include动作实现 它总是会检查所含文件中的变化,适合用于包含动态页面,并且可以带参数。静态INCLUDE用include伪码实现,并不会检查所含文件的变化,适用于包含静态页面
91.1000个人来买100件商品
缓存架构(KyotoCabinet、Memcached等)的先进先出队列,
不能随便加锁,淘宝的双11活动。很明显的一点是商品没有提供一个非常即时的锁,即便商品实际没有了也是可以下单成功的。但是在支付的时候会提示你商品没有了。猜测只是在支付的时候才有即时的锁。
92 你们做移动端没有,如果没有移动端,你们为什么做单点登录?
单点登录并不是为移动端准备的,移动端有自己的登录方式。单点登录是解决在同一个公司
内部多个互信网站之间进行跳转时不需要多次登录,多个系统统一登录入口。
93.单点登录的核心是什么?
单点登录的核心是如何在多个系统之间共享身份信息
94.solr 的索引查询为什么比数据库要快。
Solr 使用的是 Lucene API 实现的全文检索。全文检索本质上是查询的索引。而数据库中并
不是所有的字段都建立的索引,更何况如果使用 like 查询时很大的可能是不使用索引,所以
使用 solr 查询时要比查数据库快。
95.solr 索引库个别数据索引丢失怎么办。
首先 Solr 是不会丢失个别数据的。如果索引库中缺少数据,那就向索引库中添加
96.IO和NIO
IONIO
面向流面向缓冲
阻塞IO非阻塞IO
无选择器
97.https和http
HTTP:是互联网上应用最为广泛的一种网络协议,是一个客户端和服务器端请求和应答的标准(TCP),用于从WWW服务器传输超文本到本地浏览器的传输协议,它可以使浏览器更加高效,使网络传输减少。
HTTPS:是以安全为目标的HTTP通道,简单讲是HTTP的安全版,即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。
HTTPS协议的主要作用可以分为两种:一种是建立一个信息安全通道,来保证数据传输的安全;另一种就是确认网站的真实性。
区别:
1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
98.序列化
序列化一般是指把结构化的对象变成无结构的字节流,便于存储、传输
首先序列化并不是JAVA所独有的,基本所有编程语言都提供了序列化的方式,序列化是编程的一种解决问题的方式。JAVA序列化就是将对象按照某种协议格式(某种约定方式)放入一个buffer中,其目的是便于网络传输或持久存储。反序列化,就是将序列化后的buffer按照序列化时还原成原来的对象,这样程序就能直接使用还原的对象了。
99.安全性问题(别的网站使用爬虫技术爬你的网站怎么办?有没有安全措施)
单位时间内请求次数超过某个阈值就让输入验证码,可以极大降低抓取的速度,如果多次超
过某个阀值可以加入黑名单。还有就是页面内容使用 json 返回,数据经常变一变格式,或
者 js 动态生成页面内容
100.订单表的数据量太大, 我把订单分到许多表中, 那么我我想用一条 sql 查处所有的订单, 怎么
解决?
分库情况下:可以使用 mycat 数据库中间件实现多个表的统一管理。虽然物理上是把一个表
中的数据保存到多个数据库中,但是逻辑上还是一个表,使用一条 sql 语句就可以把数据全
部查询出来。
单库情况下:需要动态生成 sql 语句。先查询订单相关的表,然后将查询多个表的 sql 语句
使用 union 连接即可
101.TCP和UDP的区别
1.tcp面向连接(如打电话要先拨号连接);udp是无连接的,即发送数据之前不需要连接
2.tcp提供可靠的服务。也就是说通过tcp传送的数据,无差错,无丢失,不重复,且按序到达;udp尽最大努力交付,不保证交付是否成功
3.tcp面下字节流,实际上tcp把数据看成是一连串无结构的字节流;udp是面向报文的,udp没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,比如视频会议)
4.每一条tcp连接只能是点到点的;udp支持一对一,一对多,多对一,多对多的交互通信
5.tcp首部开销20字节;udp首部开销小,只有8字节
6.tcp通信信道是全双工的可靠信道;udp则是不可靠
102.tcp三次握手和四次挥手
1.三次握手
2.四次挥手
103.为什么挥手会比握手多一次
因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,”你发的FIN报文我收到了”。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。
104.spring对bean的管理
1.BeanFactory: BeanFactory采用了工厂设计模式,负责读取bean配置文档,管理bean的加载,实例化,维护bean之间的依赖关系,负责bean的生命周期。
2.ApplicationContext:除了提供上述BeanFactory所能提供的功能之外,还提供了更完整的框架功能:国际化支持、aop、事务等。
3.BeanFactory在解析配置文件时并不会初始化对象,只有在使用对象getBean()才会对该对象进行初始化,而ApplicationContext在解析配置文件时对配置文件中的所有对象都初始化了,getBean()方法只是获取对象的过程。
105.mybatis返回最近插入的数据的id
SELECT LAST_INSERT_ID() AS ID insert into t_employee (ID, EmployeeName, Position, Salary, Tel, DepartmentID)values (#{id,jdbcType=INTEGER}, #{employeename,jdbcType=VARCHAR}, #{position,jdbcType=VARCHAR},#{salary,jdbcType=DOUBLE}, #{tel,jdbcType=VARCHAR}, #{departmentid,jdbcType=INTEGER})
1
2
3
4
5
6
7
8
9
10
11
Employee employee = new Employee();employee.setDepartmentid(1);employee.setEmployeename("xiaoA");employee.setPosition("manager");employee.setSalary(13000d);int result = employeeMapper.insert(employee);int id = employee.getId();//获取新插入的idLOGGER.info("last insert id : "+ id);}}
1
2
3
4
5
6
7
8
9
10
106.redis存储对象
1.对象要实现序列化接口:
public class Person implements Serializable {
private int id;
private String name;
2.序列化与反序列化工具
public class SerializeUtil {
public static byte[] serialize(Object object) {
ObjectOutputStream oos = null;
ByteArrayOutputStream baos = null;
try {
//序列化
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(object);
byte[] bytes = baos.toByteArray();
return bytes;
} catch (Exception e) {
}
return null;
}
public static Object unserialize(byte[] bytes) {
ByteArrayInputStream bais = null;
try {
//反序列化
bais = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bais);
return ois.readObject();
} catch (Exception e) {
}
return null;
}
}
.测试
publicvoidsetObject() { Person person =newPerson(100,"alan"); jedis.set("person:100".getBytes(), SerializeUtil.serialize(person));//将key转成字节,将value也就是对象序列化}
107.springmvc和springboot的区别
Spring 是一个“引擎”;
Spring MVC 是基于Spring的一个 MVC 框架 ;
Spring Boot 是基于Spring4的条件注册的一套快速开发整合包:
1. 创建独立的Spring应用程序
2. 嵌入的Tomcat,无需部署WAR文件
3. 简化Maven配置
4. 自动配置Spring
5. 提供生产就绪型功能,如指标,健康检查和外部配置
6. 绝对没有代码生成和对XML没有要求配置 [1]