(文末思维脑图将会打开你的新世界)
1、在 java 中如何跳出当前的多重嵌套循环?
在Java中,要想跳出多重循环,可以在外面的循环语句前定义一个标号,然后在里层循环体的代码中使用带有标号的break语句,即可跳出外层循环。例如,
ok:for (int i = ; i < 10; i++) {
for (int j = ; j < 10; j++) {
System.out.println("i=" + i + ",j=" + j);
if (j == )
break ok;
}
}
另外,我个人通常并不使用标号这种方式,而是让外层的循环条件表达式的结果可以受到里层循环体代码的控制,例如,要在二维数组中查找到某个数字。
int arr[][] = { { , 2, 3 }, { 4, 5, 6, 7 }, { 9 } };
boolean found = false;
for (int i = ; i < arr.length && !found; i++) {
for (int j = ; j < arr[i].length; j++) {
System.out.println("i=" + i + ",j=" + j);
if (arr[i][j] == ) {
found = true;
break;
}
}
}
2、请说出作用域public,private,protected,以及不写时的区别。
- private修饰的成员变量和函数只能在类本身和内部类中被访问。
- protected 修饰的成员变量和函数能被类本身、子类及同一个包中的类访问。
- public修饰的成员变量和函数可以被类、子类、同一个包中的类以及任意其他类访问。
默认情况(不写)下,属于一种包访问,即能被类本身以及同一个包中的类访问。
下面这个表能清楚的说明java中作用域操作符的作用:
3、说说对javaee中的 session 的理解,你是怎么用session的?
在 Servlet 的api中,session表示的是浏览器和web服务器的一次会话。在web服务器中是通过session来区别不同的浏览器的,因为web 服务器采用的是http协议进行通讯,web 服务器根本不知道正在请求的浏览器是谁,它不会记录浏览器的访问信息,所以需要session来记录发出请求的浏览器是谁,session 和浏览器之间是怎么保持通信的呢? 当浏览器第一次对一个web站点发出请求后,web服务器按照请求路径查找资源,并生成一个session,web服务器将查找到的资源作为响应返回给浏览器,在这个响应中会附带上一个特殊名称的cookie信息,这个cookie 就是session的id。之后浏览器再次发出请求时,会在请求信息中带上这个cookie信息,这个cookie 的作用就是用来告诉web服务器,我这个浏览器已经访问过你了,你不需要再生成session了。
Session 的应用有很多
- 过滤未登录用户 可以用于存放用户信息,当用户登录后,就将用户信息放入session,如果没有登录,在session中就不会有用户信息,这样就可以防止未登录用户查看一些信息。
- 防止表单重复提交
- 网上商城中的购物车
4、分层设计的好处?
- 把各个功能按调用流程进行了模块化,模块化带来的好处就是可以随意组合。分层的好处:
- 实现了软件之间的解耦
- 便于进行分工
- 便于维护
- 提高软件组件的重用
- 便于替换某种产品,比如持久层用的是 Hibernate ,需要更换产品为 MyBatis ,就不用改其他业务的代码,直接把配置一改即可
- 便于产品功能的扩展
- 便于适用用户需求的不断变化
5、java中实现多态的机制是什么?
靠的是父类或接口定义的引用变量可以指向子类或具体实现类的实例对象,而程序调用的方法在运行期才动态绑定,就是引用变量所指向的具体实例对象的方法,也就是内存里正在运行的那个对象的方法,而不是引用变量的类型中定义的方法。
6、abstract(抽象类)和interface(接口)有什么区别?
含有abstract修饰符的class即为抽象类,abstract 类不能创建的实例对象。含有abstract方法的类必须定义为abstract class,abstract class类中的方法不必是抽象的。abstract class类中定义抽象方法必须在具体(Concrete)子类中实现,所以,不能有抽象构造方法或抽象静态方法。如果子类没有实现抽象父类中的所有抽象方法,那么子类也必须定义为abstract类型。
接口(interface)可以说成是抽象类的一种特例,接口中的所有方法都必须是抽象的。接口中的方法定义默认为public abstract类型,接口中的成员变量类型默认为public static final。
下面比较一下两者的语法区别:
- 抽象类可以有构造方法,接口中不能有构造方法。
- 抽象类中可以有普通成员变量,接口中没有普通成员变量
- 抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。
- 抽象类中的抽象方法的访问类型可以是public,protected和默认类型,但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。
- 抽象类中可以包含静态方法,接口中不能包含静态方法
- 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型。
- 一个类可以实现多个接口,但只能继承一个抽象类。
7、构造方法Constructor是否可被override(重写)?
构造方法Constructor不能被继承,因此不能重写Override,但可以被重载Overload。
8、面向对象的特征有哪些方面?
面向对象的三大特征:
- 封装:保证对象自身数据的完整性和安全性。
- 继承:建立类之间的关系,实现代码复用,方便系统的扩展。
- 多态:相同的方法调用,可以实现不同的实现方式。
9、String是最基本的数据类型吗,是否可以继承String类?
java的基本数据类型有以下8种:
- 整型: byte short int long
- 浮点型: float double
- 字符型: char
- 布尔: boolean
java.lang.String类是final类型的,因此不可以继承这个类、也不能修改这个类 。为了提高效率节省空间,对于要经常修改的字符串,建议使用StringBuffer类。
10、数组有没有length()这个方法? String有没有length()这个方法?
数组没有length()这个方法,有length的属性。
String有length()这个方法。
需要更多学习资料和面试真题资料的朋友,可以转发后,点击我的主页,私信我回复【资料】二字,即可获取免费领取方式,还有本文中分享的思维脑图都可获取。
11、String s = new String(“abc”);创建了几个String Object? 二者之间有什么区别?
答案:一个或者两个
解析:
- 1.如果String缓冲区中,已经创建”abc”,则不会继续创建,此时只创建了一个对象new String(“abc”);
- 2.如果String缓冲区中,没有创建”abc”,则会创建两个对象,一个对象的值是”abc”,一个对象new String(“abc”)。
12、下面这条语句一共创建了多少个对象:String s=”a”+”b”+”c”+”d”
只创建了一个String对象,因为这行代码被编译器编译时进行了优化,相当于直接定义了一个”abcd”的字符串,所以只创建了一个String对象。
13、try {}里有一个return语句,那么紧跟在这个try后的finally {}里的code会不会被执行,什么时候被执行,在return前还是后?
finally中的代码肯定会执行,但是会先执行try中的代码,如果try中有return,那么return的东西会先放到函数栈中,然后再执行finally中的代码。
- ①、如果finally中也有return,则会直接返回并终止程序,函数栈中的return不会被完成;
- ②、如果finally中没有return,则在执行完finally中的代码之后,会将函数栈中的try中的return的内容返回并终止程序;
14、final, finally, finalize的区别
- Final:是全局变量声明的时候使用,意思是这个变量不可被修改,不可被override,一般用于声明常量,或者系统设置的值。
- finally:是在异常处理时提供finally块来执行任何清除操作。不管有没有异常被抛出、捕获,finally块都会被执行。
- finalize:是方法名。java技术允许使用finalize()方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。
15、运行时异常与一般异常有何异同?
Java提供了两类主要的异常:运行时异常runtime exception和一般异常checked exception
- 运行时异常runtime exception,我们可以不处理。这样的异常由虚拟机接管。出现运行时异常后,系统会把异常一直往上层抛,一直遇到处理代码。如果不对运行时异常进行处理,那么出现运行时异常之后,要么是 线程 中止,要么是主程序终止。
- 一般异常checked exception,JAVA要求程序员对其进行try catch处理。所以,面对这种异常不管我们是否愿意,只能自己去写一大堆catch块去处理可能的异常。
16、error和exception有什么区别?
- Error(错误)表示系统级的错误和程序不必处理的异常,是java运行环境中的内部错误或者硬件问题。比如:内存资源不足等。对于这种错误,程序基本无能为力,除了退出运行外别无选择,它是由Java虚拟机抛出的。
- Exception(违例)表示需要捕捉或者需要程序进行处理的异常,它处理的是因为程序设计的瑕疵而引起的问题或者在外的输入等引起的一般性问题,是程序必须处理的。Exception又细分为运行时异常runtime exception,受检查异常checked exception(一般异常)。
17、请写出你最常见到的5个运行时异常 runtime exception
- ClassCastException 类型强制转换异常
- ClassNotFoundException 类没找到时,抛出该异常
- FileNotFoundException 文件未找到异常
- NullPointerException 空指针异常
- SQLException 操作数据库异常
- ArithmeticException 算术异常
- IllegalArgumentException 传递非法参数异常
- IndexOutOfBoundsException 下标越界异常
- NoSuchElementException 方法未找到异常
18、Java语言如何进行异常处理,关键字:throws,throw,try,catch,finally分别代表什么意义?在try块中可以抛出异常吗?
- try{}语句块 中放的是要检测的java代码,可能有会抛出异常,也可能会正常执行;
- catch(异常类型){}块 是当Java运行时系统接收到try块中所抛出的异常对象时,会寻找能处理这一异常的catch块来进行处理(可以有多个catch块);
- finally{}块 不管系统有没有抛出异常都会去执行,一般用来释放资源。除了在之前执行了System.exit(0);
- throw 用于手动抛出异常。作为程序员可以在任意位置手动抛出异常;
- throws 用于在方法上标识要抛出的异常,抛出的异常交由调用者处理;
19、ArrayList和 vector 、LinkedList的区别?
- (1)Vector是线程安全的,而ArrayList不是。
- (2)当存储空间不足的时候,ArrayList默认增加为原来的50%,Vector默认增加为原来的一倍。
- (3)Vector可以设置容量增加的参数,而ArrayList不可以。
- (4)LinkedList使用双向链表实现存储,按序号 索引 数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。
20、List 和 Map 区别?
- (1)、List是存储单列数据的集合,List中存储的数据是有顺序,并且允许重复;
- (2)、Map是存储键和值这样的双列数据的集合,Map中存储的数据是没有顺序的,其键是不能重复的,它的值是可以有重复的。
21、List、Map、Set三个接口,存取元素时,各有什么特点?
List与Set都是单列元素的集合,它们有一个共同的父接口Collection。
- (1)List表示有先后顺序的集合 存元素:多次调用add(Object)方法时,每次加入的对象按先来后到的顺序排序,也可以插队,即调用add(int index,Object)方法,就可以指定当前对象在集合中的存放位置。 取元素:
方法1:Iterator接口取得所有,逐一遍历各个元素
方法2:调用get(index i)来明确说明取第几个。
- (2)Set里面不允许有重复的元素 存元素:add方法有一个boolean的返回值,当集合中没有某个元素,此时add方法可成功加入该元素时,则返回true;当集合含有与某个元素equals相等的元素时,此时add方法无法加入该元素,返回结果为false。 取元素:没法说取第几个,只能以Iterator接口取得所有的元素,再逐一遍历各个元素。
- (3)Map是双列的集合,存放用put方法:put(obj key,obj value),每次存储时,要存储一对key/value,不能存储重复的key,这个重复的规则也是按equals比较相等。 取元素:用get(Object key)方法根据key获得相应的value。
22、说出一些常用的类,包,接口,请各举例5个
- 常用的类: Object Date File Exception Random String integer
- 常用的包: java.io java.lang java.util java.sql java.net
- 常用的接口: Set List Map Collection Runnable Session Servlet
23、java中有几种类型的流?JDK为每种类型的流提供了一些抽象类以供继承,请说出他们分别是哪些类?
- 基于流方向: InputStream OutputStream
- 基于字符: Reader Writer
- 流和字符之间的配接: InputStreamReader OutputStreamWriter
24、字节流与字符流的区别?
- (1)字节流在操作时本身不会用到缓冲区(内存),是文件本身直接操作的,而字符流在操作时使用了缓冲区,通过缓冲区再操作文件。
- (2)字节流中,中文可能会乱码,字符流不会。
25、什么是java序列化,如何实现java序列化?或者请解释Serializable接口的作用。
序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时所引发的问题。
序列化的实现:将需要被序列化的类实现Serializable接口,然后使用一个输出流(如:FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,接着,使用ObjectOutputStream对象的writeObject(Object obj)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流;
Serializable.只有实现了 serializable和Externalizable接口的类的对象才能被序列化
Java 序列化技术可以使你将一个对象的状态写入一个Byte 流里,并且可以从其它地方把该Byte 流里的数据读出来,重新构造一个相同的对象。这种机制允许你将对象通过网络进行传播,并可以随时把对象持久化到数据库、文件等系统里。Java的序列化机制是RMI、EJB等技术的技术基础。用途:利用对象的序列化实现保存应用程序的当前工作状态,下次再启动的时候将自动地恢复到上次执行的状态。
26、GC是什么? 为什么要有GC?
GC是垃圾收集的意思,内存处理是编程人员容易出现问题的地方,忘记或者错误的内存会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法。Java程序员不用担心内存管理,因为垃圾收集器会自动进行管理。
27、排序都有哪几种方法?请用JAVA实现一个 冒泡排序 。
排序的方法有:
- 插入排序(直接插入排序、希尔排序)
- 交换排序(冒泡排序、快速排序)
- 选择排序(直接选择排序、堆排序)
- 归并排序
- 分配排序(箱排序、基数排序)
- 冒泡排序:
for(int i=;i<arr.length-1;i++){ //外层循环控制排序趟数
for(int j=;j<arr.length-1-i;j++){ //内层循环控制每一趟排序多少次
if(arr[j]>arr[j+]){
int temp=arr[j];
arr[j]=arr[j+];
arr[j+]=temp;
}
}
}
冒泡排序口诀:
- 1. N个数字来排队,两两相比小靠前。
- 2. 外层循环N-1,内层循环N-1-i
- 3. 如果要降序,只要把程序中的大于号换成小于号。
28、说一说Servlet的生命周期?
servlet的生命周期分为以下几个步骤:
- 第一、加载并实例化
- 第二、初始化
- 第三、服务
- 第四、销毁
容器启动的时候,会加载servlet的class,并new出这个对象,然后,当用户请求这个servlet的时候,容器会调用init方法初始化这个servlet,这也是整个生命周期中只会调用一次的方法,然后,会调用service方法,由这个方法调用doGet或doPost方法来响应用户,然后,容器在可用资源紧张或是长期没有对Servlet发出请求的情况下,会销毁这个servlet。
29、servlet api中forward() 与redirect()的区别?
- (1)forward仅是容器中控制权的转向,在客户端浏览器地址栏中不会显示出转向后的地址;
- (2)redirect则是完全的跳转,浏览器将会得到跳转的地址,并重新发送请求链接。这样,从浏览器的地址栏中可以看到跳转后的链接地址。所以,forward更加高效,在forward可以满足需要时,尽量使用forward()方法,并且,这样也有助于隐藏实际的链接。但在某些情况下(比如需要跳转到另一个服务器上的资源),则必须使用sendRedirect()方法。
- (3)forward:转发页面和转发到的页面可以共享 request 里面的数据.
- (4)redirect:不能共享数据
30、request.getAttribute() 和 request.getParameter() 有何区别?
- (1)request.getParameter 是用来接收post、get方法传递过来的参数值
- (2)request.getAttribute 是获取对象容器(session)的值
- (3)request.getParameter()方法返回String类型的数据。
- (4)request.getAttribute()方法返回的是request范围内存在的对象。
31、jsp有哪些常用内置对象?
- <1>、request
- <2>、response
- <3>、session
- <4>、out
- <5>、page
- <6>、application
- <7>、exception
- <8>、pageContext
- <9>、config
32、JSP和Servlet有哪些相同点和不同点,他们之间的联系是什么?
- ①、JSP是Servlet技术的扩展,本质上是Servlet的简易方式,更强调应用的外表表达,JSP编译后是”类servlet”。
- ②、JSP是Java和HTML组合成的一个扩展名为.jsp的文件。JSP侧重于视图,Servlet主要用于控制逻辑。
- ③、Servlet和JSP最主要的不同点在于,Servlet的应用逻辑是在Java文件中,并且完全从表示层中的HTML里分离开来。
33、MVC的各个部分都有哪些技术来实现?
MVC 是 Model-View-Controller 的简写,通过这种设计模型把应用逻辑、处理过程和显示逻辑分成不同的组件实现。
- (1)模型(Model)代表的是应用的业务逻辑( 通过 JavaBean , EJB 组件实现)
- (2)视图(View)是应用的表示面( 由 JSP 页面产生)
- (3)控制器( Controller ) 是提供应用的处理过程控制( 一般是一个 Servlet)
34、数据库三范式是什么?
- 第一范式:确保每一列的原子性 (原子性字段不可再分,否则就不是关系型数据库)
- 第二范式:在第一范式的基础上更进一层,确保表中的每列都和主键相关 (唯一性,一个表只说明一个事物)
- 第三范式:在第二范式的基础上更进一层,确保每列都和主键列直接相关,而不是间接相关 (每列都与主键有直接关系,不存在传递依赖)
35、说出一些数据库优化方面的经验?
- 1.用索引提高效率,避免在索引列上使用计算。
- 2.SELECT子句中避免使用‘ * ‘
- 3.减少访问数据库的次数
- 4.尽量多使用COMMIT
- 5.用Where子句替换HAVING子句
- 6.用EXISTS替代IN、用NOT EXISTS替代NOT IN
- 7.使用表的别名(Alias)
- 8.避免使用耗费资源的操作
- 9.用 PreparedStatement 一般来说比 Statement 性能高
- 10.有外键约束会影响插入和删除性能, 如果程序能够保证数据的完整性, 那在设计数据库时就去掉外键
- 11.要查询的数据多时,使用分页进行查询
- 12.尽量不用ORDER BY RAND()
- 13.利用查询缓存来优化查询
- 14.尽量不使用NOT IN和like语句操作
36、Class.forName的作用是什么?
- Class.forName(xxx.xx.xx) 返回的是一个类,Java里面任何class都要装载在虚拟机上才能运行,这句话就是装载类用的。
- Class.forName(xxx.xx.xx)的作用是要求JVM查找并加载指定的类,也就是说JVM会执行该类的静态代码段,动态加载和创建Class对象,最熟悉的就是JDBC连接数据库的时候加载驱动类。
37、说说数据连接池的工作机制是什么?
J2EE服务器启动时会建立一定数量的池连接,并一直维持不少于此数目的池连接。客户端程序需要连接时,池驱动程序会返回一个未使用的池连接并将其标记为忙。如果当前没有空闲连接,池驱动程序就新建一定数量的连接,新建连接的数量由配置参数决定。当使用的池连接调用完成后,池驱动程序将此连接标记为空闲,其他调用就可以使用这个连接。
38、为什么要用 ORM ? 和JDBC有何不一样?
- 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配现象的技术。简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中。
- ORM是一种思想,就是把object转变成数据库中的记录,或者把数据库中的记录转变成object,我们可以用jdbc来实现这种思想,其实,如果我们的项目是严格按照oop方式编写的话,我们的jdbc程序不管是有意还是无意,就已经在实现ORM的工作了。
- 现在有许多ORM工具,它们底层调用jdbc来实现了ORM工作,我们直接使用这些工具,就省去了直接使用jdbc的繁琐细节,提高了开发效率,现在用的较多的ORM工具是hibernate。
39、xml有哪些解析技术?区别是什么?
xml有以下2种解析技术:
- (1)DOM(Document Object Model)文档对象模型
- (2)SAX(Simple API for XML)
两者的区别:DOM是一次性将整个文档读入内存操作,如果是文档比较小,读入内存,可以极大提高操作的速度,但如果文档比较大,那么DOM就比较吃力了。所以此时SAX应用而生,它不是一次性的将整个文档读入内存,这对于处理大型文档就比较给力了。
40、谈谈你对Struts的理解。
- Struts框架是对MVC模式的封装,为开发者提供了MVC的3个逻辑组成部分,主要由ActionServlet、Action和struts-config.xml配置文件组成控制层,由ActionForm来承担模型层的功能,而struts 的视图层主要由jsp完成;
- 它处理一次请求的流程:由ActionServlet接受一个请求,然后依据配置文件来判断由哪个Action来处理和由哪个ActionForm来保存数据,再通过Action的返回值来判断应该由哪个jsp来展示数据。
41、Struts优缺点
优点:
- (1) 实现了MVC模式,层次结构清晰,使程序员只需关注业务逻辑的实现。
- (2) 丰富的标签库,大大提高了开发的效率。
- (3) Struts2提供丰富的拦截器实现。
- (4) 通过配置文件,就可以掌握整个系统各个部分之间的关系。
- (5) 异常处理机制,只需在配置文件中配置异常的映射,即可对异常做相应的处理。
- (6) Struts2的可扩展性高。Struts2的核心jar包中由一个struts-default.xml文件,在该文件中设置了一些默认的bean,resultType类型,默认拦截器栈等,所有这些默认设置,用户都可以利用配置文件更改,可以更改为自己开发的bean,resulttype等。因此用户开发了插件的话只要很简单的配置就可以很容易的和Struts2框架融合,这实现了框架对插件的可插拔的特性。
- (7) 面向切面编程的思想在Strut2中也有了很好的体现,最重要的体现就是拦截器的使用。拦截器就是一个一个的小功能单位,用户可以将这些拦截器合并成一个大的拦截器,这个合成的拦截器就像单独的拦截器一样,只要将它配置到一个、Action中就可以
缺点:
- (1) Struts2中Action中取得从jsp中传过来的参数时还是有点麻烦。可以为Struts2的Action中的属性配置上Getter和Setter方法,通过默认拦截器,就可以将请求参数设置到这些属性中。如果用这种方式,当请求参数很多时,Action类就会被这些表单属性弄的很臃肿,让人感觉会很乱。还有Action中的属性不但可以用来获得请求参数还可以输出到Jsp中,这样就会更乱。假设从JSP1中获得了参数money=100000,但是这个Action还要输出到JSP2中,但是输出的格式却不同,money=100,000,这样这个Action中的money中的值就变了。
- (2) 校验还是感觉比较繁琐,太烦乱,也太细化了,如果校验出错的只能给用户提示一些信息。如果有多个字段,每个字段出错时返回到不同的画面,这个功能在Strut2框架下借助框架提供的校验逻辑就不容易实现。
- (3) 安全性有待提高。Struts2曝出2个高危安全漏洞,一个是使用缩写的导航参数前缀时的远程代码执行漏洞,另一个是使用缩写的重定向参数前缀时的开放式重定向漏洞。这些漏洞可使黑客取得网站服务器的“最高权限”,从而使企业服务器变成黑客手中的“肉鸡”
42、谈谈你对 Spring 的理解。
首先Spring是一个开源的框架,Spring为简化企业级应用开发而生,使用Spring可以使简单的JavaBean实现以前只有EJB才能实现的功能。Spring是一个IOC和AOP容器框架。
在java开发领域,Spring相对于EJB来说是一种轻量级的,非侵入性的Java开发框架。
Spring主要核心是:
- (1).控制反转(IOC):以前传统的java开发模式中,当需要一个对象时我们,我们会自己使用new或者getInstance等直接或者间接调用构造方法创建一个对象,而在Spring开发模式中,Spring容器使用了工厂模式为我们创建了所需要的对象,我们使用时不需要自己去创建,直接调用Spring为我们提供的对象即可,这就是控制反转的思想。实例化一个java对象有三种方式:使用类构造器,使用静态工厂方法,使用实例工厂方法,当使用spring时我们就不需要关心通过何种方式实例化一个对象,spring通过控制反转机制自动为我们实例化一个对象。
- (2).依赖注入(DI):Spring使用java Bean对象的Set方法或者带参数的构造方法为我们在创建所需对象时将其属性自动设置所需要的值的过程就是依赖注入的基本思想。
- (3).面向切面编程(AOP):在面向对象编程(OOP)思想中,我们将事物纵向抽象成一个个的对象。而在面向切面编程中,我们将一个个对象某些类似的方面横向抽象成一个切面,对这个切面进行一些如权限验证,事物管理,记录日志等公用操作处理的过程就是面向切面编程的思想。
43、AOP的作用是什么?
AOP(面向切面编程)是一种编程范式,用于提供从另一角度来考虑程序结构以完善面向对象编程。
主要作用:
- 1.降低模块之间的耦合度。
- 2.使系统容易扩展。
- 3.更好的代码复用
44、谈谈你对Hibernate的理解。
Hibernate是一个开放源代码的对象关系映射(ORM)框架,它对JDBC进行了非常轻量级的对象封装,使得java程序员可以随心所欲的使用对象编程思维来操纵数据库。
Hibernate的优点:
- 1. 对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。
- 2. Hibernate是一个基于JDBC的主流持久化框架,是一个优秀的ORM实现。他很大程度的简化DAO层的编码工作
- 3、 Hibernate使用Java反射机制而不是字节码增强程序来实现透明性。
- 4、 Hibernate的性能好,映射的灵活性比较出色。它支持各种关系数据库,从一对一到多对多的各种复杂关系。
hibernate的核心类:
Configuration、SessionFactory 、Session
45、hibernate中的update()和saveOrUpdate()的区别
- update() 如果是对一个已经存在的托管对象进行更新那么肯定是要使用update()方法了,数据中有这个对象。
- saveOrUpdate() 这个方法是更新或者插入,有主键就执行更新,如果没有主键就执行插入。
46、简述 Hibernate 和 JDBC 的优缺点?
- (1)JDBC与Hibernate在性能上相比,JDBC灵活性有优势。
- (2)而Hibernate在易学性,易用性上有优势。
- (3)当用到很多复杂的多表联查和复杂的数据库操作时,JDBC有优势。
47、Hibernate中,如何书写一个 one to many 配置文件?
one to many 配置文件的方法:
在一方添加集合对象,并封装。然后在对应的映射文件追加标签,设置外检,以及通过one-to-many标签设置集合对象所对应的类型即可。
48、MyBatis与Hibernate有什么不同?
Mybatis优势:
- (1)MyBatis可以进行更为细致的SQL优化,可以减少查询字段。
- (2)MyBatis容易掌握,而Hibernate门槛较高。
Hibernate优势:
- <1>、Hibernate的DAO层开发比MyBatis简单,Mybatis需要维护SQL和结果映射。
- <2>、Hibernate对对象的维护和缓存要比MyBatis好,对增删改查的对象的维护要方便。
- <3>、Hibernate数据库移植性很好,MyBatis的数据库移植性不好,不同的数据库需要写不同SQL。
- <4>、Hibernate有更好的二级缓存机制,可以使用第三方缓存。MyBatis本身提供的缓存机制不佳。
49、hibernate的inverse属性有什么作用?
- 用来指定关联的控制方的,inverse属性默认是false:
- 若为false,则关联由自己控制
- 若为true,则关联由对方控制
50、介绍一下Hibernate的二级缓存
内置缓存:Hibernate自带的,不可卸载,通常在Hibernate的初始化阶段,Hibernate会把映射元数据和预定义的SQL语句放置到SessionFactory的缓存中。该内置缓存是只读的。
外置缓存:通常说的二级缓存也就是外置缓存,在默认情况下SessionFactory不会启用这个缓存插件,外置缓存中的数据是数据库数据的复制,外置缓存的物理介质可以是内存或者硬盘。
适合放入二级缓存中数据:
- 很少被修改
- 不是很重要的数据,允许出现偶尔的并发问题
- 不适合放入二级缓存中的数据
- 经常被修改
- 财务数据,绝对不允许出现并发问题
- 与其他应用数据共享的数据
51、session中load()和get()的区别
- (1)load方法支持延迟加载,而get方法则不支持。
- (2)load方法在没找到数据的时候会抛出ObjectNotFoundException,而get方法则会返回null。
52、B/S与C/S的联系与区别
(1)c/s(client/ server )客户端/服务器
概念:指的是客户端和服务端之间的通信方式,客户端提供用户请求接口,服务端响应请求进行对应的处理,并返回给客户端,客户端来显示这些内容
协议:任何通用协议
优势:降低系统开销,充分利用两端硬件环境的优势
缺点:维护成本高
(2)B/S(browser/server) 浏览器/服务器
概念:这种结构用户界面是完全通过www浏览器来实现,一部分事务在前端实现,主要事务逻辑在服务器端实现
协议:http协议
优势:节约开发成本
两者区别:
硬件环境不同:
- c/s:专用网络、小型局域网
- b/s:广域网,只有要操作系统和浏览器就行
对安全要求不同:
- c/s:一般面向固定用户群,安全性高
- b/s:用b/s发布部分可公开信息
对程序架构不同:
- c/s:注重流程,对权限多次校验,少考虑系统运行速度
- b/s:对安全和访问速度多重考虑
软件重用不同:
- c/s:需要整体考虑,构建重用性没有b/s好
- b/s:构件独立,重用性好
系统维护不同:
- c/s:要从整体考察,维护困难
- b/s:构件个别替换,维护升级简单
处理问题不同:
- c/s:用户面固定,安全性高,操作系统相同
- b/s:用户不固定,与操作平台关系小
用户接口不同:
- c/s:Windows平台上,表现方法有限
- b/s:浏览器,表现方式生动,难度减低,减低开发成本
信息流不同:
- c/s:中央集权机械式管理,交互低
- b/s:信息流可变化,更像交易中心
53、Spring MVC Framework有那些特点?
- 1.它是基于组件技术的,全部的应用对象,无论控制器和视图,还是业务对象之类的都是java组件,并且和Spring提供的其他基础结构紧密集成。
- 2.不依赖于Servlet API(目标虽是如此,但是在实现的时候确实是依赖于Servlet的)
- 3.可以任意使用各种视图技术,而不仅仅局限于JSP
- 4.支持各种请求资源的映射策略
- 5.它应是易于扩展的
54、 springmvc 的工作流程?
- 1. 用户发送请求至前端控制器DispatcherServlet
- 2. DispatcherServlet收到请求调用HandlerMapping处理器映射器。
- 3. 处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
- 4. DispatcherServlet通过HandlerAdapter处理器适配器调用处理器
- 5. 执行处理器(Controller,也叫后端控制器)。
- 6. Controller执行完成返回ModelAndView
- 7. HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet
- 8. DispatcherServlet将ModelAndView传给ViewReslover视图解析器
- 9. ViewReslover解析后返回具体View
- 10.DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)
- 11.DispatcherServlet响应用户
55、简单介绍下springMVC和struts2的区别有哪些?
- 1. springmvc的入口是一个servlet即前端控制器,而struts2入口是一个filter过虑器。
- 2. springmvc是基于方法开发(一个url对应一个方法),请求参数传递到方法的形参,可以设计为单例或多例(建议单例),struts2是基于类开发,传递参数是通过类的属性,只能设计为多例。
- 3. Struts采用值栈存储请求和响应的数据,通过OGNL存取数据,springmvc通过参数解析器是将request请求内容解析,并给方法形参赋值,将数据和视图封装成ModelAndView对象,最后又将ModelAndView中的模型数据通过reques域传输到页面。Jsp视图解析器默认使用jstl。
56、请介绍线程的五种状态
- 第一、创建状态。在生成线程对象,并没有调用该对象的start方法,这是线程处于创建状态手写字符串反转和冒泡排序;
- 第二、就绪状态。当调用了线程对象的start方法之后,该线程就进入了就绪状态,但是此时线程调度程序还没有把该线程设置为当前线程,此时处于就绪状态。在线程运行之后,从等待或者睡眠中回来之后,也会处于就绪状态。
- 第三、运行状态。线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就进入了运行状态,开始运行run函数当中的代码。
- 第四、阻塞状态。线程正在运行的时候,被暂停,通常是为了等待某个时间的发生(比如说某项资源就绪)之后再继续运行。sleep,suspend,wait等方法都可以导致线程阻塞。
- 第五、死亡状态。如果一个线程的run方法执行结束或者调用stop方法后,该线程就会死亡。对于已经死亡的线程,无法再使用start方法令其进入就绪
57、post提交方式和get提交方式的区别
Get 方法通过 URL 请求来传递用户的数据,将表单内各字段名称与其内容,以成对的字符串连接,以URL字串本身传递数据参数,在服务器端可以从’QUERY_STRING’这个变量中直接读取,效率较高,但缺乏安全性,也无法来处理复杂的数据(只能是字符串,比如在servlet/jsp中就无法处理发挥java的比如vector之类的功能,输的数据量非常小,一般限制在 2 KB 左右);
Post 方法通过 HTTP post 机制,将表单内各字段名称与其内容放置在 HTML 表头(header)内一起传送给服务器端交由 action 属性能所指的程序处理,该程序会通过标准输入(stdin)方式,将表单的数据读出并加以处理post方式:就传输方式讲参数会被打包在数据报中传输,从CONTENT_LENGTH这个环境变量中读取,便于传送较大一些的数据,同时因为不暴露数据在浏览器的地址栏中,安全性相对较高,但这样的处理效率会受到影响。
建议:除非你肯定你提交的数据可以一次性提交,否则请尽量用 Post方法;Get方式提交数据,会带来安全问题;通过 Get 方式提交数据时,用户名和密码将出现在 URL 上;所以表单提交建议使用Post。
58、什么是数据库脏读,不可重复读,幻觉读
脏读又称无效数据读出。一个事务读取另外一个事务还没有提交的数据叫脏读。
例如:事务T1修改了一行数据,但是还没有提交,这时候事务T2读取了被事务T1修改后的数据,之后事务T1因为某种原因Rollback了,那么事务T2读取的数据就是脏的不可重复读是指在同一个事务内,两个相同的查询返回了不同的结果。
例如:事务T1读取某一数据,事务T2读取并修改了该数据,T1为了对读取值进行检验而再次读取该数据,便得到了不同的结果。
幻觉读是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行,同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。例如:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。
59、请介绍spring的事务隔离级别
- (1)Default默认的事务隔离级别
- (2)READ_UNCOMMITTED(read_uncommitted)读未提交,一个事务可以操作另外一个未提交的事务,不能避免脏读,不可重复读,幻觉读,隔离级别最低,并发性能最高
- (3)READ_COMMITTED(read_committed)读已提交,一个事务不可以操作另外一个未提交的事务, 能防止脏读,不能避免不可重复读,幻觉读。
- (4)REPEATABLE_READ(repeatable_read)能够避免脏读,不可重复读,不能避免幻读
- (5)SERIALIZABLE(serializable)隔离级别最高,消耗资源最低,代价最高,能够防止脏读, 不可重复读,幻觉读
60、默写选择排序
public static void selectSort(int[] a) {
int minIndex = ;
int temp = ;
if ((a == null) || (a.length == ))
return;
for (int i = ; i < a.length - 1; i++) {
minIndex = i; // 无序区的最小数据数组下标
for (int j = i + ; j < a.length; j++) {
// 在无序区中找到最小数据并保存其数组下标
if (a[j] < a[minIndex]) {
minIndex = j;
}
}
// 将最小元素放到本次循环的前端
temp = a[i];
a[i] = a[minIndex];
a[minIndex] = temp;
}
}
61、session和cooie的区别
具体来说cookie机制采用的是在客户端保持状态的方案,而session 机制采用的是在服务器端保持状态的方案。由于服务器端保持状态的方案在客户端也需要保存一个标识,所以session机制需要借助于cookie机制来达到保存标识的目的 。
62、什么是Spring IOC 容器?
Spring IOC 负责创建对象,管理对象(通过依赖注入(DI),装配对象,配置对象,并且管理这些对象的整个生命周期。
63、spring有哪些不同类型的IOC(依赖注入)方式?
构造器依赖注入:构造器依赖注入通过容器触发一个类的构造器来实现的,该类有一系列参数,每个参数代表一个对其他类的依赖。
Setter方法注入:Setter方法注入是容器通过调用无参构造器或无参static工厂 方法实例化bean之后,调用该bean的setter方法,即实现了基于setter的依赖注入
64、 Spring支持哪几种bean的作用域?
- singleton :bean在每个Spring ioc 容器中只有一个实例。
- prototype:一个bean的定义可以有多个实例。
- request:每次http请求都会创建一个bean,该作用域仅在基于web的Spring ApplicationContext情形下有效。
- session:在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。
- global-session:在一个全局的HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。
65、j2ee常用的设计模式有哪些,简单说一下工厂模式
Java中的23种设计模式:
Factory(工厂模式), Builder(建造模式), Factory Method(工厂方法模式),Prototype(原始模型模式),Singleton(单例模式), Facade(门面模式),Adapter(适配器模式), Bridge(桥梁模式), Composite(合成模式),Decorator(装饰模式), Flyweight(享元模式), Proxy(代理模式),Command(命令模式), Interpreter(解释器模式), Visitor(访问者模式),Iterator(迭代子模式), Mediator(调停者模式), Memento(备忘录模式),Observer(观察者模式), State(状态模式), Strategy(策略模式),Template Method(模板方法模式), Chain Of Responsibleity(责任链模式)
工厂模式:工厂模式是一种经常被使用到的模式,根据工厂模式实现的类可以根据提供的数据生成一组类中某一个类的实例,通常这一组类有一个公共的抽象父类并且实现了相同的方法,但是这些方法针对不同的数据进行了不同的操作。首先需要定义一个基类,该类的子类通过不同的方法实现了基类中的方法。然后需要定义一个工厂类,工厂类可以根据条件生成不同的子类实例。当得到子类的实例后,开发人员可以调用基类中的方法而不必考虑到底返回的是哪一个子类的实例
66、谈谈你对数据库事务的理解?
在数据库中,所谓事务是指一组逻辑操作单元即一组sql语句。当这个单元中的一部分操作失败,整个事务回滚,只有全部正确才完成提交。判断事务是否配置成功的关键点在于出现异常时事务是否会回滚,在JDBC中,事务默认是自动提交的,每次执行一个SQL语句时,如果执行成功,就会向数据库自动提交,而不能回滚。
事务的特征(ACID属性):
- 1.原子性(Atomicity) 原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
- 2.一致性(Consistency) 事务必须使数据库从一个一致性状态变换到另外一个一致性状态。(数据不被破坏)
- 3.隔离性(Isolation) 事务的隔离性是指一个事务的执行不能被其他事务干扰.
- 4.持久性(Durability) 持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的.即使系统重启也不会丢失.
67、谈谈你对数据库索引的理解
1、索引的概念
索引就是为了提高数据的检索速度。数据库的索引类似于书籍的索引。在书籍中,索引允许用户不必翻阅完整个书就能迅速地找到所需要的信息。在数据库中,索引也允许数据库程序迅速地找到表中的数据,而不必扫描整个数据库.
2、索引的优点
b.大大加快数据的检索速度,这也是创建索引的最主要的原因
c.减少磁盘IO(向字典一样可以直接定位)
3、索引的缺点
a.创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加
b.索引需要占用额外的物理空间
c.当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,降低了数据的维护速度
68、jdbc操作数据库的步骤
①、加载数据库驱动程序 Class.forName(“数据库驱动类”);
②、连接数据库 Connection con = DriverManager.getConnection();
③、操作数据库 PreparedStatement stat = con.prepareStatement(sql);stat.executeQuery();
④、关闭数据库,释放连接 con.close();
69、介绍下乐观锁,悲观锁
- 乐观锁(Optimistic Lock), 每次去查询数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号,时间戳等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量
- 悲观锁(Pessimistic Lock), 每次去查询数据的时候都认为别人会修改,所以每次在查询数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁。传统的关系型数据库里边就用到了这种锁机制,比如通过select ….for update进行数据锁定。
70、你对ajax是怎么理解的
- AJAX全称为“Asynchronous JavaScript and XML”(异步JavaScript和XML),是一种创建交互式网页应用的网页开发技术。
- 使用ajax可以提高用户的体验度,进行异步数据传输从而提高性能。ajax不能跨域,所谓不能跨域就是不能跨多个网站(多个域名),或者多个项目。
- 可以通过jsonp来解决ajax跨域的问题,而jsonp的实质就是通过动态添加script标签来实现的。
71、你对负载均衡这块有认识吗?
负载均衡(Load Balance)是分布式系统架构设计中必须考虑的因素之一,它通常是指,将请求数据均匀分摊到多个操作单元上执行,负载均衡的关键在于“均匀”。常见互联网分布式架构上,分为客户端层、反向代理nginx层、站点层、服务层、数据层。
负载均衡有两方面的含义:
- 1、大量的并发访问或数据流量分担到多台节点设备上分别处理,减少用户等待响应的时间;
- 2、单个重负载的运算分担到多台节点设备上做并行处理,每个节点设备处理结束后,将结果汇总,返回给用户,系统处理能力得到大幅度提高。
72、请说说你熟悉的Linux指令
ls 列出目录下的文件
cd 到某个目录里
cp 复制
mv 移动
rm 删除
pwd 查看当前位置
tar 解压tar.gz文件
mkdir 创建文件夹
touch 创建文件
vi 编辑(vim)
cat 查看
chmod 设置文件权限
73、简单介绍项目的生命周期
- 1.需求分析
- 2.概要设计
- 3.详细设计(用例图,流程图,类图)
- 4.数据库设计(powerdesigner)
- 5.代码开发(编写)
- 6.单元测试(junit 白盒测试)(开发人员) svn版本管理工具(提交,更新代码,文档)
- 7.集成测试 (黑盒测试,loadrunner(编写测试脚本)(高级测试))
- 8.上线试运行 (用户自己检查)
- 9.压力测试(loadrunner)
- 10.正式上线
- 11.维护
74、说说你理解中的线程死锁
死锁是因为多线程访问共享资源,由于访问的顺序不当所造成的,通常是一个线程锁定了一个资源A,而又想去锁定资源B;在另一个线程中,锁定了资源B,而又想去锁定资源A以完成自身的操作,两个线程都想得到对方的资源,而不愿释放自己的资源,造成两个线程都在等待,而无法执行的情况。
死锁产生的原因:是由访问共享资源顺序不当所造成的
简单的说:所谓死锁,是指两个或两个以上的线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。
75、 介绍下守护线程
在Java中有两类线程:User Thread(用户线程)、Daemon Thread(守护线程)
- (1)用个比较通俗的说法,任何一个守护线程都是整个JVM中所有非守护线程的保姆:只要当前JVM实例中尚存在任何一个非守护线程没有结束,守护线程就全部工作;只有当最后一个非守护线程结束时,守护线程才随着JVM一同结束工作。
- (2)守护线程最典型的应用就是 GC (垃圾回收器),它就是一个很称职的守护者。
- (3)守护线程与普通线程的唯一区别是:当JVM中所有的线程都是守护线程的时候,JVM就可以退出了;如果还有一个或以上的非守护线程则不会退出。(以上是针对正常退出,调用System.exit则必定会退出)
文章所有内容均收集于网络,如有错误或其它问题,欢迎小伙伴留言评论、指正。如有帮助,欢迎转发分享,如需更多资料可以点进我主页,私信我回复【资料】二字。
以下是Java面试要点集合汇总:
反模式设计
简单的来说,反模式是指在对经常面对的问题经常使用的低效,不良,或者有待优化的设计模式/方法。甚至,反模式也可以是一种错误的开发思想/理念。在这里我举一个最简单的例子:在面向对象设计/编程中,有一条很重要的原则, 单一责任原则(Single responsibility principle)。其中心思想就是对于一个模块,或者一个类来说,这个模块或者这个类应该只对系统/软件的一个功能负责,而且该责任应该被该类完全封装起来。当开发人员需要修改系统的某个功能,这个模块/类是最主要的修改地方。相对应的一个反模式就是上帝类(God Class),通常来说,这个类里面控制了很多其他的类,同时也依赖其他很多类。整个类不光负责自己的主要单一功能,而且还负责了其他很多功能,包括一些辅助功能。很多维护老程序的开发人员们可能都遇过这种类,一个类里有几千行的代码,有很多功能,但是责任不明确单一。单元测试程序也变复杂无比。维护/修改这个类的时间要远远超出其他类的时间。很多时候,形成这种情况并不是开发人员故意的。很多情况下主要是由于随着系统的年限,需求的变化,项目的资源压力,项目组人员流动,系统结构的变化而导致某些原先小型的,符合单一原则类慢慢的变的臃肿起来。最后当这个类变成了维护的噩梦(特别是原先熟悉的开发人员离职后),重构该类就变成了一个不容易的工程。
分库与分表设计
垂直分表在日常开发和设计中比较常见,通俗的说法叫做“大表拆小表”,拆分是基于关系型数据库中的“列”(字段)进行的。通常情况,某个表中的字段比较多,可以新建立一张“扩展表”,将不经常使用或者长度较大的字段拆分出去放到“扩展表”中。在字段很多的情况下,拆分开确实更便于开发和维护(笔者曾见过某个遗留系统中,一个大表中包含100多列的)。某种意义上也能避免“跨页”的问题( MySQL 、MSSQL底层都是通过“数据页”来存储的,“跨页”问题可能会造成额外的性能开销,拆分字段的操作建议在数据库设计阶段就做好。如果是在发展过程中拆分,则需要改写以前的查询语句,会额外带来一定的成本和风险,建议谨慎。
垂直分库在“微服务”盛行的今天已经非常普及了。基本的思路就是按照业务模块来划分出不同的数据库,而不是像早期一样将所有的数据表都放到同一个数据库中。系统层面的“服务化”拆分操作,能够解决业务系统层面的耦合和性能瓶颈,有利于系统的扩展维护。而数据库层面的拆分,道理也是相通的。与服务的“治理”和“降级”机制类似,我们也能对不同业务类型的数据进行“分级”管理、维护、监控、扩展等。
众所周知,数据库往往最容易成为应用系统的瓶颈,而数据库本身属于“有状态”的,相对于Web和应用服务器来讲,是比较难实现“横向扩展”的。数据库的连接资源比较宝贵且单机处理能力也有限,在高并发场景下,垂直分库一定程度上能够突破IO、连接数及单机硬件资源的瓶颈,是大型分布式系统中优化数据库架构的重要手段。
然后,很多人并没有从根本上搞清楚为什么要拆分,也没有掌握拆分的原则和技巧,只是一味的模仿大厂的做法。导致拆分后遇到很多问题(例如:跨库join,分布式事务等)。
水平分表也称为横向分表,比较容易理解,就是将表中不同的数据行按照一定规律分布到不同的数据库表中(这些表保存在同一个数据库中),这样来降低单表数据量,优化查询性能。最常见的方式就是通过主键或者时间等字段进行Hash和取模后拆分。水平分表,能够降低单表的数据量,一定程度上可以缓解查询性能瓶颈。但本质上这些表还保存在同一个库中,所以库级别还是会有IO瓶颈。所以,一般不建议采用这种做法。
水平分库分表与上面讲到的水平分表的思想相同,唯一不同的就是将这些拆分出来的表保存在不同的数据中。这也是很多大型互联网公司所选择的做法。某种意义上来讲,有些系统中使用的“冷热数据分离”(将一些使用较少的历史数据迁移到其他的数据库中。而在业务功能上,通常默认只提供热点数据的查询),也是类似的实践。在高并发和海量数据的场景下,分库分表能够有效缓解单机和单库的性能瓶颈和压力,突破IO、连接数、硬件资源的瓶颈。当然,投入的硬件成本也会更高。同时,这也会带来一些复杂的技术问题和挑战(例如:跨分片的复杂查询,跨分片事务等)。
分布式困境与应对之策
- 数据迁移与扩容问题 前面介绍到水平分表策略归纳总结为随机分表和连续分表两种情况。连续分表有可能存在数据热点的问题,有些表可能会被频繁地查询从而造成较大压力,热数据的表就成为了整个库的瓶颈,而有些表可能存的是历史数据,很少需要被查询到。连续分表的另外一个好处在于比较容易,不需要考虑迁移旧的数据,只需要添加分表就可以自动扩容。随机分表的数据相对比较均匀,不容易出现热点和并发访问的瓶颈。但是,分表扩展需要迁移旧的数据。 如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析、双十一实战或者是面试难题的朋友可以加582505643里面的群主感觉蠢萌蠢萌的可以到她那骗资料,都是干货。 针对于水平分表的设计至关重要,需要评估中短期内业务的增长速度,对当前的数据量进行容量规划,综合成本因素,推算出大概需要多少分片。对于数据迁移的问题,一般做法是通过程序先读出数据,然后按照指定的分表策略再将数据写入到各个分表中。
- 表关联问题 在单库单表的情况下,联合查询是非常容易的。但是,随着分库与分表的演变,联合查询就遇到跨库关联和跨表关系问题。在设计之初就应该尽量避免联合查询,可以通过程序中进行拼装,或者通过反范式化设计进行规避。
- 分页与排序问题 一般情况下,列表分页时需要按照指定字段进行排序。在单库单表的情况下,分页和排序也是非常容易的。但是,随着分库与分表的演变,也会遇到跨库排序和跨表排序问题。为了最终结果的准确性,需要在不同的分表中将数据进行排序并返回,并将不同分表返回的结果集进行汇总和再次排序,最后再返回给用户。
- 分布式事务问题 随着分库与分表的演变,一定会遇到分布式事务问题,那么如何保证数据的一致性就成为一个必须面对的问题。目前,分布式事务并没有很好的解决方案,难以满足数据强一致性,一般情况下,使存储数据尽可能达到用户一致,保证系统经过一段较短的时间的自我恢复和修正,数据最终达到一致。
- 分布式全局唯一ID 在单库单表的情况下,直接使用数据库自增特性来生成主键ID,这样确实比较简单。在分库分表的环境中,数据分布在不同的分表上,不能再借助数据库自增长特性。需要使用全局唯一 ID,例如 UUID、GUID等。
MySQL 遇到的死锁问题
产生死锁的四个必要条件:
(1) 互斥条件:一个资源每次只能被一个进程使用。
(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。下列方法有助于最大限度地降低死锁:
(1)按同一顺序访问对象。
(2)避免事务中的用户交互。
(3)保持事务简短并在一个批处理中。
(4)使用低隔离级别。
(5)使用绑定连接。
数据库索引的原理
数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据。索引的实现通常使用B树及其变种B+树。
聚集索引与非聚集索引的区别
- 1).聚集索引一个表只能有一个,而非聚集索引一个表可以存在多个
- 2).聚集索引存储记录是物理上连续存在,而非聚集索引是逻辑上的连续,物理存储并不连续
- 3).聚集索引:物理存储按照索引排序;聚集索引是一种索引组织形式,索引的键值逻辑顺序决定了表数据行的物理存储顺序 非聚集索引:物理存储不按照索引排序;非聚集索引则就是普通索引了,仅仅只是对数据列创建相应的索引,不影响整个表的物理存储顺序.
- 4).索引是通过二叉树的数据结构来描述的,我们可以这么理解聚簇索引:索引的叶节点就是数据节点。而非聚簇索引的叶节点仍然是索引节点,只不过有一个指针指向对应的数据块。
Redis 持久化机制和如何实现
redis有两种持久化机制RDB与AOF。
- RDB持久化方式会在一个特定的间隔保存那个时间点的一个数据快照。
- AOF持久化方式则会记录每一个服务器收到的写操作。在服务启动时,这些记录的操作会逐条执行从而重建出原来的数据。写操作命令记录的格式跟Redis协议一致,以追加的方式进行保存。
- Redis的持久化是可以禁用的,就是说你可以让数据的生命周期只存在于服务器的运行时间里。
两种方式的持久化是可以同时存在的,但是当Redis重启时,AOF文件会被优先用于重建数据。
缓存降级
- 页面降级:在大促或者某些特殊情况下,某些页面占用了一些稀缺服务资源,在紧急情况下可以对其整个降级,以达到丢卒保帅;
- 页面片段降级:比如商品详情页中的商家部分因为数据错误了,此时需要对其进行降级;
- 页面异步请求降级:比如商品详情页上有推荐信息/配送至等异步加载的请求,如果这些信息响应慢或者后端服务有问题,可以进行降级;
- 服务功能降级:比如渲染商品详情页时需要调用一些不太重要的服务:相关分类、热销榜等,而这些服务在异常情况下直接不获取,即降级即可;
- 读降级:比如多级缓存模式,如果后端服务有问题,可以降级为只读缓存,这种方式适用于对读一致性要求不高的场景;如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析、双十一实战或者是面试难题的朋友可以加582505643里面的群主感觉蠢萌蠢萌的可以到她那骗资料,都是干货。
- 写降级:比如秒杀抢购,我们可以只进行Cache的更新,然后异步同步扣减库存到DB,保证最终一致性即可,此时可以将DB降级为Cache。
- 爬虫降级:在大促活动时,可以将爬虫流量导向静态页或者返回空数据,从而保护后端稀缺资源。
- 自动开关降级 自动降级是根据系统负载、资源使用情况、SLA等指标进行降级。
- 超时降级 当访问的数据库/http服务/远程调用响应慢或者长时间响应慢,且该服务不是核心服务的话可以在超时后自动降级;比如商品详情页上有推荐内容/评价,但是推荐内容/评价暂时不展示对用户购物流程不会产生很大的影响;对于这种服务是可以超时降级的。如果是调用别人的远程服务,和对方定义一个服务响应最大时间,如果超时了则自动降级。
Java Web学习路径
Java编程所需的工具及知识
JVM的基本结构
SSH框架
设计模式之间的关系