EJB 3.0
Sun App/JBoss/Weblogic
Day1
1. What is EJB
EJB(Enterprise JavaBean)是JavaEE应用的业务层技术标准, 以这项技术开发的组件叫做EJB组件,常常简称EJB
EJB架构是一个用于开发和部署基于组件的分布式业务应用的组件架构。
采用EJB架构编写的应用是可伸缩的、事务性的、多用户安全的。
可以一次编写这些应用,然后部署到任何支持EJB规范的应用服务器平台上。
特点(和JavaBean比较):
1)提供远程访问的能力
2)可扩展、可插拔的能力
3)必须在EJB服务器上运行, 可享受服务器提供的事务、安全等服务
(Jboss, Weblogic, Websphere, Sun Application server)
名词解析:
1.分布式计算:
1)把大任务分成小块,分发给大家分别地做,再把每个人的计算结果汇总。
特点:分解工作,减轻成员的负担,成员之间做到职责分明。
2)充分利用网络上空闲的计算机的计算能力。
分布式组件:
1)分布对象技术是伴随网络而发展起来的一种面向对象的技术。
以前的计算机系统多是单机系统,多个用户是通过联机终端来访问的,没有网络的概念。
网络出现后,产生了C/S、B/S的计算服务模式。
2)分布式对象技术主要使用了面向对象技术的封装性,组件可以分布在网络的任何位置。
对外界来说,它所需关心的只是组件的界面(接口),至于内部是如何实现的则无需考虑,
远程客户通过方法调用来访问它。这是分布式对象技术和传统的面向对象技术的最大不同点。
2.组件:可独立发布的二进制单元
3.框架,即framework。其实就是某种应用的半成品,就是一组组件,供你选用完成你自己的系统;
代表:Struts,Spring,Hibernate…
4.中间件,是一种独立的系统软件或服务程序,分布式应用软件借助这种软件在不同的技术之间共享资源;
代表:Weblogic,WebSphere,Sun App Server…
5.容器:
EJB的家。 离开容器,EJB就失去了它的生命和意义
EJB分布式对象的基础
JRMI(Java Remote Method Invocation) (远程方法调用)
--- 使用远程消息交换协议JRMP(Java Remote Messaging Protocol) 进行通讯
CORBA对象调用
--- 使用IIOP(Internet Inter-ORB Protocal)
2. Why EJB
简化大型分布式系统的开发过程。
1)利用网络中多台计算机的计算能力,构建瘦客户端(简化分布式访问)
2)使用EJB服务器提供的系统级的企业服务(事务、安全、对象池....),开发人员需要写业务组件
3)EJB组件具有热部署的能力(可插拔)
4)可以扩展现有系统的JavaBean
优点:可维护性、重用性、可扩展性、可插拔性
1)缩短开发时间: 编程人员可将先行开发的部件装配到新的程序中,从而加速了新程序的开发
2)降低集成费用: 在将组件集成为一个完整的方案时,不同开发商采用了一致的标准接口,减少了特殊的定制工作
3)开发更具灵性: 只需简单调整全部应用的一些组件,即可为企业不同领域的应用提供特定的解决方案
4)降低维护费用: 各组件的软件功能是相对独立的,在维护和升级一个组件时,不必变动整个应用。维护简便
3. When to use EJB
少量的需要分布式技术支持的大型项目,比如:
1)应付巨大的客户访问量 2)和已有的系统做集成
EJB可以做什么?
1)服务器端的业务层框架 2)遵循EJB规范的标准组件 3)分布式组件
4)持久化数据支持 5)事务性支持 6)支持并发多用户安全
技术选择:
表现层技术:Servlet, JSP MVC框架:Struts,Tapestry,MyFaces...
业务层组件:JavaBean 集成层: Spring,EJB
持久层技术:JDBC ORM框架:Hibernate,TopLink,OpenJPA,EJB JPA...
常见技术组合:
Struts/MyFaces + EJB(JDBC)
需要分布式技术的大型项目,大并发访问量,性能要求高
Struts/MyFaces + Spring + Hibernate
多数中小型项目
EJB 3.0
1)会话Bean:对业务逻辑建模
分类: 有状态,能分辨不同的客户;无状态,不能分辨不同的客户
2)实体(Entity)
POJO
3)消息Bean
支持异步通信。没有直接的客户端,由消息触发(驱动)
4. First EJB开发步骤:
EJB组件开发:
1)安装JBoss,并启动
默认端口:8080;可以修改 %jboss_home%/server/default/deploy/jboss-web.deployer 的server.xml
把 <Service name="jboss.web"> 的 <Connector port="8080" ... 改成想要的就行
2)开发一个普通的Java组件
3)classpath加上Java EE 5 Libraries(MyEclipse自带类库)
4)加EJB的标注,声明为EJB组件
IHello.java (接口标注:@Remote )
HelloBean.java (无状态会话bean标注:@Stateless )
5)编译,在 FirstEJB/bin 运行命令: jar cvf HelloEJB.jar .
6)拷贝HelloEJB.jar到%jboss_home%/server/default/deploy目录下
这是正常发布方法。需要启动%jboss_home%/bin/run.jar (win下用run.bat,linux用run.sh启动)
7)确认组件已部署(控制台没有异常)
EJB客户端开发:
1)classpath加上jbossall-client.jar(这个包在 %jboss_home%/client/ 下)
引入这个jar包之后才可以初始化上下文(context)
2)引入IHello.class
3)Client.java
5. JNDI(Java 命名和目录服务接口)
JNDI为JavaEE平台提供了一个通过名字查找网络中一切对象的标准机制
是一套为开发者提供通过名字方便查找用户、机器、网络、对象和服务的 Java API
JNDI实现了EJB对象位置的透明性,客户端只要能访问JNDI服务,便可以调用EJB服务。
1) 部署ejb的时候,容器将会把EJB对象绑定到命名服务
2) 像JDBC可以访问不同的数据库,可以通过JNDI访问不同的JNDI服务
a.设置上下文工厂
b.设置JNDI服务提供者的url
3) JNDI的API的使用
初始化上下文(Context ctx = new InitialContext() )
--- 不同的应用服务器初始化上下文的工厂类是不同的,协议也可能不一样!!!查文档吧
三种方式初始化上下文:
a)设置系统属性(Test.java中)
System.setProperty(Context.INITIAL_CONTEXT_FACTORY,
org.jnp.interfaces.NamingContextFactory.class.getName());
上句也可以这样写: System.setProperty("java.naming.factory.initial",
"org.jnp.interfaces.NamingContextFactory");
System.setProperty(Context.PROVIDER_URL, "localhost");
//"localhost" 也可以写: jnp://127.0.0.1:1099
b)通过命令行设置
c)在类路径下添加jndi.properties ---名字不能修改!!
jboss中:
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.provider.url=jnp://localhost:1099
Sun App Server 9.0 中:
java.naming.factory.initial=com.sun.enterprise.naming.SerialInitContextFactory
java.naming.provider.url=iiop://127.0.0.1:3700
4) JNDI API(javax.naming.Context接口) 主要方法的使用
void bind(String name, Object object); //将名称绑定到对象。如果已经存在,则抛出异常。
void rebind(String name, Object object); //将名称绑定到对象。如果存在,重写所有绑定。
void rename(String oldName,String newName); //把某一个已经绑定的旧名称改新名字
void unbind(String name); //取消指定对象的绑定。
Object lookup(String name); //查找指定的对象。
注意:这4个方法都 throws NamingException;
5) JBoss下配置JNDI名称
在jboss下配置bean的JNDI名可以采取三种方式:
第一种:也是默认的,"beanname/remote"
第二种:使用@RemoteBinding注释。(导入jboss-annotations-ejb3.jar)
@RemoteBinding(jndiBinding="jndiName") --- 这种方式不好,与JBoss耦合!!!
第三种:使用jboss.xml文件,此文件要放在src\META-INF目录下。具体内容见下面:
<jboss>
<enterprise-beans>
<session>
<ejb-name>BeanName</ejb-name>
<jndi-name>jnidname</jndi-name>
</session>
</enterprise-beans>
</jboss>
6. 远程调用的原理
1)使用Socket进行网络通信
2)使用代理模式,使得调用服务器端的远程对象,看起来像调用本地对象一样
3)客户端的代理叫做Stub(桩)
4)服务端的Skeleton(框架)
5)调用过程: Client -> Stub(远程接口) -> Skeleton -> EJB Object(也叫远程对象)
RMI简介
1)RMI(Remote Method Invocation,远程方法调用)是用Java在JDK1.1中实现的,它增强了开发分布式应用的能力。
2)Java RMI 则支持存储于不同地址空间的程序级对象之间彼此进行通信,实现远程对象之间的无缝远程调用。
3)RMI目前使用Java远程消息交换协议JRMP(Java Remote Messaging Protocol)进行通信。
4)用Java RMI开发的应用系统可以部署在任何支持JRE(Java Run Environment,Java运行环境)的平台上。但由于JRMP是专为Java对象制定的,因此,RMI 对于用非Java语言开发的应用系统的支持不足。不能与用非Java语言书写的对象进行通信。
RMI架构
1) Stub/Skeleton层
该层提供了客户程序和服务程序彼此交互的接口。
2) 远程引用层(Remote Reference)
中间层,负责处理远程对象引用的创建和管理。
3) 传输协议(Transport Protocal)
提供了数据协议,用以通过线路传输客户程序和远程对象间的请求和应答。
编写RMI的程序
1) 定义远程接口
通过扩展 java.rmi.Remote 接口,并定义所需的业务方法实现
远程方法必须声明抛出 java.rmi.RemoteException 异常;或者这异常的父类
远程方法的参数和返回值必须是实现序列化接口的类(基本类型也可以)
2) 定义远程接口的实现类
即实现上一步所定义的接口,给出业务方法的具体实现逻辑。
3) 编写运行 Skeleton 引导程序注册RMI服务 (定义协议,并等待客户端调用)
4) 编写客户端 Stub;(遵守协议的端口、读取发送信息的方式;供调用)
使用动态类加载机制(反射机制)
5) 编写客户端Client,调用远程对象
7. Local接口和EJB组件的依赖注入
1)本地接口: @Local
2)EJB组件的依赖注入:@EJB(mappedName="EJB Name/remote")
ejb客户端开发步骤:
1)引入ejb远程接口(a方式.引入ejb工程, b.把远程接口直接Copy过来)
2)引入jbossall-client.jar
3)保证src目录下面有一个jndi.properties
4)客户代码,如:Test.java
8. Remote 和 Local
Local(默认方式) Remote
使用@Local标注 使用@Remote标注
只能本地调用,远程不行 既可以本地调用,也可以远程调用
避免网络交换过程 无法避免网络交换过程,性能差
允许传递未序列化的参数 不允许传递未序列化的参数
注意:要调用实现Local接口的sessionbean,客户端程序和EJB必须在同一JVM的服务器环境。
远程客户端也可以通过 与EJB在同一JVM的代理去访问(如Stub/Skeleton;或者用一个@Remote的Bean间接调用)
-----------------------------------------------------------
Day2
1. EJB的Web客户
在web项目中调用EJB
web项目在tomcat部署:
web项目中必须包含远程接口
web项目必须导入jbossall-client.jar
web项目在jboss部署: (在同一台服务器上部署)
web项目: 不需要 远程接口和jbossall-client.jar(注意: 一个JBoss中不能出现两个相同的类)
2. EJB编程模型
3. EJB的分类(2.X分类)
1)Session Bean(会话Bean) (Stateless和Stateful) --- 对业务逻辑建模
2)Entity Bean(实体Bean,3.0使用JPA替代) -- POJO ---对领域模型建模
3)Message Driven Bean(消息驱动Bean) --- 支持异步通讯,没有直接的客户端,由消息驱动
4.EJB的系统服务
1)事务
2)安全
3)对象池
5. 部署描述符和标注
早期版本使用配置文件开发EJB, EJB3.0使用Annotation简化开发
1)开发阶段:开发人员使用Annotation开发
2)部署阶段:部署人员使用部署描述符部署(将覆盖annotation配置)
部署描述符:
1) 标准部署描述符:ejb-jar.xml
<ejb-jar version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd ">
<enterprise-beans>
<session>
<ejb-name>BeanName</ejb-name>
<remote>package.IBeanName</remote>
<local>package.IBeanName</local>
<ejb-class>package.IBeanImplements</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
</ejb-jar>
2) 特定应用服务器部署描述符:
JBoss:jboss.xml
Weblogic:weblogic-ejb-jar.xml
Sun:sun-ejb-jar.xml
标注和部署描述符的区别:
标注 部署描述符
简单便利,直观 复杂,容易出错
分散管理,无法应付复杂应用 集中管理,可以应付较复杂应用
EJB提供者和部署者不是同一人 适合于EJB提供者和部署者不是同一人的情况
容易出错
注意:标注与部署描述符同时使用,部署描述符的优先级更高,会覆盖标注!!!
6. Session Bean(会话Bean)
业务组件: 由客户端程序调用的一段业务逻辑, 作用相当于Spring管理的服务组件。一个EJB组件在容器中可能包含多个实例。
会话Bean:对业务逻辑建模:用程序模拟处理一件事情的流程和步骤
7. 会话Bean的分类:
Stateless Sesssion Bean(无状态会话Bean,简称:SLSB)
1)一次方法调用代表一次会话
2)多次方法请求之间不保存状态 (只能调用方法,不能访问属性)
3)Bean的对象实例可以被任何客户调用
Stateful session Bean(有状态会话Bean,简称:SFSB)
1)会话贯穿于多次方法调用之间
2)多次方法请求之间保存状态
SFSB像servlet中的Session对象,可以访问SFSB的属性,SFSB的属性值会自动保留,供下次访问
3)只有一个客户能访问这个Bean的对象实例和它的状态
8. 无状态会话Bean的对象和并发服务
1)实例数量是容器根据客户端数量,来创建的。创建以后不会销毁,容器销毁或删除此项目时才销毁
2)不能区分不同的客户。由哪个实例响应客户端,是由容器决定的。按静态方法来使用。
3)实例可共享,和客户stub是多对多。不能拥有实例变量,即使有,也不能暴露给客户
4)生命周期:不存在 -> 就绪
5)回调方法和Remove方法
6)并发访问
a.没有状态,因此也无需做并发处理
b.串行共享
c.对象池 --- 容器会初始化n个Bean对象应付成千上万的客户端的并发请求。
9. 无状态会话Bean的生命周期(状态图)
1)不存在 -> 就绪
过程: 1创建Bean实例 2依赖注入 3@PostConstrcut回调方法)
2)就绪 -> 不存在
过程: @PreDestroy回调方法
3)回调方法@PostConstrcut和@PreDestroy,可以定义在Bean类中,也可以定义在单独的类中
@PostConstrcut 进行初始化工作,比如获取一些不能用依赖注入获得的资源
@PreDestroy 释放初始化时获得的资源
4)独立的回调类
@Interceptors(Callback.class)
10.有状态会话Bean的对象池和并发服务
1)能区分不同的客户,可以记住客户信息
2)跨越多个请求(方法调用),维护会话状态(bean类的实例变量)
3)Bean对象和stub一对一
4)生命周期:不存在 -> 就绪 -> 钝化
状态包括:
成员变量是非transient类型的java基本类型或对象
本地或者远程接口的EJB引用
容器管理的资源
JNDI命名上下文Context
5)回调方法和Remove方法(初始化实例变量,获得或关掉外部资源等)
6)多用户并发访问:
a.容器考虑,开发人员无需处理并发
b.钝化和激活过程
c.容器的并发策略(annotaion和DD)
需导包:jboss-annotation-ejb3.jar (这个包在 %jboss_home%/client/ 下)
d.Bean编写的要求,必须具备序列化能力(serializable)
7)占用更多资源:cpu(查找bean、激活、钝化)和内存(有多少个在线用户就有多少stateful bean)
有状态会话Bean:
1.一个Stub就是一个客户,lookup到Stub以后,保存在servlet的session中
2.EJB重新部署之后,需要lookup一个新的Stub
生命周期:不存在 -> 就绪 -> 钝化
1.当客户端lookup时,Bean并不存在;直到客户端首次请求调用时,服务器才构造bean实例,并调用postConstruct方法进入就绪状态;然后客户端才可以正常调用
2.如果客户端太久不用,服务器会调用prePassivate方法使bean钝化;当客户端再次请求调用时,又构造新实例,调用postActivate重新激活;然后客户端才正常调用
3.客户端调用remove后,服务器端会调用preDestroy方法令bean不存在;此后不能再使用这个bean,如需再用要再次lookup
11. 示例:购物篮
购物篮EJB组件
包含状态:产品信息(产品,数量)
业务功能:1添加产品 2生成订单
数据源 模板的位置: %jboss_home%/docs/examples/jca/
数据源配置文件位置: %jboss_home%/server/default/deploy/mysql-ds.xml
mysql驱动程序位置: %jboss_home%/server/default/lib/
issue:
无法访问数据库时,注意:
1. 检查数据库驱动程序
2. 检查mysql-ds.xml是否正确(url,username,password);放到 %jboss_home%/server/default/deploy/
3. 检查数据源是否部署成功,JNDI引用名称是否正确( 以 "java:/" 开始)
-----------------------------------------------------------
Day3
1. JPA(Java Persistence API)简介
1)ORM(object relational mapping): 实现对象到关系数据库中的表的自动持久化(翻译)
通过元数据描述对象于数据库间的映射。
2)JPA, Sun提出的又一套Java持久化规范标准
3)整合当前各种ORM框架和技术,为各种ORM框架提供统一编程接口
4)只是一套接口,要求持久化提供商实现支持
5)使用Annotation和XML描述对象和关系表的关系
6)EJB和普通Java程序都可使用
2. JPA编程
EntityManager接口
J2SE环境下JPA 编程步骤:
a.导入包: Java EE 5 Libraries(MyEclipse的类库,javaee.jar);
数据库驱动包; PP(持久化提供者)的包
b.配置persistence.xml(名字固定)
提供访问数据库的信息 和指定具体的PP(persistence provider)
c.开发实体(注解或orm.xml)
1)在POJO类上添加@Entity
2)实体必须声明主键@Id,(可以使用@GeneratedValue配置主键产生的策略)
3)默认情况下,实体类名和属性名等同于表的字段名(可用@Table/@Column 加上(name="new_name")另外起名)
//4)实体能够包括业务方法(不建议这么做,会导致实体的职责不清)
d.Session Bean(注入EntityManager)
e.开发客户程序
3. JPA支持两种事务类型
本地资源事务(RESOURCE_LOCAL):使用JDBC驱动管理的本地事务。不需发布。
Java事务API(JTA):容器管理的事务。要使用JTA必须使用服务器的DataSource。
JavaEE环境下
容器管理的EntityManager(@PersistenceContext注入)必须使用JTA事务。
应用程序管理的EntityManager可以使用本地资源事务,也可以使用JTA事务
在JavaSE环境下,使用本地资源事务
比较 Hibernate 与 JPA 的开发过程:
Hibernate jpa
1.POJO(entity) 1.entity
2.xxx.hbm.xml 2.Annotation(orm.xml)
3.hibernate.cfg.xml 3.persistence.xml
4.SessionFactory 4.EntityManagerFactory
from http://hi.baidu.com/sp_hrz/blog/item/d9b0aeed23428c4278f0551b.html