java/javaWeb高频面试笔试题,全面!

tomcat下的最大线程数,排队线程数,等待时间
默认值:最大线程数200,排队100,超时45秒,在server.xml中的connector标签中配置。

HTTP状态码
200 - 请求成功
301 - 资源(网页等)被永久转移到其它URL
400(错误请求) 服务器不理解请求的语法。
401(身份验证错误) 此页要求授权。您可能不希望将此网页纳入索引。
403(禁止) 服务器拒绝请求。
404 - 请求的资源(网页等)不存在
500 - 内部服务器错误

Linux常用命令:
ls   显示文件或目录
-l 列出文件详细信息l(list)
-a 列出当前目录下所有文件及目录,包括隐藏的a(all)
mkdir 创建目录
-p 创建目录,若无父目录,则创建p(parent)
cd 切换目录
touch 创建空文件
echo 创建带有内容的文件。
cat 查看文件内容
cp 拷贝
mv 移动或重命名
rm 删除文件
-r 递归删除,可删除子目录及文件
-f 强制删除
find 在文件系统中搜索某文件
wc 统计文本中行数、字数、字符数
grep 在文本文件中查找某个字符串
rmdir 删除空目录
tree 树形结构显示目录,需要安装tree包
pwd 显示当前目录
ln 创建链接文件
more、less 分页显示文本文件内容
head、tail 显示文件头、尾内容
top 实时显示系统中各个进程的资源占用状况(-u 按照用户查询)
ps 显示内存使用情况(根据进程号显示)

JAVA中哪种整型的取值范围巧好是-2147483648(-2^31)~2147483647(2^31-1)()
number型 不是
A.short型 -32768-32768
B.int型
C.long型 -2的63次方---2的63次方减一

char型变量中能不能存贮一个中文汉字?为什么?
char型变量是用来存储Unicode编码的字符的,unicode编码字符集中包含了汉字,所以,char型变量中当然可以存储汉字啦。不过,如果某个特殊的汉字没有被包含unicode编码字符集中,那么,这个char型变量中就不能存储这个特殊汉字。

假定变量x=8的类型是int(它可以存放着负值),则哪些方式能正确地使x的值翻倍,请选出四个正确的答案()
A.x<<1;
B.X=x*2;
C.X*=2;
D.X+=x;
E.X<<=1;
ava中有三种移位运算符
<<      :     左移运算符,num << 1,相当于num乘以2
>>      :     右移运算符,num >> 1,相当于num除以2
>>>    :     无符号右移,忽略符号位,空位都以0补齐

编译运行如下程序后,将以什么次序打印出哪些数字?
Public class Myclass {
Public static void main(String[] args){
RuntimeException re = null;
Throw re;
}
}
A.代码将无法被编译,因为mian()方法在其声明中表示自己会抛出RuntimeException
B.程序将无法被编译,因为它无法抛出re
C.程序可以被无措地编译,并且运行时将爬出java.lang.RuntimeExcetion
D.程序可以被无措地编译,并且运行时将抛出java.lang.NullPointExcetion

给定如下代码,那个声明能插入至所示的位置而不会导致编译错误。()
interface MyConstancts{
int r = 42;
int s = 69;
int Area;
//插入代码
} 接口属性只能是public static 或者final
A.final double circumference = 2*Math.PI*r;
B.Int total = total + r+s;
C.Int ArRa = r*s;
D.Public static MAIN = 15;
E.Protected int CODE = 31337;

哪个方法不是在String类中定义的?
A.trim() 去掉起始和结尾的空格
B.length()
C.concat(String) 连接字符串
D.hashCode()重写了object的hashcode();
E.reverse()

Struts框架会使用不同的共享资源区来存储对象,共享资源区都有一个lifetime和visibility规则,请列举出四种不同的作用域并说明作用范围,并简述转发与重定向的主要差异:
ActionContext ctx = ActionContext.getContext();//得到Struts2的上下文
Map request = (Map)ctx.get("request");//得到request
Map session = ctx.getSession();//得到会话
Map application = ctx.getApplication();//得到应用程序
Request封装了来自客户端的get、post的请求,
Session代表客户端与服务器的一次会话,从客户端与服务器建立链接开始直到关闭浏览器,ActionContext.getContext().getSession().put(key,value)可以将session的值保存在值栈(ValueStack)中,由于session在一次会话中的数据是共享的,所以在其他页面也就可以通过<s:property value="#session.key" />访问值栈中的值了
Application代表应用本身,可存放全局变量,因此可实现用户数据共享,他的生命周期与服务器一致,在任何地方对此对象的操作都将影响到其他用户对此对象的操作。
转发forward重定向redirect
转发时页面不跳转,通过服务器内部直接访问目标地址,在转发过程中服务器使用同一个request域,数据共用。
重定向是直接页面进行一次跳转 由客户端像下一台服务器重新发送一次请求,因为多了一次客户端发出的请求所以效率比重定向低。

JSP标准提供了三种独立的向JSP添加代码的技术,请列举两种
Include动作和jsp include指令 用来引入文件
指令:<%@include file=”test.jsp” %>
动 作: <jsp:include page=”test.jsp” flush=”true”>
<jsp:param name=”name” value=”value”/>
</jsp:include>
区别:指令是编译阶段的指令,在编译时编译器会把指定文件复制到指令所在位置来替换指令,如果内容有变化需要重新编译,因此适于静态页面。
动作是在运行时执行的,当页面被请求时才将用到的jsp包含进来,类似方法调用,适于动态页面。一般优先考虑动作

在web.xml的配置文件中,利用struts的error-page元素,增加一段代码配置,将404产生时转到error404.jsp进行处理,或者用文字来描述出这种配置方式,系统的处理机制和原理过程。
在web.xml对404拦截,并进入jsp判断,跳转到错误action处理方法,并进行不同的处理:
<error-page>
<error-code>404</error-code>
<location>/errorForward.jsp?code=404</location>
</error-page>
<error-page>
然后跳转到errorpage进行错误码判断,如果是404,跳转到指定action.
<script type="text/javascript">
window.onload = function() {
var code = '<%=request.getParameter("code")%>';
switch(code) {
case '404' :
window.top.location.replace("<%=request.getContextPath()%>/forward!notFound");
break;
// 可以在这里添加对别的错误码的判断
default:
window.top.location.replace("<%=request.getContextPath()%>/forward!notFound");
break;
}
};
</script>
然后配置action和结果页面,最大程度显示友好界面
<default-action-ref name="unknown" />
<action name="notFound">
<result>/404.jsp</result>
</action>

List<String> 转换为String[]常用方法有?
数组转list:
Arrays类中的asList()方法 List<String> list = Arrays.asList(array)
也可以通过向ArrayList类中添加数组元素实现

List转数组:
arryList中都有toArray()方法,这里需要注意的是:toArray()方法内的如果没有参数返回的是object类型数组,如果要为string类型,则需要加:new String[list.size()]; String[] arr = list.toArray(new String[list.size()]);
或者将list中元素逐个赋值给数组。

java object类常用方法:
toString()、finallize()、equals();
重写equals方法需要注意的事项:
重写equals方法的要求:
1、自反性:对于任何非空引用x,x.equals(x)应该返回true。
2、对称性:对于任何引用x和y,如果x.equals(y)返回true,那么y.equals(x)也应该返回true。
3、传递性:对于任何引用x、y和z,如果x.equals(y)返回true,y.equals(z)返回true,那么x.equals(z)也应该返回true。
4、一致性:如果x和y引用的对象没有发生变化,那么反复调用x.equals(y)应该返回同样的结果。
5、非空性:对于任意非空引用x,x.equals(null)应该返回false。

重载与覆盖的异同:
重载:一个类中有多个同名方法,但是方法有着不同的参数。属于编译时多态,,对于继承来说,若父类方法为私有则不能重载。通过返回值类型区分不了重载(不能区分,但是真正的重载可以修改返回值类型)。
覆盖:子类可覆盖父类的方法,同样的方法在子类和父类中可以有不同的表现形式。返回值,参数和函数名要相同,同样的若父类方法为私有能不能覆盖,只是相当于新定义了一个方法。
区别:覆盖是垂直关系,重载是水平关系。覆盖要求参数一样,重载要求不一样。覆盖关系中调用的具体方法是根据对象来确定的,而重载是根据参数列表确定。

Ip地址正则表达式匹配:
ip地址的生成规则。
  IP地址,是由32位数字二进制转为四个十进制的字符串组成。
  怎么转化?下面讲解:
二进制:11111111111111111111111111111111
分为四部分:11111111.11111111.11111111.11111111
转化:2^7+2^6+2^5+2^4+2^3+2^2+2^1+2^0=255
转为十进制范围:0~255.0~255.0~255.0~255
第一部分:匹配3个0~255.(注意后面的一个点)
第二部分:匹配最后的数字0~255
一:第一段数字,分百位数十位数个位数讨论,匹配三次
((1[0-9][0-9]\.)|(2[0-4][0-9]\.)|(25[0-5]\.)|([1-9][0-9]\.)|([0-9]\.)){3}
二:用(?:pattern)匹配 pattern 但不捕获该匹配的子表达式来防止正则对每一个小的分组都进行匹配,然后拼上最后一段数字,并加上头尾标识。
^(?:(?:1[0-9][0-9]\.)|(?:2[0-4][0-9]\.)|(?:25[0-5]\.)|(?:[1-9][0-9]\.)|(?:[0-9]\.)){3}(?:(?:1[0-9][0-9])|(?:2[0-4][0-9])|(?:25[0-5])|(?:[1-9][0-9])|(?:[0-9]))$

HashMap常见问题:
hashmaop结构:数组加链表。
常见问题:
1、“你知道HashMap的工作原理吗?” “你知道HashMap的get()方法的工作原理吗?”
  HashMap是基于hashing的原理,我们使用put(key, value)存储对象到HashMap中,使用get(key)从HashMap中获取对象。当我们给put()方法传递键和值时,我们先对键调用hashCode()方法,返回的hashCode用于找到bucket位置来储存Entry对象。”这里关键点在于指出,HashMap是在bucket中储存键对象和值对象,作为Map.Entry。
2、“当两个对象的hashcode相同会发生什么?”
  因为hashcode相同,所以它们的bucket位置相同,‘碰撞’会发生。因为HashMap使用LinkedList存储对象,这个Entry(包含有键值对的Map.Entry对象)会存储在LinkedList中。(当向 HashMap 中添加 key-value 对,由其 key 的 hashCode() 返回值决定该 key-value 对(就是 Entry 对象)的存储位置。当两个 Entry 对象的 key 的 hashCode() 返回值相同时,将由 key 通过 eqauls() 比较值决定是采用覆盖行为(返回 true),还是产生 Entry 链(返回 false)。)
3、“如果两个键的hashcode相同,你如何获取值对象?”
  当我们调用get()方法,HashMap会使用键对象的hashcode找到bucket位置,然后获取值对象。如果有两个值对象储存在同一个bucket,将会遍历LinkedList直到找到值对象。找到bucket位置之后,会调用keys.equals()方法去找到LinkedList中正确的节点,最终找到要找的值对象。(当程序通过 key 取出对应 value 时,系统只要先计算出该 key 的 hashCode() 返回值,在根据该 hashCode 返回值找出该 key 在 table 数组中的索引,然后取出该索引处的 Entry,最后返回该 key 对应的 value 即可。)

什么情况下使用HashMap(),什么情况下使用LinkedHashMap()
Hashmap 是一个最常用的Map,它根据键的HashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度,遍历时,取得数据的顺序是完全随机的。 HashMap最多只允许一条记录的键为Null;允许多条记录的值为 Null;HashMap不支持线程的同步,即任一时刻可以有多个线程同时写HashMap;可能会导致数据的不一致。如果需要同步,可以用 Collections的synchronizedMap方法使HashMap具有同步的能力,或者使用ConcurrentHashMap。
LinkedHashMap 是HashMap的一个子类,保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的.也可以在构造时用带参数,按照应用次数排序。在遍历的时候会比HashMap慢,不过有种情况例外,当HashMap容量很大,实际数据较少时,遍历起来可能会比 LinkedHashMap慢,因为LinkedHashMap的遍历速度只和实际数据有关,和容量无关,而HashMap的遍历速度和他的容量有关。
一般情况下,我们用的最多的是HashMap,在Map 中插入、删除和定位元素,HashMap 是最好的选择。。如果需要输出的顺序和输入的相同,那么用LinkedHashMap 可以实现,它还可以按读取顺序来排列.

哪些map是有序的,如何实现的:
TreeMap 基于红黑树实现。
linkedhashmap,对于LinkedHashMap而言,它继承与HashMap、底层使用哈希表与双向链表来保存所有元素。

Hashtable和HashMap的区别:
1.Hashtable是Dictionary的子类,HashMap是Map接口的一个实现类;
2.Hashtable中的方法是同步 的,而HashMap中的方法在缺省情况下是非同步的。即是说,在多线程应用程序中,不用专门的操作就安全地可以使用Hashtable了;而对于 HashMap,则需要额外的同步机制。但HashMap的同步问题可通过Collections的一个静态方法得到解决:
Map Collections.synchronizedMap(Map m)
这个方法返回一个同步的Map,这个Map封装了底层的HashMap的所有方法,使得底层的HashMap即使是在多线程的环境中也是安全的。
3. 在HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。当get()方法返回null值时,即可以表示 HashMap中没有该键,也可以表示该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键, 而应该用containsKey()方法来判断。

HashMap是Hashtable的轻量级实现(非线程安全的实现),他们都完成了Map接口,主要区别在于HashMap允许空(null)键值(key),由于非线程安全,效率上可能高于Hashtable。
HashMap允许将null作为一个entry的key或者value,而Hashtable不允许。
HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因为contains方法容易让人引起误解。
Hashtable继承自Dictionary类,而HashMap是Java1.2引进的Map interface的一个实现。
最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步。
Hashtable和HashMap采用的hash/rehash算法都大概一样,所以性能不会有很大的差异。

请用代码获取TOMCAT的路径
System.getProperty("catalina.home") 

如何创建xmlhttprequest对象?
XMLHttpRequest 是 AJAX 的基础,是ajax核心引擎,所有现代浏览器均支持 XMLHttpRequest 对象,所有现代浏览器(IE7+、Firefox、Chrome、Safari 以及 Opera)均内建 XMLHttpRequest 对象
variable=new XMLHttpRequest();
为了应对所有的现代浏览器,包括 IE5 和 IE6,请检查浏览器是否支持 XMLHttpRequest 对象。如果支持,则创建 XMLHttpRequest 对象。如果不支持,则创建 ActiveXObject :
var xmlhttp;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}

session监听机制:
为了统计在线用户以及实际的登录次数等数据,可以监听session的创建、销毁等状态来达到目的。 
javax.servlet API为此提供了两个接口,包含的方法如下,各方法的名称已经对其功能有较好的描述:
attributeAdded、attributeRemoved、attributeReplaced、sessionCreated、sessionDestroyed

说出ArrayList,Vector, LinkedList的存储性能和特性
ArrayList 和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元 素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized方法(线程安全),通常性能上较ArrayList差, 而LinkedList使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。

sleep() 和 wait() 有什么区别?
sleep是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep不会释放对象锁。
wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。

线程池是什么?种类?有哪些实现?在什么情况下使用线程池?
线程池简介:
    多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力。 假设一个服务器完成一项任务所需时间为:T1 创建线程时间,T2 在线程中执行任务的时间,T3 销毁线程时间。
如果:T1 + T3 远大于 T2,则可以采用线程池,以提高服务器性能。在什么情况下使用线程池? 1.单个任务处理的时间比较短 2.将需处理的任务的数量大
一个线程池包括以下四个基本组成部分:
1、线程池管理器(ThreadPool):用于创建并管理线程池,包括 创建线程池,销毁线程池,添加新任务;
2、工作线程(PoolWorker):线程池中线程,在没有任务时处于等待状态,可以循环的执行任务;
3、任务接口(Task):每个任务必须实现的接口,以供工作线程调度任务的执行,它主要规定了任务的入口,任务执行完后的收尾工作,任务的执行状态等;
4、任务队列(taskQueue):用于存放没有处理的任务。提供一种缓冲机制。
java.util.concurrent包中提供了许多jdk自带的线程池。
1、newFixedThreadPool创建一个指定工作线程数量的线程池。每当提交一个任务就创建一个工作线程,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中。
2、newCachedThreadPool创建一个可缓存的线程池。这种类型的线程池特点是:
1).工作线程的创建数量几乎没有限制(其实也有限制的,数目为Interger. MAX_VALUE), 这样可灵活的往线程池中添加线程。
2).如果长时间没有往线程池中提交任务,即如果工作线程空闲了指定的时间(默认为1分钟),则该工作线程将自动终止。终止后,如果你又提交了新的任务,则线程池重新创建一个工作线程。
3、newSingleThreadExecutor创建一个单线程化的Executor,即只创建唯一的工作者线程来执行任务,如果这个线程异常结束,会有另一个取代它,保证顺序执行(我觉得这点是它的特色)。单工作线程最大的特点是可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的 。
4、newScheduleThreadPool创建一个定长的线程池,而且支持定时的以及周期性的任务执行,类似于Timer。(这种线程池原理暂还没完全了解透彻)
总结: 一.FixedThreadPool是一个典型且优秀的线程池,它具有线程池提高程序效率和节省创建线程时所耗的开销的优点。但是,在线程池空闲时,即线程池中没有可运行任务时,它不会释放工作线程,还会占用一定的系统资源。
二.CachedThreadPool的特点就是在线程池空闲时,即线程池中没有可运行任务时,它会释放工作线程,从而释放工作线程所占用的资源。但是,但当出现新任务时,又要创建一新的工作线程,又要一定的系统开销。并且,在使用CachedThreadPool时,一定要注意控制任务的数量,否则,由于大量线程同时运行,很有会造成系统瘫痪。

short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错?
short s1 = 1; s1 = s1 + 1; (s1+1运算结果是int型,需要强制转换类型)
short s1 = 1; s1 += 1;(可以正确编译)
强制类型转换注意事项:java在设计byte short char类型运算时会首先吧这些类型变量的值强制转换为int,然后对int类型计算,最后得到的值也是int,,因此两个short相加,编译器会先把两个short转为int相加,结果为int,但s1是short类型,所以会报错,如果想得到short类型,需要显示强制类型转换。 += 是java规定的运算法则,编译器会特殊处理所以不会报错。

Math类中round ceil 和 floor方法
Math类位于java.lang包下 可自动导入
Round:四舍五入 在原来数字基础上先+0.5再向下取整。
Ceil:向上取整:取大于a的最小整数。
Floor:向下取整,取小于a的最大整数。

String s=new String("xyz")究竟创建几个String Object
分为两种情况:
1.如果String常理池中,已经创建"xyz",则不会继续创建,此时只创建了一个对象new String("xyz");
2.如果String常理池中,没有创建"xyz",则会创建两个对象,一个对象的值是"xyz",一个对象new String("xyz")。

常见的几种RuntimeException:
常见的几种如下:
NullPointerException - 空指针引用异常:空指针异常。当应用试图在要求使用对象的地方使用了null时,抛出该异常。譬如:调用null对象的实例方法、访问null对象的属性、计算null对象的长度、使用throw语句抛出null等等。
ClassCastException - 类型强制转换异常。:假设有类A和B(A不是B的父类或子类),O是A的实例,那么当强制将O构造为类B的实例时抛出该异常。该异常经常被称为强制类型转换异常。
ArithmeticException - 算术运算异常:算术条件异常。譬如:整数除零等。
ArrayStoreException - 向数组中存放与声明类型不兼容对象异常:数组存储异常。当向数组中存放非数组声明类型对象时抛出
IndexOutOfBoundsException - 下标越界异常:索引越界异常。当访问某个序列的索引值小于0或大于等于序列大小时,抛出该异常。
NegativeArraySizeException - 创建一个大小为负数的数组错误异常
UnsupportedOperationException - 不支持的操作异常

接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承实体类(concrete class)?
接口可以继承接口。抽象类可以实现(implements)接口,
抽象类可继承实体类,但前提是实体类必须有明确的构造函数。

说出数据连接池的工作机制是什么?
J2EE 服务器启动时会建立一定数量的池连接,并一直维持不少于此数目的池连接。客户端程序需要连接时,池驱动程序会返回一个未使用的池连接并将其表记为忙。如果 当前没有空闲连接,池驱动程序就新建一定数量的连接,新建连接的数量有配置参数决定。当使用的池连接调用完成后,池驱动程序将此连接表记为空闲,其他调用 就可以使用这个连接。

JSP的内置对象及方法。
request表示HttpServletRequest对象。它包含了有关浏览器请求的信息,并且提供了几个用于获取cookie, header, 和session数据的有用的方法。
response表示HttpServletResponse对象,并提供了几个用于设置送回 浏览器的响应的方法(如cookies,头信息等)
out对象是javax.jsp.JspWriter的一个实例,并提供了几个方法使你能用于向浏览器回送输出结果。
pageContext表示一个javax.servlet.jsp.PageContext对象。它是用于方便存取各种范围的名字空间、servlet相关的对象的API,并且包装了通用的servlet相关功能的方法。
session表示一个请求的javax.servlet.http.HttpSession对象。Session可以存贮用户的状态信息
applicaton 表示一个javax.servle.ServletContext对象。这有助于查找有关servlet引擎和servlet环境的信息
config表示一个javax.servlet.ServletConfig对象。该对象用于存取servlet实例的初始化参数。
page表示从该页面产生的一个servlet实例
数据库存储过程和函数是什么:
存储过程:存储过程是 SQL 语句和可选控制流语句的预编译集合,以一个名称存储并作为一个单元处理。存储过程存储在数据库内,可由应用程序通过一个调用执行,而且允许用户声明变量、有条件执行以及其它强大的编程功能。可以进行增删查改dml操作,甚至可以进行建表等ddl操作;不能return返回值,可以用out参数返回值。用exec 过程名 的方法调用。
函数:Microsoft SQL Server 2000 允许创建用户定义函数,可以return返回值;一般来说,只能进行select操作,不能进行增删改,也不能进行ddl操作。可以通过赋值的方式调用,也可以在sql语句中使用。

jdbc的连接://标准八步
1.通过反射加载数据库驱动com.mysql.jdbc.Driver
2.通过驱动获得数据库连接
3.定义sql
4.通过连接获得preparestatement
5.设置sql参数
6.发送sql进行数据库交互
7.遍历结果集
8.释放资源关闭连接。
try {
//1、加载数据库驱动
Class.forName("com.mysql.jdbc.Driver");
//2、通过驱动管理类获取数据库链接
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8", "root", "root");
//3、定义sql语句 ?表示占位符
String sql = "select * from user where username = ?";
//4、获取预处理statement
preparedStatement = connection.prepareStatement(sql);
//5、设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值
preparedStatement.setString(1, "王五");
//6、向数据库发出sql执行查询,查询出结果集
resultSet = preparedStatement.executeQuery();
//7、遍历查询结果集
while(resultSet.next()){
User user
System.out.println(resultSet.getString("id")+" "+resultSet.getString("username"));
}
} catch (Exception e) {
e.printStackTrace();
}finally{
//8、释放资源
if(resultSet!=null){

数据库分页:
主要常用两种分页:hibernate和sql语句两种实现。
Hibernate:获取session对象,通过session获取Query对象,query对象有setFirstResult()方法来设置要查询的第一行数据,setMaxResult()设置查询结果集大小。
SQL: select * from table where 条件 limit begin,count;

数据库的左右连接:
左右连接都输入外连接,外连接指的是,当联结需要包含那些没有关联行的行时,使用OUTER JOIN,比如查询所有客户的订单,但是有些客户没有下单。
Select customer.cust_id order.ord_num from customer LEFT OUTER JOIN order ON customer.cust_id = order.cust_id;

mysql数据库有哪几种引擎,区别。
最常用的:常用的引擎主要就是:Innodb和MyIASM
Innodb引擎提供了对数据库ACID事务的支持。并且还提供了行级锁和外键的约束。Mysql运行的时候,Innodb会在内存中建立缓冲池,用于缓冲数据和索引。但是,该引擎是不支持全文搜索的。同时,启动也比较的慢,它是不会保存表的行数的。当进行Select count(*) from table指令的时候,需要进行扫描全表。所以当需要使用数据库的事务时,该引擎就是首选。由于锁的粒度小,写操作是不会锁定全表的。所以在并发度较高的场景下使用会提升效率的。

MyIASM是MySql的默认引擎,但不提供事务的支持,也不支持行级锁和外键。因此当执行Insert插入和Update更新语句时,即执行写操作的时候需要锁定这个表。所以会导致效率会降低。不过和Innodb不同的是,MyIASM引擎是保存了表的行数,于是当进行Select count(*) from table语句时,可以直接的读取已经保存的值而不需要进行扫描全表。所以,如果表的读操作远远多于写操作时,并且不需要事务的支持的。可以将MyIASM作为数据库引擎的首选。
两种引擎的选择 :
1、大容量的数据集时趋向于选择Innodb。因为它支持事务处理和故障的恢复。Innodb可以利用数据日志来进行数据的恢复。主键的查询在Innodb也是比较快的。
2、大批量的插入语句时(这里是INSERT语句)在MyIASM引擎中执行的比较的快,但是UPDATE语句在Innodb下执行的会比较的快,尤其是在并发量大的时候。

mysql的锁机制
根据锁的类型分,可以分为共享锁,排他锁,意向共享锁和意向排他锁。根据锁的粒度分,又可以分为行锁,表锁。
共享锁的代号是S,是Share的缩写,共享锁的锁粒度是行或者元组(多个行)。
排它锁的代号是X,是eXclusive的缩写,排它锁的粒度与共享锁相同。
意向锁是一种表锁,锁定的粒度是整张表,分为意向共享锁(IS)和意向排它锁(IX)两类。意向共享锁表示一个事务有意对数据上共享锁或者排它锁。有意向 的意思就是指事务想做这个但是做没做成还未定。
比如一个事务t执行了这样一个语句:select * from table lock in share model ,如果这个语句执行成功,就对表table上了一个意向共享锁。lock in share model就是说事务t1在接下来要执行的语句中要获取S锁。如果t1的select * from table lock in share model执行成功,那么接下来t1应该可以畅通无阻的去执行只需要共享锁的语句了。

为什么索引能提高数据库查找速度:
首先明白为什么索引会增加速度,DB在执行一条Sql语句的时候,默认的方式是根据搜索条件进行全表扫描,遇到匹配条件的就加入搜索结果集合。如果我们对某一字段增加索引,查询时就会先去索引列表中一次定位到特定值的行数,大大减少遍历匹配的行数,所以能明显增加查询的速度。索引是B树结构,查找时间复杂度O(log2N)

Java常用缓存cache实现:
缓存,就是将程序或系统经常要调用的对象存在内存中,一遍其使用时可以快速调用,不必再去创建新的重复的实例。
这样做可以减少系统开销,提高系统效率。
缓存主要可分为二大类:
一、通过文件缓存,顾名思义文件缓存是指把数据存储在磁盘上,不管你是以XML格式,序列化文件DAT格式还是其它文件格式;
二、内存缓存,也就是实现一个类中静态Map,对这个Map进行常规的增删查.
linux常用命令


简述synchronized和java.util.concurrent.locks.Lock的异同?
主要相同点:Lock能完成synchronized所实现的所有功能
主要不同点:Synchronized既可以加载方法上也可以加载指定代码块上,括号中表示要锁的对象,而lock需要手动指定起始和终止位置。Synchronized是托管给jvm的 而lock通过代码控制。在竞争不激烈时,Synchronized性能优于lock,反之则差于lock。 synchronized会按照反序自动释放锁,而Lock一定要求程序员手工释放,并且必须在finally从句中释放,否则会死锁。

Lock接口的使用,有哪些Lock:
lock()、tryLock()、tryLock(long time, TimeUnit unit)和lockInterruptibly()是用来获取锁的。unLock()方法是用来释放锁的。
lock()方法是平常使用得最多的一个方法,就是用来获取锁。如果锁已被其他线程获取,则进行等待。
tryLock()方法是有返回值的,它表示用来尝试获取锁,如果获取成功,则返回true,如果获取失败(即锁已被其他线程获取),则返回false,也就说这个方法无论如何都会立即返回。在拿不到锁时不会一直在那等待。
tryLock(long time, TimeUnit unit)方法和tryLock()方法是类似的,只不过区别在于这个方法在拿不到锁时会等待一定的时间,在时间期限之内如果还拿不到锁,就返回false。如果如果一开始拿到锁或者在等待期间内拿到了锁,则返回true。
lockInterruptibly()方法比较特殊,如果获得了锁则立即返回,没有获得锁则当前线程处于休眠状态,直到获得锁,或者当前线程被其他线程中断。也就使说,当两个线程同时通过lock.lockInterruptibly()想获取某个锁时,假若此时线程A获取到了锁,而线程B只有在等待,那么对线程B调用threadB.interrupt()方法能够中断线程B的等待过程。会抛出异常(InterruptedException)。

有哪些lock:
Lock接口有三个实现类,一个是ReentrantLock,另两个是ReentrantReadWriteLock类中的两个静态内部类ReadLock和WriteLock。

Java中锁的分类:
公平锁/非公平锁、可重入锁、独享锁/共享锁、乐观锁/悲观锁、分段锁、偏向锁/轻量级锁/重量级锁、自旋锁
这些分类并不是全是指锁的状态,有的指锁的特性,有的指锁的设计。
公平锁是指多个线程按照申请锁的顺序来获取锁。
可重入锁又名递归锁,是指在同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁。可重入锁的一个好处是可一定程度避免死锁。
独享锁是指该锁一次只能被一个线程所持有。
共享锁是指该锁可被多个线程所持有。对于Java ReentrantLock而言,其是独享锁。但是对于Lock的另一个实现类ReadWriteLock,其读锁是共享锁,其写锁是独享锁。读锁的共享锁可保证并发读是非常高效的。
悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。
乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于write_condition机制的其实都是提供的乐观锁。
分段锁其实是一种锁的设计,并不是具体的一种锁,对于ConcurrentHashMap而言,其并发的实现就是通过分段锁的形式来实现高效的并发操作。ConcurrentHashMap中的分段锁称为Segment,每个segment内部拥有一个Entry数组,数组中的每个元素又是一个链表,当需要put元素的时候,并不是对整个hashmap进行加锁,而是先通过hashcode来知道他要放在那一个分段中,然后对这个分段进行加锁,所以当多线程put的时候,只要不是放在一个分段中,就实现了真正的并行的插入。
偏向锁是指一段同步代码一直被一个线程所访问,那么该线程会自动获取锁。降低获取锁的代价。
轻量级锁是指当锁是偏向锁的时候,被另一个线程所访问,偏向锁就会升级为轻量级锁,其他线程会通过自旋的形式尝试获取锁,不会阻塞,提高性能。
重量级锁是指当锁为轻量级锁的时候,另一个线程虽然是自旋,但自旋不会一直持续下去,当自旋一定次数的时候,还没有获取到锁,就会进入阻塞,该锁膨胀为重量级锁。重量级锁会让其他申请的线程进入阻塞,性能降低。
自旋锁是指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁,这样的好处是减少线程上下文切换的消耗,缺点是循环会消耗CPU。

wait()、slee()区别:sleep是Thread类的方法,wait是Object类中定义的方法,sleep不释放锁,到时间自动恢复。wait释放锁,需要用notify或者notifyAll激活。

说说你所熟悉或听说过的j2ee中的几种常用模式?
Session Facade Pattern:使用SessionBean访问EntityBean
Message Facade Pattern:实现异步调用
EJB Command Pattern:使用Command JavaBeans取代SessionBean,实现轻量级访问
Data Transfer Object Factory:通过DTO Factory简化EntityBean数据提供特性
Generic Attribute Access:通过AttibuteAccess接口简化EntityBean数据提供特性
Business Interface:通过远程(本地)接口和Bean类实现相同接口规范业务逻辑一致性


工厂模式:
根据工厂模式实现的类可以根据提供的数据生成一组类中某一个类的实例,通常这一组类有一个公共的抽象父类并且 实现了相同的方法,但是这些方法针对不同的数据进行了不同的操作。首先需要定义一个基类,该类的子类通过不同的方法实现了基类中的方法。然后需要定义一个 工厂类,工厂类可以根据条件生成不同的子类实例。当得到子类的实例后,开发人员可以调用基类中的方法而不必考虑到底返回的是哪一个子类的实例。

动态加载jar包,实例化jar包中的类,并调用类中的方法:
实现方法:
1手动调用类加载器动态加载jar包;URL url = new URL("file:///C:/test_reverse.jar");
URLClassLoader myClassLoader = new URLClassLoader(new URL[] {url});、
2.应用java中的反射实例化类,得到类的一个实例;Class<?> clazz = myClassLoader.loadClass("ReverseService.java");
AbstractReverseService instance = (AbstractReverseService) clazz.newInstance();
3. 运用类实例调用类方法。instance.testJava();

三次握手建立连接四次挥手关闭连接的过程:
建立TCP需要三次握手才能建立,而断开连接则需要四次握手
首先Client端发送连接请求报文SYN,Server收到后回复ACK+SYN报文,接受连接,并为这次连接分配资源。Client端接收到ACK报文后也向Server段发生ACK报文,并分配资源,这样TCP连接就建立了。
假设Client端发起中断连接请求,也就是发送FIN报文。Server端接到FIN报文后,意思是说"我Client端没有数据要发给你了,但是如果你还有数据没有发送完成,则不必急着关闭Socket,可以继续发送数据。所以你先发送ACK,告诉Client端,你的请求我收到了,但是我还没准备好,请继续你等我的消息"。这个时候Client端就进入FIN_WAIT状态,继续等待Server端的FIN报文。当Server端确定数据已发送完成,则向Client端发送FIN报文,"告诉Client端,好了,我这边数据发完了,准备好关闭连接了"。Client端收到FIN报文后,"就知道可以关闭连接了,但是他还是不相信网络,怕Server端不知道要关闭,所以发送ACK后进入TIME_WAIT状态,如果Server端没有收到ACK则可以重传。“,Server端收到ACK后,"就知道可以断开连接了"。Client端等待了2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,我Client端也可以关闭连接了。Ok,TCP连接就这样关闭了!

TCP和UDP的异同:
TCP注重数据安全性,TCP有三次握手、四次握手;UDP没有握手定则,无法确认数据传输开始跟结束,因为没有握手所以效率快一点,但是不可靠。但是其安全性却一般。
1.TCP面向连接的运输层协议,UDP无连接
2.TCP是可靠交付,UDP是尽最大努力交付
3.TCP面向字节流,UDP面向报文
4.TCP是点对点连接的,UDP一对一,一对多,多对多都可以
5.TCP适合用于网页,邮件等,UDP适合用于视频,语音广播等









JVM内存模型:
jvm中内存划分:


如上图,一共分为五块,其中:
线程共享区域为:
1、java堆 2、方法区
线程私有区域为:
3、JVM栈 4、本地方法栈 5、程序计数器
各区域作用:
1、java堆:
java堆是jvm内存管理中最大的一块,线程共享。在jvm启动的时候创建。此区域唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。但是随着JIT编译器(即时编译器)的发展与逃逸分析技术的逐渐成熟,栈上分配、标量替换优化技术将会导致一些微妙变化(对象可能会分配到栈上),所以这种所有对象都分配在堆上也不是那么绝对的。
java堆细分为新生代和老年代,新生代又分为Eden空间、From Survivor空间、To Survivor空间,新生代中垃圾回收算法为复制算法,复制算法是先将内存分为连个部分,一部分用来放入对象,而另一部分暂时不用,当使用的一部分内存要进行垃圾回收的时候会将不需要回收的对象复制保存在另一个空间中,然后再对使用过的那部分区域进行垃圾回收,这样虽然效率很高,但是很浪费空间,所以一般将新生代分为Eden空间和两个Survivor空间,其大小在HotSpot虚拟机中默认比例为8:1:1,这样在新生代中采用复制算法回收垃圾效率就很高了,具体回收过程是将Eden区域和From Survivor区域作为对象的存储空间,当要进行垃圾回收的时候先将这两个区域中不需要回收的对象复制保存在To Survivor区域中,然后再进行垃圾回收。另外有一点是当一个对象在Eden区域和From Survivor区域中存储的时候发现内存不足,这时会进行内存分配担保,就是将此对象直接存入在老年代中。
老年代中采用的GC算法为标记-清除算法或者标记-整理算法。标记-清除算法为:首先标记出要进行GC的对象,标记完成后再进行GC。这种算法效率不高,并且会产生很多内存碎片。标记-整理算法:同样是先对要进行GC的对象进行标记,但是不同的是在标记完成后不是立刻执行GC,而是先将不需要GC的对象移动到一端,然后在边界外再对要回收的对象进行GC。
关于对象的分配:对象优先在Eden区域分配,大对象会直接进入老年代,长期存活的对象会进入老年代,这里的长期存活是根据新生代中的对象年龄阈值来定义的,对象刚分配到新生代的时候年龄为1,每进行一次GC对象的年龄会加1,HotSpot中默认的阈值是15,也就是说对象年龄达到15岁的时候会被分配到老年区,这个值是可以通过参数配置的。
在进行垃圾回收的时候新生代GC又叫minor GC,老年代GC可以设置内存容量达到百分比的多少的时候进行GC,老年代的GC又叫Full GC,minor GC时间短,频率高,而Full GC时间长,频率低。

2、方法区
方法区又被称为永久区,线程共享,是用来存储已被JVM加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。方法区为堆的一个逻辑部分,但是在JDK1.7的HotSpot中已经将方法区中的字符串常量池移出,部分资料显示JDK1.8已经去除了方法区(不确定)。不过已经可以猜测此区域将会被本地内存逐步取代。
这个区域很少进行垃圾回收,回收目标主要是针对常量池的回收和对类型的卸载。

3、JVM栈
JVM栈是线程私有的,它的生命周期与线程相同。JVM栈描述的是java方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。
局部变量表中存放了编译期可知的各种基本数据类型、对象的引用类型。局部变量表中需要的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小。

4、本地方法栈
本地方法栈和JVM栈非常相似,它们之间的区别不过是jvm栈是为执行java方法服务,而本地方法栈是为jvm使用到对的本地方法服务。HotSpot虚拟机中直接把本地方法栈和JVM栈合二为一了。

5、程序计数器
程序计数器是一块较小的内存空间,线程私有。它可以看作是当前线程所执行的字节码的行号指示器。在jvm的概念模型里,字节码解释器工作就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。
如果线程正在执行的是一个java方法,这个计数器记录的是正在执行的jvm字节码指令的地址;如果正在执行的是本地方法,这个计数器值则为空。

描述一下JVM加载class文件的原理机制?
JVM中类的装载是由ClassLoader和它的子类来实现的,Java ClassLoader 是一个重要的Java运行时系统组件。它负责在运行时查找和装入类文件的类。Java中所有类只有被加载到jvm中才能运行,当运行指定程序时,jvm会将编译生成的.class文件按照需求和一定规则加载到内存中,这个工作就是类加载器完成的。
类加载器工作方式分为隐式加载和显示加载两种,隐式:指在程序使用new等方法创建对象时会隐式调用类加载器吧对应类加载到内存里,显式:通过直接调用class.forName(class)方法来创建所需类的对象。
Java中类加载是动态的,他不会一次性将所有类都加载,而且先加载保证程序可以允许的基础类(例如基类),其他类会按需加载。使用这种方法可以节省空间和加快速度。此外,每个类或者接口都单独对应一个.class文件,这些文件可以被视作一个个可动态加载的单元,当有类被修改时 只需重新编译被修改的类即可,因此加快了编译速度。
类加载器的执行步骤:
1.装载:根据指定路径查找对应class文件并导入
2.链接:检查待加载文件的正确性,给类中的静态变量分配存储空间,将符号引用转为直接引用(这一小步可选)。
3.初始化:对静态变量和静态代码块初始化。

GC是什么? 为什么要有GC? GC分类
   GC是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以 自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法。
一、serial GC(发展最久,单线程的,用复制算法。不适合大型服务器,适用于简单客户端)
二、Parallel GC(并行多线程,吞吐量较大,被称作吞吐量优先GC)
三、Serial OLD 和parallel OLD(老年代版本,使用标记-整理算法)
四、CMS GC(基于标记-清除算法,以获得最短停顿为目标,适合大型互联网、B/S服务器)
五、
GC的分代回收
分代回收中将内存分成了3代:年轻代,年老代,持久代。
年轻代一般内分为eden区和两个survivor区。eden区存储刚刚建立的新对象。eden区满后,将还存活的对象复制到一个survivor区中,然后这个survivor区满了以后,将还存活的对象复制到第二个survivor区中去,同时清空第一个survivor区。第二个区满了以后,从第一个survior复制过来并且还存活的对象将被复制到年老代。
年老代存储的是生命周期比较长的对象,年老代用标记+清理的方法进行GC。
持久代一般存放静态对象,class,方法等,持久代对垃圾回收基本没有影响。
由于对象进行了分代处理,因此垃圾回收区域、时间也不一样。GC有两种类型:Scavenge GC和Full GC。
一般情况下,当新对象生成,并且在Eden申请空间失败时,就会触发Scavenge GC,对Eden区域进行GC,清除非存活对象,并且把尚且存活的对象移动到Survivor区。然后整理Survivor的两个区。
Full GC是对三代都进行处理,所以比Scavenge GC要慢,应该尽量减少full GC。
触发full GC通常以下原因:年老代(Tenured)被写满· 持久代(Perm)被写满 · System.gc()被显示调用等。

JAVA内存泄漏情况:
内存泄漏的定义:对象已经没有被应用程序使用,但是垃圾回收器没办法移除它们,因为还在被引用着。
一般两种情况:在堆中申请的空间没有被释放、对象已经没有被使用但仍然在内存中保留着。
在java中出现内存泄漏一般是以下几点:
1.静态集合。他们的生命周期与程序一致,容器中的对象在程序结束前不能被释放。
2.各种连接(数据库连接,IO,网络连接等),使用完毕后没有close(); 这样就没有被gc回收。
3.在用到监听器时,当被监听对象释放后没有删除监听器。
4.变量的作用域大于其实际适用范围
5.单例模式(饿汉)可能会导致内存泄漏,因为有一个private static 的单例对象。

spring解耦原理:
依靠IOC,IOC理论提出的观点大体是这样的:借助于“第三方”实现具有依赖关系的对象之间的解耦
普通java实现功能时,每个类中都要new一些对象,也就是所谓的依赖关系,类与类之间直接互相调用,互相依赖,关系错综复杂,而对象交由spring管理后,对象在使用的时候不是去new,而是通过IOC容器获取,对象与对象之间不再有直接联系,他们通过中间人IOC容器联系。Spring IOC 容器 通过反射拿到对象的实例,使类的功能更加单一化,减少了类与类的依赖关系,降低了耦合
调用者和被调用者没有直接联系,就是解藕了,这个关系被容器维护着,虽然a通过IOC容器取到了b,但是a不知道他引用了b,引用b这个行为并不是由a决定的,而是由容器决定的,就如主板接口在那,他不会要求我必须插具体的某个显卡,而只是符合接口的显卡就可以了,这个决定权归组装的人决定
IOC的别名:依赖注入(DI):所谓控制反转,就是获得依赖对象的过程被反转了。控制被反转之后,获得依赖对象的过程由自身管理变为了由IOC容器主动注入,这个定义实际上给出了实现IOC的方法:注入。所谓依赖注入,就是由IOC容器在程序运行期间动态的将某种依赖关系注入到对象中。

spring 的优点:
.降低了组件之间的耦合性 ,实现了软件各层之间的解耦
2.可以使用容易提供的众多服务,如事务管理,消息服务等
3.容器提供单例模式支持
4.容器提供了AOP技术,利用它很容易实现如权限拦截,运行期监控等功能
5.容器提供了众多的辅助类,能加快应用的开发
6.spring对于主流的应用框架提供了集成支持,如hibernate,JPA,Struts等
7.spring属于低侵入式设计,代码的污染极低
8.独立于各种应用服务器
9.spring的DI机制降低了业务对象替换的复杂性
10.Spring的高度开放性,并不强制应用完全依赖于Spring,开发者可以自由选择spring的部分或全部

struts1和struts2区别
1、struts1的action类继承一个抽象类,而struts2的action实现一个接口,更灵活,从而实现服务定制,同时提供常用的actionSupport接口实现,且接口不是必须的。
2、Struts1 Action是单例模式并且必须是线程安全的Struts2 Action对象为每一个请求产生一个实例,因此没有线程安全问题。
3、 Struts1 Action 依赖于Servlet API ,因为当一个Action被调用时HttpServletRequest 和 HttpServletResponse 被传递给execute方法。 Struts 2 Action不依赖于容器,允许Action脱离容器单独被测试。
4、Struts1 使用ActionForm对象捕获输入。所有的ActionForm必须继承一个基类。因为其他JavaBean不能用作ActionForm,开发者经常创建多余的类捕获输入。• Struts 2直接使用Action属性作为输入属性,消除了对第二个输入对象的需求。
5、Struts2支持ognl表达式 1 不支持
6、 Struts 1使用标准JSP机制把对象绑定到页面中来访问。 Struts 2 使用 "ValueStack"技术,使taglib能够访问值而不需要把你的页面(view)和对象绑定起来。
7、 Struts1支持每一个模块有单独的Request Processors(生命周期),但是模块中的所有Action必须共享相同的生命周期。 
Struts2支持通过拦截器堆栈(Interceptor Stacks)为每一个Action创建不同的生命周期。堆栈能够根据需要和不同的Action一起使用。

spring事务管理:
Spring并不直接管理事务,而是提供了多种事务管理器,他们将事务管理的职责委托给Hibernate或者JTA等持久化机制所提供的相关平台框架的事务来实现。 
Spring事务管理器的接口是org.springframework.transaction.PlatformTransactionManager,通过这个接口,Spring为各个平台如JDBC、Hibernate等都提供了对应的事务管理器

spring事务回滚规则:
默认spring事务只在发生未被捕获的 runtimeexcetpion时才回滚。
spring aop 异常捕获原理:被拦截的方法需显式抛出异常,并不能经任何处理,这样aop代理才能捕获到方法的异常,才能进行回滚,默认情况下aop只捕获runtimeexception的异常,但可以通过配置来捕获特定的异常并回滚
换句话说在service的方法中不使用try catch 或者在catch中最后加上throw new runtimeexcetpion(),这样程序异常时才能被aop捕获进而回滚
解决方案:
方案1.例如service层处理事务,那么service中的方法中不做异常捕获,或者在catch语句中最后增加throw new RuntimeException()语句,以便让aop捕获异常再去回滚,并且在service上层(webservice客户端,view层action)要继续捕获这个异常并处理
方案2.在service层方法的catch语句中增加:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();语句,手动回滚,这样上层就无需去处理异常(现在项目的做法)

hibernate load get区别:
hibernate中我们知道如果要从数据库中得到一个对象,通常有两种方式,一种是通过session.get()方法,另一种就是通过session.load()方法,然后其实这两种方法在获得一个实体对象时是有区别的,在查询性能上两者是不同的。
一.load加载方式
当使用load方法来得到一个对象时,此时hibernate会使用延迟加载的机制来加载这个对象,即:当我们使用session.load()方法来加载一个对象时,此时并不会发出sql语句,当前得到的这个对象其实是一个代理对象,这个代理对象只保存了实体对象的id值,只有当我们要使用这个对象,得到其它属性时,这个时候才会发出sql语句,从数据库中去查询我们的对象。
二.get加载方式
相对于load的延迟加载方式,get就直接的多,当我们使用session.get()方法来得到一个对象时,不管我们使不使用这个对象,此时都会发出sql语句去从数据库中查询出来。
区别:当查询的数据库中不存在要查的对象,load会泡一个ObjectNotFoundException异常,而get返回null.
Get会先查询session内部缓存,若不存在接着查询二级缓存,最后查询数据库。
Load先查询session内部缓存,若数据不存在则创建代理对象,实际使用数据时才会查询二级缓存和数据库。

Struts内部工作逻辑:














中文乱码解决
Get请求乱码

Post乱码
Spring编码过滤器:在web.xml配置


String、StringBuffer与StringBuilder之间区别
String类中使用字符数组保存字符串,如下就是,因为有“final”修饰符,所以可以知道string对象是不可变的。

    private final char value[];

StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串,如下就是,可知这两种对象都是可变的。
char[] value;
StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的
速度:StringBuilder >  StringBuffer  >  String

去掉int数组中大于10 的元素
1.遍历数组元素将小于10的数输出到新的arrayList里,
2.外层循环从投开始遍历数组,遇到大于10的数,计数变量+1,进入内层循环,内层循环从尾部开始遍历数组,依次判断是否小于10,大于10则跳过,计数变量再+1,若小于10,则用该数替换外层循环中大于10 的数,结束内层循环。待外层循环也结束后,数组缩容,newarr = Arrays.copyOf(arr, 原数组长度减去计数变量值);



Collection和Collections的区别
java.util.Collection 是一个集合接口,它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java 类库中有很多具体的实现。如list(arraylis,vector,linkedlist)、set。
java.util.Collections 是一个包装类,它包含有各种有关集合操作的静态多态方法。此类不能实例化,就像一个工具类,服务于Java的Collection框架。比如说collections.sort()、Reverse、coppy、min、max方法等。

tomcat中,什么是DefaultServlet?他的功能是什么?
缺省servlet:org.apache.catalina.servlets.DefaultServlet,作用是处理其他servlet处理不到的请求
在工程的web.xml中,会配置servlet映射,所有的请求进入tomcat,都会流经servlet,如果没有匹配到任何应用指定的servlet,那么就会流到默认的servlet。默认的servlet是配置在$catalina/conf/web.xml里面的。
应用的一些静态资源就可以交给该servlet去处理,以减轻服务器压力,节省资源,如一些静态图片,一些js文件等。
如使用SpringMVC时所有资源都会被拦截,此时可以配置默认servlet处理图片、js/css等资源。
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.jpg</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.css</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>

servlet的生命周期:
web容器加载servlet,生命周期开始。通过调用servlet的init()方法进行servlet的初始化。通过调用service()方法实现,根据请求的不同调用不同的doPost/doGet()方法。结束服务,web容器调用servlet的destroy()方法。

get提交和post提交有何区别
(1)get一般用于从服务器上获取数据(get可以传递少量数据,通过拼接url),post一般用于向服务器传送数据(上传文件)
(2)请求参数,get的参数是拼接在url后面,用户在浏览器地址栏可以看到。post是放在http包的包体中。
(3)能提交的数据有区别,get方式能提交的数据只能是文本,且大小不超过1024个字节,而post不仅可以提交文本还有二进制文件。
(4) get比post快一点点。,因为get会缓存、post包含更多的请求头,且post在真正传输前会把请求头发给服务器确认。
四种会话跟踪技术/servlet、JSP四大作用域(从小到大)
page是代表与一个页面相关的对象和属性。就是一个JSP页面,或者一个servlet 类
request是是代表与客户端发出的一个请求相关的对象和属性。request和page的生命周期都是短暂的,他们之间的区别就是:一个request可以包含多个page页(include,forward以及filter)。
session是是代表与用于某个 Web 客户机的一个用户体验相关的对象和属性。一个 Web 会话可以也经常会跨越多个客户机请求,生命周期:会话开始 到 会话超时,或者服务器端强制使会话失效。
application是是代表与整个 Web 应用程序相关的对象和属性。这实质上是跨越整个 Web 应用程序,包括多个页面、请求和会话的一个全局作用域,生命周期为:应用程序启动到停止。

先看Request 消息的结构, Request 消息分为3部分,第一部分叫Request line, 第二部分叫Request header, 第三部分是body. header和body之间有个空行, 结构如下图

看下请求头Request Headers,
Accept : 指定客户端能够接收的内容类型,内容类型中的先后次序表示客户端接收的先后次序。在Ajax代码中,可以使用XMLHttpRequest 对象中setRequestHeader函数方法来动态设置这些Header信息。
Accept-Charset:浏览器可接受的字符集
  Accept-Encoding : 指定客户端浏览器可以支持的web服务器返回内容压缩编码类型,比如gzip。表示允许服务器在将输出内容发送到客户端以前进行压缩,以节约带宽。而这里设置的就是客户端浏览器所能够支持的返回压缩格式。
Accept-Language : 指定HTTP客户端浏览器用来展示返回信息所优先选择的语言。
Authorization:授权信息
  Connection : 表示是否需要持久连接。如果web服务器端看到这里的值为“Keep-Alive”,或者看到请求使用的是HTTP 1.1(HTTP 1.1默认进行持久连接),它就可以利用持久连接的优点,当页面包含多个元素时(例如Applet,图片),显著地减少下载所需要的时间。
  Content-Length : 请求头正文的长度。
  Connect-Type : 显示此HTTP请求提交的内容类型。一般只有post提交时才需要设置该属性。
  cookie : 浏览器端cookie。
  Hose : 客户端地址
Origin : 目标地址
Referer : 包含一个URL,用户从该URL代表的页面出发访问当前请求的页面
  User-Agent : 客户端信息
x-Requested-With : 是否为同步请求 ,如果为XMLHttpRequest,则为 Ajax 异步请求。为null则为传统同步请求

Session和cookie异同:
1、cookie数据存放在客户的浏览器上,session数据放在服务器上。
2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,如果涉及安全问题应当使用session。
3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应 当使用COOKIE。
4、单个cookie容量小,保存的数据不能超过4K,目前大多数浏览器限制每个域名只能保存20个左右cookie
序列化Serializable接口与Externalizable接口区别:
被Serializable接口声明的类的对象的内容都将被序列化,如果现在用户希望自己指定序列化的内容,则可以让一个类实
现Externalizable接口
实现serializable接口是默认序列化所有属性,如果有不需要序列化的属性使用transient修饰。
Externalizable接口是Serializable接口的子接口,实现这个接口需要重写writeExternal和readExternal方法:
writeExternal(ObjectOutputout):在此方法中指定要保存的属性信息,对象序列化时调用。
readExternal(ObjectInputin):在此方法中读取被保存的信息,对象反序列化时调用。

判断一个树是不是完全二叉树:
完全二叉树树主要有两点:
当一个结点有右孩子,但是没有左孩子,直接返回false
当一个节点有左孩子无右孩子,那么接下来要遍历的节点必须是叶子结点。(叶子结点左右孩子为空)
public class CompleteBinaryTree {
//检查一棵树是不是完全二叉树
public static boolean checkBTree(Node root){
if(root==null){
System.out.println("空树!");
return true; }
MyQueue<Node> queue=new MyQueue<Node>();
queue.push(root);
Node temp;
int flag=0;
while(queue.size()>0){
temp=queue.pop();
if(null!=temp.left) {
if(1==flag) { return false; }
queue.push(temp.left);
if(null!=temp.right) { queue.push(temp.right); }
else{ flag=1; }
}else{
if(null!=temp.right){ return false; }
flag=1;
} }
return true; }
如何判断两个二叉树相等?
先序遍历,递归实现。先判断根节点是否相等,然后在判断左右子树是否相等.
public class Solution{
public boolean isSameTree(TreeNode p,TreeNode q){
if (p==null&&q==null){
return true;
}
else if (p==null||q==null){
return false;
}
if(p!=null&&q!=null){
if(p.val!=q.val){
return false;
} else {
return isSameTree(p.left,q.left)&&isSameTree(p.right,q.right);
} }
return false; } }


在dubbo中如果zookeeper或者管理中心挂掉其中一个能否继续工作?为什么?
dubbo具有健壮性,监控中心挂掉不影响使用,只是会丢失部分采样数据。
在不添加新服务的情况下能正常工作,启动dubbo时,消费者会从zk拉取注册的生产者的地址接口等数据,缓存在本地。·
每次调用时,按照本地存储的地址进行调用。

单例设计模式:
饱汉:实例在开始时为空,第一次加载后才实例化,可节约一些资源,但在并发时有可能出现多个单例.
public class Test{
private test();
valatile Test test;
public static Test getInsatnce(){
if(test = =null;){
synchronized(Test.class){
if(test = =null;){
private Test test = new Test(); }
}}
return test;}}



饿汉:一上来就先实例化,但若类没有使用的话,就有点浪费资源类
public class Test{
private test();
private Test test = new Test();
public static Test getInsatnce(){
return test;
}
}
如何不用临时变量原地交换两数: 用加法运算或 异或运算。
1、a=5,b=10;a=a+b; b=a-b; a=a-b
2、a = a ^ b; b = a ^ b; a = a ^ b

按值传递和按引用传递:
按值传递时,一般是传递的参数属于基本类型的情况,方法体外的参数传值进入方法,在方法中的操作不会影响到方法体外。
按引用传递,一般是传递对象的引用,例如包装类或自定义类的对象引用,方法体内的操作会改变方法体外变量的值。如果不想有这种影响,那么在方法体中新new出一个 所传参数对应类型的对象即可。

Redis常用五大数据类型:String Hash Set List Zset(有序集合)








JAVA实现快速排序:
public static int partition(int []array,int lo,int hi){
//固定的切分方式
int key=array[lo];
while(lo<hi){
while(array[hi]>=key&&hi>lo){//从后半部分向前扫描
hi--;
}
array[lo]=array[hi];
while(array[lo]<=key&&hi>lo){从前半部分向后扫描
lo++;
}
array[hi]=array[lo];
}
array[hi]=key;
return hi;
}
public static void sort(int[] array,int lo ,int hi){
if(lo>=hi){
return ;
}
int index=partition(array,lo,hi);
sort(array,lo,index-1);
sort(array,index+1,hi);
}
JAVA实现插入排序:
public static void InsertSort(int[] arr)
{int i, j; int n = arr.Length; int target;
//假定第一个元素被放到了正确的位置上
//这样,仅需遍历1 - n-1
for (i = 1; i < n; i++)
{
j = i;
target = arr[i];
while (j > 0 && target < arr[j - 1])
{
arr[j] = arr[j - 1];
j--;
}
arr[j] = target;
}
}

猜你喜欢

转载自blog.csdn.net/playadota/article/details/78425063
今日推荐