【前言】别人都在你看不到的地方暗自努力,在你看获得的地方,他们也和你同样显得不务正业,和你同样会抱怨,而只有你本身相信这些都是真的,最后,也只有你一我的继续不思进取 …… java
【下载】我的结合诸多资料,总结的一些JavaEE常见面试题,主要针对初/中级程序员。想要word完整版下载的,评论里留言留下你的邮箱!程序员
1.Struts2中,Action经过什么方式获取用户从页面输入的数据,又是经过什么方法把数据传给视图层显示的?面试
答:(1)Action从页面获取数据的方式有三种:sql
①经过Action属性接收参数;(例:${pageContext.request.contextPath}/***.action? id=xxxx)数据库
②经过域模型获取参数;(例:ServletActionContext.getRequest().getParameter(arg0))缓存
③经过模型驱动获取参数(例:extends ModelDriven<T>)安全
(2)Action将数据存入值栈(Value Stack)中,视图能够经过表达式语言(EL)从值栈中获取;session
2.阐述Struts2中的Action如何编写,是否采用单例?多线程
答:(1)Struts2的Action有三种写法:并发
①POJO类——无继承无实现;
②实现Action接口,重写execute()方法;
③继承ActionSupport(经常使用);
(2)Action没有像Servlet同样,使用单实例多线程的工做方式,很明显,每个Action要接收不一样用户的请求参数,这就意味着Action是有状态的,所以在设计上使用了,每个请求对应一个Action的处理方式,因此是多例的。
3.Struts2中,Action并无直接收到用户的请求,那它为何能够处理用户的请求?又凭什么知道一个请求到底交给哪个Action来处理?
答:(1)Struts2的核心过滤器收到用户的请求后,会对用户的请求进行简单的预处理(如解析、封装参数),而后经过反射来建立Action实例,并调用Action中指定的方法来处理用户请求。
(2)通知具体调用哪一个Action来处理请求的方式,有两种:
①利用配置文件,Struts.xml中配置的<action>标签来肯定;
②利用约定,Struts2中可使用约定(convention)插件。例如:约定xxx老是对应XxxAction,这是对约定优于配置理念的践行;
4.简述Struts2异常处理机制?
答:Struts2提供了声明式的异常处理机制,能够在配置文件中加入以下代码:
<!-- 配置全局结果视图 -->
<global-results>
<result name="error">/WEB-INF/pages/error.jsp</result>
</global-results>
<!-- struts2自带异常处理配置-->
<global-exception-mappings>
<exception-mapping result="error" exception="com.itheima.exception.SysException"></exception-mapping>
<exception-mapping result="error" exception="java.lang.Exception"></exception-mapping>
</global-exception-mappings>
5.简述拦截器的工做原理?
答:在Struts2中,能够实现Interceptor接口或继承AbstractInterceptor类,来自定义拦截器。
①接口中的init()方法,在拦截器被建立后当即被调用,它在拦截器的生命周期内只被调用一次,能够在该方法中对相关资源进行必要的初始化;
②每拦截一个请求,intercept()方法就会被调用一次;
③destory()方法将在拦截器销毁以前被调用。
6.谈一下拦截器和过滤器的区别?
答:拦截器和过滤器均可以用来实现横切关注功能,其区别主要在于:
①拦截器是基于JAVA反射机制的,而过滤器是基于函数回调的
②过滤器依赖于Servlet容器,而拦截器不依赖于Servlet容器
③拦截器只能对Action请求起做用(Action中的方法),而过滤器能够对几乎全部的请求起做用(CSS JSP JS)
7.谈一下你的项目选择Struts2的理由?
答:①Action是POJO类,没有依赖Servlet API,具备良好的可测试性;
②强大的拦截器,简化了开发的复杂度;
③支持多种表现层技术:JSP、Freemarker等;
④灵活的验证方式;
⑤国际化(I18N)支持
⑥声明式异常管理;
⑦经过JSON插件简化Ajax;
⑧经过Spring插件跟Spring整合;
8.Struts2中如何访问HttpServletRequest、HttpSession和ServletContext三个域对象?
答:有两种方式:
①经过ServletActionContext的方法得到;
②经过ServletRequestAware、SessionAware和ServletContextAware接口注入。
9.Struts2中的默认包struts-default有什么做用?
答:它定义了Struts2内部的众多拦截器和Result类型,而Struts2不少核心的功能是经过这些内置的拦截器实现,如:从请求中把参数封装到action、文件上传和数据校验等等,都是经过拦截器实现的。在Struts2的配置文件中,自定义的包,继承了struts-default包,就可使用Struts2为咱们提供这些功能。
10.简述值栈的原理和生命周期?
答:Value-Stack贯穿整个Action的生命周期,保存在request做用域中,因此它和request的生命周期同样。当Struts2接受一个请求时,会建立ActionContext、Value-Stack和Action对象,而后把Action存放进Value-Stack,因此Action的实例变量能够经过OGNL访问。因为Action是多实例的,和使用单例的Servlet不一样,每一个Action都有一个对应的Value-Stack,Value-Stack存放的数据类型是该Action的实例,以及该Action中的实例变量,Action对象默认保存在栈顶。
11.SessionFactory是线程安全的吗?Session是线程安全的吗?两个线程能共享一个Session吗?
答:(1)SessionFactory对应Hibernate的一个数据存储的概念,它是线程安全的,能够被多个线程并发访问。SessionFactory通常只会在启动的时候构建。对于应用程序,最好将SessionFactory经过单例的模式进行封装以便于访问。
(2)Session是一个轻量级非线程安全的对象(线程间不能共享Session),它表示与数据库进行交互的一个工做单元。Session是由SessionFactory建立的,在任务完成以后会被关闭。Session是持久层服务对外提供的主要接口。Session会延迟获取数据库链接(也就是在须要的时候才会获取)。为了不建立太多的session,可使用TreadLocal来获取当前的session,不管你调用多少次getCurrentSession()方法,返回的都是同一个session。
12.Session的load和get方法区别是什么?
答:①若是没有找到符合条件的记录,get方法返回null值,而load方法会抛出异常;
②get方法直接返回实体类对象,load方法返回实体类对象的代理;
③在Hibernate3以前,get方法只在一级缓存(内部缓存)中进行数据查找,若是没有找到对应的数据则越过二级缓存,直接发出SQL语句完成数据的读取;load方法则能够充分利用二级缓存中现有数据,进行延迟加载。固然从Hibernate3开始,get方法再也不是对二级缓存只写不读,它也是能够访问二级缓存的;
简单的是,对于load()方法,hibernate认为该数据在数据库中必定存在,能够放心的使用代理来实现延迟加载,若是没有数据,就会抛出异常,而经过get()方法去取数据,是能够不存在的。
13.阐述Session加载实体对象的过程?
答:①Session在调用数据查询功能以前,首先会在缓存中进行查询,在一级缓存中,经过实体类型和主键进行查询,若是一级缓存查找命中且数据状态合法,则直接返回;
②若是一级缓存没有命中,接下来Session会在当前NonExists记录(至关于一个查询黑名单,若是出现重复的无效查询能够迅速判断,从而提高性能)中进行查询,若是NonExists中存在一样的查询条件,则返回null;
③对于load方法,若是一级缓存查询失败,则查询二级缓存,若是二级缓存命中则直接返回;
④若是以前的查询都未命中,则发出sql语句,若是查询未发现对应的记录,则这次查询添加到Session的NonExists中加以记录,并返回null;
⑤根据映射配置和sql语句,获得ResultSet,并建立对应的实体对象;
⑥将对象归入Session(一级缓存)管理;
⑦执行拦截器的onload方法(若是有对应的拦截器);
⑧将数据对象归入二级缓存;
⑨返回数据对象。
14.Query接口的list方法和iterate方法有什么区别?
答:①list()方法返回的每一个对象都是完整的(对象中的每一个属性都被表中的字段填充上了),list方法没法利用缓存,它对一级缓存只写不读;
②iterate方法能够充分利用一级缓存,它所返回的对象中仅包含了主键值(标识符),只有当你对iterator中的对象进行操做时,Hibernate才会向数据库再次发送SQL语句来获取该对象的属性值;
②list方法不会引发N+1查询问题,而iterate方法会引发N+1查询问题。
15.Hibernate如何实现分页查询?
答:经过Hibernate实现分页查询,开发人员只须要提供HQL语句、查询起始行数(setFirstResult()方法)和最大查询行数(setMaxResult()方法),并调用Query接口的list()方法,Hibernate会自动生成分页查询的SQL语句。