讲清楚一个SSH框架的WEB请求的详细经过,FILTER+web.xml,包括JSP和SERVLET的调度过程,Tomcat的线程池和JDBC连接池,STRUTS2的拦截器和自动装配机制及涉及的相关类,SPRING的事务,AOP,及自动装配及涉及的相关类,HIBERNATE的CACHE和自动装配机制和事务;
一。JSP请求
1.浏览器发起请求:
一般有POST和GET方法,两者的处理过程基本相同,因此通常在Servlet端只实现其中之一,然后在另一个方法中调用已实现的方法;
两者的区别在于:
(1)参数长度:
GET方法的参数在浏览器地址栏中,因此有长度的限制;?将路径和参数分开,&将参数之间分开;
POST方法的参数则放在消息体中,因此无长度限制;
(2)安全
GET方法的参数显示在地址栏中,可见,故不安全;
POST方法的参数放在消息体中,不可见,故较安全;
(3)书签
GET可建立,而POST不可建立;
(4)幂等
理论上讲GET方法应该是幂等的(可重复执行多次无副作用),POST方法是非幂等的,实际应用中不一定;
(5)转码区别
在实际中发现,GET和POST还会有一个问题,即GET方法的参数通常还需要手工解码,而POST则不需要,原因在于应用服务器的编码未正确设置,默认为ISO-8859-1;
2.经过Filter
(1)一般来说,需要先经过SPRING的字符集转码机制,CharacterEncodingFilter,用来处理前台JSP页面与后台JAVA代码编码机制不同的情况;
(2)然后会经过其它的Filter,有时是权限和安全验证,更多的情况是直接由STRUTS2来拦截请求,由SSH框架来处理;
Tomcat中各种配置的加载顺序:
context-param -> listener -> filter -> servlet
context-param用来配置容器的上下文初始化参数,只在容器重新部署时初始化,一般来说,配置的参数是SPRING的配置文件名;
listener 用来将上下文初始化参数组装成对象,一般来说,为SPRING的org.springframework.web.context.ContextLoaderListener 类;
filter主要用于对用户请求进行预处理,一般来说,首先是SPRING的转码机制,然后是安全和权限控制(如果有),再下来是STRUTS2的框架或者Webservice;Filter的加载顺序由其在web.xml中的配置顺序决定;
安全和权限控制(Session):
基本的方法是先登录,然后在Session中存储用户信息以及状态信息,以后的会话通过传送SessionID来进行确认;
Session存在有效期,一般来说二十分钟,也可人工设置;
Tomcat设置SESSION有效期的三种方法:在server.xml中定义context时defaultSessionTimeOut设置
在web.xml中通过<session-config>的<session-timeout>设置
在程序中通过HttpSession的setMaxInactiveInterval设置;
sessionID的交换:第一次生成时会通过首部的set-cookie和在URL后追加来传递sessionID,因为有可能有的浏览器不支持COOKIE;
如果后来客户发送的请求中有sessionID的COOKIE,则以后只通过第一种方法来传递;
HTTPSession中存储信息:ActionContext.getContext().getSession().put()方法来存储;
3.返回JSP
如果请求HTML,则返回HTML,请求JSP,一般会由服务器生成HTML并返回;
(1)JSP与SERVLET的区别:
JSP也是SERVLET,因为在SERVLET中直接拼HTML的字符串比较麻烦且因为涉及到转码及前后台分工的问题,最终使用JSP来做响应SERVLET;
JSP先被转化为JAVA文件,再被编译为CLASS文件,然后由窗口加载并初始化成SERVLET对象;
(2)JSP中include与jsp:include的区别:
都用来在JSP文件中加入重复内容;
include的作用等同于直接复制相关文字到标签位置,因此其对位置敏感,include的文件不是一个完整的JSP,应用启动时,包含文件则自动复制到各个JSP中;
jsp:include的作用则是通过运行时原JSP作为Dispatch响应来发挥,因此其对位置不敏感,jsp:include文件是一个完整的JSP,也会成为SERVLET;
jsp:include内容若改变则会实时反应到运行中,但现在实现上include内容改变也可反应到运行中;
(3)forward与sendRedirect的区别
forward发生在服务器内部,即通过JSP间的调用来实现,故客户端看不到变化,但因此其只能调用同一WEB程序内的资源,参数传递必须通过setAttribute()来设置;
Redirect发生在客户端,由浏览器直接向服务器请求新的URL,因此可以调用不同WEB程序内的资源,可通过URL来传递参数;
(4)EL与JSTL
EL表达式用来向HTML输出WEB程序内的一些参数,如JAVABEAN,SESSION,REQUEST,SERVLET等的参数,只能调用参数,不能调用方法,因为其默认的隐式对象其实并不是WEB中的真正对象,而是将对象内参数复制后生成的MAP;
JSTL表达式用来用标签来表示一些动作,如输出,循环,判断等;
二。ACTION请求
1.浏览器请求:
两种方式:HTTP和AJAX;
AJAX通过XMLHttpRequest来进行通信;
AJAX通过redayState与request.status来确定状态;
AJAX常用的传输格式有XML和JSON两种,一种结构清晰明了,一种传输量少;
AJAX的readyState的有几种:0(未初始化),1(开启),2(已传送),3(接收中),4(已载入)
2.STRUTS2执行
(1)request请求首先经过一系列的filter(转码,验证以及STRUTS自带Filter),最后到FilterDispatcher;
(2)FilterDispatcher通过ActionMapper来确定是否需要调用某个Action(应该是通过url-pattern决定),如需要则把请求处理交给ActionProxy
(3)ActionProxy通过Configuration Manager(struts.xml)找以需要调用的Action类;
(4)ActionProxy创建一个ActionInvocation实例,该实例通过一个链表(存放拦截器链)来依次调用拦截器及Action方法;
(5)Action执行完成后,返回result中的结果;
STRUTS2中的自动组装机制:
分为属性驱动和模型驱动:STRUTS2负责组装和类型转换,若转换失败,会进入名为input的逻辑视图;
属性驱动:即在ACTION中直接定义属性,由STRUTS2按名称组装;
模型驱动:首先定义模型类,再在ACTION中扩展ModelDriven接口,且须在ACTION中生成模型类的实例,STRUTS2由GET方法得到后组装;
STRUTS2中的异常机制:
通过<exception-mapping.../>元素配置,需指定exception和result两个属性;
3.Action的执行(SPRING)
生成ACTION实例,一般来说由SPRING来组装,在ACTION中配置类ID,真正的类由SPRING来生成;
SPRING中主要有三个功能:依赖注入,AOP,事务;
依赖注入:
(1)依赖注入的实现:分为构造注入或SET注入;
通过Class.forname()创建新的类,通过构造注入或SET注入;
构造注入:即用带参数的构造器来创建新类的,须用<constructor-arg..>来配置,一种为基本类型,通过index和value(有相同类型参数时)来 指定,一种则是非基本类型,通过bean来定义;
SET 注入:即调用无参数构造器后,通过SET来注入;
(2)依赖注入的bean的几种作用域:
singleton,prototype,request,session,global session;
其中request,session,global session需要在web.xml中配置<listener>RequestContextListener类;
singleton中依赖prototype时的方法注入:
<lookup-mehtod name="..." bean="..."/>
(3)依赖注入的手动组装与自动组装
常用的为手动组装,因为结构清晰;
其它的为自动组装,缺点是必须根据与属性类完全一致的类名来装配,接口再不能被实例化;
自动装配一般用的是byName;
AOP:
(1)通知类型:前置通知,后置通知,异常通知,最终通知,环绕通知;
环绕通知与其它通知的区别:可控制何时调用目标方法
可控制返回对象
后置通知与最终通知的区别:后置通知在方法正常返回时执行
最终通知无论方法正常还是异常都会执行
(2)AOP的两种方式:通过AspectJ即注释(annotation)、XMLSchema的方式;
AspectJ与XML的区别:
实现方式:AspectJ通过在通知类中加入匹配的注释来实现,需要在SPRING配置中加<aop:aspectj-autoproxy/>
XML则通过在XML中配置来实现,通知类中不需要加注释;
JDK支持:AspectJ需要JDK5+支持,XML不需要;
习惯:用户更习惯于XML;
XML缺点:
1.比起AspectJ来,配置更繁琐,且会使配置文件混乱,毕竟AOP的配置和一般的配置的写法并不太相同,ASPECTJ则将切面完全封装在一个类中,更符合将需求的实现封装到一个位置的做法;
2.XML只支持单例模式;
(3)代理机制:
Spring的AOP和事务都是用的动态代理来实现的;
代理分两种:CGLIB和JDK的动态代理,二者的实现机制基本相同,不同点在于JDK只支持接口代理,故须用CGLIB来实现对普通类的代理;
Spring默认接口采用JDK,普通类采用CGLIB,也可配置为全部用CGLIB;
SPRING事务基础知识:
(1)JDBC连接池:
一般用dbcp来实现,原理为连接池先从数据库获得连接,然后分配给线程;覆盖了原Connection的get和close方法,故getConnection方法是从连接池取连接,而close则将连接归还连接池,并未与数据库进行交互;
(2)全局事务与本地事务
全局事务:跨数据库,使用JTA;本地事务:一般为一个连接;
(3)事务可能出现问题:
更新丢失(lost update )
脏读 (dirty read )
非重复读(nonrepeatable read )
幻读 (phantom read )
(4)事务隔离
ISOLATION_READ_UNCOMMITTED 未提交读(可读缓存中的数据) 会造成脏读,非重复读,幻读
ISOLATION_READ_COMMITTED 提交读 (大部分数据库采用的默认方式)会造成非重复读,幻读
ISOLATION_REPEATABLE_READ 可重复读(一个事务不会修改已经由另一个事务读取但未提交(回滚)的数据)会造成幻读
ISOLATION_SERIALIZABLE 序列化 (事务串行执行) 无;
(5)事务传播
PROPAGATION_REQUIRED 有则加入,无则新建 这是最常见的选择。
PROPAGATION_SUPPORTS 有则以事务执行,无则以非事务执行
PROPAGATION_MANDATORY 有则以事务执行,无则抛出异常
PROPAGATION_REQUIRES_NEW 新建事务,当前已有的事务挂起
PROPAGATION_NOT_SUPPORTED 以非事务执行,有则挂起
PROPAGATION_NEVER 以非事务执行,有则抛异常
PROPAGATION_NESTED 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。
***PROPAGATION_REQUIRED与PROPAGATION_NESTED与PROPAGATION_REQUIRES_NEW的区别:
PROPAGATION_REQUIRED:外部事务和内部事务为一个事务,若一个失败,则全部回滚,成功,全部提交;
PROPAGATION_REQUIRES_NEW:内部事务为一个新事务,和外部事务作为两个事务看待,无论成功失败,都不影响另一个;
PROPAGATION_REQUIRES_NEW:若内部事务失败,则只回滚内部事务,若外部事务失败,则全部回滚,只有外部事务可以提交,若提交两个都提交;
(6)事务属性:事务隔离,事务传播,超时,只读属性;
SPRING事务:
(1)SPRING事务的三种方式:
XML配置:先XML配置不同策略的事务拦截器,再像AOP一样插入到aop:poing-cut下面;
注释形式:在需要事务的类方法前面加@Transactional注释即可,要求JDK5+,须配事务拦截器,但不需配置插入点,因为代码上注明了;
编程式:new一个PlatformTransactionManager类并设置拦截属性,需要配置事务管理器;
(2)如何选择:
较少用到事务,嫌麻烦时,用编程式;大量地还是用声明式(包括XML和注释);
4.数据访问与修改(hibernate)
(1)自动生成hibernate实体类与XML文件:
可通过数据库表来生成对应的实体BEAN和XML配置文件;工具有:PowerDesigher(PD),XDoclet,sechmaExport;
(2) hibernate主键生成策略
assigned:在新增数据时由应用程序指定主键的值;
适用于主键不是自动增长的列;
缺点:插入数据时需判断主键是否已存在;
increment:由hibernate自动生成主键值,先查询最大值,再加1;
适用于代理主键的主键列;
缺点:主键类型只能为int或long ;插入前须先查询一次,低效 ;并发操作时的冲突问题;
identity: 采用数据库的主键生成机制;
适用于DB2,MySQL,MS SQL Server,Sybase,HypersonicSQL
sequence: 采用数据库的主键生成机制;
适用于DB2,ORACLE,SAP DB;
hilo : 使用高低位算法来生成标识符;
native :根据不同底层数据库,自动选择identity,sequence,hilo主键生成方式;
UUID :使用UUID,适合于并发;
foreign : 用于一对一关系中,适用于MYSQL,SQLSERVER;
**sequence与identity的区别:
sequence作用于整个数据库,identity作用于单个表;
**UUID:
uuid为一个标准,用4个连字符将32位的字符串分隔生成字符串;
目前有两种主要实现:GUID和COMB;
GUID为微软的实现,COMB为数据库特有的一种设计,将UUID的最后6位用来表示时间,因为GUID因为无规律性导致了索引的效率低下;
(3)hibernate事务
hibernate层一般不需要事务管理,放在service层由SPRING来管理最好;
(4)hibernate的乐观锁和悲观锁
乐观锁使用版本号和时间戳来实现并发控制;
而悲观锁则使用数据库的锁定机制;一般使用JDBC配置好隔离级别后由数据库来搞定;
(5)session线程不安全解决方法,使用Threadlocal来保存session;
之所以不安全的原因就在于hibernate的session内置有一级缓存用来保存数据库数据,故可能读到错的数据;
(6)hibernate的cache机制:
hibernate的查询是先到一级缓存查,再到二级缓存(可选)查,再到数据库查;
session的cache(一级缓存,线程级别):
一般局限于事务一级,为防止并发事务导致数据不一致,一般使用ThreadLocal来保证一个线程一个session的缓存不会出现数据不一致问题;
sessionFactory(二级缓存,进程级别)
故二级缓存不太适用于并发情况,适用于少并发或只读的情况;
二级缓存策略如下:
1.条件查询时,使用select * from 将表中所有数据都查询出来;
2.把获得的所有数据对象根据ID放入到第二级缓存中
3.当Hibernate根据ID访问数据对象的时候,首先从Session一级缓存中查;查不到,如果配置了二级缓存,那么从二级缓存中查;查不到,再查询数据库,把结果按照ID放入到缓存。
4.删除、更新、增加数据的时候,同时更新缓存。
三。WEBSERVICE调用
SOAP:简单对象访问协议.
WSDL:Web服务描述语言.
UDDI(Universal Description, Discovery and Integration):通用描述、发现与集成,它是一种独立于平台的,基于XML语言的用于在互联网上描述商务的协议。
一。JSP请求
1.浏览器发起请求:
一般有POST和GET方法,两者的处理过程基本相同,因此通常在Servlet端只实现其中之一,然后在另一个方法中调用已实现的方法;
两者的区别在于:
(1)参数长度:
GET方法的参数在浏览器地址栏中,因此有长度的限制;?将路径和参数分开,&将参数之间分开;
POST方法的参数则放在消息体中,因此无长度限制;
(2)安全
GET方法的参数显示在地址栏中,可见,故不安全;
POST方法的参数放在消息体中,不可见,故较安全;
(3)书签
GET可建立,而POST不可建立;
(4)幂等
理论上讲GET方法应该是幂等的(可重复执行多次无副作用),POST方法是非幂等的,实际应用中不一定;
(5)转码区别
在实际中发现,GET和POST还会有一个问题,即GET方法的参数通常还需要手工解码,而POST则不需要,原因在于应用服务器的编码未正确设置,默认为ISO-8859-1;
2.经过Filter
(1)一般来说,需要先经过SPRING的字符集转码机制,CharacterEncodingFilter,用来处理前台JSP页面与后台JAVA代码编码机制不同的情况;
(2)然后会经过其它的Filter,有时是权限和安全验证,更多的情况是直接由STRUTS2来拦截请求,由SSH框架来处理;
Tomcat中各种配置的加载顺序:
context-param -> listener -> filter -> servlet
context-param用来配置容器的上下文初始化参数,只在容器重新部署时初始化,一般来说,配置的参数是SPRING的配置文件名;
listener 用来将上下文初始化参数组装成对象,一般来说,为SPRING的org.springframework.web.context.ContextLoaderListener 类;
filter主要用于对用户请求进行预处理,一般来说,首先是SPRING的转码机制,然后是安全和权限控制(如果有),再下来是STRUTS2的框架或者Webservice;Filter的加载顺序由其在web.xml中的配置顺序决定;
安全和权限控制(Session):
基本的方法是先登录,然后在Session中存储用户信息以及状态信息,以后的会话通过传送SessionID来进行确认;
Session存在有效期,一般来说二十分钟,也可人工设置;
Tomcat设置SESSION有效期的三种方法:在server.xml中定义context时defaultSessionTimeOut设置
在web.xml中通过<session-config>的<session-timeout>设置
在程序中通过HttpSession的setMaxInactiveInterval设置;
sessionID的交换:第一次生成时会通过首部的set-cookie和在URL后追加来传递sessionID,因为有可能有的浏览器不支持COOKIE;
如果后来客户发送的请求中有sessionID的COOKIE,则以后只通过第一种方法来传递;
HTTPSession中存储信息:ActionContext.getContext().getSession().put()方法来存储;
3.返回JSP
如果请求HTML,则返回HTML,请求JSP,一般会由服务器生成HTML并返回;
(1)JSP与SERVLET的区别:
JSP也是SERVLET,因为在SERVLET中直接拼HTML的字符串比较麻烦且因为涉及到转码及前后台分工的问题,最终使用JSP来做响应SERVLET;
JSP先被转化为JAVA文件,再被编译为CLASS文件,然后由窗口加载并初始化成SERVLET对象;
(2)JSP中include与jsp:include的区别:
都用来在JSP文件中加入重复内容;
include的作用等同于直接复制相关文字到标签位置,因此其对位置敏感,include的文件不是一个完整的JSP,应用启动时,包含文件则自动复制到各个JSP中;
jsp:include的作用则是通过运行时原JSP作为Dispatch响应来发挥,因此其对位置不敏感,jsp:include文件是一个完整的JSP,也会成为SERVLET;
jsp:include内容若改变则会实时反应到运行中,但现在实现上include内容改变也可反应到运行中;
(3)forward与sendRedirect的区别
forward发生在服务器内部,即通过JSP间的调用来实现,故客户端看不到变化,但因此其只能调用同一WEB程序内的资源,参数传递必须通过setAttribute()来设置;
Redirect发生在客户端,由浏览器直接向服务器请求新的URL,因此可以调用不同WEB程序内的资源,可通过URL来传递参数;
(4)EL与JSTL
EL表达式用来向HTML输出WEB程序内的一些参数,如JAVABEAN,SESSION,REQUEST,SERVLET等的参数,只能调用参数,不能调用方法,因为其默认的隐式对象其实并不是WEB中的真正对象,而是将对象内参数复制后生成的MAP;
JSTL表达式用来用标签来表示一些动作,如输出,循环,判断等;
二。ACTION请求
1.浏览器请求:
两种方式:HTTP和AJAX;
AJAX通过XMLHttpRequest来进行通信;
AJAX通过redayState与request.status来确定状态;
AJAX常用的传输格式有XML和JSON两种,一种结构清晰明了,一种传输量少;
AJAX的readyState的有几种:0(未初始化),1(开启),2(已传送),3(接收中),4(已载入)
2.STRUTS2执行
(1)request请求首先经过一系列的filter(转码,验证以及STRUTS自带Filter),最后到FilterDispatcher;
(2)FilterDispatcher通过ActionMapper来确定是否需要调用某个Action(应该是通过url-pattern决定),如需要则把请求处理交给ActionProxy
(3)ActionProxy通过Configuration Manager(struts.xml)找以需要调用的Action类;
(4)ActionProxy创建一个ActionInvocation实例,该实例通过一个链表(存放拦截器链)来依次调用拦截器及Action方法;
(5)Action执行完成后,返回result中的结果;
STRUTS2中的自动组装机制:
分为属性驱动和模型驱动:STRUTS2负责组装和类型转换,若转换失败,会进入名为input的逻辑视图;
属性驱动:即在ACTION中直接定义属性,由STRUTS2按名称组装;
模型驱动:首先定义模型类,再在ACTION中扩展ModelDriven接口,且须在ACTION中生成模型类的实例,STRUTS2由GET方法得到后组装;
STRUTS2中的异常机制:
通过<exception-mapping.../>元素配置,需指定exception和result两个属性;
3.Action的执行(SPRING)
生成ACTION实例,一般来说由SPRING来组装,在ACTION中配置类ID,真正的类由SPRING来生成;
SPRING中主要有三个功能:依赖注入,AOP,事务;
依赖注入:
(1)依赖注入的实现:分为构造注入或SET注入;
通过Class.forname()创建新的类,通过构造注入或SET注入;
构造注入:即用带参数的构造器来创建新类的,须用<constructor-arg..>来配置,一种为基本类型,通过index和value(有相同类型参数时)来 指定,一种则是非基本类型,通过bean来定义;
SET 注入:即调用无参数构造器后,通过SET来注入;
(2)依赖注入的bean的几种作用域:
singleton,prototype,request,session,global session;
其中request,session,global session需要在web.xml中配置<listener>RequestContextListener类;
singleton中依赖prototype时的方法注入:
<lookup-mehtod name="..." bean="..."/>
(3)依赖注入的手动组装与自动组装
常用的为手动组装,因为结构清晰;
其它的为自动组装,缺点是必须根据与属性类完全一致的类名来装配,接口再不能被实例化;
自动装配一般用的是byName;
AOP:
(1)通知类型:前置通知,后置通知,异常通知,最终通知,环绕通知;
环绕通知与其它通知的区别:可控制何时调用目标方法
可控制返回对象
后置通知与最终通知的区别:后置通知在方法正常返回时执行
最终通知无论方法正常还是异常都会执行
(2)AOP的两种方式:通过AspectJ即注释(annotation)、XMLSchema的方式;
AspectJ与XML的区别:
实现方式:AspectJ通过在通知类中加入匹配的注释来实现,需要在SPRING配置中加<aop:aspectj-autoproxy/>
XML则通过在XML中配置来实现,通知类中不需要加注释;
JDK支持:AspectJ需要JDK5+支持,XML不需要;
习惯:用户更习惯于XML;
XML缺点:
1.比起AspectJ来,配置更繁琐,且会使配置文件混乱,毕竟AOP的配置和一般的配置的写法并不太相同,ASPECTJ则将切面完全封装在一个类中,更符合将需求的实现封装到一个位置的做法;
2.XML只支持单例模式;
(3)代理机制:
Spring的AOP和事务都是用的动态代理来实现的;
代理分两种:CGLIB和JDK的动态代理,二者的实现机制基本相同,不同点在于JDK只支持接口代理,故须用CGLIB来实现对普通类的代理;
Spring默认接口采用JDK,普通类采用CGLIB,也可配置为全部用CGLIB;
SPRING事务基础知识:
(1)JDBC连接池:
一般用dbcp来实现,原理为连接池先从数据库获得连接,然后分配给线程;覆盖了原Connection的get和close方法,故getConnection方法是从连接池取连接,而close则将连接归还连接池,并未与数据库进行交互;
(2)全局事务与本地事务
全局事务:跨数据库,使用JTA;本地事务:一般为一个连接;
(3)事务可能出现问题:
更新丢失(lost update )
脏读 (dirty read )
非重复读(nonrepeatable read )
幻读 (phantom read )
(4)事务隔离
ISOLATION_READ_UNCOMMITTED 未提交读(可读缓存中的数据) 会造成脏读,非重复读,幻读
ISOLATION_READ_COMMITTED 提交读 (大部分数据库采用的默认方式)会造成非重复读,幻读
ISOLATION_REPEATABLE_READ 可重复读(一个事务不会修改已经由另一个事务读取但未提交(回滚)的数据)会造成幻读
ISOLATION_SERIALIZABLE 序列化 (事务串行执行) 无;
(5)事务传播
PROPAGATION_REQUIRED 有则加入,无则新建 这是最常见的选择。
PROPAGATION_SUPPORTS 有则以事务执行,无则以非事务执行
PROPAGATION_MANDATORY 有则以事务执行,无则抛出异常
PROPAGATION_REQUIRES_NEW 新建事务,当前已有的事务挂起
PROPAGATION_NOT_SUPPORTED 以非事务执行,有则挂起
PROPAGATION_NEVER 以非事务执行,有则抛异常
PROPAGATION_NESTED 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。
***PROPAGATION_REQUIRED与PROPAGATION_NESTED与PROPAGATION_REQUIRES_NEW的区别:
PROPAGATION_REQUIRED:外部事务和内部事务为一个事务,若一个失败,则全部回滚,成功,全部提交;
PROPAGATION_REQUIRES_NEW:内部事务为一个新事务,和外部事务作为两个事务看待,无论成功失败,都不影响另一个;
PROPAGATION_REQUIRES_NEW:若内部事务失败,则只回滚内部事务,若外部事务失败,则全部回滚,只有外部事务可以提交,若提交两个都提交;
(6)事务属性:事务隔离,事务传播,超时,只读属性;
SPRING事务:
(1)SPRING事务的三种方式:
XML配置:先XML配置不同策略的事务拦截器,再像AOP一样插入到aop:poing-cut下面;
注释形式:在需要事务的类方法前面加@Transactional注释即可,要求JDK5+,须配事务拦截器,但不需配置插入点,因为代码上注明了;
编程式:new一个PlatformTransactionManager类并设置拦截属性,需要配置事务管理器;
(2)如何选择:
较少用到事务,嫌麻烦时,用编程式;大量地还是用声明式(包括XML和注释);
4.数据访问与修改(hibernate)
(1)自动生成hibernate实体类与XML文件:
可通过数据库表来生成对应的实体BEAN和XML配置文件;工具有:PowerDesigher(PD),XDoclet,sechmaExport;
(2) hibernate主键生成策略
assigned:在新增数据时由应用程序指定主键的值;
适用于主键不是自动增长的列;
缺点:插入数据时需判断主键是否已存在;
increment:由hibernate自动生成主键值,先查询最大值,再加1;
适用于代理主键的主键列;
缺点:主键类型只能为int或long ;插入前须先查询一次,低效 ;并发操作时的冲突问题;
identity: 采用数据库的主键生成机制;
适用于DB2,MySQL,MS SQL Server,Sybase,HypersonicSQL
sequence: 采用数据库的主键生成机制;
适用于DB2,ORACLE,SAP DB;
hilo : 使用高低位算法来生成标识符;
native :根据不同底层数据库,自动选择identity,sequence,hilo主键生成方式;
UUID :使用UUID,适合于并发;
foreign : 用于一对一关系中,适用于MYSQL,SQLSERVER;
**sequence与identity的区别:
sequence作用于整个数据库,identity作用于单个表;
**UUID:
uuid为一个标准,用4个连字符将32位的字符串分隔生成字符串;
目前有两种主要实现:GUID和COMB;
GUID为微软的实现,COMB为数据库特有的一种设计,将UUID的最后6位用来表示时间,因为GUID因为无规律性导致了索引的效率低下;
(3)hibernate事务
hibernate层一般不需要事务管理,放在service层由SPRING来管理最好;
(4)hibernate的乐观锁和悲观锁
乐观锁使用版本号和时间戳来实现并发控制;
而悲观锁则使用数据库的锁定机制;一般使用JDBC配置好隔离级别后由数据库来搞定;
(5)session线程不安全解决方法,使用Threadlocal来保存session;
之所以不安全的原因就在于hibernate的session内置有一级缓存用来保存数据库数据,故可能读到错的数据;
(6)hibernate的cache机制:
hibernate的查询是先到一级缓存查,再到二级缓存(可选)查,再到数据库查;
session的cache(一级缓存,线程级别):
一般局限于事务一级,为防止并发事务导致数据不一致,一般使用ThreadLocal来保证一个线程一个session的缓存不会出现数据不一致问题;
sessionFactory(二级缓存,进程级别)
故二级缓存不太适用于并发情况,适用于少并发或只读的情况;
二级缓存策略如下:
1.条件查询时,使用select * from 将表中所有数据都查询出来;
2.把获得的所有数据对象根据ID放入到第二级缓存中
3.当Hibernate根据ID访问数据对象的时候,首先从Session一级缓存中查;查不到,如果配置了二级缓存,那么从二级缓存中查;查不到,再查询数据库,把结果按照ID放入到缓存。
4.删除、更新、增加数据的时候,同时更新缓存。
三。WEBSERVICE调用
SOAP:简单对象访问协议.
WSDL:Web服务描述语言.
UDDI(Universal Description, Discovery and Integration):通用描述、发现与集成,它是一种独立于平台的,基于XML语言的用于在互联网上描述商务的协议。