J2EE面试整理

hacker0ne 2014-10-14

1 web.xml加载顺序:

  context param 》 listener 》 filter 》servlet。

  相同位置的过滤器,一般按照 filter-mapping的顺序过滤,所以 编码过滤器 一般放在最前面。

2 struts2的工作流程

(1)客户端提交一个HttpServletRequest请求(.action或JSP页面)
(2)请求被提交到一系列Filter过滤器,如ActionCleanUp和FilterDispatcher等
(3)FilterDispatcher是Struts2控制器的核心,它通常是过滤器链中的最后一个过滤器
(4)请求发到FilterDispatcher后,FilterDispatcher询问ActionMapper是否需要调用某个Action来处理这个Request(一般根据URL后缀是否为.action来判断)
(5)如果ActionMapper决定需要调用某个Action,FilterDispatcher则把请求交到ActioProxy,由其进行处理.
(6)ActionProxy通过ConfigurationManager(它会访问struts.xml)询问框架的配置文件,找到需要调用的Action类.
(7)ActionProxy创建一个ActionInvocation实例,而ActionInvocation通过代理模式调用Action,(在调用之前会根据配置文件加载相关的所有Interceptor拦截器)
(8)Action执行完毕后,返回一个result字符串,此时再按相反的顺序通过Interceptor拦截器.(9)最后ActionInvocation负责根据struts.xml中配置的result元素,找到与返回值对应的result,决定进行下一步输出

1.java.util.*包的UML结构图。
2.Vector和ArrayList、LinkedList区别?Hashtable和HashMap之间的区别3.String、StringBuffer,StringBuilder之间区别。--回答--1.Collection?|?
|_List?
|?|_LinkedList?|?|_ArrayList?|?|_Vector?||_Stack|?|_Set
|_HashSet??Map?
|?|_HashMap?|?
|Dictionary?|_|_HashtableComparetor
2.?LinkedList内部以链表形式存储数据??ArrayList内部以数组形式存储数据。?
?Vector同ArrayList,不过它与ArrayList比较起来是thread-safe的。?
?Hashtable是继承了Dictionary,是线程安全的。HashMap实现了Map接口,不是线程安全的。???如何保证线程安全的?每个修改容器中数据的操作都是同步的(synchronized),因此保证了线程安全。
3.String是长度不可变的,StringBuffer和StringBuilder长度都是可以变化的。StringBuffer是线程安全的,StringBuilder不是线程安全的。

☆ 多线程有几种实现方法,都是什么?同步有几种实现方法,都是什么??
答:多线程有两种实现方法,分别是继承Thread类与实现Runnable接口?同步的实现方面有两种,分别是synchronized,wait与notify

☆  线程的基本概念、线程的基本状态以及状态之间的关系答:线程指在程序执行过程中,能够执行程序代码的一个执行单位,每个程序至少都有一个线程,也就是程序本身。Java中的线程有四种状态分别是:运行、就绪、挂起、结束 

☆  简述synchronized和java.util.concurrent.locks.Lock的异同??
答:主要相同点:Lock能完成synchronized所实现的所有功能主要不同点:Lock有比synchronized更精确的线程语义和更好的性能。synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且必须在finally从句中释放。

=============================================================

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

什么是Hibernate的并发机制?怎么去处理并发问题?    Hibernate并发机制: 
   a、Hibernate的Session对象是非线程安全的,对于单个请求,单个会话,单个的工作单元(即单个事务,单个线程),它通常只使用一次,       然后就丢弃。 
      如果一个Session 实例允许共享的话,那些支持并发运行的,例如Http request,session beans将会导致出现资源争用。 
      如果在Http Session中有hibernate的Session的话,就可能会出现同步访问Http Session。只要用户足够快的点击浏览器的“刷新”,  
      就会导致两个并发运行的线程使用同一个Session。 
   b、多个事务并发访问同一块资源,可能会引发第一类丢失更新,脏读,幻读,不可重复读,第二类丢失更新一系列的问题。  
   解决方案:设置事务隔离级别。  
     Serializable:串行化。隔离级别最高              Repeatable Read:可重复读              Read Committed:已提交数据读 
             Read Uncommitted:未提交数据读。隔离级别最差  
             设置锁:乐观锁和悲观锁。 
             乐观锁:使用版本号或时间戳来检测更新丢失,在<class>的映射中设置 optimistic-lock="all"可以在没有版本或者时间
         戳属性映射的情况下实现 版本检查,此时Hibernate将比较一行记录的每个字段的状态 行级悲观锁:Hibernate总是使用数据库的锁定机制,
   从不在内存中锁定对象!只要为JDBC连接指定一下隔 离级别,然后让数据库去搞定一切就够了。类LockMode 定义了Hibernate所需的不同
   的锁定级别:LockMode.UPGRADE,LockMode.UPGRADE_NOWAIT,LockMode.READ; 


    Hibernate与jdbc的联系 
    hibernate是jdbc的轻量级封装,包括jdbc的与数据库的连接(用hibernate.property的配置文件实现当然本质是封装了jdbc的forname), 
    和查询,删除等代码,都用面向对象的思想用代码联系起来,hibernate通过hbm 配置文件把po类的字段和数据库的字段关联起来比如数据库的id, 
    在po类中就是pravite Long id; public Long getId() public setId(Long id); 
    然后hql语句也是面向对象的,它的查询语句不是查询数据库而是查询类的,这些实现的魔法就是xml文件,其实hibernate=封装的jdbc+xml文件


    Hibernate与spring的联系 
    hibernate中的一些对象可以给Spring来管理,让Spring容器来创建hibernate中一些对象实例化。例如:SessionFactory,HibernateTemplate等。 
    Hibernate本来是对数据库的一些操作,放在DAO层,而Spring给业务层的方法定义了事务,业务层调用DAO层的方法,很好的将Hibernate的操作也加入到事务中来了。


 Hibernate自带的分页机制是什么?如果不使用Hibernate自带的分页,则采用什么方式分页?    

 1、hibernate自带的分页机制:获得Session对象后,从Session中获得Query对象。
    用Query.setFirstResult():设置要显示的第一行数据, Query.setMaxResults():设置要显示的最后一行数据。
 
 2、不使用hibernate自带的分页,可采用sql语句分页, 
    如:5:为每页显示的记录,2为当前页: select * top 5 from table where tabId not in (select tabId top (2-1)*5 from table);
         这个应该是oracle的,如果是mysql的话,用的是limit关键字

hibernate的三种状态之间如何转换 
    当对象由瞬时状态(Transient)一save()时,就变成了持久化状态。 
    当我们在Session里存储对象的时候,实际是在Session的Map里存了一份, 
    也就是它的缓存里放了一份,然后,又到数据库里存了一份,在缓存里这一份叫持久对象(Persistent)。
     Session 一 Close()了,它的缓存也都关闭了,整个Session也就失效了,     
 这个时候,这个对象变成了游离状态(Detached),但数据库中还是存在的。     
 当游离状态(Detached)update()时,又变为了持久状态(Persistent)。     
 当持久状态(Persistent)delete()时,又变为了瞬时状态(Transient),     
 此时,数据库中没有与之对应的记录。
 
 
 
 
 hibernate拒绝连接、服务器崩溃的原因?最少写5个 
 1. db没有打开   2. 网络连接可能出了问题 3. 连接配置错了 
 4. 驱动的driver,url是否都写对了 
 5. LIB下加入相应驱动,数据连接代码是否有误 6. 数据库配置可能有问题 
 7. 当前联接太多了,服务器都有访问人数限制的 
 8. 服务器的相应端口没有开,即它不提供相应的服务 
 
 
 ===============================================================================================================
  spring的事务如何配置     
 spring的声明式事务配置:     
 1. <!-- 配置sessionFactory -->  
 <bean id="sessionFactory"   class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">   
  <property name="configLocation">    
    <value>/WEB-INF/classes/hibernate.cfg.xml</value>   
  </property> 
    </bean>   
    2.  <!-- 配置事务管理器 -->  
 <bean id="transactionManager"   class="org.springframework.orm.hibernate3.HibernateTransactionManager">   
  <property name="sessionFactory">    
   <ref local="sessionFactory" />   
  </property> 
 </bean> 
    3. 配置事务特性 
        <tx:advice id="txAdvice"  transaction-manager="transactionManager">   
   <tx:attributes> 
      <tx:method name="add*" propagation="REQUIRED"/> 
      <tx:method name="update*" propagation="REQUIRED"/>                     
      <tx:method name="del*" propagation="REQUIRED"/>                     
      <tx:method name="*" read-only="true"/>                 
   </tx:attributes>        
  </tx:advice> 

    4. 配置哪些类的哪些方法配置事务        
  <aop:config> 
           <aop:pointcut id="allManagerMethod" ession="execution(* com.yyaccp.service.impl.*.*(..))"/>
            <aop:advisor advice-ref="txAdvice" pointcut-ref="allManagerMethod">
        </aop:config>

propagation定义了7个事务传播行为  
REQUIRED: 如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。  
SUPPORTS: 如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行。但是对于事务同步的事务管理器,SUPPORTS与不使用事务有少许不同。  
REQUIRES_NEW 总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。  NOT_SUPPORTED 总是非事务地执行,并挂起任何存在的事务。  NEVER 总是非事务地执行,如果存在一个活动事务,则抛出异常  
NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务, 则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行。  
嵌套事务一个非常重要的概念就是内层事务依赖于外层事务。外层事务失败时,会回滚内层事务所做的动作。而内层事务操作失败并不会引起外层事务的回滚。 

=========================================================================

缓存管理 
  Hibernate 中提供了两级Cache,第一级别的缓存是Session级别的缓存,它是属于事务范围的缓存。这一级别的缓存由hibernate管理的,
一般情况下无需进行干预;第二级别的缓存是SessionFactory级别的缓存,它是属于进程范围或群集范围的缓存。这一级别的缓存可以进行
配置和更改,并且可以动态加载和卸载。 Hibernate还为查询结果提供了一个查询缓存,它依赖于第二级缓存。 
  1. 一级缓存和二级缓存的比较:第一级缓存 第二级缓存 存放数据的形式 相互关联的持久化对象 对象的散装数据 缓存的范围 事务范围,
每个事务都有单独的第一级缓存进程范围或集群范围,缓存被同一个进程或集群范围内的所有事务共享 并发访问策略由于每个事务都拥有单
独的第一级缓存,不会出现并发问题,无需提供并发访问策略由于多个事务会同时访问第二级缓存中相同数据,因此必须提供适当的并发访
问策略,来保证特定的事务隔离级别 数据过期策略没有提供数据过期策略。处于一级缓存中的对象永远不会过期,除非应用程序显式清空
缓存或者清除特定的对象必须提供数据过期策略,如基于内存的缓存中的对象的最大数目,允许对象处于缓存中的最长时间,以及允许对象
处于缓存中的最长空闲时间 物理存储介质内存内存和硬盘。对象的散装数据首先存放在基于内在的缓存中,当内存中对象的数目达到数据
过期策略中指定上限时,就会把其余的对象写入基于硬盘的缓存中。缓存的软件实现 在Hibernate的Session的实现中包含


了缓存的实现由第三方提供,Hibernate仅提供了缓存适配器(CacheProvider)。用于把特定的缓存插件集成到Hibernate中。启用缓存的方
式只要应用程序通过Session接口来执行保存、更新、删除、加载和查询数据库数据的操作,Hibernate就会启用第一级缓存,把数据库中的
数据以对象的形式拷贝到缓存中,对于批量更新和批量删除操作,如果不希望启用第一级缓存,可以绕过Hibernate API,直接通过JDBC API
来执行指操作。用户可以在单个类或类的单个集合的粒度上配置第二级缓存。如果类的实例被经常读但很少被修改,就可以考虑使用第二级
缓存。只有为某个类或集合配置了第二级缓存,Hibernate在运行时才会把它的实例加入到第二级缓存中。 用户管理缓存的方式第一级缓存的
物理介质为内存,由于内存容量有限,必须通过恰当的检索策略和检索方式来限制加载对象的数目。Session的evit()方法可以显式清空缓存
中特定对象,但这种方法不值得推荐。 第二级缓存的物理介质可以是内存和硬盘,因此第二级缓存可以存放大量的数据,数据过期策略
的maxElementsInMemory属性值可以控制内存中的对象数目。管理第二级缓存主要包括两个方面:选择需要使用第二级缓存的持久类,设置
合适的并发访问策略:选择缓存适配器,设置合适的数据过期策略。
 
  2. 一级缓存的管理: 当应用程序调用Session的save()、update()、savaeOrUpdate()、get()或load(),
以及调用查询接口的 list()、iterate()或filter()方法时,如果在Session缓存中还不存在相应的对象,Hibernate就会把该
对象加入到第一级缓存中。当清理缓存时,Hibernate会根据缓存中对象的状态变化来同步更新数据库。 Session为应用程序提
供了两个管理缓存的方法: evict(Object obj):从缓存中清除参数指定的持久化对象。 clear():清空缓存中所有持久化对象。   

3. 二级缓存的管理: 

3.1. Hibernate的二级缓存策略的一般过程如下: 
  1) 条件查询的时候,总是发出一条select * from table_name where …. (选择所有字段)这样的SQL语句查询数据库,
一次获得所有的数据对象。   
  2) 把获得的所有数据对象根据ID放入到第二级缓存中。 
  3) 当Hibernate根据ID访问数据对象的时候,首先从Session一级缓存中查;查不到,如果配置了二级缓存,那么从二级缓存
中查;查不到,再查询数据库,把结果按照ID放入到缓存。   4) 删除、更新、增加数据的时候,同时更新缓存。  
  Hibernate的二级缓存策略,是针对于ID查询的缓存策略,对于条件查询则毫无作用。为此,Hibernate提供了针对条件查询的Query Cache。 
 
3.2. 什么样的数据适合存放到第二级缓存中? 
1 很少被修改的数据 
2 不是很重要的数据,允许出现偶尔并发的数据 
3 不会被并发访问的数据 
4 参考数据,指的是供应用参考的常量数据,它的实例数目有限,它的实例会被许多其他类的实例引用,实例极少或者从来不会被修改。   

3.3. 不适合存放到第二级缓存的数据?
 1 经常被修改的数据 2 财务数据,绝对不允许出现并发 3 与其他应用共享的数据。 
  3.4. 常用的缓存插件 Hibernater 的二级缓存是一个插件,下面是几种常用的缓存插件:   

  EhCache:可作为进程范围的缓存,存放数据的物理介质可以是内存或硬盘,对Hibernate的查询缓存提供了支持。 
  OSCache:可作为进程范围的缓存,存放数据的物理介质可以是内存或硬盘,提供了丰富的缓存数据过期策略,对Hibernate的查询缓存提供了支持
  SwarmCache:可作为群集范围内的缓存,但不支持Hibernate的查询缓存。 
  JBossCache:可作为群集范围内的缓存,支持事务型并发访问策略,对Hibernate的查询缓存提供了支持。 
  
3.5. 配置二级缓存的主要步骤: 
  1) 选择需要使用二级缓存的持久化类,设置它的命名缓存的并发访问策略。这是最值得认真考虑的步骤。 
  2) 选择合适的缓存插件,然后编辑该插件的配置文件。

相关推荐