3.3程序设计框架架构基础相关知识点-技术
本文内容纲要:3.3程序设计框架架构基础相关知识点-技术
0.1请你谈谈SSH整合:
SSH:
Struts(表示层)+Spring(业务层)+Hibernate(持久层)
Struts:
Struts是一个表示层框架,主要作用是界面展示,接收请求,分发请求。
在MVC框架中,Struts属于VC层次,负责界面表现,负责MVC关系的分发。(View:沿用JSP,HTTP,Form,Tag,Resourse ;Controller:ActionServlet,struts-config.xml,Action)
Hibernate:
Hibernate是一个持久层框架,它只负责与关系数据库的操作。
Spring:
Spring是一个业务层框架,是一个整合的框架,能够很好地黏合表示层与持久层。
0.2 Spring+Struts+Hibernate
- Spring对多种ORM框架提供了很好的支持,简单描述在Spring中使用Hibernate的方法,并结合事务管理?
参考答案:Hibernate是最优秀的ORM框架,Spring对其提供了很好的支持,那么在Spring中使用Hibernate时要:
(1)为每一个bean写hibernate映射文件,配置datasourse,hibernateDaoTemplate,sessionFactory,把datasourse和映射文件注入到sessionFactory
(2)每个dao都继承spring容器中提供的一个类HibernateDaoSupport,为每个dao注入hibernateDaoTemplate
(3)在dao中使用getHibernateDaoTemplate()的方法。Spring中可以把需要进行事务控制的Biz注入到transactionProxy,为biz方法配置transactionAttribute
2.请比较一下Spring framework与Struts?
参考答案:Struts只是一个MVC框架(Framework),用于快速的开发Java Web应用。Struts实现的重点在C(Controller),包括Actionservlet/RequestProcessor和我们定制的Action,也为V(View)提供了一系列的标签(Custom Tag)。而Spring是一个轻型容器,其中核心是bean工厂(beanfactory),用以构造我们所需要的Model。在此基础上,spring提供了AOP(面向切面编程)的实现,用它来提供非管理环境下申明方式的事务、安全等服务;对Bean工厂的扩展ApplicationContext更加方便我们实现j2ee的应用;Dao/ORM的实现方便我们进行数据库的开发;Web MVC和Spring Web提供了java Web应用的框架或与其他流行的Web框架进行集成。两者进行结合在一起使用是最好的方式。
- 请叙述编写业务逻辑的方法?
参考答案:继承HibernateDaoSupport类,使用HibernateTemplate来持久化,HibernateTemplate是Hibernate Session的轻量级封装。默认情况下运行期异常才会回滚(包括继承了RuntimeException子类),普通异常是不会滚的。编写业务逻辑方法时,最好将异常一直向上抛出,在表示层(struts)处理。关于事务边界的设置,通常设置到业务层,不要添加到Dao上。
- 在Web分层架构中业务层为什么都选择Spring?
参考答案:因为Service层需要处理业务逻辑和交叉业务逻辑,处理事务,日志,安全等,而这些与Spring的IoC特性,AOP等不谋而合。
1Spring要出20-30核心问题:26个问题
-----------------------------Spring start---------------------------------------------------------------------------------
1.1.1 什么是Spring? Spring工作机制是什么?为什么要用Spring(或Spring的优势)?
1.1.2 说说AOP和IoC的概念以及在spring中是如何应用的?
1.1.3 Spring的优点和缺点?
1.1.4 Spring对多种ORM框架提供了很好的支持,简单描述在Spring中使用Hibernate的方法?
1.1.5 spring的配置的主要标签是什么?有什么作用?
1.1.6 spring中的核心类有那些,各有什么作用?
1.1.7 Bean的调用?
1.1.8 Spring框架有哪几部分组成?
1.1.9 简述Spring容器提供了哪些功能?
1.1.10请叙述设值注入的优点?
1.1.11 请叙述构造注入的优点?
1.2.1 什么是事务? 事务有哪些特性?Spring的事物有几种方式?谈谈spring事物的传播行为和隔离级别?Spring中如何配置事务的隔离级别和传播行为?
1.2.2 Spring 在MVC中怎么运用的?起到什么作用?
1.2.3 为什么用aop?
1.2.4 说出bean工厂创建bean的三种方式?
1.2.5 谈谈目标对象实现接口与目标对象不实现接口有什么区别?
1.2.6 请描述JDK动态代理和CGLI代理的区别?
1.2.7 简述ProxyFactoryBean的作用是什么?
1.2.8 叙述Spring中的自动代理的原理?
1.2.9 写出创建代理对象需指定的三要素是什么?
1.2.10 写出代理的两种方式分别是什么?
1.2.11请简述:什么是AOP?
1.3.1 Spring Bean的生命周期、Spring scope?
1.3.2 spring中的BeanFactory与ApplicationContext的作用和区别?
1.3.4 如何在web环境中配置applicationContext.xml文件?
1.1Spring初级问题:-------------------------------------------------
1.1.1 什么是Spring? Spring工作机制是什么?为什么要用Spring(或Spring的优势)?
Spring是一个开源框架,是为了解决企业应用程序开发复杂性而创建的。Spring既是一个AOP框架,也是一IOC容器。
SpringFramework的组成:Spring AOP,Spring DAO,Spring ORM,Spring Web,Spring Context, Spring Web MVC。
Spring的核心就是IoC和AOP,所以Spring的工作机制简单的理解也就是IoC和AOP的工作机制。
借助于Spring AOP,Spring IoC能够很方便的使用到非常健壮、灵活的企业级服务,通过使用IoC能够降低组件之间的耦合度,最终,能够提高类的重用性,利于测试,而且更利于整个产品或系统集成和配置。
框架的主要优势之一就是其分层架构,分层架构允许您选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架。
1.1.2 说说AOP和IoC的概念以及在spring中是如何应用的?
AOP,Aspect Oriented Program,面向(方面)切面的编程;
IOC,Invert Of Control,控制反转。又称DI Denpendency Injection:依赖注入
简单说一下,IoC就是其实就是依赖注入,即用接口编程,在程序中不出现new关键字,而是用接口来命名引用,然后通过某种方式(XML/注解)把接口的某个实现类的实例注入到引用里,从而实现接口与具体实现类的松耦合。
由容器控制程序之间的关系(通过XML/注解配置),而非传统实现中的由程序代码直接操控,(在一个Class对象中引用另一个Class对象时,我们通常都是直接通过new contructor)。控制权由应用代码中转到了外部容器,控制权的转移,是所谓的反转。
依赖注入(Dependecy Injection)和控制反转(Inversion of Control)是同一个概念,具体的讲:当某个角色
需要另外一个角色协助的时候,在传统的程序设计过程中,通常由调用者来创建被调用者的实例。但在spring中
创建被调用者的工作不再由调用者来完成,因此称为控制反转。创建被调用者的工作由spring来完成,然后注入调用者
因此也称为依赖注入。
spring以动态灵活的方式来管理对象 , 注入的两种方式,
方式一:接口注入,在实际中得到了普遍应用,即使在IOC的概念尚未确立时,这样的方法也已经频繁出现在我们的代码中。
方式二:Type2 IoC: Setter injection对象创建之后,将被依赖对象通过set方法设置进去
方式三:Type3 IoC: Constructor injection对象创建时,被依赖对象以构造方法参数的方式注入
设置注入的优点:直观,自然
构造注入的优点:可以在构造器中决定依赖关系的顺序。
AOP方式很类似filter,就是在程序正常的业务流中间像切面一样插入很多其他需要执行的代码,比如登录时候,在进入登录页面前写入日志,很常用的,尤其是跟数据库有关的,或者跟支付有关的程序肯定会在每一步前面插入日志。
面向方面的编程,即AOP,是一种编程技术,它允许程序员对横切关注点或横切典型的职责分界线的行为(例如日志和事务管理)进行模块化。AOP的核心构造是方面,它将那些影响多个类的行为封装到可重用的模块中。
AOP Advice(AOP通知)分为:
前置通知 @Before
后置通知 @AfterReturning :after returning advice
异常通知 @AfterThrowing :after throwing advice
最终通知 @After
环绕通知 @Around
1.1.3 Spring的优点和缺点?
⑴Spring的优点:
①Spring能有效地组织你的中间层对象,不管你是否选择使用了EJB;
②Spring能消除在许多工程中常见的对Singleton的过多使用。(因为它降低了系统的可测试性和面向对象的程度);
③通过一种在不同应用程序和项目间一致的方法来处理配置文件,Spring能消除各种各样自定义格式的属性文件的需要。Inversion of Control的使用帮助完成了这种简化;
④通过把对接口编程而不是对类编程的代价几乎减少到没有,Spring能够促进养成好的编程习惯;
⑤Spring被设计为让使用它创建的应用尽可能少的依赖于他的APIs。在Spring应用中的大多数业务对象没有依赖于Spring;
⑥使用Spring构建的应用程序易于单元测试;
⑦Spring能使EJB的使用成为一个实现选择,而不是应用架构的必然选择。你能选择用POJOs或local EJBs来实现业务接口,却不会影响调用代码;
⑧Spring帮助你解决许多问题而无需使用EJB。Spring能提供一种EJB的替换物,他们适用于许多web应用。例如:Spring能使用AOP提供声明性事务管理而不通过EJB容器;
⑨Spring为数据存取提供了一个一致的框架不论使用的是JDBC还是O/R mapping产品;
⑵Spring的缺点:
①使用人数不多,jsp中要写很多代码;
②控制器过于灵活,缺少一个公用控制器。
1.1.4 Spring对多种ORM框架提供了很好的支持,简单描述在Spring中使用Hibernate的方法。
在context中定义DataSource,创建SessionFactoy,设置参数;DAO类继承HibernateDaoSupport,实现具体接口,从中获得HibernateTemplate进行具体操作。在使用中如果遇到OpenSessionInView的问题,可以添加 OpenSessionInViewFilter或OpenSessionInViewInterceptor
1.1.5 spring的配置的主要标签是什么?有什么作用?
1.1.6 spring中的核心类有那些,各有什么作用?
BeanFactory:产生一个新的实例,可以实现单例模式
BeanWrapper:提供统一的get及set方法
ApplicationContext:提供框架的实现,包括BeanFactory的所有功能
1.1.7 Bean的调用?
有三种方式可以得到Bean并进行调用:
1、使用BeanWrapper
HelloWorld hw=new HelloWorld();
BeanWrapper bw=new BeanWrapperImpl(hw);
bw.setPropertyvalue(”msg”,”HelloWorld”);
system.out.println(bw.getPropertyCalue(”msg”));
2、使用BeanFactory
InputStream is=new FileInputStream(”config.xml”);
XmlBeanFactory factory=new XmlBeanFactory(is);
HelloWorld hw=(HelloWorld) factory.getBean(”HelloWorld”);
system.out.println(hw.getMsg());
3、使用ApplicationConttext
ApplicationContext actx=new FleSystemXmlApplicationContext(”config.xml”);
HelloWorld hw=(HelloWorld) actx.getBean(”HelloWorld”);
System.out.println(hw.getMsg());
1.1.8 Spring框架有哪几部分组成?
Spring框架有七个模块组成组成,这7个模块(或组件)均可以单独存在,也可以与其它一个或多个模块联合使用,主要功能表现如下:
* Spring 核心容器(Core):提供Spring框架的基本功能。核心容器的主要组件是BeanFactory,她是工厂模式的实现。BeanFactory使用控制反转(Ioc)模式将应用程序的配置和依赖性规范与实际的应用代码程序分开。
* Spring AOP:通过配置管理特性,Spring AOP模块直接面向方面的编程功能集成到了Spring框架中,所以可以很容易的使Spring框架管理的任何对象支持 AOP。Spring AOP模块为基于Spring的应用程序中的对象提供了事务管理服务。通过使用Spring AOP,不用依赖于EJB组件,就可以将声明性事务管理集成到应用程序中。
* Spring ORM:Spring框架集成了若干ORM框架,从而提供了ORM的对象关系工具,其中包括 JDO、Hibernate、iBatis和TopLink。所有这些都遵从Spring的通用事务和DAO异常层结构。
* Spring DAO:JDBC DAO抽象层提供了有意义的异常层次的结构,可用该结构来管理异常处理和不同数据供应商抛出的异常错误信息。异常层次结构简化了错误处理,并且大大的降低 了需要编写的异常代码数量(例如,打开和关系连接)。Spring DAO的面向JDBC的异常遵从通用的DAO异常层结构。
* Spring WEB:Web上下文模块建立在上下文模块(Context)的基础之上,为基于Web服务的应用程序提供了上下文的服务。所以Spring框架支持 Jakarta Struts的集成。Web模块还简化了处理多部分请求及将请求参数绑定到域对象的工作。
* Spring上下文(Context):Spring上下文是一个配置文件,向Spring框架提供上下文信息。Spring上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化校验和调度功能。
* Spring MVC:Spring的MVC框架是一个全功能的构建Web应用程序的MVC实现。通过策略接口,MVC框架变成为高度可配置的,MVC容纳的大量视图技术,包括JSP、Velocity、Tiles、iText和Pol
1.1.9 简述Spring容器提供了哪些功能?
Spring容器提供了对对象的管理,如Spring容器负责生成、组装、销毁组件,另外Spring容器还提供了对持久化的支持,对事务的支持。另外Spring容器提供了国际化等功能。
1.1.10 . 请叙述设值注入的优点?
设置注入的优点:
(1)与传统的JavaBean的写法更相似,程序开发人员更容易了解和接受。通过setter方法设定依赖关系显得更加直观、自然。
(2)对于有复杂的依赖关系,如果采用构造注入,会导致构造器过于臃肿,难以阅读。Spring在创建bean实例时,需要同时实例化其依赖的全部实例,因而导致性能的下降,而使用设值注入能够解决这些问题。
(3)尤其是某些属性可选的情况下,多参数的构造器更加笨重。
1.1.11 请叙述构造注入的优点?
构造注入的优点:
(1)可以在构造器中决定依赖关系的注入顺序,优先依赖的优先注入。
(2)对于依赖关系无须变化的bean,构造注入更加有用处。因为没有setter方法,所有的依赖关系全部在构造器内设定,因此,无须担心后续的代码对依赖关系产生破坏。
(3)依赖关系只能在构造器中设定,则只有组建的创建者才能改变组建的依赖关系。对组建的调用者而言,组建内部的依赖关系完全透明,更符合高内聚的原则。
1.2Spring中级问题:---------------------------------------------------------------
1.2.1 什么是事务? 事务有哪些特性?Spring的事物有几种方式?谈谈spring事物的传播行为和隔离级别?Spring中如何配置事务的隔离级别和传播行为?
事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。事务通常由高级数据库操纵语言或编程语言(如SQL,C++或Java)书写的用户程序的执行所引起,并用形如begin transaction和end transaction语句(或函数调用)来界定。事务由事务开始(begin transaction)和事务结束(end transaction)之间执行的全体操作组成。
例如:在关系数据库中,一个事务可以是一条SQL语句,一组SQL语句或整个程序。
事务特性:
事务是恢复和并发控制的基本单位。atomicity
事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。
原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。
一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。隔离级别?
持久性(durability)。持续性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
事务种类:声明式(xml/annotation)和编码式
spring事物的传播行为:事务传播:通常在一个事务中执行的所有代码都会在这个事务中运行。但是,如果一个事务上下文已经存在,有几个选项可以指定一个事务性方法的执行行为:例如,简单地在现有的事务中继续运行(大多数情况);或者挂起现有事务,创建一个新的事务。
Propagation (事务的传播属性):
Propagation :key属性确定代理应该给哪个方法增加事务行为。这样的属性最重要的部份是传播行为。有以下选项可供使用:
PROPAGATION_REQUIRED--支持当前事务,如果当前有事务,则使用该事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。
1: PROPAGATION_REQUIRED
加入当前正要执行的事务不在另外一个事务里,那么就起一个新的事务
比如说,ServiceB.methodB的事务级别定义为PROPAGATION_REQUIRED, 那么由于执行ServiceA.methodA的时候,
ServiceA.methodA已经起了事务,这时调用ServiceB.methodB,ServiceB.methodB看到自己已经运行在ServiceA.methodA
的事务内部,就不再起新的事务。而假如ServiceA.methodA运行的时候发现自己没有在事务中,他就会为自己分配一个事务。
这样,在ServiceA.methodA或者在ServiceB.methodB内的任何地方出现异常,事务都会被回滚。即使ServiceB.methodB的事务已经被
提交,但是ServiceA.methodA在接下来fail要回滚,ServiceB.methodB也要回滚
2: PROPAGATION_SUPPORTS
如果当前在事务中,即以事务的形式运行,如果当前不再一个事务中,那么就以非事务的形式运行
3: PROPAGATION_MANDATORY
必须在一个事务中运行。也就是说,他只能被一个父事务调用。否则,他就要抛出异常
4: PROPAGATION_REQUIRES_NEW This in particular applies to JtaTransactionManager
这个就比较绕口了。 比如我们设计ServiceA.methodA的事务级别为PROPAGATION_REQUIRED,ServiceB.methodB的事务级别为PROPAGATION_REQUIRES_NEW,
那么当执行到ServiceB.methodB的时候,ServiceA.methodA所在的事务就会挂起,ServiceB.methodB会起一个新的事务,等待ServiceB.methodB的事务完成以后,
他才继续执行。他与PROPAGATION_REQUIRED的事务区别在于事务的回滚程度了。因为ServiceB.methodB是新起一个事务,那么就是存在
两个不同的事务。如果ServiceB.methodB已经提交,那么ServiceA.methodA失败回滚,ServiceB.methodB是不会回滚的。如果ServiceB.methodB失败回滚,
如果他抛出的异常被ServiceA.methodA捕获,ServiceA.methodA事务仍然可能提交。
5: PROPAGATION_NOT_SUPPORTED:This in particular applies to JtaTransactionManager
当前不支持事务。比如ServiceA.methodA的事务级别是PROPAGATION_REQUIRED ,而ServiceB.methodB的事务级别是PROPAGATION_NOT_SUPPORTED ,
那么当执行到ServiceB.methodB时,ServiceA.methodA的事务挂起,而他以非事务的状态运行完,再继续ServiceA.methodA的事务。
6: PROPAGATION_NEVER
不能在事务中运行。假设ServiceA.methodA的事务级别是PROPAGATION_REQUIRED, 而ServiceB.methodB的事务级别是PROPAGATION_NEVER ,那么ServiceB.methodB就要抛出异常了。
7: PROPAGATION_NESTED JDBC 3.0 driver 和 JTA
理解Nested的关键是savepoint。他与PROPAGATION_REQUIRES_NEW的区别是,PROPAGATION_REQUIRES_NEW另起一个事务,将会与他的父事务相互独立,
而Nested的事务和他的父事务是相依的,他的提交是要等和他的父事务一块提交的。也就是说,如果父事务最后回滚,他也要回滚的。
而Nested事务的好处是他有一个savepoint。
****************************************
ServiceA {
/**
* 事务属性配置为 PROPAGATION_REQUIRED
*/
void methodA() {
try {
//savepoint
ServiceB.methodB(); //PROPAGATION_NESTED 级别
} catch (SomeException) {
// 执行其他业务, 如 ServiceC.methodC();
}
}
}
********************************************
也就是说ServiceB.methodB失败回滚,那么ServiceA.methodA也会回滚到savepoint点上,ServiceA.methodA可以选择另外一个分支,比如
ServiceC.methodC,继续执行,来尝试完成自己的事务。
但是这个事务并没有在EJB标准中定义。
Spring事务的隔离级别:
Isolation Level(事务隔离等级):
1、Serializable串行化:最严格的级别,事务串行执行,资源消耗最大;
2、REPEATABLE READ可重复读:保证了一个事务不会修改已经由另一个事务读取但未提交(回滚)的数据。避免了“脏读取”和“不可重复读取”的情况,但是带来了更多的性能损失。
3、READ COMMITTED读已提交数据:大多数主流数据库的默认事务等级,保证了一个事务不会读到另一个并行事务已修改但未提交的数据,避免了“脏读取”。该级别适用于大多数系统。
4、Read Uncommitted读未提交数据(会出现脏读):保证了读取过程中不会读取到非法数据。隔离级别在于处理多事务的并发问题。
我们知道并行可以提高数据库的吞吐量和效率,但是并不是所有的并发事务都可以并发运行,这需要查看数据库教材的可串行化条件判断了。
这里就不阐述。
我们首先说并发中可能发生的3中不讨人喜欢的事情
1: Dirty reads--读脏数据。也就是说,比如事务A的未提交(还依然缓存)的数据被事务B读走,如果事务A失败回滚,会导致事务B所读取的的数据是错误的。
2: non-repeatable reads--数据不可重复读。比如事务A中两处读取数据-total-的值。在第一读的时候,total是100,然后事务B就把total的数据改成 200,事务A再读一次,结果就发现,total竟然就变成200了,造成事务A数据混乱。
3: phantom reads--幻象读数据,这个和non-repeatable reads相似,也是同一个事务中多次读不一致的问题。但是non-repeatable reads的不一致是因为他所要取的数据集被改变了(比如total的数据),但是phantom reads所要读的数据的不一致却不是他所要读的数据集改变,而是他的条件数据集改变。比如Select account.id where account.name="ppgogo*",第一次读去了6个符合条件的id,第二次读取的时候,由于事务b把一个帐号的名字由"dd"改成"ppgogo1",结果取出来了7个数据。
Dirty reads non-repeatable reads phantom reads
Serializable 不会 不会 不会
REPEATABLE READ 不会 不会 会
READ COMMITTED 不会 会 会
Read Uncommitted 会 会 会
什么是脏数据,脏读,不可重复读,幻觉读?
脏读: 指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,
另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据, 那么另外一
个事务读到的这个数据是脏数据,依据脏数据所做的操作可能是不正确的。
不可重复读: 指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。
那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的数据
可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。
幻觉读: 指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及
到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,
以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。
Spring事务readOnly:事务属性中的readOnly标志表示对应的事务应该被最优化为只读事务。
这是一个最优化提示。在一些情况下,一些事务策略能够起到显著的最优化效果,例如在使用Object/Relational映射工具(如:Hibernate或TopLink)时避免dirty checking(试图“刷新”)。
Spring事务Timeout:
在事务属性中还有定义“timeout”值的选项,指定事务超时为几秒。在JTA中,这将被简单地传递到J2EE服务器的事务协调程序,并据此得到相应的解释
参考http://www.blogjava.net/RoyPayne/archive/2012/01/05/367919.html
spring提供了几个关于事务处理的类:
TransactionDefinition //事务属性定义
TranscationStatus //代表了当前的事务,可以提交,回滚。
PlatformTransactionManager这个是spring提供的用于管理事务的基础接口,其下有一个实现的抽象类AbstractPlatformTransactionManager,我们使用的事务管理类例如 DataSourceTransactionManager等都是这个类的子类。
一般事务定义步骤:
TransactionDefinition td = new TransactionDefinition();
TransactionStatus ts = transactionManager.getTransaction(td);
try{ //do sth
transactionManager.commit(ts);
} catch(Exception e){transactionManager.rollback(ts);}
spring提供的事务管理可以分为两类:编程式的和声明式的。编程式的,比较灵活,但是代码量大,存在重复的代码比较多;声明式的比编程式的更灵活。
编程式主要使用transactionTemplate。省略了部分的提交,回滚,一系列的事务对象定义,需注入事务管理对象.
void add(){
transactionTemplate.execute( new TransactionCallback(){
pulic Object doInTransaction(TransactionStatus ts){ //do sth}
}
}
1.2.2 Spring 在MVC中怎么运用的?起到什么作用?
1.spring mvc将所有的请求都提交给DispatcherServlet,它会委托应用系统的其他模块负责对请求进行真正的处理工作。
2.DispatcherServlet查询一个或多个HandlerMapping,找到处理请求的Controller.
3.DispatcherServlet请请求提交到目标Controller
4.Controller进行业务逻辑处理后,会返回一个ModelAndView
5.Dispathcher查询一个或多个ViewResolver视图解析器,找到ModelAndView对象指定的视图对象
6.视图对象负责渲染返回给客户端。
1.2.3 为什么用aop?
1就是为了方便,看一个国外很有名的大师说,编程的人都是“懒人”,因为他把自己做的事情都让程序做了。用了aop能让你少写很多代码,这点就够充分了吧
2就是为了更清晰的逻辑,可以让你的业务逻辑去关注自己本身的业务,而不去想一些其他的事情,这些其他的事情包括:安全,事物,日志等。
3.那些aop的术语
初看这么多术语,一下子都不好接受,慢慢来,很快就会搞懂。
1.通知(Advice)
就是你想要的功能,也就是上面说的 安全,事物,日志等。你给先定义好把,然后在想用的地方用一下。
2.连接点(JoinPoint)
这个更好解释了,就是spring允许你使用通知的地方,那可真就多了,基本每个方法的前,后(两者都有也行),或抛出异常时都可以是连接点,spring只支持方法连接点.其他如aspectJ还可以让你在构造器或属性注入时都行,不过那不是咱关注的,只要记住,和方法有关的前前后后(抛出异常),都是连接点。
3.切入点(Pointcut)
上面说的连接点的基础上,来定义切入点,你的一个类里,有15个方法,那就有几十个连接点了对把,但是你并不想在所有方法附近都使用通知(使用叫织入,以后再说),你只想让其中的几个,在调用这几个方法之前,之后或者抛出异常时干点什么,那么就用切点来定义这几个方法,让切点来筛选连接点,选中那几个你想要的方法。
4.切面(Aspect)
切面是通知和切入点的结合。现在发现了吧,没连接点什么事情,连接点就是为了让你好理解切点,搞出来的,明白这个概念就行了。通知说明了干什么和什么时候干(什么时候通过方法名中的before,after,around等就能知道),而切入点说明了在哪干(指定到底是哪个方法),这就是一个完整的切面定义。
5.引入(introduction)
允许我们向现有的类添加新方法属性。这不就是把切面(也就是新方法属性:通知定义的)用到目标类中吗
6.目标(target)
引入中所提到的目标类,也就是要被通知的对象,也就是真正的业务逻辑,他可以在毫不知情的情况下,被咱们织入切面。而自己专注于业务本身的逻辑。
7.代理(proxy)
怎么实现整套aop机制的,都是通过代理,这个一会给细说。
8.织入(weaving)
把切面应用到目标对象来创建新的代理对象的过程。有3种方式,spring采用的是运行时,为什么是运行时,后面解释。
关键就是:切点定义了哪些连接点会得到通知
1.2.4 说出bean工厂创建bean的三种方式?
参考答案:Bean工厂创建bean的三种方式分别是:
(1)直接构造,需要一个default constructor和相应的setters/getters方法。
要注意的是,我们可以为getter/setter方法传递参数(用preperties标签),也可以为构造函数传递参数
(2)采用静态工厂方法,如:
<bean id="exampleBean"class="examples.ExampleBean2"
factory-method="createInstance"/>
这里要求examples.ExampleBean2类有个静态方法createInstance
(3)非静态工厂方法
在这里,必须没有class标签,factory-bean是BeanFactory,factory-method是它的非静态方法,myFactoryBean可以通过容器来管理和配置。
1.2.5 谈谈目标对象实现接口与目标对象不实现接口有什么区别?
参考答案:目标对象实现接口与目标对象不实现接口主要有以下几点区别:
(1)如果目标对象实现了接口,默认采用JDK的动态代理机制实现AOP
(2)如果目标对象实现了接口,可以强制spring采用CGLIB实现代理
(3)如果目标对象没有实现接口,必须采用CGLIB实现代理,spring会自动的在CGLIB和JDK动态代理之间切换
1.2.6 请描述JDK动态代理和CGLI代理的区别?
参考答案:JDK 的动态代理只能对实现了接口的目标类进行代理,而不实现接口的类就不能使用JDK的动态代理
CGLIB 是针对类来实现代理,当没有实现接口的类需要代理时就需要通过CGLIB来实现代理了,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但是因为采用的是继承,所以不能对final类进行继承。
二者在某些特殊场合需混合使用
1.2.7 简述ProxyFactoryBean的作用是什么?
参考答案:ProxyFactoryBean的作用是依照配置信息,将切面应用到目标对象,生成动态代理对象。
1.2.8 叙述Spring中的自动代理的原理?
参考答案:Spring在生成代理对象的时候,默认情况下,会使用被代理对象的接口来生成代理对象。如果被代理对象没有实现接口,此时,Spring会使用CGLIB生成代理对象,此时该代理对象是被代理对象的子类。
1.2.9 写出创建代理对象需指定的三要素是什么?
参考答案:创建代理对象需要指定的三要素是:
target:设定目标对象(只能是一个);
proxyInterfaces:设定代理接口(目标对象所实现的接口);
interceptorNames:设定拦截器的名字(各个advice或advisor bean的列表)
1.2.10 写出代理的两种方式分别是什么?
参考答案:代理的两种方式是:静态代理和动态代理,其中静态代理针对每个具体类分别编写代理类;针对一个接口编写一个代理类。
而动态代理针对一个方面编写一个InvocationHandler,然后借用JDK反射包中的Proxy类为各种接口动态生成相应的代理
1.2.11请简述:什么是AOP?
参考答案:将程序中的交叉业务逻辑提取出来,称之为切面。将这些切面动态织入到目标对象,然后生成一个代理对象的过程。
Spring怎么进行事务处理的?
Spring中的transaction的用法?
1.3Spring高级问题:------------------------------------------------------------
1.3.1 Spring Bean的生命周期、Spring scope?
在传统的Java应用中,Bean的生命周期非常简单。
Java的关键词new用来实例化Bean(或许他是非序列化的)。这样就够用了。
相反,Bean的生命周期在Spring容器中更加细致。
理解Spring Bean的生命周期非常重要,因为你或许要利用Spring提供的机会来订制Bean的创建过程。
1.容器寻找Bean的定义信息并且将其实例化。
2.受用依赖注入,Spring按照Bean定义信息配置Bean的所有属性。
3.如果Bean实现了BeanNameAware接口,工厂调用Bean的setBeanName()方法传递Bean的ID。
4.如果Bean实现了BeanFactoryAware接口,工厂调用setBeanFactory()方法传入工厂自身。
5.如果BeanPostProcessor和Bean关联,那么它们的postProcessBeforeInitialzation()方法将被调用。
6.如果Bean指定了init-method方法,它将被调用。
7.最后,如果有BeanPsotProcessor和Bean关联,那么它们的postProcessAfterInitialization()方法将被调用。
到这个时候,Bean已经可以被应用系统使用了,并且将被保留在Bean Factory中知道它不再需要。
有两种方法可以把它从Bean Factory中删除掉。
1.如果Bean实现了DisposableBean接口,destory()方法被调用。
2.如果指定了订制的销毁方法,就调用这个方法。
Bean在Spring应用上下文的生命周期与在Bean工厂中的生命周期只有一点不同,
唯一不同的是,如果Bean实现了ApplicationContextAwre接口,setApplicationContext()方法被调用。
只有singleton行为的bean接受容器管理生命周期。
non-singleton行为的bean,Spring容器仅仅是new的替代,容器只负责创建。
对于singleton bean,Spring容器知道bean何时实例化结束,何时销毁,
Spring可以管理实例化结束之后,和销毁之前的行为,管理bean的生命周期行为主要是如下两个时机:
Bean全部依赖注入之后
Bean即将销毁之前
1)依赖关系注入后的行为实现:
有两种方法:A.编写init方法 B.实现InitializingBean接口
afterPropertiesSet和init同时出现,前者先于后者执行,使用init方法,需要对配置文件加入init-method属性
2)bean销毁之前的行为
有两种方法:A.编写close方法 B.实现DisposableBean接口
destroy和close同时出现,前者先于后者执行,使用close方法,需要对配置文件加入destroy-method属性
Spring scope:
Spring容器最初提供了两种bean的scope类型:singleton和prototype,但发布2.0以后,又引入了另外三种scope类型:request、session和global session,这三种只能在web 应用中才可以使用。
singleton: Spring容器只会创建该bean定义的唯一实例,这个实例会被保存到缓存中,并且对该bean的所有后续请求和引用都将返回该缓存中的对象实例,一般情况下,无状态的bean使用该scope。
prototype:每次对该bean的请求都会创建一个新的实例,一般情况下,有状态的bean使用该scope。
request:每次http请求将会有各自的bean实例,类似于prototype。
session:在一个http session中,一个bean定义对应一个bean实例。
global session:在一个全局的http session中,一个bean定义对应一个bean实例。典型情况下,仅在使用portlet context的时候有效。
1.3.2 spring中的BeanFactory与ApplicationContext的作用和区别?
作用:
- BeanFactory负责读取bean配置文档,管理bean的加载,实例化,维护bean之间的依赖关系,负责bean的声明周期。
- ApplicationContext除了提供上述BeanFactory所能提供的功能之外,还提供了更完整的框架功能:
a. 国际化支持
b. 资源访问:Resource rs = ctx. getResource(”classpath:config.properties”), “file:c:/config.properties”
c. 事件传递:通过实现ApplicationContextAware接口
- 常用的获取ApplicationContext的方法:
FileSystemXmlApplicationContext:从文件系统或者url指定的xml配置文件创建,参数为配置文件名或文件名数组
ClassPathXmlApplicationContext:从classpath的xml配置文件创建,可以从jar包中读取配置文件
WebApplicationContextUtils:从web应用的根目录读取配置文件,需要先在web.xml中配置,可以配置监听器或者servlet来实现
这两种方式都默认配置文件为web-inf/applicationContext.xml,也可使用context-param指定配置文件
参考资料:建议看看Spring框架的IOC容器,理解Spring的Xml配置
1.3.4 如何在web环境中配置applicationContext.xml文件?
在web.xml中配置
org.springframework.web.context.ContextLoaderListener
或:
org.springframework.web.context.ContextLoaderServlet
通过如下方法取出applicationContext实例:
ApplicationContext ac=WebApplicationContextUtils.getWebApplicationContext(this.getServletContext);
1.3.5 Spring工作原理?
Spring内部最核心的就是IoC了,
动态注入,让一个对象的创建不用new了,可以自动的生产,这其实就是利用java里的反射
反射其实就是在运行时动态的去创建、调用对象,Spring就是在运行时,跟xml Spring的配置
文件来动态的创建对象,和调用对象里的方法的 。
Spring还有一个核心就是AOP这个就是面向切面编程,可以为某一类对象 进行监督和控制(也就是
在调用这类对象的具体方法的前后去调用你指定的 模块)从而达到对一个模块扩充的功能。这些都是通过
配置类达到的。
Spring目的:就是让对象与对象(模块与模块)之间的关系没有通过代码来关联,都是通过配置类说明
管理的(Spring根据这些配置 内部通过反射去动态的组装对象)
要记住:Spring是一个容器,凡是在容器里的对象才会有Spring所提供的这些服务和功能。
Spring里用的最经典的一个设计模式就是:模板方法模式。(这里我都不介绍了,是一个很常用的设计模式)
Spring里的配置是很多的,很难都记住,但是Spring里的精华也无非就是以上的两点,把以上两点跟理解了 也就基本上掌握了Spring.
Spring AOP与IOC
一、 IoC(Inversion of control): 控制反转
1、IoC:
概念:控制权由对象本身转向容器;由容器根据配置文件去创建实例并创建各个实例之间的依赖关系
核心:bean工厂;在Spring中,bean工厂创建的各个实例称作bean
二、AOP(Aspect-Oriented Programming): 面向方面编程
1、 代理的两种方式:
静态代理:
针对每个具体类分别编写代理类;
针对一个接口编写一个代理类;
动态代理:
针对一个方面编写一个InvocationHandler,然后借用JDK反射包中的Proxy类为各种接口动态生成相应的代理类
-----------------------------Spring end----------------------------------------------------------------------------------
-----------------------------hibernate/ibatis/jdbc start-----------------------------------------------------------------
2hibernate/ibatis/jdbc 20-30问题
2.1.1Hibernate工作原理?
2.1.2 Hibernate是如何延迟加载?
2.1.3.Hibernate中怎样实现类之间的关系?(如:一对多、多对多的关系)
2.1.4. 说下Hibernate的缓存机制?
2.1.5. Hibernate的查询方式Sql、Criteria,object comptosition Hql?
2.1.6. 如何优化Hibernate?
2.1.7Hibernate有哪几种查询数据的方式?
2.1.8 load()和get()的区别?
2.1.9 在数据库中条件查询速度很慢的时候,如何优化?
2.1.10 在Hibernate中进行多表查询,每个表中各取几个字段,也就是说查询出来的结果集并没有一个实体类与之对应,如何解决这个问题?
2.1.11 Hibernate的主键生成机制?
2.2.1 hibernate都支持哪些缓存策略?
2.2.2 jdbc、hibernate、ibatis的区别?
2.2.3 三种检索策略是什么,分别适用于哪种场合?
2.2.4 ORM解决的不匹配问题(域模型与关系模型之间存在的不匹配)?
2.2.5 映射继承关系的三种方式?
2.2.6 请简述Session的特点有哪些?
2.2.7 Hibernate中数据表映射关系主要有什么类型?
2.2.8 在Hibernate应用中Java对象的状态有哪些?
2.2.9 session的清理和清空有什么区别?
2.3.1 为什么用IBATIS不用Hibernate?
2.3.2 为什么使用ibatis而不用spring jdbcTemplate?
2.3.3 Ibatis中使用like ‘%#filedName#%’ 时,有什么问题?
2.3.4 Java主流数据库连接池有哪些?
2.3.5 JDBC连接数据库6步?
2.3.6 如何在生产环境下跟踪数据库服务器执行的sql语句?
2.1初级问题
2.1.1Hibernate工作原理?
学习过程是首先看看java反射的概念,然后学学AOP
原理:
1.读取并解析配置文件
2.读取并解析映射信息,创建SessionFactory
3.打开Sesssion
4.创建事务Transation
5.持久化操作
6.提交事务
7.关闭Session
8.关闭SesstionFactory
为什么要用:
- 对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。
- Hibernate是一个基于JDBC的主流持久化框架,是一个优秀的ORM实现。他很大程度的简化DAO层的编码工作
- hibernate使用Java反射机制,而不是字节码增强程序来实现透明性。
- hibernate的性能非常好,因为它是个轻量级框架。映射的灵活性很出色。它支持各种关系数据库,从一对一到多对多的各种复杂关系。
2.1.2 Hibernate是如何延迟加载?
- Hibernate2延迟加载实现:a)实体对象 b)集合(Collection)
- Hibernate3 提供了属性的延迟加载功能
当Hibernate在查询数据的时候,数据并没有存在与内存中,当程序真正对数据的操作时,对象才存在与内存中,就实现了延迟加载,他节省了服务器的内存开销,从而提高了服务器的性能。
2.1.3.Hibernate中怎样实现类之间的关系?(如:一对多、多对多的关系)
类与类之间的关系主要体现在表与表之间的关系进行操作,它们都市对对象进行操作,我们程序中把所有的表与类都映射在一起,它们通过配置文件中的many-to-one、one-to-many、many-to-many、
2.1.4. 说下Hibernate的缓存机制?
- 内部缓存存在Hibernate中又叫一级缓存,属于应用事物级缓存
- 二级缓存:
a) 应用及缓存
b) 分布式缓存
条件:数据不会被第三方修改、数据大小在可接受范围、数据更新频率低、同一数据被系统频繁使用、非 关键数据
c) 第三方缓存的实现
2.1.5. Hibernate的查询方式Sql、Criteria,object comptosition Hql?
1、 属性查询
2、 参数查询、命名参数查询
3、 关联查询
4、 分页查询
5、 统计函数
2.1.6. 如何优化Hibernate?
1.使用双向一对多关联,不使用单向一对多
2.灵活使用单向一对多关联
3.不用一对一,用多对一取代
4.配置对象缓存,不使用集合缓存
5.一对多集合使用Bag,多对多集合使用Set
- 继承类使用显式多态
- 表字段要少,表关联不要怕多,有二级缓存撑腰
2.1.7Hibernate有哪几种查询数据的方式?
(1)导航对象图查询
(2)OID查询
(3)HQL
(4)QBC
(5)本地SQL
2.1.8 load()和get()的区别?
load加载方法:
Java代码
- Users user = (Users)session.load(Users.class, userId);
Users user = (Users)session.load(Users.class, userId);
get加载方法:
Java代码
- Users user = (Users)session.get(Users.class, userId);
Users user = (Users)session.get(Users.class, userId);
两加载方法区别:
区别1:如果数据库中,没有userId的对象。如果通过get方法加载,则返回的是一个 null;如果通过load加载,则返回一个代理对象,如果后面代码如果调用user对象的某个属性(比如user.getPassword())会抛出异常:org.hibernate.ObjectNotFoundException;
区别2:load支持延迟加载,get不支持延迟加载。
也就是说:
Java代码
- Users user = (Users)session.load(Users.class, userId);
这句代码不会去执行数据库查询,只有用到user时才会去执行数据库查询。
而:
Java代码
- Users user = (Users)session.get(Users.class, userId);
则立即去执行数据库查询。 所以Users user = (Users)session.load(Users.class, userId);不会执行任何sql。
注意:
Java代码
- Users user = (Users)session.load(Users.class, userId);
- System.out.println(user.getId());
上面这2句代码,不会去执行数据库操作。因为load后会在hibernate的一级缓存里存放一个map对象,该map的key就是userId的值,但 是当你getId()时,它会去一级缓存里拿map的key值,而不去执行数据库查询。所以不会报任何错。不会执行任何数据库操作。
2.1.9 在数据库中条件查询速度很慢的时候,如何优化?
1.建索引
2.减少表之间的关联
3.优化sql,尽量让sql很快定位数据,不要让sql做全表查询,应该走索引,把数据量大的表排在前面
4.简化查询字段,没用的字段不要,已经对返回结果的控制,尽量返回少量数据
2.1.10 在Hibernate中进行多表查询,每个表中各取几个字段,也就是说查询出来的结果集并没有一个实体类与之对应,如何解决这个问题?
解决方案一,按照Object[]数据取出数据,然后自己组bean
解决方案二,对每个表的bean写构造函数,比如表一要查出field1,field2两个字段,那么有一个构造函数就是Bean(type1 filed1,type2 field2) ,然后在hql里面就可以直接生成这个bean了。具体怎么用请看相关文档,我说的不是很清楚。
session.load()和session.get()的区别
2.1.11 Hibernate的主键生成机制?
- assigned 主键由外部程序负责生成,无需Hibernate参与。
- hilo通过hi/lo 算法实现的主键生成机制,需要额外的数据库表保存主键生成历史状态。
- seqhilo 与hilo 类似,通过hi/lo 算法实现的主键生成机制,只是主键历史状态保存在Sequence中,适用于支持Sequence的数据库,如Oracle。
- increment 主键按数值顺序递增。此方式的实现机制为在当前应用实例中维持一个变量,以保存着当前的最大值,之后每次需要生成主键的时候将此值加1作为主键。这种方式可能产生的问题是:如果当前有多个实例访问同一个数据库,那么由于各个实例各自维护主键状态,不同实例可能生成同样的主键,从而造成主键重复异常。因此,如果同一数据库有多个实例访问,此方式必须避免使用。
- identity 采用数据库提供的主键生成机制。如DB2、SQL Server、MySQL中的主键生成机制。
- sequence 采用数据库提供的sequence 机制生成主键。如Oralce 中的Sequence。
- native 由Hibernate根据底层数据库自行判断采用identity、hilo、sequence其中一种作为主键生成方式。
- uuid.hex 由Hibernate基于128位唯一值产生算法生成16进制数值(编码后以长度32 的字符串表示)作为主键。
- uuid.string 与uuid.hex 类似,只是生成的主键未进行编码(长度16)。在某些数据库中可能出现问题(如PostgreSQL)。
- foreign 使用外部表的字段作为主键。
一般而言,利用uuid.hex方式生成主键将提供最好的性能和数据库平台适应性。
这10中生成OID标识符的方法,increment 比较常用,把标识符生成的权力交给Hibernate处理.但是当同时多个Hibernate应用操作同一个数据库,甚至同一张表的时候.就推荐使用 identity 依赖底层数据库实现,但是数据库必须支持自动增长,当然针对不同的数据库选择不同的方法.如果你不能确定你使用的数据库具体支持什么的情况下.可以选择用 native 让Hibernate来帮选择identity,sequence,或hilo.
另外由于常用的数据库,如Oracle、DB2、 SQLServer、MySql 等,都提供了易用的主键生成机制(Auto-Increase 字段或者Sequence)。我们可以在数据库提供的主键生成机制上,采用generator-class=native的主键生成方式。
不过值得注意的是,一些数据库提供的主键生成机制在效率上未必最佳,大量并发insert数据时可能会引起表之间的互锁。数据库提供的主键生成机制,往往是通过在一个内部表中保存当前主键状态(如对于自增型主键而言,此内部表中就维护着当前的最大值和递增量),之后每次插入数据会读取这个最大值,然后加上递增量作为新记录的主键,之后再把这个新的最大值更新回内部表中,这样,一次Insert操作可能导致数据库内部多次表读写操作,同时伴随的还有数据的加锁解锁操作,这对性能产生了较大影响。因此,对于并发Insert要求较高的系统,推荐采用uuid.hex 作为主键生成机制。
中级问题--------------------------------------------
2.2.1 hibernate都支持哪些缓存策略?
* Read-only: 这种策略适用于那些频繁读取却不会更新的数据,这是目前为止最简单和最有效的缓存策略,字典表
* Read/write:这种策略适用于需要被更新的数据,比read-only更耗费资源,在非JTA环境下,每个事务需要在session.close和session.disconnect()被调用
* Nonstrict read/write: 这种策略不保障两个同时进行的事务会修改同一块数据,这种策略适用于那些经常读取但是极少更新的数据
* Transactional: 这种策略是完全事务化得缓存策略,可以用在JTA环境下
2.2.2 jdbc、hibernate、ibatis的区别?
jdbc:手动
手动写sql
delete、insert、update要将对象的值一个一个取出传到sql中,不能直接传入一个对象。
select:返回的是一个resultSet,要从ResultSet中一行一行、一个字段一个字段的取出,然后封装到一个对象中,不直接返回一个对象。
ibatis的特点:半自动化
sql要手动写
delete、insert、update:直接传入一个对象
select:直接返回一个对象
hibernate:全自动
不写sql,自动封装
delete、insert、update:直接传入一个对象
select:直接返回一个对象
2.2.3 三种检索策略是什么,分别适用于哪种场合?
答:立即检索——
优点:对应用程序完全透明,缺点:select语句数目多。适用:类级别。
延迟检索——
优点: 由应用程序决定加载哪些对象,可以避免执行多余的select语句以及避免加载不需要访问的对象,节省内存空间,提高检索效率。
缺点: 应用程序如果要访问游离态的代理类实例,必须保证它在持久化时已经被初始化。
适用: 一对多或多对多关联。应用程序不需要立即访问或者根本不会访问的对象。
迫切左外连接检索:
优点:对应用程序完全透明,不管对象处于持久化状态还是游离状态,应用程序都可以方便的从一个对象导航到另一个与它相关联的对象。使用了外连接,select语句数目少。
缺点:可能会加载程序不需要访问的对象。复杂的数据库表连接影响检索性能。
适用:一对一或多对一关联。应用程序需要立即访问的对象。数据库系统具有良好的表连接性能。
2.2.4 ORM解决的不匹配问题(域模型与关系模型之间存在的不匹配)?
答: 域模型是面向对象的,关系模型是面向关系的。
域模型中有继承关系,关系模型中不能直接表示继承关系。
域模型中有多对多关联关系,关系模型中通过连接表来表示多对多关联关系。
域模型中有双向关联关系,关系模型中只有单向参照关系,而且总是many参照one方。
域模型提倡精粒度模型,关系模型提倡粗粒度模型。
2.2.5 映射继承关系的三种方式?
答:(1)继承关系树的每个具体类对应一张表:在具体类对应的表中,不仅包含和具体类属性对应的字段,还包括与具体类的父类属性对应的字段。
(2)继承关系树的根类对应一张表:在根类对应的表中,不仅包括根类属性对应的字段,
还包括根类的所有子类属性对应的字段。
(3)继承关系树中的每个类对应一张表,每个表中只包括和这个类本身属性对应的字段,子类的表参照父类对应的表。
2.2.6 请简述Session的特点有哪些?
答案:
(1)不是线程安全的,因此在设计软件架构时,应该避免多个线程共享同一个Session实例。
(2)Session实例是轻量级的,所谓轻量级是指它的创建和销毁不需要消耗太多的资源。这意味着在程序中可以经常创建或销毁Session对象,例如为每个客户请求分配单独的Session实例,或者为每个工作单元分配单独的Session实例。
(3)在Session中,每个数据库操作都是在一个事务(transaction)中进行的,这样就可以隔离开不同的操作(甚至包括只读操作)。
2.2.7 Hibernate中数据表映射关系主要有什么类型?
one-to-many
inverse:主控方,外键的关系有谁控制
inverse=false 是主控方,外键是由它控制的
inverse=true 是被控方,外键与它没关系
要想实现主控方的控制必须将被控方作为主控方的属性
cascade:级联
主表增从表增
主表修从表修
主表删从表删
lazy:延迟
lazy=false:一下将所有的内容取出,不延时(常用)
lazy=true:取出部分内容,其余内容动态去取
通过get可以取出对方的所有内容
2.2.8 在Hibernate应用中Java对象的状态有哪些?
1临时状态(transient):刚刚用new语句创建,还没有被持久化,不处于Session的缓存中。处于临时状态的Java对象被称为临时对象。
2持久化状态(persistent):已经被持久化,加入到Session的缓存中。处于持久化状态的Java对象被称为持久化对象。
3游离状态(detached):已经被持久化,但不再处于Session的缓存中。处于游离状态的Java对象被称为游离对象。
2.2.9 session的清理和清空有什么区别?
session清理缓存是指按照缓存中对象的状态的变化来同步更新数据库;清空是session关闭;
高级问题--------------------------------------------
2.3.1 为什么用IBATIS不用Hibernate??
我已经用了hibernate好多年了,现在也要转型,因为hibernate多变查询的表现实在太差还有一查就是一个表所有字段要么就是自己写构造函数查询时候new 我感觉太失去灵活性了,无法接受,虽然我们现在还是用hibernate但是我决定转型了
- iBatis 易于掌握。拿来文档看半天到两天就可以掌握了。
Hibernate 可能需要 3 倍以上的时间来掌握。
- iBatis 更容易进行 sql 的优化。
这个应该大家都有共识了。另外 Hibernate 生成的 sql 也实在是太难看了。鉴
于有的朋友提到了 sql 不太重要。我想在这里强调一下我的经验,一般系统性能
的瓶颈都在数据库上。所以这一点是 iBatis 非常重要的一个优势。
- iBatis 可以进行细粒度的优化
3.1 比如说我有一个表,这个表有几个或者几十个字段,我需要更新其中
的一个字段,iBatis 很简单,执行一个sql
UPDATE TABLE_A SET column_1=#column_1# WHERE id=#id#
但是用 Hibernate 的话就比较麻烦了,缺省的情况下 hibernate 会更新所有字段。
当然我记得 hibernate 有一个选项可以控制只保存修改过的字段,但是我不太确
定这个功能的负面效果。
3.2 我需要列出一个表的部分内容,用 iBatis 的时候,这里面的好处是可以少从数据
库读很多数据,节省流量
SELECT ID, NAME FROM TABLE_WITH_A_LOT_OF_COLUMN WHERE ...
3.2.1 一般情况下
Hibernate 会把所有的字段都选出来。比如说有一个上面表有8个字段,
其中有一两个比较大的字段,varchar(255)/text。上面的场景中我为什么要把他
们也选出来呢?
3.2.2 用 hibernate 的话,你又不能把这两个不需要的字段设置为 lazy load,因
为还有很多地方需要一次把整个 domain object 加载出来。这个时候就能显现出
ibatis 的好处了
3.2.3 Hibernate 还有一个方案,就是生成 javabean/map/object[](感谢
leelun/cjmm),但是这样的话就可能会产生大量的多余 class。map/object[] 的方式
应该不错,我比较喜欢这种方式。
3.3 如果我需要更新一条记录(一个对象),如果使用 hibernate,需要现把对
象 select 出来,然后再做 update。这对数据库来说就是两条 sql。而 iBatis
只需要一条 update 的 sql 就可以了。减少一次与数据库的交互,对于性能的
提升是非常重要。
- 开发方面
4.1 开发效率上,我觉得两者应该差不多
4.2 可维护性方面,我觉得 iBatis 更好一些。因为 iBatis 的 sql 都保存到
单独的文件中。而 Hibernate 在有些情况下可能会在 java 代码中保存
sql/hql。
- 运行效率
5.1 在不考虑 cache 的情况下,iBatis 应该会比hibernate 快一些或者很多
(根据实际情况会有所不同)。
当然 iBatis 也有比较大的缺点
- 不同数据库类型的支持不好,如果你要开发的系统是要在对中数据间移植,那可能用 hibernate 比较好。
- 缺省的 cache 支持不好,但是 hibernate 的 cache 支持其实也不是很好,而且很复杂。尤其是对于大并发量的应用。所以我更倾向于自己管理 cache。
2.3.2 为什么使用ibatis而不用spring jdbcTemplate?
第一:ibatis仅仅是对jdbc薄薄的一层封装,完全不丧失sql的灵活性
第二:ibatis所有的sql都可以放在配置文件中,这样有利于sql的集中管理,特别是在sql tuning是很容易把得到所有的sql,如果使用spring jdbctemplate,那么难免要在sql adv上调试好了sql,然后在粘贴到java代码中,会有一大堆的StringObj+=和 StringBufferObj.append() ,如果sql 很长,那么总是copy , paste 也很烦,ibatis没有这样的问题。
第三:ibatis可以把查出的结果集自动mapping成po,不用写一行代码,只需配置一下ResultMap参数即可,而jdbcTemplate大多数情况都要手动的mapping或者实现MappingSqlQuery,ResultSetExtractor等,无论如何都要编程,这些都是体力活,如果使用了ibatis,这些体力活完全可以省去。
第四:ibatis内置cache机制,同时还可以和osCache集成,cache的也是可以配置的,如果配置得当可以大大提高程序性能。
第五:ibatis支持动态sql,不需要在java里有那么多if, else,完全配置
一般ibatis分页不用自身的分页功能,需要自己利用数据库的特性去写,比如:mysql的limit,oracle的rumnum,mssql的top,db2的rownumber等.
2.3.3 Ibatis中使用like ‘%#filedName#%’ 时,有什么问题?
在xml映射文件中,如果直接按如上写法,会报异常:java.sql.SQLException: Invalid argument in JDBC call: parameter index out of range: 1。
所以一般会采用如下两种方式:
- 将#换成$,如like ‘%$ filedName $%’,这样就没有问题了..
- 采用字符串联接符||,如:like ‘%’||# filedName #||’%’
2) Ibatis中#与$的区别?
1 #是把传入的数据当作字符串,如#field#传入的是id,则生成sql语句:order by "id";
2 $传入的数据直接生成在sql里,如#field#传入的是id,则sql语句生成是这样,order by id ;
3 #方式能够很大程度防止sql注入, 但$方式无法防止sql注入;
4 $方式一般用于传入数据库对象.例如传入表名;
5 一般能用#的就别用$ ;
2.3.4 Java主流数据库连接池有哪些?
C3P0、DBCP(Database Connection Pool)、Proxool等
池(Pool)技术在一定程度上可以明显优化服务器应用程序的性能,提高程序执行效率和降低系统资源开销。这里所说的池是一种广义上的池,比如数据库连接池、线程池、内存池、对象池等。其中,对象池可以看成保存对象的容器,在进程初始化时创建一定数量的对象。需要时直接从池中取出一个空闲对象,用完后并不直接释放掉对象,而是再放到对象池中以方便下一次对象请求可以直接复用。其他几种池的设计思想也是如此,池技术的优势是,可以消除对象创建所带来的延迟,从而提高系统的性能。
要了解Java连接池我们先要了解数据库连接池(connection pool)的原理,Java连接池正是数据库连接池在Java上的应用。——我们知道,对于共享资源,有一个很著名的设计模式:资源池(Resource Pool)。
该模式正是为了解决资源的频繁分配﹑释放所造成的问题。为解决上述问题,可以采用数据库连接池技术。数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。我们可以通过设定连接池最大连接数来防止系统无尽的与数据库连接。更为重要的是我们可以通过连接池的管理机制监视数据库的连接的数量﹑使用情况,为系统开发﹑测试及性能调整提供依据。
(1)C3P0是一个开放源代码的JDBC连接池,它在lib目录中与Hibernate一起发布,包括了实现jdbc3和jdbc2扩展规范说明的Connection 和Statement 池的DataSources 对象。(主页:http://sourceforge.net/projects/c3p0/)
(2)DBCP(Database Connection Pool)是一个依赖Jakarta commons-pool对象池机制的数据库连接池,Tomcat的数据源使用的就是DBCP。目前 DBCP 有两个版本分别是 1.3 和 1.4。1.3 版本对应的是 JDK 1.4-1.5 和 JDBC 3,而1.4 版本对应 JDK 1.6 和 JDBC 4。因此在选择版本的时候要看看你用的是什么 JDK 版本了,功能上倒是没有什么区别。(主页:http://commons.apache.org/dbcp/)
(2)Proxool是一个Java SQL Driver驱动程序,提供了对你选择的其它类型的驱动程序的连接池封装。可以非常简单的移植到现存的代码中。完全可配置。快速,成熟,健壮。可以透明地为你现存的JDBC驱动程序增加连接池功能。
数据库连接是一种关键的有限的昂贵的资源,这一点在多用户的网页应用程序中体现得尤为突出。对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标。数据库连接池正是针对这个问题提出来的。数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而再不是重新建立一个;释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。这项技术能明显提高对数据库操作的性能。
2.3.5 JDBC连接数据库6步?
- Load the JDBC Driver
- Establish the Database Connection
- Create a Statement Object
- Execute a Query
- Process the Results
- Close the Connection
2.3.6 如何在生产环境下跟踪数据库服务器执行的sql语句?
Oracle: 内置软件包DBMS_MONITOR/DBMS_SUPPORT软件包 查询 v$sqltext 和 v$session v$sql视图 /sql_trace/
toad(10.0)--query viewer
(menu) Utilities-->query viewer
toad(10.0)--sql monitor
LOGMINER /Quest SQLMonitor 2.4.3.6
Mysql: processList/show profiles;/show profile block io,cpu for query 2;
修改my.cnf,在mysqld下添加log一行,
[mysqld]
log = /tmp/mysqld.sql
然后,重新启动mysql,tail -f /tmp/mysqld.sql,就可以实时看到myql服务器当前正在执行的语句了。
---------------------------------------------------------
3Struts10-20问题
3.1 Struts初级问题
3.1.1 struts工作原理?
MVC即Model-View-Controller的缩写,是一种常用的设计模式。MVC 减弱了业务逻辑接口和数据接口之间的耦合,以及让视图层更富于变化。
Struts 是MVC的一种实现,它将 Servlet和 JSP 标记(属于 J2EE 规范)用作实现的一部分。Struts继承了MVC的各项特性,并根据J2EE的特点,做了相应的变化与扩展。
Struts有一组相互协作的类(组件)、Serlvet以及jsp tag lib组成。基于struts构架的web应用程序基本上符合JSP Model2的设计标准,可以说是MVC设计模式的一种变化类型。根据上面对framework的描述,我们很容易理解为什么说Struts是一个web framwork,而不仅仅是一些标记库的组合。但 Struts 也包含了丰富的标记库和独立于该框架工作的实用程序类。Struts有其自己的控制器(Controller),同时整合了其他的一些技术去实现模型层(Model)和视图层(View)。在模型层,Struts可以很容易的与数据访问技术相结合,包括EJB,JDBC和Object Relation Bridge。在视图层,Struts能够与JSP, Velocity Templates,XSL等等这些表示层组件想结合。
Struts的工作原理:
控制:通过图2大家可以看到有一个XML文件Struts-config.xml,与之相关联的是Controller,在Struts中,承担MVC中Controller角色的是一个Servlet,叫ActionServlet。ActionServlet是一个通用的控制组件。这个控制组件提供了处理所有发送到Struts的HTTP请求的入口点。它截取和分发这些请求到相应的动作类(这些动作类都是Action类的子类)。另外控制组件也负责用相应的请求参数填充 Action From(通常称之为FromBean),并传给动作类(通常称之为ActionBean)。动作类实现核心商业逻辑,它可以访问java bean 或调用EJB。最后动作类把控制权传给后续的JSP 文件,后者生成视图。所有这些控制逻辑利用Struts-config.xml文件来配置。
视图:主要由JSP生成页面完成视图,Struts提供丰富的JSP 标签库: Html,Bean,Logic,tiles等,这有利于分开表现逻辑和程序逻辑。
模型:模型以一个或多个java bean的形式存在。这些bean分为三类:Action Form、Action、JavaBean or EJB。Action Form通常称之为FormBean,封装了来自于Client的用户请求信息,如表单信息。Action通常称之为ActionBean,获取从ActionSevlet传来的FormBean,取出FormBean中的相关信息,并做出相关的处理,一般是调用Java Bean或EJB等。
流程:在Struts中,用户的请求一般以*.do作为请求服务名,所有的*.do请求均被指向ActionSevlet,ActionSevlet根据Struts-config.xml中的配置信息,将用户请求封装成一个指定名称的FormBean,并将此FormBean传至指定名称的ActionBean,由ActionBean完成相应的业务操作,如文件操作,数据库操作等。每一个*.do均有对应的FormBean名称和ActionBean名称,这些在Struts-config.xml中配置。
核心:Struts的核心是ActionSevlet,ActionSevlet的核心是Struts-config.xml。
3.1.2 简述Struts框架的初始化流程。
答案:
对于采用Struts框架的Web应用,在Web应用启动时就会加载并初始化控制器ActionServlet
ActionServlet从struts-config.xml文件中读取配置信息,把它们存放到ActionMappings对象中。
在Struts framework中, Controller主要是ActionServlet,但是对于业务逻辑的操作则主要由Action、ActionMapping、 ActionForward这几个组件协调完成(也许这几个组件,应该划分到模型中的业务逻辑一块)。
其中,Action扮演了真正的控制逻辑的实现者,而ActionMapping和ActionForward则指定了不同业务逻辑或流程的运行方向。
3.1.3 简述Struts框架响应客户请求的工作流程
答案:
- 检索和用户请求匹配的ActionMapping实例,如果不存在,就返回用户请求路径无效的信息。
- 如果ActionForm实例不存在,就创建一个ActionForm对象,把客户提交的表单数据保存到ActionForm对象中。
- 根据配置信息决定是否需要表单验证。如果需要验证,就调用ActionForm的validate()方法。
- 如果ActionForm的validate()方法返回null或返回一个不包含ActionMessge的ActionErrors对象,就表示表单验证成功。
- ActionServlet根据AtionMapping实例包含的映射信息决定将请求转发给哪个Action。如果应的Action实例不存在,就先创建这个实例,然后调用Action的execute()方法。
- Action的execute()方法返回一个ActionForward对象,ActionServlet再把客户请求转发给ActionForward对象指向的JSP组件。
- ActionForward对象指向的JSP组件生成动态页面,返回给客户。
对于以上流程的步骤(4),如果ActionForm的validate()方法返回一个包含一个或多个ActionError的 ActionErrors对象,就表示表单验证失败,此时ActionServlet将直接把请求转发给包含客户提交表单的JSP组件。在这种情况下,不会再创建Action对象并调用Action的execute方法。
3.2 Struts中级问题
3.3 Struts高级问题:
4 消息机制:--------------------------------------------------------------
4.1.1 什么是异步消息系统?为什么要使用异步消息?如何使用异步消息?
发送消息者可以在发送消息后进行其它的工作,不用等待接收者的回应,而接收者也不必在接到消息后立即对发送者的请求进行处理。
当使用异步消息传送时, 调用者在发送消息以后可以不用等待响应, 可以接着处理其他任务。对于异步通信, 一个应用程序(请求者或发送者)将请求发送给另一个应用程序, 然后可以继续向下执行它自身的其他任务。发送程序无须等待接收程序的执行和返回结果, 而是可以继续处理其他请求。与同步方式不同, 异步方式中两个应用系统(发送程序和接收程序)无须同时都在运行, 也无须同时都在处理通信任务。
常使用排队机制来实现异步消息传送。有两种不同类型的排队方式: 存储/转发、 发布/订阅
MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法。应用程序通过写和检索出入列队的针对应用程序的数据(消息)来通信,而无需专用连接来链接它们。消 息传递指的是程序之间通过在消息中发送数据进行通信,而不是通过直接调用彼此来通信,直接调用通常是用于诸如远程过程调用的技术。排队指的是应用程序通过 队列来通信。队列的使用除去了接收和发送应用程序同时执行的要求。
4.1.2 消息机制主要协议有哪些? 这些协议有哪些对应实现?
(1)AMQP,即Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。
AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。
(2)JMS(Java Messaging Service)是Java平台上有关面向消息中间件(MOM)的技术规范,它便于消息系统中的Java应用程序进行消息交换,并且通过提供标准的产生、发送、接收消息的接口简化企业应用的开发,翻译为Java消息服务。
MQ的消费-生产者模型的一个典型的代表,一端往消息队列中不断的写入消息,而另一端则可以读取或者订阅队列中的消息。MQ和JMS类似,但不同的是JMS是SUN JAVA消息中间件服务的一个标准和API定义,而MQ则是遵循了AMQP协议的具体实现和产品。
对应实现:
RabbitMQ一个独立的开源实现,服务器端用Erlang语言编写,支持多种客户端,如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等,支持AJAX。RabbitMQ发布在Ubuntu、FreeBSD平台。
Apache ActiveMQ 支持JMS和AMQP协议,对Spring支持
jboss Messaging 2.0(HornetQ)
Apache Qpid、
Red Hat Enterprise MRG与StormMQ(托管)
4.1.3 RabbitMQ介绍?
一个独立的开源实现,服务器端用Erlang语言编写,支持多种客户端,如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等,支持AJAX。RabbitMQ发布在Ubuntu、FreeBSD平台。支持AQMP和JMS协议
最近被Spring收购,Spring AMQP 1.0 GA发布了
RabbitMQ的几个概念:
Channel:进行消息读写的通道;
Exchange:交换机,决定了消息路由规则;
Queue:消息队列;
Bind:绑定了Queue和Exchange,意即为符合什么样路由规则的消息,将会放置入哪一个消息队列;
编写RabbitMQ生产者客户端
public class MQTestor {
public static void main(String[] args) throws Exception
{
ConnectionParameters params = new ConnectionParameters();
params.setUsername("guest");
params.setPassword("guest");
params.setVirtualHost("/");
params.setRequestedHeartbeat(0);
ConnectionFactory factory = new ConnectionFactory(params);
Connection conn = factory.newConnection("192.168.1.101", 5672);
Channel channel = conn.createChannel();
channel.exchangeDeclare("ex1", "direct", true);
channel.queueDeclare("q1",true);
channel.queueBind("q1", "ex1", "m1");
byte[] msg = "hello world".getBytes();
channel.basicPublish("ex1", "m1", MessageProperties.PERSISTENT_TEXT_PLAIN, msg);
channel.close();
conn.close();
}
}
编写消费者客户端:
ConnectionParameters params = newConnectionParameters();
params.setUsername("guest");
params.setPassword("guest");
params.setVirtualHost("/");
params.setRequestedHeartbeat(0);
ConnectionFactory factory = newConnectionFactory(params);
Connection conn = factory.newConnection("192.168.1.101", 5672);
Channel channel = conn.createChannel();
GetResponse res=channel.basicGet("q1", false);
if(res!=null){
System.out.println(new String(res.getBody()));
channel.basicAck(res.getEnvelope().getDeliveryTag(), false);
}else{
System.out.println("No message!");
}
RabbitMQ消息持久化:
- 将交换机置为可持久;
2) 将通道置为可持久
3) 消息发送时设置可持久。
当我们“生产”了一条可持久化的消息,尝试中断MQ服务,启动消费者获取消息,消息依然能够恢复。相反,则抛出异常。
4.1.4 Spring AMQP是什么?介绍一下?
Spring公司收购了RabbitMQ知名消息中间件厂商,之后将RabbitMQ客户端集成到Spring中形成的一个消息队列子模块
如何使用参考:http://www.rabbitmq.com/devtools.html#java-dev
Spring AMQP:http://www.springsource.org/spring-amqp
生产者 ->代理者 ->消费者
4.1.5 SMTP、POP3、IMAP4 都是什么协议?
SMTP:简单邮件传输协议
(SMTP:Simple Mail Transfer Protocol)
SMTP 是一种提供可靠且有效电子邮件传输的协议。 SMTP 是建模在 FTP 文件传输服务上的一种邮件服务,主要用于传输系统之间的邮件信息并提供来信有关的通知。
SMTP 独立于特定的传输子系统,且只需要可靠有序的数据流信道支持。 SMTP 重要特性之一是其能跨越网络传输邮件,即“ SMTP 邮件中继”。通常,一个网络可以由公用互联网上 TCP 可相互访问的主机、防火墙分隔的 TCP/IP 网络上 TCP 可相互访问的主机,及其它 LAN/WAN 中的主机利用非 TCP 传输层协议组成。使用 SMTP ,可实现相同网络上处理机之间的邮件传输,也可通过中继器或网关实现某处理机与其它网络之间的邮件传输。
在这种方式下,邮件的发送可能经过从发送端到接收端路径上的大量中间中继器或网关主机。域名服务系统(DNS)的邮件交换服务器可以用来识别出传输邮件的下一跳 IP 地址。
在传输文件过程中使用25号端口
POP3(Post Office Protocol 3) POP适用于C/S结构的脱机模型的电子邮件协议,
目前已发展到第三版,称POP3。,它规定怎样将个人计算机连接到Internet的邮件
服务器和下载电子邮件的电子协议。它是因特网电子邮件的第一个离线协议标准,
POP3允许用户从服务器上把邮件存储到本地主机(即自己的计算机)上,同时删除
保存在邮件服务器上的邮件,而POP3服务器则是遵循POP3协议的接收邮件服务器,
用来接收电子邮件的。
POP适用于C/S结构的脱机模型。脱机模型即不能在线操作,不像IMAP4(netscape
支持IMAP4)当客户机与服务器连接并查询新电子邮件时,被该客户机指定的所有
将被下载的邮件都将被程序下载到客户机,下载后,电子邮件客户机就可以删除或
修改任意邮件,而无需与电子邮件服务器进一步交互。POP3客户向POP3服务器发送
命令并等待响应,POP3命令采用命令行形式,用ASCII码表示。
服务器响应是由一个单独的命令行组成,或多个命令行组成,响应第一行以ASCII
文本+OK或-ERR指出相应的操作状态是成功还是失败在POP3协议中有三种状态,认
可状态,处理状态,和更新状态。
当客户机与服务器建立联系时,一旦客户机提供了自己身份并成功确认,即由认可
状态转入处理状态,
在完成相应的操作后客户机发出quit命令,则进入更新状态,更新之后最后重返认
可状态。
IMAP4(Internet Message Access Protocol 4) 即 Internet信息访问协议的第4版本,是用于从远程服务器上访问电子邮件的标准协议,它是一个客户机/服务器(Client/Server)模型协议,用户的电子邮件由服务器负责接收保存,用户可以通过浏览信件头来决定是不是要下载此信。用户也可以在服务器上创建或更改文件夹或邮箱,删除信件或检索信件的特定部分。
虽然POP和IMAP都是处理接收邮件的,但两者在机制上却有所不同。在用户访问电子邮件时,IMAP4需要持续访问服务器。POP3则是将信件保存在服务器上,当用户阅读信件时,所有内容都会被立刻下载到用户的计算机上。因此,可以把使用IMAP4协议的服务器看成是一个远程文件服务器,而把使用POP协议的服务器看成是一个存储转发服务器。就目前的应用来看,POP3的应用远比IMAP4广泛得多
---------------------------------------------------------
常用参考:JAVA 培训题库-Spring http://blog.csdn.net/wxh2008hyl/article/details/5214577
JAVA培训题库-Struts http://blog.csdn.net/wxh2008hyl/article/details/5214550
JAVA培训题库-Servlet http://blog.csdn.net/wxh2008hyl/article/details/5214505
JAVA 培训题库-JSP http://blog.csdn.net/wxh2008hyl/article/details/5214650
JAVA培训题库-AJAX http://blog.csdn.net/wxh2008hyl/article/details/5214462
JAVA培训题库-JavaScript http://blog.csdn.net/wxh2008hyl/article/details/5214485
JAVA 培训题库-OOAD和UML http://blog.csdn.net/wxh2008hyl/article/details/5214711
本文内容总结:3.3程序设计框架架构基础相关知识点-技术
原文链接:https://www.cnblogs.com/ajian005/archive/2012/02/19/2753752.html
以上是 3.3程序设计框架架构基础相关知识点-技术 的全部内容, 来源链接: utcz.com/z/295918.html