1 Struts2面试题
1.1 struts2工作流程
Struts 2框架本身大致可以分为3个部分:核心控制器FilterDispatcher、业务控制器Action和用户实现的企业业务逻辑组件。
- 核心控制器FilterDispatcher是Struts 2框架的基础,包含了框架内部的控制流程和处理机制。
- 业务控制器Action和业务逻辑组件是需要用户来自己实现的。用户在开发Action和业务逻辑组件的同时,还需要编写相关的配置文件,供核心控制器FilterDispatcher来使用。
Struts 2的基本简要流程如下:
- 1 、客户端初始化一个指向Servlet容器的请求;
- 2、 这个请求经过一系列的过滤器(Filter)
(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,
这个过滤器对于Struts2和其他框架的集成很有帮助,例如:SiteMesh Plugin) - 3 、接着FilterDispatcher被调用,
FilterDispatcher询问ActionMapper来决定这个请是否需要调用某个Action - 4、如果ActionMapper决定需要调用某个Action,
FilterDispatcher把请求的处理交给ActionProxy - 5、ActionProxy通过Configuration Manager询问框架的配置文件,
找到需要调用的Action类 - 6、ActionProxy创建一个ActionInvocation的实例。
- 7、ActionInvocation实例使用命名模式来调用,
在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。 - 8、一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果 。返回结果通常是(但不总是,也可 能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版。 在表示的过程中可以使用Struts2 框架中继承的标签。 在这个过程中需要涉及到ActionMapper
- 9、响应的返回是通过我们在web.xml中配置的过滤器
- 10、如果ActionContextCleanUp是当前使用的,则FilterDispatecher将不会清理sreadlocal ActionContext;如果ActionContextCleanUp不使用,则将会去清理sreadlocals。
1.2 拦截器和过滤器的区别
- 1、拦截器是基于java反射机制的,而过滤器是基于函数回调的。
- 2、过滤器依赖于servlet容器,而拦截器不依赖于servlet容器。
- 3、拦截器只能对Action请求起作用,而过滤器则可以对几乎所有请求起作用。
- 4、拦截器可以访问Action上下文、值栈里的对象,而过滤器不能。
- 5、在Action的生命周期中,拦截器可以多次调用,而过滤器只能在容器初始化时被调用一次。
1.3 struts2有哪些优点?
- 1.在软件设计上Struts2的应用可以不依赖于Servlet API和struts API。 Struts2的这种设计属于无侵入式设计;
- 2.拦截器,实现如参数拦截注入等功能;
- 3.类型转换器,可以把特殊的请求参数转换成需要的类型;
- 4.多种表现层技术,如:JSP、freeMarker、Velocity等;
- 5.Struts2的输入校验可以对指定某个方法进行校验;
- 6.提供了全局范围、包范围和Action范围的国际化资源文件管理实现
1.4 struts2是如何启动的?
struts2框架是通过Filter启动的,即StrutsPrepareAndExecuteFilter,此过滤器为struts2的核心过滤器;
StrutsPrepareAndExecuteFilter的init()方法中将会读取类路径下默认的配置文件struts.xml完成初始化操作。struts2读取到struts.xml的内容后,是将内容封装进javabean对象然后存放在内存中,以后用户的每次请求处理将使用内存中的数据,而不是每次请求都读取struts.xml文件。
1.5 struts2框架的核心控制器是什么?它有什么作用?
- Struts2框架的核心控制器是StrutsPrepareAndExecuteFilter。
- 作用:
负责拦截由/*指定的所有用户请求,当用户请求到达时,该Filter会过滤用户的请求。默认情况下,如果用户请求的路径 不带后缀或者后缀以.action结尾,这时请求将被转入struts2框架处理,否则struts2框架将略过该请求的处理。
可以通过常量”struts.action.extension”修改action的后缀,如:
<constant name="struts.action.extension" value="do"/>
如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号(,)隔开。
<constant name="struts.action.extension" value="do,go"/>
1.6 struts2配置文件的加载顺序?
struts2框架要能执行,必须先加载StrutsPrepareAndExecuteFilter.
在StrutsPrepareAndExecuteFilter的init方法中对Dispatcher进行了初始化.
在Dispatcher类中定义的init方法内就描述了struts2配置文件加载的顺序
在开发中,后加载文件中的配置会将先加载文件中的配置覆盖。
1.7 struts2常量的修改方式?
常量可以在struts.xml或struts.properties中配置,两种配置方式如下:
- 在struts.xml文件中配置常量
<constant name="struts.action.extension" value="do"/>
- 在struts.properties中配置常量(struts.properties文件放置在src下):
struts.action.extension=do
1.8 struts2中的默认包struts-default有什么作用?
- struts-default包是由struts内置的,它定义了struts2内部的众多拦截器和Result类型,而Struts2很多核心的功能都是通过这些内置的拦截器实现,如:从请求中
把请求参数封装到action、文件上传和数据验证等等都是通过拦截器实现的。当包继承了struts-default包才能使用struts2为我们提供的这些功能。 - struts-default包是在struts-default.xml中定义,struts-default.xml也是Struts2默认配置文件。 Struts2每次都会自动加载 struts-default.xml文件。
- 通常每个包都应该继承struts-default包。
1.9 值栈ValueStack的原理与生命周期?
- ValueStack贯穿整个 Action 的生命周期,保存在request域中,所以ValueStack和request的生命周期一样。当Struts2接受一个请求时,会迅速创建ActionContext, ValueStack,action。然后把action存放进ValueStack,所以action的实例变量可以被OGNL访问。 请求来的时候,action、ValueStack的生命开始,请求结束,action、 ValueStack的生命结束;
- action是多例的,和Servlet不一样,Servelt是单例的;
- 每个action的都有一个对应的值栈,值栈存放的数据类型是该action的实例,以及该action中的实例变量,Action对象默认保存在栈顶;
- ValueStack本质上就是一个ArrayList;
- 关于ContextMap,Struts 会把下面这些映射压入 ContextMap 中:
parameters :该 Map 中包含当前请求的请求参数
request :该 Map 中包含当前 request 对象中的所有属性
session :该 Map 中包含当前 session 对象中的所有属性
application :该 Map 中包含当前 application 对象中的所有属性
attr :该 Map 按如下顺序来检索某个属性: request, session,application
- 使用OGNL访问值栈的内容时,不需要#号,而访问request、session、application、attr时,需要加#号;
- 注意: Struts2中,OGNL表达式需要配合Struts标签才可以使用。如:
- 在struts2配置文件中引用ognl表达式 ,引用值栈的值 ,此时使用的”$”,而不是#或者%;
2 hibernate
2.1 Hibernate的持久化类状态
- Transient瞬时态:
特点:持久化对象没有唯一标识OID.没有纳入Session的管理. - Persistent持久态:
特点:持久化对象有唯一标识OID.已经纳入到Session的管理.
结论:持久化持久态对象有自动更新数据库的能力.自动更新数据库的能力依赖了Hibernate的一级缓存. - Detached脱管态:
特点:持久化对象有唯一标识OID,没有纳入到Session管理.
区分三种持久化对象的状态:
// 区分持久化对象的三种状态:
public void demo1(){
// 1.创建Session
Session session = HibernateUtils.openSession();
// 2.开启事务
Transaction tx = session.beginTransaction();
// 向数据库中保存一本图书:
Book book = new Book(); // 瞬时态:没有唯一标识OID,没有与session关联.
book.setName("Hiernate开发");
book.setAuthor("孙XX");
book.setPrice(65d);
session.save(book); // 持久态:有唯一标识OID,与session关联.
// 3.事务提交
tx.commit();
// 4.释放资源
session.close();
book.setName("Struts2开发"); // 脱管态:有唯一的标识,没有与session关联.
}
2.2 hibernate中的update()和saveOrUpdate()的区别。
- update()方法操作的对象必须是持久化了的对象。也就是说,如果此对象在数据库中不存在的话,就不能使用update()方法。
- saveOrUpdate()方法操作的对象既可以使持久化了的,也可以使没有持久化的对象。如果是持久化了的对象调用saveOrUpdate()则会 更新数据库中的对象;如果是未持久化的对象使用此方法,则save到数据库中。
2.3 session的load()和get()的区别。
- 1.发送SQL的时机:
- load这个方法采用了一个技术.lazy延迟加载(懒加载).真正使用这个对象的数据的时候.(对象的数据不包括主键).
- get这个方法是立即检索.当执行session.get()方法的时候,马上发送SQL语句查询.
- 2.返回的对象:
- load方法返回的是代理对象.
- get方法返回的是真实的对象.
- 3.查询一个不存在的数据:
- load方法抛异常:ObjectNotFoundException.
- get方法抛异常:NullPointException.
2.4 hibernate工作原理:
1.通过Configuration config = new Configuration().configure();//读取并解析hibernate.cfg.xml配置文件
2.由hibernate.cfg.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
2.5 Hibernate的缓存
- 什么是缓存:
- 缓存将数据库/硬盘上文件中数据,放入到缓存中(就是内存中一块空间).当再次使用的使用,可以直接从内存中获取.
- 缓存的好处:
- 提升程序运行的效率.缓存技术是Hibernate的一个优化的手段.
- Hibernate分成两个基本的缓存:
- 一级缓存:Session级别的缓存.一级缓存与session的生命周期一致.自带的.不可卸载.
- 二级缓存:SessionFactory级别的缓存.不是自带的.
2.6 Hibernate的检索方式:
- 导航对象图检索方式: 根据已经加载的对象导航到其他对象
- Customer customer = (Customer)session.get(Customer.class,1);
- customer.getOrders();// 获得到客户的订单
- OID 检索方式: 按照对象的 OID 来检索对象
- get()/load();方法进行检索.
- HQL 检索方式: 使用面向对象的 HQL 查询语言
- Query query = session.createQuery(“HQL”);
- QBC 检索方式: 使用 QBC(Query By Criteria) API 来检索对象. 这种 API 封装了基于字符串形式的查询语句, 提供了更加面向对象的查询接口.
- Criteria criteria = session.createCriteria(Customer.class);
- 本地 SQL 检索方式: 使用本地数据库的 SQL 查询语句
- SQLQuery query = session.createSQLQuery(“SQL”);
3 Spring
3.1 你对Spring的理解。
- 开源框架
- IoC(控制反转),将类的创建和依赖关系写在配置文件里,由配置文件注入,实现了松耦合
- AOP 将安全,事务等于程序逻辑相对独立的功能抽取出来,利用spring的配置文件将这些功能插进去,实现了按照方面编程,提高了复用性
3.2 什么是spring的IOC AOP
- I**OC的基本概念是:不创建对象,但是描述创建它们的方式。在代码中不直接与对象和服务连接,但在配置文件中描述哪一个组件需要哪一项服务。Spring容器负责将这些联系在一起。也就是说,**Spring的IOC负责管理各种对象的创建、清除以及它们之间的联系。
- AOP是指面向切面编程(也叫面向方面),可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。一般用于事务管理、权限控制、错误处理等各种业务中共同性的东西。