说起EJB,不得不提JEE,java EE 英文全称为:java Enterprise Edition企业级应用的软件架构,是一种思想,也是一种规范,方便从事这方面的开发者以及开发厂商进行规范性的开发和设计、
既然JEE在Java领域具有举足轻重的味道,那么肯定有塔的独到之处,那么他的独到之处就在于他能帮助我们以什么样独特的视角去解决问题,一个好的架构,高并发,多处理,分布式这些字眼是不能缺少的。而JEE解决的问题,就是分布式应用。
说到分布式应用,应该知道的一项技术就是RPC,英文全称为:Remote Procedure Call(远程过程调用协议),好处在于:他通过网络从远程计算机上上面请求服务,而不需要了解底层的网络技术,是不是有点像Java当中封装的概念,使之面向使用者更加好用
用到分布式,我们就需要调用远程的一些方法和服务,这个时候需要用到RPC,他可以帮助我们把调用远程方法和远程对象的细节隐藏起来,就像我们调用本地方法一样
说到RPC,调用远程方法和远程对象,需要在客户端,服务器端进行交互操作,那么着就需要说到RMI
RMI 是一种传输方式,简化了在多台计算机上的Java应用之间的通信,隐藏了底层的一些详细细节,通信传输方式有很多种,当然不止是他这一种。
RMI在传输通信的过程中针对Java面向对象的这个特点,在设计,安全,可便携,使用上进行了模仿,
面向对象:RMI可以将完整的对象作为参数和返回值进行传递,而不仅仅是单纯的数据
设计:RMI可以传递完整的对象,RMI中的对象传递功能可以使你在分布式计算当中充分的利用面向对象技术的强大性来进行编程。
可移动属性:RMI可以讲客户机移动到服务器,也可以由服务器移动到客户机
安全性:RMI使用Java内置的安全机制来保证下载执行程序用户系统的安全性,RMI专门保护系统免遭恶意小程序的侵害,而专门设计的安全管理程序。(怎么安全宝物不清楚)
便于编写和使用:RMI使得Java远程服务程序和访问这些服务程序的Java客户程序的编写工作变得轻松、简单。远程接口实际上就是Java接口。为了实现RMI的功能必须创建远程对象任何可以被远程调用的对象必须实现远程接口。但远程
接口本身并不包含任何方法。因而需要创建一个新的接口来扩展远程接口。
新接口将包含所有可以远程调用的方法。远程对象必须实现这个新接口,由于新的接口扩展了
远程接口,实现了新接口,就满足了远程对象对实现远程接口的要求,所实现的每个对象都将
作为远程对象引用。
RMI的劣势在于,只针对Java这门语言,RMI对服务器端口和IP依赖的很紧密,对于不同的语言可以用公用对象请求代理的方式来解决
RMI和Socket的比较:
第一、
RMI是面向对象的,而后者不是。
第二、
RMI是与语言相绑定的。比如当你使用Java RMI技术的时候,客户端与服务器端都必须使用Java开发。而socket的网络编程是使用独立于开发语言的,甚至独立于平台。基于socket的网络编程,客户端与服务器端可以使用不同开发语言和不同的平台。
第三、
从网络协议栈的观点来看,RMI与socket的网络编程处于不同层次上。基于socket的网络编程位于TCP协议之上,而RMI在TCP协议之上,又定义了自己的应用协议,其传输层采用的是Java远程方法协议(JRMP)。可见,在网络协议栈上,基于RMI的应用位置更高一些,这也决定了,与socket的网络编程相比,RMI会丧失一些灵活性和可控性,但是好处是它带给了应用开发者更多的简洁,方便和易用。比如:如果你用的是RMI,你不需要关心消息是怎么序列化的,你只需要像本地方法调用一样,使用RMI。代价是:应用开发者无法很好地控制消息的序列化机制。
第四、
这是最后一点不同,我认为也是比较重要的一点,就是两种方法的性能比较,其往往决定着你将使用那种技术来开发你的应用。
实验的结果是:RMI与TCP based socket相比,传输相同的有效数据,RMI需要占用更多的网络带宽(protocol overhead)。从这里,我们可以得出一个一般性的结论:RMI主要是用于远程方法的”调用“(RMI是多么的名符其实:)),其技术内涵强调的是 “调用”,基于此,我能想到的是:移动计算,和远程控制,当你的应用不需要在client与server之间传输大量的数据时,RMI是较好的选择,它简洁、易于开发。但是,一旦你的应用需要在client与server之间传输大量的数据,极端的,比如FTP应用,则RMI是不适合的,我们应该使用 socket。
PS: RMI的效率还是很高的,一般情况下会比Hessian更高效,比Web Service更是高效很多;当然和socket这种东东相比,当然要低效一点了,socket更底层一些啊。RMI的具体实现,依然是依赖于底层的Socket编程。
可以这么说:以RMI的通信,构成了JEE的分布式
JEE的体系结构
这是JEE的架构图,我们来逐层分析:
1:客户端
2:web层
3:业务逻辑层
4:企业信息层
从上图来看,JEE主要描述了服务端的的规范,当然也包括了客户端比如Applet,不过重点不在客户端
企业级应用的分析:
1:分布式应用
对于JEE来讲,一个大型的系统,肯定有很多应用,相当多的模块,而且模块之间是一种松紧耦合的关系,各种功能模块应该分布在不同的应用层当中,需要某些功能的时候,我们可以动态的进行调用
2:系统分层
企业应用中,业务的功能会非常复杂,而且各个模块之间的松紧耦合关系也就更要需要斟酌,并且要把这些模块之间关系制造的非常层次分明,传统的分层模式一般是:接入层,逻辑层,数据层。
3:异步
在上面的介绍当中,或许了解到了,如果要处理一个非常复杂的业务,那么这些数据流向会流向各个模块之间进行数据交互,模块之间的处理需要时间,因为是分布式,所以在时间等待上会存在一个时间段
4:事务,安全
事务就不多说,rollback什么的
在分布式系统中,安全的重要性是非常重要第一层次,首先,对于分布在不同地方的服务器,一起各个模块之间的权限。身份验证等,关系到数据完整数据安全和保密等重要信息的完整性
5:Java EE平台与其他已有资源,服务,系统的整合
分析完企业级应用的泛泛的各个方面,现在开始具体详细的描述一下,JEE各个组件之间的作用
1:Servlet ,JSP
JSP,Servlet 同属于Web层,并且都属于动态网页技术,所谓动态网页技术,也就是说说根据用户请求动态生成页面返回给客户,用户之间的差别,用户的资料,权限,看到的 内容自然也就不相同,而静态页面的意思HTML文件做好,放入到服务器,每个用户访问,都是同一个界面,因为是动态生成,都是由服务器来主动判断生成,页 面中难免会存在一个静态的页面,是不是需要服务器来生成的,一般的做法是采取缓存,这样可以减缓数据库端的压力。
Servlet
Servlet其实就是一个依据Servlet规范写的一个Java类,与传统的Java类不同,这个类是放入到Web服务器那端的,并且由Web服务器加载并调用
JSP
因为需要动态生成页面,服务器那端需要把页面当中需要展示的好一些HTML标签进行输出,加剧服务器的负担,更重要的是对于前台页面的显示,无法协调UI人员和编码人员的交流、
JSP的出现所提出的方法就是,在HTML页面当中嵌入JSP标记和脚本语言,JSP把静态和动态内容的分离,实现了内容和表示的分离
Servlet 与 JSP之间的关系
上图描述得比较清楚了,JSP文件先是转换为Servlet类,然后编译,并启动Servlet实例响应客户端请求。为什么说JSP是建立在Servlet上的动态网页技术,从这里可以看出来
Web层主要就是JSP以及Sevlet这两项技术。
讲了那么多,现在开始步入EJB了
2:EJB
分布式的应用是JEE一个基础的需求,只有分布式才能更好的针对企业做大型开发,而在大型开发中,业务逻辑就会更加复杂,而EJB就是属于逻辑层面的东西
所谓Bean就是组件的意思,EJB可以像搭积木一样,通过本地/分布式的调用组装各种不同的应用到大型应用当中,是开发者能够集中精力来处理企业的业务逻辑,而像事务,网络,安全等这些底层的服务则统统留给EJB开发商来解决
利用组件的开发可以把代码重用上升到一个新的高度,利用面向对象的开发,重用的类,基于组件的开发,重用的则是更大的功能块
EJB 和 Java Bean
Java Bean 是可重复的组件,对Java Bean并没有严格的规范,从理论上讲,任何一个Java 类都可以是一个Bean。但通常的情况下,由于Java Bean是被容器所创建的,所以JavaBean 应具有一个无参的构造器,另外通常的JavaBean还要去实现serializable接口用与实现Bean的持久性,JavaBean不能跨进程访问的。
EJB的全称是(Enterprise Java Bean)相当于DCOM,即分布式组件,它是基于Java的远程方法调用的(RMI)技术的,所以EJB可以被远程访问的(跨进程、跨计算机)。但EJB必须部署在 Webspere、WebLogic这样的容器中,EJB客户不直接访问真的EJB组件,而是通过容器访问的。EJB容器是EJB组件的代理,EJB组件由容器所创建和管理。客户通过访问真正的EJB组件。
3:Container
Container这个概念经常在JEE中出现,所谓的Container容器,在介绍容器的时候有必要先介绍一下组件,组件其实就是一个应用程序块,比如一台电脑,里面有主板,CPU,硬盘,内存,这些就是组件,少一个就不能运行。而容器就是来装在这些组件,这就是所谓的容器,而容器之外的程序需要和这些组件进行交互,那么就必须通过容器,容器有很多种,按照他们装载的组件类型,分为:Ejb容器和Web容器
1:Web容器
Web容器主要是负责管理Servlet 和 JSP的运行
2:Servlet容器
其实,上图中的Servlet指的就是Servlet容器。而Servlet的设计初衷,实际是基于线程池的更好的线程容器,见下图
3:EJB容器
EJB容器主要负责管理“EJB”的运行。
而EJB的设计实际上是基于对象池的思想,你可以认为EJB=对象池+远程对象池。见下图:
【4】Servlet与EJB
其实,根据Servlet和EJB的设计初衷,我们已经可以看出Java EE对两者角色的定义了。线程的本质决定了Servlet只适合一些比较简单的轻量级应用;一旦问题复杂了,最好的就是使用EJB。
(4)RMI
RMI全称:Java Remote Method Invocation,就是利用Java对象序列化的机制,实现远程类对象的实例化以及调用的方法。
RMI在Java EE中的主要是负责解决通信问题,特别是不同的EJB容器之间的通信。大家知道,在分布式应用中,各个功能模块(EJB)之间通信需要有统一的RPC协议,否则没法通信,而RMI就是负责这方面的工作。
【1】RMI 与 CORB
可以说,RMI就是CORBA的Java版实现。
【2】再谈“远程调用”
现在主流的远程调用方式,不管是com/com+,soap,webservice,rmi,.net remoting,说白了都一样的,就是序列化,网络传输,反序列化。
序列化方式:同种runtime的,可以native的二进制序列化,序列化的效率高。文本的序列化(xml/json/自定义格式)的方式,可以跨平台和语言,一般基于中间类型。但此序列化方式的效率低,数据量也偏大。
网络传输:则可以使socket/http或是自定义协议的。 socket数据冗余最小,效率最高。RMI其实是socket上的自定义协议。 http要走http的报文,文本的方式最合适,实现最简单,开发和部署方便。
(5)JMS
JMS:Java Message Service。JMS提供一种消息机制,主要作用是提供异步通信的支持,是Java EE的重要基础模块。值得注意,异步通信,一般都采用消息机制,这种情况在Windows中最常见。
(6)JTA
JTA:Java Transaction API,主要提供事务服务和分布式事务管理功能,保证分布式事务的一致性,是Java EE的重要的基础模块。
(7)JAAS
JAAS:Java Authentication Authorization Service(Java认证于授权服务),提供了对Java组件的安全保护,如哪些Servelt,JSP能被哪些用户访问,哪些EJB能被调用等。但 需要注意的是,JAAS只提供了对JAVAEE组件的保护,对于企业应用业务的权限,它是做不到的。
(8)Connector
Connector主要作用就是把其他已有的资源、服务、系统整合到Java EE系统中。不同的服务提供商和Java EE平台会定义不同的协议,而Connector就是指这些协议的实现。
至此为止,Java EE的核心模块介绍完毕,让我们来看看J2EE 1.3的架构图(当时的J2EE架构还是比较简单的):
4.J2EE 1.4 以及 Java EE 5体系结构
(1)J2EE 1.4 体系结构
J2EE 1.4加入了一个重要的主题:“Web Service”,包括:JAX-RPC,SAAJ,Web Srvcs,JAXR都属于这一块的东西。
(2)Java EE 5体系结构
关于Java EE 5这里就不详细介绍了:>,大家有兴趣可以参考《Java EE Tutorial 5》。
后记
这篇文章写了我3天,同时也翻了N多资料,希望本文确实对各位初学者有所帮助,同时本文包含很多个人观点,如有错误敬请指出:>
关于Java EE 5,如果后续有时间我会继续整理。
重要参考资料
【1】《JAVA EE 5 的发展史》
【2】《Java程序员 上班那点儿事》
【3】《Java EE Tutorial 5》
【4】《J2EE到底是什么?》
在此需要解释一下JNDI的概念:
Java命令与目录接口(Java Naming and Directory Interface)是重要的规范之一,如果没有透彻理解JNDI的作用和意义,那么就没有真正掌握JEE特别是EJB的知识。
JNDI的存在的意义:
之前的项目,当我们需要使用连接到数据库的时候,需要提供URL,UserName,Passwrod 还有具体的JDBC
这样好像没有什么不一样,但是EJB是分布式的,如果说数据库更改,URL更改,UserName和Password更改,连接池需要更改,这些东西,在JNDI里面可以进行完美解决,程序员无需关注与这些内容,把这些东西完全交给JEE的容器来进行管理,程序员只需要对其进行一个引用即可。在容器当中包含了数据库的一些详细的连接信息
这样做的好处可以说只要引用的名称不变,那么程序源代码就不需要修改
更加重要的是:JNDI进行了进一步的扩充,所有在容器之外的资源的引用,都可以通过JNDI的定义和引用,所以在jee的规范当中,JEE的资源并不局限于JDBC数据源,引用的类型很多,其中包括资源引用,环境实体,EJB引用,特别是EJB的引用,它暴露了JNDI在J2EE中的另外一个重要角色:查找其他应用程序组件。
EJB的JNDI的引用非常类似于JDBC资源的引用,在服务趋于转换的环境中,这是一种很有效的方法,可以对应用程序架构当中所得到的所有组件进行这类配置和管理,从EJB组件到JMS队列和主题,再到简单配置字符串或其他对象,这可以降低随着时间推移服务所带来变更的维护成本,同时简化部署,减少集成工作
对JNDI的总结:
J2EE 规范要求所有 J2EE 容器都要提供 JNDI 规范的实现。JNDI 在 J2EE 中的角色就是“交换机” —— J2EE 组件在运行时间接地查找其他组件、资源或服务的通用机制。在多数情况下,提供 JNDI 供应者的容器可以充当有限的数据存储,这样管理员就可以设置应用程序的执行属性,并让其他应用程序引用这些属性(Java 管理扩展(Java Management Extensions,JMX)也可以用作这个目的)。JNDI 在 J2EE 应用程序中的主要角色就是提供间接层,这样组件就可以发现所需要的资源,而不用了解这些间接性。
在 J2EE 中,JNDI 是把 J2EE 应用程序合在一起的粘合剂,JNDI 提供的间接寻址允许跨企业交付可伸缩的、功能强大且很灵活的应用程序。这是 J2EE 的承诺,而且经过一些计划和预先考虑,这个承诺是完全可以实现的。