1、Struts是一个按照MVC模式设计的web层框架。其实就是大大的Servlet,这个Servlet叫做ActionServlet,或者是其子类,我们可以在web.xml文件中将符合某种特性的所有请求交给Servlet来处理
2、ActionServlet把请求交给Action去处理之前,会将参数封装成formbean对象,具体成什么样子看配置文件
3、ActionServlet把formbean对象传递给action的execute方法之前,可能会调用formbean的validate方法进行校验。只有检验后才可以将formbean对象传递给action的execute()方法
4、action执行完成后要返回现实的结果视图,这个视图是用一个ActionForword对象来表示的,actionForward对象通过struts-config.xml配置文件关联到某个jsp页面
核心控制器(FilterDispatcher)、业务控制器Action和用户实现的企业业务逻辑组件。核心控制器FilterDispatcher是struts2框架的基础,包含框架内部的控制流程和处理机制。业务控制器Action和业务逻辑组件是需要用户自己来实现的。用户在开发Action和业务逻辑组件的同时,还需要编写相关的配置文件,供核心控制器FilterDispatcher来使用。
1、客户端浏览器发出http请求。2、根据web.xml配置,该请求会被FilterDispatcher接收。3、根据Struts.xml配置,找到对应的需要调用的Action类和方法,通过IOC方式,将值注入给Action。4、Action调用业务逻辑组件处理业务逻辑,这一步包含表单验证。5、Action执行完毕后,根据Struts.xml配置找到对应的返回结果result,并跳转到相应页面。返回http响应到客户端浏览器
不是,可以声明局部变量,或者扩展RequestProcessor,让每次都创建一个Action,或者在Spring中使用Scope=”prototype”
对象关系映射,一种解决程序的面向对象模型与数据库的关系模型互不匹配问题的技术。简单来说就是,ORM是通过描述对象和数据库之间映射的元数据(用xml或者注解),将程序中的对象自动持久化到关系数据库中或者将关系数据库表中的行转换成Java对象
步骤
1、读取核心配置文件xx.cfg.xml文件,
2、读取并解析映射文件信息,创建SessionFactory
3、获取Session,利用SessionFactory的openSession方法
4、开启事务
5、持久化操作
6、提交事务
7、关闭session和SessionFactory
原因:
1、对JDBC访问数据库的代码做了封装,大大简化了数据访问层频繁的重复性的代码
2、Hibernate是一个基于JDBC的主流持久化框架,是一个优秀的ORM实现,他简化了DAO层的编码工作
3、hibernate使用java反射机制,而不是字节码增强程序来实现透明性
4、hibernate性能非常好,轻量级的框架,支持各种关系型数据库
SessionFactory对应Hibernate的一个数据存储的概念,它是线程安全的,可以被多个线程并发访问。SessionFactory一般只会在启动时创建。对于应用程序,最好是将SessionFactory通过单例模式进行封装以便于访问。Session是一个轻量级非线程安全的对象(线程间不能共享session),它表示与数据库进行交互的一个工作单元。Session是持久层服务对外提供的主要接口。为了避免创建太多的Session,可以使用ThreadLocal将session和当前线程绑定,这样同一个线程可以获得是同一个session,Hibernate3的SessionFactory的getCurrentSession()可以实现
1、如果没找到符合条件的记录,get方法返回的是null,load方法抛出异常
2、get方法直接返回实体类的对象 load方法会犯实体类对象的代理
3、hibernate3以前,get方法只是在一级缓存中进行数据查找,如果没找到对应数据则越过二级缓存,直接发出SQL语句完成数据读取;load方法则可以从二级缓存中获取数据。
答:Session加载实体对象的步骤是:
① Session在调用数据库查询功能之前,首先会在一级缓存中通过实体类型和主键进行查找,如果一级缓存查找命中且数据状态合法,则直接返回;
② 如果一级缓存没有命中,接下来Session会在当前NonExists记录(相当于一个查询黑名单,如果出现重复的无效查询可以迅速做出判断,从而提升性能)中进行查找,如果NonExists中存在同样的查询条件,则返回null;
③ 如果一级缓存查询失败则查询二级缓存,如果二级缓存命中则直接返回;
④ 如果之前的查询都未命中,则发出SQL语句,如果查询未发现对应记录则将此次查询添加到Session的NonExists中加以记录,并返回null;
⑤ 根据映射配置和SQL语句得到ResultSet,并创建对应的实体对象;
⑥ 将对象纳入Session(一级缓存)的管理;
⑦ 如果有对应的拦截器,则执行拦截器的onLoad方法;
⑧ 如果开启并设置了要使用二级缓存,则将数据对象纳入二级缓存;
⑨ 返回数据对象。
通过Hibernate实现分页查询,开发人员只需要提供HQL语句(调用Session的CreatQuery()方法)或查询条件(调用Session的createCriteria()方法)、设置查询起始行数(调用Query或者Criteria接口的setFirstResult()方法)和最大查询行数(调用Query或者Criteria接口的setMaxResults()方法),并调用Query或者Criteria接口的list()方法,hibernate会自动生成分页查询的SQL语句
悲观锁:顾名思义悲观的认为在数据处理过程中极可能存在修改数据的并发事务(包括本系统的其他事务或来自外部系统的事务),于是将处理的数据设置为锁定状态。悲观锁必须依赖数据库本身的锁机制才能真正的保证数据访问的排他性,
乐观锁:顾名思义,对并发事务持乐观态度(认为对数据的并发操作不会经常性发生),通过更加宽松的锁机制来解决由于悲观锁排他性的数据访问对系统性能造成的严重影响。最常见的乐观锁是通过数据版本标识来实现的,读取数据时获得数据的版本号,更新数据时将此版本号加1,然后和数据库表对应记录的当前版本号进行比较。
Hibernate中通过Session的get()和load()方法从数据库中加载对象时可以通过参数指定使用悲观锁;而乐观锁可以通过给实体类加整型的版本字段再通过XML或@Version注解进行配置。
答:延迟加载就是并不是在读取的时候就把数据加载进来,而是等到使用时再加载。Hibernate使用了虚拟代理机制实现延迟加载,我们使用Session的load()方法加载数据或者一对多关联映射在使用延迟加载的情况下从一的一方加载多的一方,得到的都是虚拟代理,简单的说返回给用户的并不是实体本身,而是实体对象的代理。代理对象在用户调用getter方法时才会去数据库加载数据。但加载数据就需要数据库连接。而当我们把会话关闭时,数据库连接就同时关闭了。
① 关闭延迟加载特性。这种方式操作起来比较简单,因为Hibernate的延迟加载特性是可以通过映射文件或者注解进行配置的,但这种解决方案存在明显的缺陷。首先,出现"no session or session was closed"通常说明系统中已经存在主外键关联,如果去掉延迟加载的话,每次查询的开销都会变得很大。
② 在session关闭之前先获取需要查询的数据,可以使用工具方法Hibernate.isInitialized()判断对象是否被加载,如果没有被加载则可以使用Hibernate.initialize()方法加载对象。
③ 使用拦截器或过滤器延长Session的生命周期直到视图获得数据。Spring整合Hibernate提供的OpenSessionInViewFilter和OpenSessionInViewInterceptor就是这种做法。
1、制定合理的缓存策略(e二级缓存、查询缓存)
2、采用合理的Session管理机制
3、尽量采用延迟加载的特性
4、设定合理的批处理参数
5、选用UUID作为主键生成器
6、选择乐观锁
7、考虑数据库本身,合理的索引、恰当的数据分区策略
Hibernate的Session提供了一个一级缓存的功能,默认总是有效的,当应用程序保存到持久化实体、修改持久化实体时,Session并不总是把这种改变提交到数据库,而是缓存在当前的Session中,除非显示调用Session的flush方法或者通过close关闭Ssession。通过一级缓存可以减少程序于数据库的交互,从而提高数据库的性能
SessionFactory级别的二级缓存是全局性的,所有的Session可以共享这个二级缓存。不过二级缓存默认是关闭的,需要显示开启并指定需要使用哪种二级缓存实现类。一旦开启了二级缓存并设置了需要使用二级缓存的实体类,SessionFactory就会缓存访问过的该实体类的每个对象,除非缓存的数据超出了指定的缓存空间。
1、实现了MVC模式,结构清晰,使开发者只关注业务逻辑的实现
2、有丰富的tag可以使用,Struts的标签库,灵活运用可以提高开发效率
3、页面导航,页面导航是今后的发展方向
4、提供Exception处理机制
5、数据库连接池管理
6、支持国际化
转到展示层时,需要配置forword,当文件目录变更时需要重修修改forword
struts的Action必须是thread-safe方式,它仅仅允许一个实例去处理所有的 请求。因此action用到的资源必须是统一同步
测试不方便,Struts每个action都同web层耦合在一起,这样它的测试依赖于 web容器, 单元测试很难实现
类型转换,struts的FormBean把所有的数据作为String,它可以使用工具 Commons-BeanUtils进行类型转换
对Servlet的依赖性太强。Struts处理Action时必须要依赖ServletRequest和 ServletResponse
1、加载类(FilterDispatcher)
2、读取配置(Struts配置文件中的action)
3、派发请求(客户端发送请求)
4、调用Action(FilterDispatcher从Struts配置文件中读取与之相对应的Action)
5、启动拦截器(webWork拦截器链自动对请求应用通用功能,如验证)
6、处理业务(回调ActionExecute方法)
7、返回响应(通过execute方法将信息返回到FilterDispatcher)
8、查找响应(FilterDispather根据配置查找响应的信息)
9、响应用户(jSP-->客户端浏览器显示)
10、struts2标签库
Struts 1要求Action类要扩展自一个抽象基类。Struts1的一个共有的问题是面向抽象类编程而不是面向接口编程。
Struts 2的Action类实现了一个Action接口,连同其他接口一起实现可选择和自定义的服务。Struts 2提供一个名叫ActionSupport的基类实现一般使用的接口。虽然,Action接口不是必须的。任何使用execute方法的POJO对象可以 被当作Struts 2的Action对象使用。
哪些情况会导致重复提交
1、服务器处理服务后,转发页面,客户端点击刷新(改成重定向)
2、客户端网络过慢,按钮连续点击(按钮点击一次后,禁用按钮)
防止表单重复提交----令牌机制
请求表单页面----->服务器生成html表单页面,使用UUID等技术,生成随机令牌号码---->将令牌号保存到Session中---->在页面保存令牌号,隐藏字段---->令牌号随表单一起提交---->获取请求中的令牌号--->获取Session中的令牌号,如果一致就可以访问,否则则不可以访问