面试宝典

jsp与servlet区别
  • JSP(Java Server Page)
    • 插入Java代码和JSP标签的html文件,是一个简化的Servlet设计
    • 返回给客户端是html文件
    • 工作流程大笑
      1. 服务端收到客户端访问jsp时
      2. 执行jsp里面的java程序
      3. 将处理完毕的Java代码结果加上JSP中的html代码一起返回
  • Servlet(server-let,)
    • 客户请求与服务器响应的中间层
    • 生命周期:
      • 初始化:有下面两种方式启动,
        • 跟应用程序同时启动,在web配置文件上加servlet—->load-on-startup标签
        • 被指定访问时启动
      • 响应请求:调用service()
        • 将接受到的ServletRequest和ServletResponse转换成HttpServletRequest和HttpServletResponse,然后根据请求方式(get,post)来调用对应的方法(doget,dopost)
      • 销毁:单例模式,调用destroy(),也可以说service()结束的时候是它的生命周期消亡
        • 容器关闭
        • 手动调用destroy()
  • 都可以动态生成网页,JSP更擅长做表现层,因为他把Java代码嵌入了html中。Servlet更适合业务层面的处理,不用关注页面可以更专注处理业务。
ArraList,LinkList,List,Vector的区别, hashmap,hashtable,hashset区别,heap,stack区别
  • ArraList,LinkList,List,Vector
    • ArraList单向链表结构的,可以看成是一个可变大小的数组,查询速度较快
    • LinkList双向链表结构,插入速度较快
    • List接口
    • Vector 单链表结构,唯一和ArrayList的不同在于Vector是线程安全的
  • HashMap,HashTable,HashSet
    • HashMap:继承Map接口,实现一个KV映射的哈希表。任何非空(non-null)的对象都可作为key或者value,线程安全的(同步)
    • HashTable:HashMap是非同步的,效率比较高,并且允许null,即null value和null key。
    • HashSet:HashSet和TreeSet是Set接口的两个通用实现,都不包含重复元素,最多只有一个null元素。其中TreeSet是有序集合,会按照自然排序进行排列的。而HashSet的会将原元素进行hash排序,加快查找速度
  • Heap和Stack的区别
    • Heap是堆内存,是JVM的内存数据区,用来存放对象实例的,先进先出原则存放数据,随即分配内存,不定长度,存在内存回收问题
    • Stack是栈内存,声明一个变量的时候是分配在Stack的,后进先出原则存放数据,顺序分配,长度一样,不存在内存回收
spring的事务管理
  • 声明式事务管理:它通过Spring AOP实现,大多数Spring用户选择声明式事务管理,因为这是对代码影响最小,因此也最符合非侵入式轻量级容器的概念。
    • 事务的回滚:建议使用声明式控制回滚,如果使用编码侵入式管理的话,会违反POJO(Plain Old Java Object简单Java对象)的定义。
      • 声明式控制回滚:默认是遇见系统异常的时候执行回滚,但是这个也是可以自己配置的,可以根据异常的不同来决定是否回滚。tx:advice—>tx:method—>[rollback-for|no-rollback-for]
      • 编码控制回滚:在代码里加入TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
  • 编程式事务管理:
  • 注解式事务管理:在类或者public方法上面加上@Transactional。前提是该类在spring配置文件上开启事务行为(<tx:annotation-driven transaction-manager="事务管理器实例名" />)
spring的事务传播类型(PROPAGATION) <转载>配置方法(<tx:method name="*" propagation="REQUIRED" />),有六种类型
REQUIRED 加入当前正要执行的事务不在另外一个事务里,那么就起一个新的事务比如说,B.B()的事务级别定义为PROPAGATION_REQUIRED, 那么由于执行A.A()的时候,A.A()已经起了事务,这时调用B.B(),B.B()看到自己已经运行在A.A()的事务内部,就不再起新的事务。而假如A.A()运行的时候发现自己没有在事务中,他就会为自己分配一个事务。这样,在A.A()或者在B.B()内的任何地方出现异常,事务都会被回滚。即使B.B()的事务已经被提交,但是A.A()在接下来fail要回滚,B.B()也要回滚
REQUIRES_NEW 这个就比较绕口了。 比如我们设计A.A()的事务级别为REQUIRED,B.B()的事务级别为REQUIRES_NEW,那么当执行到B.B()的时候,A.A()所在的事务就会挂起,B.B()会起一个新的事务,等待B.B()的事务完成以后,他才继续执行。他与PROPAGATION_REQUIRED 的事务区别在于事务的回滚程度了。因为B.B()是新起一个事务,那么就是存在两个不同的事务。如果B.B()已经提交,那么A.A()失败回滚,B.B()是不会回滚的。如果B.B()失败回滚,如果他抛出的异常被A.A()捕获,A.A()事务仍然可能提交。
SUPPORTS 如果当前在事务中,即以事务的形式运行,如果当前不再一个事务中,那么就以非事务的形式运行
MANDATORY 必须在一个事务中运行。也就是说,他只能被一个父事务调用。否则,他就要抛出异常
NOT_SUPPORTED 当前不支持事务。比如A.A()的事务级别是REQUIRED ,而B.B()的事务级别是NOT_SUPPORTED ,那么当执行到B.B()时,A.A()的事务挂起,而他以非事务的状态运行完,再继续A.A()的事务。
NESTED 理解Nested的关键是savepoint。他与REQUIRES_NEW的区别是,REQUIRES_NEW另起一个事务,将会与他的父事务相互独立,而Nested的事务和他的父事务是相依的,他的提交是要等和他的父事务一块提交的。也就是说,如果父事务最后回滚,他也要回滚的。而Nested事务的好处是他有一个savepoint。
举个栗子。执行A.A()的时候,中间有一些别的操作,然后准备调用B.B()的时候相当于一个savepoint。try-catch方式来调用B.B(),B.B()失败直接catch调用C.C()。等于说B.B()不靠谱的话直接换备胎C.C()了,总之不管什么方法都能把业务跑完。
spring的事务隔离级别(ISOLATION)
DEFAULT 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.另外四个与JDBC的隔离级别相对应
READ_UNCOMMITTED 这是事务最低的隔离级别,它充许令外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。
READ_COMMITTED 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据
REPEATABLE_READ 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)
SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读。
PS:这里解释一下上面出现的名词
  • 脏读:指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是脏数据,依据脏数据所做的操作可能是不正确的。
  • 不可重复读:指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。
  • 幻觉读:指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。
oracle sql的优化方法

1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。
2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:
select id from t where num is null
可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:
select id from t where num=0
3.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。
4.应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如:
select id from t where num=10 or num=20
可以这样查询:
select id from t where num=10
union all
select id from t where num=20
5.in 和 not in 也要慎用,否则会导致全表扫描,如:
select id from t where num in(1,2,3)
对于连续的数值,能用 between 就不要用 in 了:
select id from t where num between 1 and 3
6.下面的查询也将导致全表扫描:
select id from t where name like '%abc%'
若要提高效率,可以考虑全文检索。
7.如果在 where 子句中使用参数,也会导致全表扫描。因为SQL只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时;它必须在编译时进行选择。然而,如果在编译时建立访问计划,变量的值还是未知的,因而无法作为索引选择的输入项。如下面语句将进行全表扫描:
select id from t where num=@num
可以改为强制查询使用索引:
select id from t with(index(索引名)) where num=@num
8.应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。如:
select id from t where num/2=100
应改为:
select id from t where num=100*2
9.应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。如:
select id from t where substring(name,1,3)='abc' // oracle总有的是substr函数。
select id from t where datediff(day,createdate,'2005-11-30')=0 //查过了确实没有datediff函数。
应改为:
select id from t where name like 'abc%'
select id from t where createdate>='2005-11-30' and createdate<'2005-12-1' //
oracle 中时间应该把char 转换成 date 如: createdate >= to_date('2005-11-30','yyyy-mm-dd')
10.不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。
11.在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。
12.不要写一些没有意义的查询,如需要生成一个空表结构:
select col1,col2 into #t from t where 1=0
这类代码不会返回任何结果集,但是会消耗系统资源的,应改成这样:
create table #t(...)
13.很多时候用 exists 代替 in 是一个好的选择:
select num from a where num in(select num from b)
用下面的语句替换:
select num from a where exists(select 1 from b where num=a.num)
14.并不是所有索引对查询都有效,SQL是根据表中数据来进行查询优化的,当索引列有大量数据重复时,SQL查询可能不会去利用索引,如一表中有字段sex,male、female几乎各一半,那么即使在sex上建了索引也对查询效率起不了作用。
15.索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,因为 insert 或 update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有必要。
16.应尽可能的避免更新 clustered 索引数据列,因为 clustered 索引数据列的顺序就是表记录的物理存储顺序,一旦该列值改变将导致整个表记录的顺序的调整,会耗费相当大的资源。若应用系统需要频繁更新 clustered 索引数据列,那么需要考虑是否应将该索引建为 clustered 索引。
17.尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。
18.尽可能的使用 varchar/nvarchar 代替 char/nchar ,因为首先变长字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。
19.任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。
20.尽量使用表变量来代替临时表。如果表变量包含大量数据,请注意索引非常有限(只有主键索引)。
21.避免频繁创建和删除临时表,以减少系统表资源的消耗。
22.临时表并不是不可使用,适当地使用它们可以使某些例程更有效,例如,当需要重复引用大型表或常用表中的某个数据集时。但是,对于一次性事件,最好使用导出表。
23.在新建临时表时,如果一次性插入数据量很大,那么可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果数据量不大,为了缓和系统表的资源,应先create table,然后insert。
24.如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先 truncate table ,然后 drop table ,这样可以避免系统表的较长时间锁定。
25.尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该考虑改写。
26.使用基于游标的方法或临时表方法之前,应先寻找基于集的解决方案来解决问题,基于集的方法通常更有效。
27.与临时表一样,游标并不是不可使用。对小型数据集使用 FAST_FORWARD 游标通常要优于其他逐行处理方法,尤其是在必须引用几个表才能获得所需的数据时。在结果集中包括“合计”的例程通常要比使用游标执行的速度快。如果开发时间允许,基于游标的方法和基于集的方法都可以尝试一下,看哪一种方法的效果更好。
28.在所有的存储过程和触发器的开始处设置 SET NOCOUNT ON ,在结束时设置 SET NOCOUNT OFF 。无需在执行存储过程和触发器的每个语句后向客户端发送 DONE_IN_PROC 消息。
29.尽量避免大事务操作,提高系统并发能力。
30.尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。

j2ee设计模式

设计模式分为三种类型,共23种。
创建型模式:单例模式抽象工厂模式、建造者模式、工厂模式、原型模式。
结构型模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式
行为型模式:模版方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、职责链模式、访问者模式。

nio与传统io区别 主要有两点:
  • Buffer(缓冲区)
  • Channel(无阻塞的)
jvm虚拟机机制  
内存回收机制,哪些内存回收算法  
进程间通信  
mvc的好处  
冒泡排序算法  
亿万级数据找出最大的前10个,或者类似的大数据集处理题  
所做项目的技术结构图  
分布式环境下的性能调优  
单例模式的几种写法  
类加载顺序,几种classloader  
Spring里面的bean都是单例的吗? 默认是单例的,不过也可以让他不是<bean id="accountService" class="com.foo.DefaultAccountService" singleton="false"/>
Hibernate延迟加载  
Spring事务内部实现  

 

 

 

 

 

 

 

 

 

 

 

posted @ 2013-08-02 15:25  hhhyde  阅读(277)  评论(0编辑  收藏  举报