Action对象为每一个请求产生一个实例,因此没有线程安全问题。(实际上,Servlet容器给每个请求产生许多可丢弃的对象,并且不会导致性能和垃圾回收问题)
Servlet依赖
Action 依赖于Servlet API ,因为当一个Action被调用时HttpServletRequest 和HttpServletResponse 被传递给execute方法。
Action不依赖于容器,允许Action脱离容器单独被测试。如果需要,Struts2 Action仍然可以访问初始的request和response。但是,其他的元素减少或者消除了直接访问HttpServetRequest 和 HttpServletResponse的必要性。
可测性
Action的一个主要问题是execute方法暴露了servlet API(这使得测试要依赖于容器)。
Action可以通过初始化、设置属性、调用方法来测试,“依赖注入”支持也使测试更容易。
捕获输入
使用ActionForm对象捕获输入。所有的ActionForm必须继承一个基类。因为其他JavaBean不能用作ActionForm,开发者经常创建多余的类捕获输入。
Struts2可以通过Action的属性、域模型或模型驱动等方式实现输入捕获,而且还自带了默认的类型转换机制。
表达式语言
整合了JSTL,因此使用JSTL EL。这种EL有基本对象图遍历,但是对集合和索引属性的支持较弱。
可以使用JSTL,但是也支持一个更强大和灵活的表达式语言 OGNL(坦白的说这是一个很垃圾又没有效率的表达式语言,因为前不久曝出的Struts 2高危漏洞就是由OGNL引起的)
类型转换
ActionForm 属性通常都是String类型。Struts1使用Commons-Beanutils进行类型转换。每个类一个转换器,对每一个实例来说是不可配置的。
使用OGNL进行类型转换。提供基本和常用对象的转换器。
99、谈一下你的项目选择Struts 2的理由
答:1Action是POJO,没有依赖Servlet API,具有良好的可测试性;2强大的拦截器简化了开发的复杂度;3支持多种表现层技术:JSP、Freemarker等等;4灵活的验证方式;5国际化(I18N)支持;6声明式异常管理;7通过JSON插件简化Ajax;8通过Spring插件跟Spring整合。
补充:有人为选择和评判Web框架提出了20条标准,包括:开发人员的工作效率(能用1-5天搭建一个CRUD页面吗)、开发人员的看法(用起来有意思吗)、学习曲线(学了一个星期或一个月后能干活吗)、项目健康状况(项目陷入绝境了吗)、开发人员的充足性(能找到经验丰富的开发人员吗)、就业趋势(将来能招到人吗)、模板化(遵循DRY原则吗)、组件(自带日期选择器之类的控件吗)、Ajax(是否支持异步调用和局部刷新)、插件或附加项(能加入Facebook集成之类的功能吗)、扩展性(默认的控制处理的并发用户数能到500+吗)、测试支持(能够做测试驱动的开发吗)、I18N和L10N(有多国语言、地域支持吗)、校验(能轻松校验用户输入并迅速反馈吗)、多编程语言支持(能够同时使用多种语言开发吗)、文档的质量(常见的用例和问题都在文档中有体现吗)、出版的图书(有没有行业专家使用了它并分享了自己的使用经验)、REST支持(能按HTTP协议的设计宗旨使用该协议吗)、移动支持(是否很容易就能支持Android、iOS和其他移动智能终端)、风险程度(能不能做大型项目)。很明显,Java其实算不上最优化的Web开发语言,但是它却满足了这20条中的很多,尤其是充足的开发人员、成熟的解决方案这两点。
100、Struts 2中如何访问HttpServletRequest、HttpSession和ServletContext三个域对象
答:有两种方式:
1)通过ServletActionContext的方法获得;
2)通过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方法的区别是什么?
答:主要有以下三项区别:
1) 如果没有找到符合条件的记录, get方法返回null,load方法抛出异常
2) get方法直接返回实体类对象, load方法返回实体类对象的代理
3) get方法只在一级缓存(内部缓存)中进行数据查找, 如果没有找到对应的数据则越过二级缓存, 直接发出SQL语句完成数据读取; load方法则可以充分利用二级缓存中的现有数据
简单的说,对于load()方法Hibernate认