Java面试题总结

Java基础面试:




面向对象的特征有哪些方面?


抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。


继承:继承是从已有类得到继承信息创建新类的过程。提供继承信息的类被称为父类;得到继承信息的类被称为子类。继承让变化中的软件系统有了一定的延续性,
同时继承也是封装程序中可变因素的重要手段。


封装:通常认为封装是把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口。面向对象的本质就是将现实世界描绘成一系列完全自治、封闭的对象。
我们在类中编写的方法就是对实现细节的一种封装;我们编写一个类就是对数据和数据操作的封装。可以说,封装就是隐藏一切可隐藏的东西,只向外界提供最简单的编程接口。


多态性:多态性是指允许不同子类型的对象对同一消息作出不同的响应。简单的说就是用同样的对象引用调用同样的方法但是做了不同的事情。多态性分为编译时的多态性
和运行时的多态性。方法重载实现的是编译时的多态性,而方法重写实现的是运行时的多态性。




内部类和外部类的区别:
1、内部类中的变量和方法不能声明为静态的
2、内部类实例化:B是A的内部类,实例化B: A.b b=new A().new B()
3、内部类可以引用外部类的静态或者非静态属性及方法
静态内部类:
1、静态内部类属性和方法可以声明为静态的或者非静态的
2、实例化静态内部类:B是A的静态内部类, A.b b=new A.B();
3、静态内部类只能引用外部类的静态的属性及方法

inner classes  --内部类
static nested classes  ---静态嵌套类
内部类依靠外部类的存在为前提,而 静态嵌套类则完全可以独立

非静态内部类中的变量和方法不能声明为静态的原因

静态类型的属性和方法,在类加载的时候就会存在内存中,使用某个类的静态属性和方法,那么这个类必须
加载到虚拟机中,但是非静态内部类并不是随外部类一起加载,只有在实例化外部类之后才会加载


我们设想一个场景:在外部类并没有实例化,内部类还没有加载的时候如果调用内部类的静态成员或方法,
内部类还没有加载,却试图在内存中创建该内部类的静态成员,就会产生冲突。所以非静态内部类不能有静态成员变量或静态方法。



String,StringBuffer,StringBuilder
String  字符串常量
StringBuffer   字符串变量(线程安全)
StringBuilder  字符串变量(非线程安全)

性能上  StringBuilder > StringBuffer > String 

String是不可变的对象,每次对String类型进行改变的时候等同于生成了一个新的String对象,
然后将指针指向新的String对象,所以性能最差,对于要经常改变的内容的字符串不用String
StringBuffer 是字符串变量,对它操作时,并不会生成新的对象,而是直接对该对象进行更改,所以性能好
StringBuilder 和String Buffer一样,是字符串变量,但是他不带有synchronized关键字,不保证线程安全,所以性能最好,单线程的情况下,建议StringBuilder
 
集合和数组之间的相互转换
String array[] ={"hello","world","java","zhiyin"};
List<String> list=new ArrayList<String>(Arrays.asList(array));
 
 
List<String> list=Arrays.asList(array);//这种方法不是很好,此时组合的是一个静态的内部类并未实现add、remove方法,因此在使用时存在问题
 
集合变数组:
String[] array=list.toArray(new String[list.size]);
面向对象的特征有哪些方面?
抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两个方面。抽象只关注对象
有哪些属性和行为,并不关注这些行为的细节是什么

继承:继承是从已有类得到继承信息创建新类的过程,提供继承信息的类被称为父类;得到继承信息的类被称为子类
;继承让变化中的软件系统有一定的延续性,同时继承也是封装程序中可变因素的重要手段

封装:通常认为封装是把数据和操作数据的方法绑起来,对数据的访问,只能通过已定义的接口。面向对象的本质就是将现实世界描绘成一系列完全自治、封闭的对象
我们在类中编写的方法就是对实现细节的一种封装;我们编写一个类就是对数据和数据操作的封装。可以说封装就是封装一切可以隐藏的东西,只向外界提供最简单的编程接口

多态:多态性是允许不同子类型的对象对同一消息作出不同的响应。简单的说就是用同样的对象引用调用同样的方法但是做了不同的事情。
多态性分为编译时的多态性和运行时的多态性。方法重载实现是编译时的多态性,而方法重写实现的是运行时的多态性



Java的自定义注解:
关键字:  @interface
package com.journaldev.annotations;
 
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
@Documented
@Target(ElementType.METHOD)
@Inherited
@Retention(RetentionPolicy.RUNTIME)
    public @interface MethodInfo{
    String author() default 'Pankaj';
    String date();
    int revision() default 1;
    String comments();
}


注解的方法不能带有参数
注解的方法返回值类型限定为:基本类型、String、Enums、Annotation或者是这些类型的数组
注解的方法可以有默认值
注解本身能够包含元注解,元注解被用来注解其他注解






四种类型元注解:
@Documented---- 指明拥有这个注解的元素可以被javadoc此类的工具文档化
@Target--指明该类型的注解可以注解的程序元素的范围,取值可以为:Type,METHOD,Constructor,field、如果
@Targe没有出现,那么定义的注解可以应用于程序的任何元素
@Inherited——指明该注解类型被自动继承。
@Retention——指明了该Annotation被保留的时间长短。RetentionPolicy取值为SOURCE,Class,RUNTIME
定义出来的注解要通过反射去解析这样才有意义:


package com.asiaInfo.test;


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ASIATable {
String value();
}






package com.asiaInfo.test;


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ASIAFiled {
String name();
String type();
int length();
}




程序:
Class clazz = Class.forName("com.asiaInfo.test.Student");
Annotation[] annotations = clazz.getAnnotations();
//遍历出所有的注解信息
for(Annotation an:annotations){
System.out.println(an);
}
ASIATable at=(ASIATable)clazz.getAnnotation(ASIATable.class);
System.out.println(at.value());
// 找出Student中所有的属性   如果这个属性没有注解将会报NULL异常 
Field[] declaredFields = clazz.getDeclaredFields();
//循环获取每一列的name,type,length
for(Field dat:declaredFields){
ASIAFiled fi =(ASIAFiled)dat.getDeclaredAnnotation(ASIAFiled.class);
System.out.println(fi.name()+"---"+fi.type()+"---"+fi.length());
}








Java的反射(reflection):
核心:Class clazz =Class.forName("com.bjsxt.test.bean.User"); //一个类只有对应一个Class
//对象是表示或封装一些数据。一个类被加载后,JVM会创建一个对于的Class对象,类的整个结构信息会放到对应的Class对象中
这个Class对象就像一面镜子一样。通过这面镜子我们可以看到对应的这个类的全部信息

Class clazz2 =Class.forName("com.bjsxt.test.bean.User");
clazz==clazz2 : true



集合类:
1)List和set比较(ArrayList,Vector,LinekedList;HashSet,TreeSet);
List允许重复,有序集合,可以插入多个null元素,ArrayList常用来做查询,LinkedList则经常需要从list中添加或删除元素的场合更为合适
Set不允许重复,无序的容器,可通过LinkedHashSet变为有序,ThreeSet通过Comparator或者Comparable维护一个排序的顺序,
Set接口最流行的几个实现类是HashSet,LinkedHashSet以及TreeSet.最流行的是基于HashMap实现的HashSet;TreeSet还实现了SortedSet接口,因此TreeSet
是一个根据其compare()和compareTo()的定义进行排序的有序容器


Map:map不是Collection的子接口或者实现类,Map是一个接口
Map的每个Entry都持有俩个对象,也就是一个键一个值,Map可能会持有相同的值对象,但键必须是唯一的
TreeMap也通过Comparator或者Comparable维护了一个排序顺序
Map里你可以拥有随意个null值但是最多只能有一个Null键
map接口最流行的几个实现类是HashMap,LinedHashMap、HashTable和TreeMap




2)HashMap的底层实现,之后会问ConcurrentHashMap的底层实现;
  线程不安全的HashMap,因为在多线程的环境下,使用HashMap进行put操作会引起死循环,导致cpu利用率接近100%,所以在并发情况下不能使用HashMap
效率低下的HashTable容器使用synchronized来保证线程安全,但在线程竞争激烈的情况下,HashTable的效率非常低下,因为当一个线程访问
  HashTable的同步方法时,其他线程访问HashTable的同步方法时,可能会进入阻塞或轮询状态。如线程1使用put进行添加元素,线程2不但不能
使用put方法添加严肃,并且也不能使用get方法来获取元素,所以竞争越激烈效率越低
  ConcurrentHashMap的锁分段技术
ConcurrentHashMap是由Segment数组结构和HashEntry数组结构组成。Segment是一种可重入锁ReentrantLock,在ConcurrentHashMap里扮演锁的角色,
HashEntry则用于存储键值对数据。一个ConcurrentHashMap里包含一个Segment数组,Segment的结构和HashMap类似,是一种数组和链表结构, 
一个Segment里包含一个HashEntry数组,每个HashEntry是一个链表结构的元素, 每个Segment守护者一个HashEntry数组里的元素,
当对HashEntry数组的数据进行修改时,必须首先获得它对应的Segment锁。
ConcurrentHashMap和CopyOnWriteArrayList保留了线程安全的同时,也提供了更高的并发性。


3)如何实现HashMap顺序存储:可以参考LinkedHashMap的底层实现;


HashMap中的fail-fast策略:
一直在变化的modCount又是什么东西呢?这个东西其实是渗透在HashMap类中的方法里面的,只要HashMap发生一次变化,就会对应的+1,
可以称为修改次数计数器。它主要是存在与非线程安全的集合当中。我们知道HashMap是一种非线程安全的类(这里涉及到一个HashMap与HashTable的区别),
那么如果某一个HashMap对象你在操作的过程中,被别的线程修该了怎么办?那不是乱套了么?因此,modCount就应运而生啦,
在迭代器初始化过程中会将modCount值赋的给迭代器的 expectedModCount。在迭代过程中,判断 modCount 跟 expectedModCount 是否相等,
如果不相等就表示已经有其他线程修改了 Map,从而抛出ConcurrentModificationException。这就是fail-fast策略。


我们已经知道HashMap是以散列表的形式存储数据的,LinkedHashMap继承了HashMap
HashMap是散列表的结构
LinkedHashMap是双向链表的结构


我们已经知道HashMap是以散列表的形式存储数据的,LinkedHashMap继承了HashMap,所以LinkedHashMap其实也是散列表的结构,
但是“linked”是它对HashMap功能的进一步增强,LinkedHashMap用双向链表的结构,把所有存储在HashMap中的数据连接起来。
有人会说散列表不是已经有了链表的存储结构了嘛,为什么还要来个双向链表?桶(桶的概念就是数组的一个存储节点,
比如说arr[0]是一个桶,arr[1]也是一个桶)中的链表和这个双向链表是两个概念,以下是我总结的区别:①桶中的链表是散列表结构的一部分;
而双向链表是LinkedHashMap的额外引入;②桶中的链表只做数据存储,没有存储顺序的概念;双向链表的核心就是控制数据存储顺序(存储顺序是LinkedHashMap的核心);
③桶中的链表产生是因为发生了hash碰撞,导致数据散落在一个桶中,用链表给予存储,所以这个链表控制了一个桶;双向链表是要串连所有的数据,
也就是说有桶中的数据都是会被这个双向链表管理。


4)HashTable和ConcurrentHashMap的区别;
它们都可以用于多线程的环境,但是当Hashtable的大小增加到一定的时候,性能会急剧下降,因为迭代时需要被锁定很长的时间。
因为ConcurrentHashMap引入了分割(segmentation),不论它变得多么大,仅仅需要锁定map的某个部分,而其它的线程不需要等到迭代完成才能访问map。
简而言之,在迭代的过程中,ConcurrentHashMap仅仅锁定map的某个部分,而Hashtable则会锁定整个map。


hashTable线程安全,因为他的底层就是公开的方法比如get都使用了synchronized描述符。而遍历视图比如keySet都使用了Collections.synchronizedXXX进行了同步包装,
HashTable的value不能为null
HashTable的效率比HashMap的效率低:因为HashTable在扩充的时候会尽量使用素数、奇数。而HashMap则总是使用2的幂作为哈希表的大小。
我们知道当哈希表的大小为素数时,简单的取模哈希的结果会更加均匀(具体证明,见这篇文章),所以单从这一点上看,HashTable的哈希表大小选择,
似乎更高明些。但另一方面我们又知道,在取模计算时,如果模数是2的幂,那么我们可以直接使用位运算来得到结果,效率要大大高于做除法。
所以从hash计算的效率上,又是HashMap更胜一筹。


5)String,StringBuffer和StringBuilder的区别;
String是不可变的字符串常量,StringBuffer是线程安全的,适用于多线程中大量使用,StringBuilder是线程不安全的,适用于单线程下的大量使用
6)Object的方法有哪些:比如有wait方法,为什么会有;
Object有toString,clone,equals,notify,notifyAll,
当线程b在访问某个共享资源时,想获取资源的锁对象,发现这个锁已经被线程a拿到了,这个时候线程b只能被挂起等释放锁后,再继续执行,
如果拿到锁的a在执行的过程中,需要等另一个条件满足后,在执行,在同步的代码块中必须释放锁,b才有资格进入,等b执行完,条件满足后,a再继续执行任务,
那么这个时候就必须有一个通知和等待的机制,wait就是等待机制,notify就是通知机制


7)wait和sleep的区别,必须理解;
sleep和wait的区别就是在调用sleep()的线程时候不会释放对象锁,而wait()是能够释放对象锁的


8)JVM的内存结构,JVM的算法;


9)强引用,软引用和弱引用的区别;
强引用: 
String str = “abc”; 
list.add(str); 
软引用: 
如果弱引用对象回收完之后,内存还是报警,继续回收软引用对象 
弱引用: 
如果虚引用对象回收完之后,内存还是报警,继续回收弱引用对象 
虚引用: 
虚拟机的内存不够使用,开始报警,这时候垃圾回收机制开始执行System.gc(); String s = “abc”;如果没有对象回收了, 就回收没虚引用的对象


10)数组在内存中如何分配;




11)用过哪些设计模式,手写一个(除单例);




12)springmvc的核心是什么,请求的流程是怎么处理的,控制反转怎么实现的;
13)spring里面的aop的原理是什么;
14)mybatis如何处理结果集:反射,建议看看源码;
15)java的多态表现在哪里;
Java的多态的定义:指的是同一种事物的不同状态,如:水的液体,固态,气态、
多态的3种必要条件,继承,重写,父类引用子类对象


16)接口有什么用;
  1、接口中定义类方法的原型,但是不能说是空方法,因为空方法的意思是有实现体,只不过实现体是空操作。实际上接口没有定义任何实现体。具体的实现体都是在实现接口的类中,接口只是定义了这些方法的调用方式。
 
  你当然也可以不用接口,直接在类里面写方法,但是如果你的一组方法需要在很多类里实现,那么把它们抽象出来,做成一个接口规范,不是更好么?
 
  2、一个类描述了一个实体,这个实体可能是一个复杂的对象,它的动作很多,如果把这些动作分类,用接口a定义其中的某一组动作,接口b定义其中的另外一组动作,这样的结构,比较清楚。
 
  这种方式具备了多继承的优点,避免了多继承的缺陷。实际上在历史上,接口在很大程度上,是为了解决多继承带来的种种问题而设计出来的。
 
  3、包中那些已定义的接口,怎么知道那里面定义了什么方法。
 
  接口里定义了方法的输入输出,这些都是协议,具体的实现都在每个类中。对于很多只需要抽象接口的地方,不需要知道具体的类是什么,只要这个类实现了这个接口就可以了。
 



17)说说http,https协议;
https是一个安全通信通道,它基于HTTP开发,用于在客户计算机和服务器之间交换信息,它使用安全套接字层(SSL)进行信息交换,简单来说它是HTTP的安全版
  https协议需要到ca申请证书,一般免费证书很少,需要交费。 
  http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议。 
  http和https使用的是完全不同的连接方式用的端口也不一样,前者是80,后者是443。 
  http的连接很简单,是无状态的。 
  HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议 要比http协议安全。 




18)tcp/ip协议簇;
  应用层、运输层,网络层,数据链路层


19)osi五层网络协议;
  应用层、传输层、网络层、数据链路层、物理层


20)tcp,udp区别;
tcp 面向连接,udp是无连接的
tcp提供可靠的服务,upd尽最大的努力交付,即不保证可靠交付
udp具有较好的实时性
tcp对系统资源要求较多,udp对系统资源要求较少


21)用过哪些加密算法:对称加密,非对称加密算法;
MD5加密算法


22)说说tcp三次握手,四次挥手;
答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,
很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,
因此不能一起发送。故需要四步握手。


23)cookie和session的区别,分布式环境怎么保存用户状态;


 1、session保存在服务器,客户端不知道其中的信息;cookie保存在客户端,服务器能够知道其中的信息。   
    
  2、session中保存的是对象,cookie中保存的是字符串。   
    
  3、session不能区分路径,同一个用户在访问一个网站期间,所有的session在任何一个地方都可以访问到。而cookie中如果设置了路径参数,那么同一个网站中不同路径下的cookie互相是
访问不到的。   
    
  4、session需要借助cookie才能正常<nobr οncοntextmenu="return false;" οnmοusemοve="kwM(3);" id="key3" οnmοuseοver="kwE(event,3, this);" style="COLOR: #6600ff; 
BORDER-BOTTOM: 0px dotted; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" οnclick="return kwC();" οnmοuseοut="kwL(event, this);"
 target="_blank">工作</nobr>。如果客户端完全禁止cookie,session将失效。


24)git,svn区别;


1.Git是分布式版本控制系统,那么它就没有中央服务器的,每个人的电脑就是一个完整的版本库,,SVN是集中式版本控制系统,版本库是集中放在中央服务器的


2.git是每个历史版本都存储完整的文件,便于恢复,svn是存储差异文件,历史版本不可恢复。(核心)


3.git可离线完成大部分操作,svn则不能。


4.git有着更优雅的分支和合并实现。


5.git有着更强的撤销修改和修改历史版本的能力


6.git速度更快,效率更高。
25)请写一段栈溢出、堆溢出的代码;
如果想要堆溢出,比较简单,可以循环创建对象或大的对象;


如果想要栈溢出,可以递归调用方法,这样随着栈深度的增加,JVM 维持着一条长长的方法调用轨迹,


直到内存不够分配,产生栈溢出。




26)ThreadLocal可以用来共享数据吗;
ThreadLocal重要作用并不在于多线程间的数据共享,而是数据的独立
ThreadLocal是采用哈希表的方式来为每个线程都提供一个变量的副本
ThreadLocal保证各个线程间数据安全,每个线程的数据不会被另外线程访问和破坏


概括的解释下线程的几种状态:

就绪(Runnable):线程准备运行,不一定立马就能开始执行。
运行中(Running):进程正在执行线程的代码。
等待中(Waiting):线程处于阻塞的状态,等待外部的处理结束。
睡眠中(Sleeping):线程被强制睡眠。
I/O阻塞(Blocked on I/O):等待I/O操作完成。
同步阻塞(Blocked on Synchronization):等待获取锁。
死亡(Dead):线程完成了执行。


final, finally, finalize 的区别
final修饰符:被修饰的类不能被继承,修饰的变量只能被修改一次,修饰的方法不能被重载
finally是在异常处理时提供的finally快来执行,无论是否异常都会执行finally块中的内容
finalize是方法名,是在垃圾收集器将对象从内存中清除出去的时候使用的


Exception、Error、运行时异常与一般异常有何异同
Error是由JVM所侦测到的无法预期的错误,无法捕捉
Exception:表示可恢复的例外,这是可捕捉的


Java提供了两类异常,runtime Exception 和checked Exception
checked Exception是我们经常遇到的IO异常和Sql异常对于这种异常,JAVA编译器强制要求我们必需对出现的这些异常进行catch。所以,面对这种异常不管我们是否愿意,
只能自己去写一大堆catch块去处理可能的异常。
runtime Exception是运行时异常,我们可以不处理,当出现这样的异常,总由虚拟机接管  如:NullPointerException




请写出5种常见到的runtime exception
1)IllegalArgumentException抛出的异常表明向方法传递了一个不合法或不正确的参数


2)NullPointerException当应用程序试图在需要对象的地方使用 null 时,抛出该异常


3)ArrayIndexOutOfBoundsException当使用的数组下标超出数组允许范围时,抛出该异常


4)ClassCastException当试图将对象强制转换为不是实例的子类时,抛出该异常


5)NumberFormatException当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。




int 和 Integer 有什么区别,Integer的值缓存范围
(1)Integer是int的包装类;int是基本数据类型; 
(2)Integer变量必须实例化后才能使用;int变量不需要; 
(3)Integer实际是对象的引用,指向此new的Integer对象;int是直接存储数据值 ; 
(4)Integer的默认值是null;int的默认值是0。


Integer的值范围是-128~127之间


包装类,装箱和拆箱
装箱:是指基本类型变为相应包装类的过程,如Integer a=Integer.valueOf(100);或者int a=100;Integer b=new Integer(a);这里的Integer.valueOf(100)和new Integer(a)就是装箱,
由基本数据类型构造出一个包装类的对象。


拆箱:就是装箱的逆过程。如Integer a=new Integer(100);int b=a.intValue();这里的a.intValue()就是拆箱的过程,由一个包装类对象转换到相应的基本数据类型。




重载和重写的区别


override(重写)


   1、方法名、参数、返回值相同。


   2、子类方法不能缩小父类方法的访问权限。


   3、子类方法不能抛出比父类方法更多的异常(但子类方法可以不抛出异常)。


   4、存在于父类和子类之间。


   5、方法被定义为final不能被重写。


 overload(重载)


  1、参数类型、个数、顺序至少有一个不相同。 


  2、重载返回相同的方法名。


  3、存在于父类和子类、同类中。


抽象类和接口有什么区别
接口类描述的是行为 抽象类描述的是根源; 
接口是对动作的抽象,抽象类是对根源的抽象。
原则一:static永远不能和abstract碰头; 
原则二:interface是更抽象的抽象类,接口的所有方法都未实现,接口的方法默认为public abstract ,根据原则一,当然不能是static了; 
原则三:抽象类是部分实现的,其中non-abstract方法可以带static,abstract方法不能带static


抽象类和接口的区别在于使用动机。使用抽象类是为了代码的复用,而使用接口的动机是为了实现多态性。所以,如果你在为某个地方该使用接口还是抽象类而犹豫不决时,那么可以想想你的动机是什么。






说说反射的用途及实现
反射的核心:是 JVM 在运行时 才动态加载的类或调用方法或属性,他不需要事先(写代码的时候或编译期)知道运行对象是谁。
spring 的 ioc/di 也是反射…. 
javaBean和jsp之间调用也是反射…. 
struts的 FormBean 和页面之间…也是通过反射调用…. 
JDBC 的 classForName()也是反射….. 
hibernate的 find(Class clazz) 也是反射….
反射还有一个不得不说的问题,就是性能问题,大量使用反射系统性能大打折扣。


说说自定义注解的场景及实现






HTTP请求的GET与POST方式的区别


GET方法会把各键值对追加在请求的URL后面。因为URL对字符数目有限制,进而限制了用在客户端请求的参数值的数目。并且请求中的参数值是可见的,因此,敏感信息不能用这种方式传递。


POST方法通过把请求参数值放在请求体中来克服GET方法的限制,因此,可以发送的参数的数目是没有限制的。最后,通过POST请求传递的敏感信息对外部客户端是不可见的。


Session与Cookie区别


cookie 是 Web 服务器发送给浏览器的一块信息。浏览器会在本地文件中给每一个 Web 服务 
器存储 cookie。以后浏览器在给特定的 Web 服务器发请求的时候,同时会发送所有为该服 
务器存储的 cookie。下面列出了 session 和 cookie 的区别: 
无论客户端浏览器做怎么样的设置,session都应该能正常工作。客户端可以选择禁用 cookie, 
但是, session 仍然是能够工作的,因为客户端无法禁用服务端的 session


列出自己常用的JDK包


1、java.lang


2、java.sql


3、java.io


4、java.math


5、java.text


6、java.net


7、java.util


8、java.awt


9、java.applet


10、java.nio


MVC设计思想
MVC就是model   view     Controller
模型就是封装业务逻辑的如dao层,service,  Controller就是Controller层    view就是jsp




equals与==的区别
如果是值类型的话都是判断相等,
如果是引用类型的话 ==是判断引用对象所指的对象是否是同一个,equals是Object的成员函数,有些类会覆盖这个方法,用于判断对象的等价性


hashCode和equals方法的区别与联系
1.equal()相等的两个对象他们的hashCode()肯定相等,也就是用equal()对比是绝对可靠的。
2.hashCode()相等的两个对象他们的equal()不一定相等,也就是hashCode()不是绝对可靠的。
每当需要对比的时候,首先用hashCode()去对比,如果hashCode()不一样,则表示这两个对象肯定不相等(也就是不必再用equal()去再对比了),
如果hashCode()相同,此时再对比他们的equal(),如果equal()也相同,则表示这两个对象是真的相同了,这样既能大大提高了效率也保证了对比的绝对正确性!
 




什么是Java序列化和反序列化,如何实现Java序列化?或者请解释Serializable 接口的作用
当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象。
只能将支持 java.io.Serializable 接口的对象写入流中。每个 serializable 对象的类都被编码,编码内容包括类名和类签名、对象的字段值和数组值,以及从初始对象中引用的其他所有对象的闭包。


序列化:把Java对象转换为字节序列的过程。
反序列化:把字节序列恢复为Java对象的过程。


Java的平台无关性如何体现出来的


JDK和JRE的区别
JDK顾名思义是java开发工具包
JRE是Java的运行时环境
JDK包含jre






线程和进程的概念、并行和并发的概念
一个程序至少有一个进程,一个进程至少有一个线程
线程:是程序执行流的最小单位,是系统独立调度和分配CPU的基本单位
程序:是资源分配的基本单位。一个进程包括多个线程
并行:指在同一时间点同时执行,进程之间相互独立,可实现并行,但线程是不可以的
并发:指在同一时间片段同时执行,多线程只能并发执行,实际还是顺序执行,只是在同一时间按片段,假似同时执行








创建线程的方式及实现


1)继承Thread类创建线程


2)实现Runnable接口创建线程


3)使用Callable和Future创建线程


进程间通信的方式


说说 CountDownLatch、CyclicBarrier 原理和区别




package main.java.CountDownLatch;


import java.util.concurrent.CountDownLatch;


/**
 * PROJECT_NAME:downLoad
 * Author:lucaifang
 * Date:2016/3/18
 */
public class countDownlatchTest {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(5);
        for(int i=0;i<5;i++){
            new Thread(new readNum(i,countDownLatch)).start();
        }
        countDownLatch.await();调用此方法会一直阻塞当前线程,直到计时器的值为0
        System.out.println("线程执行结束。。。。");
    }


    static class readNum  implements Runnable{
        private int id;
        private CountDownLatch latch;
        public readNum(int id,CountDownLatch latch){
            this.id = id;
            this.latch = latch;
        }
        @Override
        public void run() {
            synchronized (this){
                System.out.println("id:"+id);
                System.out.println("线程组任务"+id+"结束,其他任务继续");
    latch.countDown(); 当前线程调用此方法,则计数减一
            }
        }
    }
}




说说 Semaphore 原理


说说 Exchanger 原理


ThreadLocal 原理分析,ThreadLocal为什么会出现OOM,出现的深层次原理
1、ThreadLocal.get: 获取ThreadLocal中当前线程共享变量的值。


2、ThreadLocal.set: 设置ThreadLocal中当前线程共享变量的值。


3、ThreadLocal.remove: 移除ThreadLocal中当前线程共享变量的值。


4、ThreadLocal.initialValue: ThreadLocal没有被当前线程赋值时或当前线程刚调用remove方法后调用get方法,返回此方法值。


线程池的一个线程使用完ThreadLocal对象之后,再也不用,由于线程池中的线程不会退出,线程池中的线程的存在,同时ThreadLocal变量也会存在,占用内存!造成OOM溢出!






讲讲线程池的实现原理


线程池的几种实现方式


线程的生命周期,状态是如何转移的


新建状态——就绪状态<——阻塞状态<——运行状态——死亡状态
                 |                        |
                 |                        |
                 |<———————————>|






说说线程安全问题,什么是线程安全,如何保证线程安全
线程安全:就是多线程访问同一代码,不会产生不确定结果。(比如死锁)
一般说来,确保线程安全的方法有这几个:竞争与原子操作、同步与锁、可重入、过度优化。
竞争和原子操作:多个线程在同时访问和修改一个数据,可能造成的严重后果,一般将单指令的操作称为原子的,不论如何,单条指令的执行不会被打断
同步与锁:同步最常用的方法就是锁,每个线程在访问数据或资源获取之前就需先获取锁,并在访问结束之后释放锁,锁被占用时,线程会等待,直到锁重用
可重入:可重入是并发安全的强力保障,一个可重入的函数可以在多线程环境下方心使用
过度优化:在很多情况下,即使我们合理地使用了锁,也不一定能够保证线程安全,因此,我们可能对代码进行过度的优化,以确保线程安全。
我们可以使用volatile关键字试图阻止过度优化,它可以做两件事:第一,阻止编译器为了提高速度将一个变量缓存到寄存器而不写回;第二,
阻止编译器调整操作volatile变量的指令顺序。


重入锁的概念,重入锁为什么可以防止死锁
是指允许同一个线程多次对该锁进行acquire动作。对于不可重入的锁,当一个线程多次调用acquire后将造成死锁。


产生死锁的四个条件(互斥、请求与保持、不剥夺、循环等待)


如何检查死锁(通过jConsole检查死锁)


volatile 实现原理(禁止指令重排、刷新内存)


synchronized 实现原理(对象监视器)


synchronized 与 lock 的区别


AQS同步队列


CAS无锁的概念、乐观锁和悲观锁


常见的原子操作类


什么是ABA问题,出现ABA问题JDK是如何解决的


乐观锁的业务场景及实现方式


Java 8并法包下常见的并发类


偏向锁、轻量级锁、重量级锁、自旋锁的概念






Redis有哪些类型:
Redis支持五种数据类型:String(字符串),hash(哈希),list(列表) set(集合)  zset(有序集合)
Redis内部结构






BIO、NIO、AIO的概念
同步阻塞IO(BIO)
同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,
当然可以通过线程池机制改善


同步非阻塞(NIO):
同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。
用户进程也需要时不时的询问IO操作是否就绪,这就要求用户进程不停的去询问。


异步阻塞IO(NIO)
此种放肆下是指应用发起一个IO操作以后,不等待内核IO操作的完成,等内核完成IO操作以后会通知应用程序,这其实就是同步和异步最关键的区别,同步必须等待或者
主动的去询问IO是否完成,那么为什么说是阻塞的呢?因为此时是通过select系统调用来完成的,而select函数本身的实现方式是阻塞的,而采用select函数有个好处就是
它可以同时监听多个文件句柄,从而提高系统的并发性






BIO、NIO、AIO适用场景分析:
 BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序直观简单易理解
 NIO方式适用于连接数目多且连接比较短的架构,比如聊天服务器,并发局限于应用中,编程比较复杂
 AIO方式使用于连接数目多且连接比较长的架构,比如相册服务器,充分调用OS参与的并发操作,编程比较复杂,jdk1.7开始支持








Netty


为什么不选择java原生NIO编程的原因
 1、NIO的类库和API繁杂,使用麻烦,你需要熟练掌握Selector、ServerSocektChannel、SocketChannel、ByteBufferdeng
 2、需要具备其他的额外技能做铺垫,例如:熟悉java多线程编程。这是因为NIO编程涉及到Reactor模式,你必须对多线程和网络编程非常熟悉
 3、可靠性能力补齐,工作量和难度都非常大。例如:客户端面临断连重连、网络闪断、半包读写、失败缓存、网络拥塞和异常码流的处理等问题,NIO编程的特点是功能开发
相当容易,但是可靠性能力补齐的工作量和难度都非常大
 4、jdk NIO的bug 例如:臭名昭著的epoll bug,它会导致Selector空轮询,最终导致CPU100%,jdk1.7后这个问题只不过发生概率降低了一些而已,并没有得到根本性解决
  为什么选择Netty
     Netty是业界最流行的NIO框架之一,它的健壮性、功能、性能、可定制性和可扩展性在同类框架中都是首屈一指的,它已经得到成百上千的商用项目验证,例如Hadoop的RPC框架Avro就使用
了Netty作为底层通信框架,其他还有业界主流的RPC框架,也使用Netty来构建高性能的异步通信能力
   Netty的优点:
API使用简单,开发门槛低
功能强大,预置了多种边解码功能,支持多种主流协议
定制能力强,可以通过ChannelHandler对通信框架进行灵活地扩展;
        性能高,通过于其他业界交流的NIO框架对比,Netty的综合性能最优
       成熟、稳定,Netty修复了已经发现的所有JDK NIO BUG,业务开发人员不需要再为NIO的Bug而烦恼
       社区活跃,版本迭代周期短,发现的BUG可以被及时修复,同时,更多的新功能会加入
       经历了大规模的商业应用考验,质量得到验证,Netty在互联网、大数据、网络、游戏、企业应用、电信软件等众多行业已经得到成功商用,证明它已经完全能够满足不同行业的商业应用了


说说业务中,Netty 的使用场景






NIO和AIO的区别?
对分布式系统的理解
多个独立运行的计算机(称为结点)组成,各个结点利用计算机网络进行信息传递,从而实现共同的‘目标或者任务’
在分布式计算机中,一个问题被细化分成多个任务,每个任务可以被一个或者多个计算机来完成
为什么使用Redis
redis不仅仅支持简单的key-value类型的数据,同时还提供list、set、zset、hash等数据结构的存储
redis支持master-slave(主-从)模式应用
redis支持数据持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用
redis单个value的最大限制是1GB,memcache只能保存1mb的数据
redis和memcache的区别
Redis和memcache不同的是,存储在Redis中的数据是持久化的,断电或重启后,数据也不会丢失。因为Redis的存储分为内存存储、磁盘存储和log文件3部分,重启后,Redis可以从磁盘重新将数据加载到内存中,这些可以通过配置文件对其进行配置,正因为这样,Redis才能实现持久化
Redis支持主从模式,可以配置集群,这样更利于支撑起大型的项目,这也是Redis的一大亮点
控制反转和依赖注入?
是用来对对象进行解耦。就是不需要自己创建对象,由Spring容器来控制




dubbo的配置?
Java中如何获取javaBean的实例
ApplicationContext ac = new FileSystemXmlApplicationContext("applicationContext.xml");
ac.getBean("beanId");


























Spring的面试题:


Servlet的生命周期
servlet的生命主要有三个阶段: 初始化--服务--销毁
初始化:主要包括加载、配置、创建实例三部分
    加载:在客户端首次请求该Servlet时,或者在web.xml中配置该servlet
    配置:为每个Servlet设置信息产生一个ServletConfig对象;
    创建:调用Servlet接口的init()方法,并将产生的ServletConfig对象当作参数传入。在servlet生命周期中,仅执行一次init()方法。它在web服务装入Servlet时执行,
负责初始化Servlet对象。同一个类型的Servlet对象在web服务器中以单例的形式存在




转发与重定向的区别
1)重定向时1浏览器上的网址改变,转发是浏览器的网址不变
2)重定向实际产生了两次请求,转发只有一次请求
3)重定向的网址可以是任何网址,转发的网址必须是本站点的网址






BeanFactory 和 ApplicationContext 有什么区别


beanfactory它的核心就是bean工厂,用作于管理bean的生命周期,而applicationContext这个概念就比较丰富了,(应用上下文)就能看出它包含的范围更广,它继承自bean factory但不仅仅是继承
自这一个接口,还有继承了其他的接口,所以它不仅仅有bean factory相关概念,更是一个应用系统的上下文,其设计初衷应该是一个包罗万象的对外暴露的一个综合的API




Spring Bean 的生命周期


1、首先实例化一个bean,也就是我们通常说的new
2、按照spring上下文对实例话的Bean进行配置,也就是IOC注入
3、如果这个Bean实现了BeanNameAware接口,会调用它实现的SetBeanName(String beanId)方法,此处传递的是Spring配置文件中的Bean的ID
4、如果这个Bean实现了BeanFactoryAware接口,会调用它实现的setBeanFactory(),传递的是Spring工厂本身
5、如果这个Bean实现了ApplicationContextAware接口,会调用setApplicationContext(ApplicationContext)方法,传入Spring上下文,该方式同样可以实现步骤4,但比4更好,以为ApplicationContext是beanFactory的子接口,有更多的实现方法
6、如果这个Bean关联了BeanPostProcessor接口,将会调用postProcessBeforeInitialization(Object obj,String s)方法,BeanPostProcessor经常被用作是Bean内容的更改,并且由于这个是再Bean初始化结束时调用After方法,也可以用于内存或缓存技术
7、如果这个Bean再spring配置文件中配置了init-method属性会自动调用其配置的初始化方法
8、如果这个Bean关联了BeanPostProcessor接口,将会调用PostAfterInitialization(Object obj,String s)方法
9、当Bean不在需要时,会经过清理阶段,如果Bean实现了DisposableBean接口,会调用其实现的destroyfangfa
10、最后,如果这个Bean的Spring配置中配置了destroy-method属性,会调用其配置的销毁方法




Spring IOC 如何实现


什么是IOC:最主要的是完成对象的创建和依赖的管理注入等等。。
所谓控制反转,就是把原先我们代码里边需要实现的对象创建、依赖的代码,反转给容器来帮忙实现。那么必然的我们需要创建一个容器,同时需要一种描述来让容器知道需要创建的对象于对象的关系。






Spring中Bean的作用域,默认的是哪一个  
在xml配置中使用scope属性
<bean id="xxx" class="xxx.xxx.xxx" scope="session" >
    <aop:scoped-proxy/>
</bean>
使用注解
@Scope
Spring的作用域有以下几种:
singleton作用域   单例     整个应用只创建一个实例
prototype作用域   原型     每次注入时都新建一个实例
request作用域     请求     为每个请求创建一个实例
session作用域     会话     为每个会话创建一个实例
global-session作用域


默认的是singleton作用域  scope="singleton"
bean设置为该作用域时,Spring IOC容器中只会存在一个共享的bean实例,也就意味着Spring IOC容器只会创建该bean定义的唯一实例。这个单一实例会被存储到单例缓存中


prototype作用域 scope="prototype"
prototype作用域部署的bean,每一次请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean())都会产生一个新的bean实例,相当于一个new操作。


注意:request作用域、session作用域、global-session作用域使用的时候首先要在初始化web的web.xml中做以下配置
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
request作用域
表示该作用域下,针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP-request内有效
session作用域
session作用域表示针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前的http-session内有效
global-session作用域
全局会话内有效




说说 Spring AOP、Spring AOP 实现原理


Spring AOP的两种实现原理:jdk动态代理、CGLIB代理


Spring AOP面向切面编程,是面向对象编程的补充和完善。实现AOP的技术,主要分为两类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为执行


二是采用静态织入的方式,引入特定的语法创建”方面“,从而使得编译器可以在编译期间织入有关”方面“的代码


动态代理(CGLib 与 JDK)、优缺点、性能对比、如何选择




Spring 事务实现方式、事务的传播机制、默认的事务类别


事物的5种配置方式:








Spring 事务底层原理


Spring事务失效(事务嵌套),JDK动态代理给Spring事务埋下的坑,可参考《JDK动态代理给Spring事务埋下的坑!》


如何自定义注解实现功能


Spring MVC 运行流程


1、用户发送请求到DispatcServlet
2、DispatchServlet根据请求路径查询具体的Handler
3、HandlerMapping返回一个HandlerExcutionChain给DispatchServlet
 Handle人ExcutionChain:Handler和Interceptor
4、DispatchServlet调用HandlerAdapter适配器
5、HandlerAdapter调用具体的Handler处理业务
6、Handler处理结束返回一个具体的ModelAndView给适配器
7、适配器将ModelAndView给DispatchServlet
8、DispatchServlet把视图名称给ViewResolver视图解析器
9、ViewResolver返回一个具体的视图给DispatchServlet
10、渲染视图
11、展示给用户


自己总结:
用户发送一个请求到DispatchServlet,DispatchServlet接受到请求后,会使用HandlerMapping来处理对应的Handler(平常叫Controller),
并返回一个Handler执行链给DispatchServlet,DispatchServlet接收到执行链后会调用Handler适配器去执行handler.之后返回一个ModelandView,返回给DispatchServlet,会根据其中的
视图解析器解析成一个View视图,然后再将model模型中的数据渲染到View上


Spring MVC 启动流程


Spring 的单例实现原理


Spring 框架中用到了哪些设计模式
1、工厂模式,在各种BeanFactory以及ApplicationContext创建中都用到了
2、模板模式,同上
3、代理模式,在Aop实现中用到了jdk的动态代理
4、单例模式,比如在创建bean的时候
5、外观模式,
6、策略模式
7、原型模式
8、迭代器模式




Spring 其他产品(Srping Boot、Spring Cloud、Spring Secuirity、Spring Data、Spring AMQP 等)


有没有用到Spring Boot,Spring Boot的认识、原理




什么是数据库连接池:




MyBatis的原理






#{}和${}的区别是什么
#{}是预编译处理,${}是字符串替换
mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值
mybatis在处理${}时,就会把${}替换成变量
使用#{}可以有效的防止SQL注入,提高系统安全性




当实体类中的属性名和表中的字段名不一样,怎么办?
1、通过在查询的sql语句中定义字段名的别名,让字段名的别名和实体类的属性名一致
如: <select id=”selectorder” parametertype=”int” resultetype=”me.gacl.domain.order”> 
       select order_id id, order_no orderno ,order_price price form orders where order_id=#{id}; 
    </select> 
2、通过<resultMap>来映射字段名和实体类属性名的一一对应关系
  <select id="getOrder" parameterType="int" resultMap="orderresultmap">
        select * from orders where order_id=#{id}
    </select>
   <resultMap type=”me.gacl.domain.order” id=”orderresultmap”> 
        <!–用id属性来映射主键字段–> 
        <id property=”id” column=”order_id”> 
        <!–用result属性来映射非主键字段,property为实体类属性名,column为数据表中的属性–> 
        <result property = “orderno” column =”order_no”/> 
        <result property=”price” column=”order_price” /> 
    </reslutMap>




通常一个xml映射文件,都会写一个Dao接口与之对应,请问,这个Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗?
Dao接口,就是人们常说的Mapper接口,接口的全限名,就是映射文件中的namespace的值,接口的方法名,就是映射文件中MappedStatement的id值,接口方法内的参数,就是传递给sql的参数。Mapper接口是没有实现类的,当调用接口方法时,接口全限名+方法名拼接字符串作为key值,可唯一定位一个MappedStatement,
举例:com.mybatis3.mappers.StudentDao.findStudentById,可以唯一找到namespace为com.mybatis3.mappers.StudentDao下面id = findStudentById的MappedStatement。在Mybatis中,每一个<select>、<insert>、<update>、<delete>标签,都会被解析为一个MappedStatement对象。


Dao接口里的方法,是不能重载的,因为是全限名+方法名的保存和寻找策略。


Dao接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Dao接口生成代理proxy对象,代理对象proxy会拦截接口方法,转而执行MappedStatement所代表的sql,然后将sql执行结果返回。




mybatis是如何进行分页的?
Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页,可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。


分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。




1、物理分页:只从数据库中查询当前页的数据


2、逻辑分页:从数据库中将所有记录查询出来,存储到内存中,展示当前页,然后数据再直接从内存中获取


大部分我们用的都是物理分页:


我用 都是mysql 所以就说下limit


select * from 表 limit m,n;


oracle用的是rownum






如何执行批量插入?
<insert id="insertname">
insert into names(name) values (#value)
</insert>


用java 如:
list<String> names=new ArrayList();
names.add("fred");
names.add("barney");
names.add("betty");
names.add("wilma");


sqlsession sqlsession=sqlsessionfactory.opensession(executortype.batch);
try{
 namemapper mapper=sqlsession.getmapper(namemapper.class);
for(String name:names){
mapper.insertname(name);
}
sqlsessionn.commit();
}finally{
sqlsession.close();
}




mapper中如何传递多个参数?
1、
//DAO层的函数


Public UserselectUser(String name,String area);  




//对应的xml,#{0}代表接收的是dao层中的第一个参数,#{1}代表dao层中第二参数,更多参数一致往后加即可。


<select id="selectUser"resultMap="BaseResultMap">  
    select *  fromuser_user_t   whereuser_name = #{0} anduser_area=#{1}  
</select>  




2、import org.apache.ibatis.annotations.param; 
        public interface usermapper { 
         user selectuser(@param(“username”) string username, 
         @param(“hashedpassword”) string hashedpassword); 
        }


然后,就可以在xml像下面这样使用(推荐封装为一个map,作为单个参数传递给mapper): 
2
    <select id=”selectuser” resulttype=”user”> 
         select id, username, hashedpassword 
         from some_table 
         where username = #{username} 
         and hashedpassword = #{hashedpassword} 
    </select>






为什么说Mybatis是半自动ORM映射工具?他与全自动的区别在哪里?
Hibernate属于全自动ORM映射工具,使用hibernate查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。而Mybatis在查询关联对象或关联集合对象时
需要手动编写sql来完成,所以,称之为半自动ORM映射工具






SpringMVC和Struts2的区别:
springmvc的入口是一个servlet即前端控制器,而struts2人口是一个filter过滤器
SpringMVC是基于方法开发(一个url对应一个方法),请求参数传递到方法的形参,可以设计为单例或多例,struts2是基于类开发的传递参数是通过类属性只能设计为多例
Struts采用值栈存储请求和响应数据。通过OGNL存取数据,springmvc通过参数解析器是将request请求内容解析,并给方法形参赋值,将数据和视图封装成ModelAndView对象
最后将ModelAndView模型数据通过request域传输到页面,jsp视图解析器默认使用jstl










数据库的连接池:
每当用户请求一个连接时,系统首先检查空闲池内有没有空闲连接,如果有就把建立连接时间最长的那个连接分配给他,如果没有则检查当前所开连接池是否达到连接池所允许的最大连接数,如果没有达到
就新建一个连接,如果已经达到,就等待一定的时间,如果在等待的时间内有连接被释放出来就可以把这个连接分配给等待的用户,如果等待的时间超过预定时间timeout,返回null值。系统对已经分配出去正在使用的
连接只做计数,当使用完后再还给空闲池。对于空闲连接的状态,可开辟专门的线程定时检测,这样会花费一定的系统开销,但可以保证较快的响应速度。也可采取不开辟专门线程,只是在分配前检测的方法








hibernate工作原理:
1.通过Configuration config = new Configuration().configure();//读取并解析hibernate.cfg.xml配置文件
2.由hibernate.cfg.xml中的<mapping resource="com/xx/User.hbm.xml"/>读取并解析映射信息
3.通过SessionFactory sf = config.buildSessionFactory();//创建SessionFactory
4.Session session = sf.openSession();//打开Sesssion
5.Transaction tx = session.beginTransaction();//创建并启动事务Transation
6.persistent operate操作数据,持久化操作
7.tx.commit();//提交事务
8.关闭Session
9.关闭SesstionFactory


如何优化Hibernate?
1、使用双向一对多关联,不使用单向一对多
2、灵活使用单向一对多关联
3、不用一对一,用多对一取代
4、配置对象缓存,不使用集合缓存
5、一对多集合使用Bag,多对多集合使用Set
6、继承类使用显示多态
7、表字段要少,表关联不要怕多,有二级缓存撑腰、


hibernate中get和load的区别
使用get方法查找对象是否存在,如果未能发现符合条件的记录,get方法会返回null,而load方法会抛出一个ObjectNotFoundException




hibernate的缓存机制:
hibernate缓存包括两大类:hibernate一级缓存和hibernate二级缓存
一级缓存又称:session缓存,它是内置的,只要你使用hibernate就必须使用session缓存。由于session对象的生命周期通常对应一个数据库事务或应用事务,因此它的缓存时事务范围的缓存
二级缓存又称:sessionFactory缓存,由于sessionFactory对象的生命周期和应用程序的整个过程对应,因此Hibernate二级缓存是进程范围或者集群范围的缓存,有可能出现并发问题,因此需要
采用适当的并发访问策略,该策略为被缓存的数据提供了事务隔离级别,第二级缓存是可选的,是一个可配置的插件,在默认的情况下,sessionfactory是不会启用这个插件的。






什么样的数据适合存放到二级缓存中?
1、很少被修改的
2、不是很重要的数据,允许偶尔出现并发的数据
3、不会被并发访问的数据
4、常量数据


不适合存放到第二级缓存中的数据?
1、经常被修改的
2、绝对不允许出现并发访问的数据,如财务数据,绝对不允许出现并发
3、与其他应用共享的数据




hibernate查询对象如何应用缓存?
当hibernate根据ID访问数据对象的时候,首先从session一级缓存中查;查不到,如果配置了二级缓存,那么二级缓存中查,如果都查不到,在查找数据库,把结果按照ID放入缓存,删除、更新
增加数据的时候,同时更新缓存






项目中为什么会使用ssh
1、使用struts2是因为struts2是基于MVC模式的,很好的将应用程序进行了分层,使开发者更关注与业务的逻辑的实现,还有,struts有着丰富的taglib,如能灵活运用,则能大大提高开发效率
2、使用hibernate:因为hibernate为Java应用提供了一个易用的、高效率的对象关系映射框架。hibernate是个轻量级的持久性框架,功能丰富。
3、使用Spring:因为spring基于IOC和AOP构架多层将j2ee系统的框架,但他不强波你必须再每一层中必须使用Spring,因为它模块化的很好,允许你根据自己的需要选择使用。它的某一个模块;采用IOC使得可以很容易的实现bean的装配
提供了简洁的AOP并据此实现事务管理,等等




hibernate的三种状态之间的转换:
游离状态:session中没有,数据库中有
持久状态:数据库和缓存中都有的
瞬时状态:数据库中没有,session中有









  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值