框架面试题二

89、阐述Struts 2中的Action如何编写?Action是否采用了单例?

答:Struts2的Action有三种写法:

①POJO

②实现Action接口重写execute()方法

③继承ActionSupport类

一个请求对应一个Action实例,struts2是多例的

90、Struts 2中的Action并没有直接收到用户的请求,那它为什么可以处理用户的请求,又凭什么知道一个请求到底交给哪个Action来处理?

答:Struts2的核心过滤器接收到用户请求后,会对用户的请求进行简单的预处理(例如解析、封装参数),然后通过反射来创建Action实例,并调用Action中指定的方法来处理用户请求。

91、你经常用到的Struts 2常量配置有哪些?

答:

①struts.i18n.encoding– 指定默认编码

②struts.objectFactory/ struts.objectFactory.spring.autoWire – 对象工厂 / Spring的自动装配方式(名字、类型)

③struts.devMode– 是否使用开发模式

⑥struts.enable.DynamicMethodInvocation– 是否允许动态方法调用

92、简述Struts2的异常处理机制。

答:Struts 2提供了声明式的异常处理机制,可以在配置文件中加入如下代码:

<global-exception-mappings>

<exception-mapping exception=”…” result=”…”/>

</global-exception-mappings>

95、简述拦截器的工作原理以及你在项目中使用过哪些自定义拦截器。

答:Struts 2中定义了拦截器的接口以及默认实现,实现了Interceptor接口或继承了AbstractInterceptor的类可以作为拦截器。

接口中的init()方法在拦截器被创建后立即被调用,它在拦截器的生命周期内只被调用一次,可以在该方法中对相关资源进行必要的初始化。每拦截一个请求,intercept()方法就会被调用一次。destory()方法将在拦截器被销毁之前被调用, 它在拦截器的生命周期内也只被调用一次。

97、谈一下拦截器和过滤器的区别。

①拦截器是基于Java反射机制的,而过滤器是基于接口回调的。

②过滤器依赖于Servlet容器,而拦截器不依赖于Servlet容器。

③拦截器只能对Action请求起作用,而过滤器可以对所有请求起作用。

④拦截器可以访问Action上下文、值栈里的对象,而过滤器不能。

100、Struts 2中如何访问HttpServletRequest、HttpSession和ServletContext三个域对象

答:有两种方式:

①通过ServletActionContext的方法获得;

②通过ServletRequestAware、SessionAware和ServletContextAware接口注入

101、Struts 2中的默认包struts-default有什么作用?

答:它定义了Struts 2内部的众多拦截器和Result类型,而Struts 2很多核心的功能都是通过这些内置的拦截器实现,如:从请求中把请求参数封装到action、文件上传和数据验证等等都是通过拦截器实现的。在Struts 2的配置文件中,自定义的包继承了struts-default包就可以使用Struts 2为我们提供的这些功能。

102、简述值栈(Value-Stack)的原理和生命周期

答:Value-Stack贯穿整个 Action 的生命周期,保存在request作用域中,所以它和request的生命周期一样。当Struts 2接受一个请求时,会创建ActionContext、Value-Stack和Action对象,然后把Action存放进Value-Stack,所以Action的实例变量可以通过OGNL访问。由于Action是多实例的,和使用单例的Servlet不同,  每个Action都有一个对应的Value-Stack,Value-Stack存放的数据类型是该Action的实例,以及该Action中的实例变量,Action对象默认保存在栈顶。

103、SessionFactory是线程安全的吗?Session是线程安全的吗,两个线程能够共享同一个Session吗?

答:SessionFactory对应Hibernate的一个数据存储的概念,它是线程安全的,可以被多个线程并发访问。SessionFactory一般只会在启动的时候构建。对于应用程序,最好将SessionFactory通过单例的模式进行封装以便于访问。Session是一个轻量级非线程安全的对象(线程间不能共享session),它表示与数据库进行交互的一个工作单元。Session是由SessionFactory创建的,在任务完成之后它会被关闭。Session是持久层服务对外提供的主要接口.。Session会延迟获取数据库连接(也就是在需要的时候才会获取)。为了避免创建太多的session,可以使用ThreadLocal来取得当前的session,无论你调用多少次getCurrentSession()方法,返回的都是同一个session。

104、Session的load和get方法的区别是什么?

答:主要有以下三项区别:

① 如果没有找到符合条件的记录, get方法返回null,load方法抛出异常

②get方法直接返回实体类对象, load方法返回实体类对象的代理

③ 在Hibernate 3之前,get方法只在一级缓存(内部缓存)中进行数据查找, 如果没有找到对应的数据则越过二级缓存, 直接发出SQL语句完成数据读取; load方法则可以充分利用二级缓存中的现有数据;当然从Hibernate 3开始,get方法不再是对二级缓存只写不读,它也是可以访问二级缓存的

105.简述hibernate三种状态


对于load方法, 如果一级缓存查询失败则查询二级缓存, 如果二级缓存命中则直接返回

107、Query接口的list方法和iterate方法有什么区别?

答:

1) list方法无法利用缓存,它对缓存只写不读; iterate方法可以充分利用缓存, 如果目标数据只读或者读取频繁, iterate可以减少性能开销

108、Hibernate如何实现分页查询?

答:通过Hibernate实现分页查询,开发人员只需要提供HQL语句、查询起始行数

(setFirstresult()方法)和最大查询行数(setMaxResult()方法),并调用Query接口的list()方法,Hibernate会自动生成分页查询的SQL语句。


临时状态:当new一个实体对象后,这个对象处于临时状态,即这个对象只是一个保存临时数据的内存区域,如果没有变量引用这个对象,则会被JVM的垃圾回收机制回收。

这个对象所保存的数据与数据库没有任何关系,除非通过Session的save或者saveOrUpdate把临时对象与数据库关联,并把数据插入或者更新到数据库,这个对象才转换为持久对象

持久状态:持久化对象的实例在数据库中有对应的记录,并拥有一个持久化标识。

对持久化对象进行delete操作后,数据库中对应的记录将被删除,那么持久化对象与数据库记录不再存在对应关系,持久化对象变成临时状态。

持久化对象被修改变更后,不会马上同步到数据库,直到数据库事务提交。

  • 游离状态:当Session进行了close、clear或者evict后,持久化对象虽然拥有持久化标识符和与数据库对应记录一致的值,但是因为会话已经消失,对象不在持久化管理之内,所以处于游离状态(也叫脱管状态)。游离状态的对象与临时状态对象是十分相似的,只是它还含有持久化标识。

111、如何理解Hibernate的延迟加载机制。在实际应用中,延迟加载与session关闭的矛盾是如何处理的?

答:延迟加载就是并不是在读取的时候就把数据加载进来,而是等到使用时再加载。Hibernate使用了虚拟代理机制实现延迟加载。返回给用户的并不是实体本身,而是实体对象的代理。代理对象在用户调用getter方法时就会去数据库加载数据。但加载数据就需要数据库连接。而当我们把会话关闭时,数据库连接就同时关闭了。

延迟加载与session关闭的矛盾一般可以这样处理:

① 关闭延迟加载特性。这种方式操作起来比较简单,因为hibernate的延迟加载特性是可以通过映射文件或者注解进行配置的,但这种解决方案存在明显的缺陷。首先,出现no session or session was closed就证明了系统中已经存在主外键关联,如果去掉延迟加载的话,则每次查询的开销都会变得很大。

②在session关闭之前先获取需要查询的数据(Hibernate.initialize()方法)。

③ 使用拦截器(Interceptor)或过滤器(Filter)控制Session。

112、举一个多对多关联的例子,并说明如何实现多对多关联映射。

答:例如:商品和订单、学生和课程都是典型的多对多关系。可以在实体类上通过@ManyToMany注解配置多对多关联或者通过映射文件中的<set>和<many-to-many>标签配置多对多关联,但是通常情况下,可以将多对多关联转换成两个多对一关联来实现多对多关联映射。

115、谈一谈Hibernate的一级缓存、二级缓存和查询缓存。

答:Hibernate的Session提供了一级缓存的功能,默认总是有效的,当应用程序保存持久化实体、修改持久化实体时,Session并不会立即把这种改变提交到数据库,而是缓存在当前的Session中,除非显示调用了Session的flush()方法或通过close()方法关闭Session。通过一级缓存,可以减少程序与数据库的交互,从而提高数据库访问性能。

SessionFactory级别的二级缓存是全局性的,所有的Session可以共享这个二级缓存。不过二级缓存默认是关闭的,需要显示开启并指定需要使用哪种二级缓存实现类(可以使用第三方提供的实现)。一旦开启了二级缓存并设置了需要使用二级缓存的实体类,SessionFactory就会缓存访问过的该实体类的每个对象,除非缓存的数据超出了指定的缓存空间。

一级缓存和二级缓存都是对整个实体进行缓存,不会缓存普通属性,如果希望对普通属性进行缓存,可以使用查询缓存。查询缓存是将HQL或SQL语句以及它们的查询结果作为键值对进行缓存,对于同样的查询可以直接从缓存中获取数据。查询缓存默认也是关闭的,需要显示开启。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值