资源描述
1济南大学信息学院济南大学信息学院 刘鹍刘鹍2回顾:JSF 开发步骤:开发步骤:3补充:JavaEE概述4补充:典型的JavaEE应用系统层次结构5补充:JavaEE容器基于组件和平台独立的基于组件和平台独立的JavaEE使分层的企业分使分层的企业分布式应用程序容易开发,因为各种应用的功能逻布式应用程序容易开发,因为各种应用的功能逻辑被封装在可重用的辑被封装在可重用的JavaEE组件中。另外组件中。另外JavaEE服务器以容器的形式为所有服务器以容器的形式为所有JavaEE组件组件提供底层公共服务提供底层公共服务,因此您不必再为这些底层公,因此您不必再为这些底层公共服务伤脑筋,而可以专注于解决应用系统的商共服务伤脑筋,而可以专注于解决应用系统的商业问题。业问题。容器(容器(Container)是组件和支持组件功能的底)是组件和支持组件功能的底层特定平台(如数据库、分布式的网络环境及层特定平台(如数据库、分布式的网络环境及Java虚拟机等)之间的接口虚拟机等)之间的接口。在运行。在运行Web组件、组件、企业企业Bean组件或者组件或者JavaEE客户端组件之前,您客户端组件之前,您必须将它们装配到一个必须将它们装配到一个JavaEE应用程序中,并应用程序中,并部署它们到容器中。部署它们到容器中。6补充:JavaEE容器JavaEE的容器类型的容器类型7补充: JavaEE应用打包与部署 JAR/WAR/EAR文件格式文件格式 JAR是是Java技术中的一种与平台无关的文件格式,它允技术中的一种与平台无关的文件格式,它允许将许多文件组合成一个压缩文件。许将许多文件组合成一个压缩文件。JAR 文件格式以流文件格式以流行的行的 ZIP 文件格式为基础。与文件格式为基础。与 ZIP 文件不同的是,文件不同的是,JAR 文件不仅用于压缩和发布,而且还用于部署和封装库、文件不仅用于压缩和发布,而且还用于部署和封装库、组件和插件程序,并可被像编译器和组件和插件程序,并可被像编译器和 JVM 这样的工具直这样的工具直接使用。在接使用。在 JAR 中包含特殊的文件,如中包含特殊的文件,如 manifests 和和部署描述符,用来指示工具如何处理特定的部署描述符,用来指示工具如何处理特定的 JAR。8补充: JavaEE应用打包与部署 JAR/WAR/EAR文件格式文件格式 WAR和和EAR文件也是文件也是Java技术中的一种与平台无关的技术中的一种与平台无关的文件格式,也同样允许将许多文件组合成一个压缩文件。文件格式,也同样允许将许多文件组合成一个压缩文件。 与与JAR文件不同的是,文件不同的是,WAR文件除了可以组合文件除了可以组合JSP文件文件和和servlet类文件等类文件等web组件程序文件之外,还可以包含组件程序文件之外,还可以包含GIF文件、静态文件、静态HTML文件等多种其它类型的文件。文件等多种其它类型的文件。 EAR文件则主要用于由多个文件则主要用于由多个JavaEE应用模块所构成的应用模块所构成的一个完整应用程序的打包,其可以包含多个一个完整应用程序的打包,其可以包含多个JAR文件和文件和WAR文件。文件。 从打包粒度上讲,按由小至大的顺序排列,分别是从打包粒度上讲,按由小至大的顺序排列,分别是JAR、WAR和和EAR。9补充: JavaEE应用打包与部署JAR、WAR和和EAR文件的一般目录结构文件的一般目录结构10补充: JavaEE应用开发角色企业企业Bean开发者开发者提供企业提供企业Bean的的EJB JAR文件文件Web组件开发者组件开发者的工作任务是提供的工作任务是提供WAR文件文件JavaEE应用程序客户端开发者应用程序客户端开发者也提供一个也提供一个JAR文件文件应用程序组装者应用程序组装者将从组件开发者获得的组件文件将从组件开发者获得的组件文件装配成一个装配成一个JavaEE应用程序应用程序EAR文件。文件。应用程序部署者和系统管理员应用程序部署者和系统管理员配置和部署配置和部署JavaEE应用程序,在程序运行时管理计算机和应用程序,在程序运行时管理计算机和网络结构,并且监控运行时环境。包括设置事务网络结构,并且监控运行时环境。包括设置事务控制、安全属性和指定数据库连接。控制、安全属性和指定数据库连接。11补充: Java 5语言新特性12补充: Java 5语言新特性增强的增强的for循环循环注释注释枚举枚举enum泛型泛型类型自动转换类型自动转换静态导入静态导入格式化输入与输出格式化输入与输出13补充: Java 5语言新特性 加强的加强的For循环:循环:局限性:不可以在迭代期间访问迭代器或下标局限性:不可以在迭代期间访问迭代器或下标int sum = 0;Integer numbers = computeNumbers();for (int i=0; i numbers.length ; i+) sum += numbersi;int sum = 0;for ( int number: computeNumbers() ) sum += number; 14补充: Java 5语言新特性 注释(注释()的作用)的作用 可以被用来生成文档,检查代码间依赖关系,帮助编译器作可以被用来生成文档,检查代码间依赖关系,帮助编译器作语法检查。代码检查举例:语法检查。代码检查举例:public class Parent public void foo() System.out.println(Original Implementation of foo); public class Child extends Parent Override public void fob() System.out.println(Overide Implementation of foo); 错误提示:错误提示: Child.java:3: method does not override a method from its superclass Override 1 error15补充: Java 5语言新特性 内置注释类型内置注释类型 Override(覆写)(覆写):Override 应该仅用于方法(不用于类、应该仅用于方法(不用于类、包声明或其他构造),它指明注释的方法将覆盖超类中的方包声明或其他构造),它指明注释的方法将覆盖超类中的方法。法。 Deprecated(不赞成使用)(不赞成使用):与:与 Override 一样,一样, Deprecated 是标记注释,是标记注释,Deprecated 应该与正在声明为过应该与正在声明为过时的方法放在同一行中。时的方法放在同一行中。 SuppressWarnings(压制安全警告)(压制安全警告):SupressWarnings 与与 Override 和和 Deprecated 不同,是具有变量的,例如:不同,是具有变量的,例如:SuppressWarings(value=unchecked) 16补充: Java 5语言新特性 枚举枚举enum类型:类型: 在在enum中定义方法和变量中定义方法和变量 :public enum Color Red, Green, Blue; private static int number = Color.values().length ; public static Color getRandomColor() long random = System.currentTimeMillis() % number; switch (int) random) case 0: return Color.Red; case 1: return Color.Green; case 2: return Color.Blue; default : return Color.Red; 17补充: Java 5语言新特性 枚举枚举enum类型:类型: 遍历所有枚举值:遍历所有枚举值: for (Color c: Color.values() System.out.println(“find value:” + c); 18补充: Java 5语言新特性范型定义:范型定义:所谓范型是指类型参数化所谓范型是指类型参数化(parameterized types)。Java是一种强类型的语言,在是一种强类型的语言,在J2SE 1.4以及以前的版本中,我们在定义一个以及以前的版本中,我们在定义一个Java类类的接口或者方法的时候,必须指定变量的类型。的接口或者方法的时候,必须指定变量的类型。在声明范型类、接口或者函数时,定义变量的时在声明范型类、接口或者函数时,定义变量的时候不指定某些变量的具体类型,而是用一个类型候不指定某些变量的具体类型,而是用一个类型参数代替。在使用这个类、接口或者方法的时候,参数代替。在使用这个类、接口或者方法的时候,这个类型参数由一个具体类型所代替。这个类型参数由一个具体类型所代替。19补充: Java 5语言新特性其他新特性:其他新特性:类型自动转换类型自动转换静态导入静态导入格式化输出与输入格式化输出与输入20补充: Java EE应用服务器21补充: Java EE应用服务器Sun GlassFish金蝶金蝶ApusicJBoss2223学习要点:学习要点:1了解了解EJB3.0的基础知识。的基础知识。2了解了解EJB3.0中的中的Bean类型。类型。3掌握会话掌握会话Bean。4掌握消息驱动掌握消息驱动Bean。248.1 EJB3.0概述概述 8.2 会话会话Bean 8.3 消息驱动消息驱动Bean25Enterprise JavaBeans(EJB)是一种服务器端的是一种服务器端的软件组件模型,是软件组件模型,是J2EE的基础和最重要的部分。的基础和最重要的部分。如今开发电于商务平台已大量使用组件技术,这如今开发电于商务平台已大量使用组件技术,这是因为组件技术提供了服务器上的自治、企业级是因为组件技术提供了服务器上的自治、企业级和分布式功能,并帮助开发者在不同颗粒度级别和分布式功能,并帮助开发者在不同颗粒度级别上定义和封装系统功能。上定义和封装系统功能。268.1.1 传统的传统的EJB8.1.2 EJB3.0简介简介8.1.3 EJB3.0中的中的Bean类型类型27引入引入 Enterprise JavaBeans(EJB)是为了构)是为了构建分布式组件。最初,该技术承诺可以解决建分布式组件。最初,该技术承诺可以解决 CORBA的所有问题并降低其复杂性。作为的所有问题并降低其复杂性。作为J2EE的核心,的核心,EJB经历了几次较大的修订,并加入了经历了几次较大的修订,并加入了许多特性,因而变得臃肿起来。随着许多特性,因而变得臃肿起来。随着 EJB 规范规范的相继发布,它还变得越来越复杂了。由于其复的相继发布,它还变得越来越复杂了。由于其复杂性和本身庞大的体系,传统的杂性和本身庞大的体系,传统的EJB技术被喻为技术被喻为一头笨重的大象。一头笨重的大象。288.1.2 EJB3.0简介 Do more with less workJava EE 5的正式宣言的正式宣言 在在JavaEE 5中采用了中采用了EJB3.0技术规范实现的技术规范实现的EJB技术在技术在这方面作出了改进的努力。这方面作出了改进的努力。 EJB3.0减轻了开发人员进行底层开发的工作量,它取消减轻了开发人员进行底层开发的工作量,它取消或最小化了很多(以前这些是必须实现)回调方法的实或最小化了很多(以前这些是必须实现)回调方法的实现,并且降低了实体现,并且降低了实体Bean及及O/R映射模型的复杂性。映射模型的复杂性。 EJB3.0规范与规范与Java Persistence 1.0的规范紧密结合,的规范紧密结合,借鉴了轻量级企业数据对象的很多优点,将借鉴了轻量级企业数据对象的很多优点,将Java Persistence 1.0的规范运用到的规范运用到EJB3.0的的Entity Bean中,中,大大提高了大大提高了Entity Bean的开发效率,也使的开发效率,也使Entity Bean更加通用、简洁、轻巧。更加通用、简洁、轻巧。 32+1298.1.3 EJB3.0中的Bean类型 EJB 3.0中的组件分为三个主要类别:会话中的组件分为三个主要类别:会话Bean、消息、消息驱动驱动Bean和实体和实体Bean。 根据根据Bean处理状态、事务和持久性的方式这些类别还可处理状态、事务和持久性的方式这些类别还可以进一步细分,如会话以进一步细分,如会话Bean可分为无状态会话可分为无状态会话Bean和和有状态会话有状态会话Bean;实体;实体Bean可分为可分为CMP(Container Mangement Persitence)方式的实体)方式的实体Bean和和BMP(Bean Mangement Persitence)方式的实体方式的实体Bean。308.1 EJB3.0概述概述 8.2 会话会话Bean 8.3 消息驱动消息驱动Bean318.2.1 会话会话Bean的生命周期的生命周期8.2.2 无状态会话无状态会话Bean8.2.3 有状态会话有状态会话Bean8.2.4 会话会话Bean实例实例8.2.5 将会话将会话Bean发布为发布为web服务服务328.2.1 会话Bean的生命周期如果是无状态无状态如果是无状态无状态session bean,其生命周期如下:,其生命周期如下:338.2.1 会话Bean的生命周期而有状态而有状态session bean的生命周期则复杂一些,因为涉及的生命周期则复杂一些,因为涉及到钝化、激活和事务,其生命周期如下:到钝化、激活和事务,其生命周期如下:348.2.2 无状态会话Bean无状态会话无状态会话Bean是这样一种是这样一种EJB,其服务的业,其服务的业务过程务过程只需要单个业务方法即可完成只需要单个业务方法即可完成。由于它们。由于它们不需维护客户多个方法调用间的会话状态,因此不需维护客户多个方法调用间的会话状态,因此它是无状态的。它是无状态的。在每次方法调用结束后,在每次方法调用结束后,EJB容器可能会销毁无容器可能会销毁无状态会话状态会话Bean实例,或者实例化新的实例,或实例,或者实例化新的实例,或者清除掉上次方法调用中的相关信息。当然,者清除掉上次方法调用中的相关信息。当然,EJB容器还可能保留前一会话容器还可能保留前一会话Bean实例,并且实例,并且供其他所有客户使用,从而实现同一会话供其他所有客户使用,从而实现同一会话Bean实例的重用,至于具体的实现策略则与具体实例的重用,至于具体的实现策略则与具体EJB容器相关。容器相关。358.2.3 有状态会话Bean有状态会话有状态会话Bean是这样一种是这样一种EJB,即其服务的,即其服务的业务过程能够业务过程能够延伸到多个方法请求或者事务中延伸到多个方法请求或者事务中。为完成这种业务过程,有状态会话为完成这种业务过程,有状态会话Bean需要为需要为单个客户单个客户保存状态信息保存状态信息。如果在方法调用期间有。如果在方法调用期间有状态会话状态会话Bean的状态发生改变,则这种改变必的状态发生改变,则这种改变必须反映到同一客户的随后调用中。须反映到同一客户的随后调用中。368.2.4 会话Bean实例在在EJB3.0规范中,写一个无状态会话规范中,写一个无状态会话Bean(Stateless Session Bean)只需要为一个只需要为一个普通的普通的Java类加上类加上Stateless注释注释(annotation)就可以了。这个)就可以了。这个Bean可以实现可以实现某个业务接口(某个业务接口(Business Interface)也可以不)也可以不实现它。实现它。378.2.5 将会话Bean发布为web服务在在EJB2.1就规定了无状态会话就规定了无状态会话Bean(Stateless Session Bean)对)对Web Service的支持,而在的支持,而在EJB3.0中运用注释(中运用注释(annotation)就可以轻松把)就可以轻松把一个一个无状态会话无状态会话Bean发布为发布为Web服务服务。 需要注意的是:只有无状态会话需要注意的是:只有无状态会话Bean可以发布成可以发布成Web Service; 要暴露给要暴露给Web服务客户端的业务方法必须是服务客户端的业务方法必须是public的;的; Bean类可以通过类可以通过WebService注释的注释的endpointInterface元素实现一个元素实现一个Service Endpoint Interface(SEI),但这不是必须的,如果没有这样一个,但这不是必须的,如果没有这样一个endpointInterface,SEI也能被隐含定义。也能被隐含定义。38例子:开发一个会话bean39例子:开发一个会话bean首先我们先定义一个接口:首先我们先定义一个接口:HelloEjb.java然后实现该接口:然后实现该接口:HelloEjbBean.javapackage cn.edu.ujn.ejb.test.impl;import cn.edu.ujn.ejb.test.HelloEjb;public class HelloEjbBean implements HelloEjb public String hello(String name) / TODO Auto-generated method stubreturn name+:hello EJB!;40例子:开发一个会话bean 刚才的实现类只是一个普通的刚才的实现类只是一个普通的Java类,并不是类,并不是EJB。 下面我们给实现类加入两个注释下面我们给实现类加入两个注释Stateless , Remote,第一个注释定义这是一个无状态会话第一个注释定义这是一个无状态会话 Bean,第二个注释,第二个注释指明这个无状态指明这个无状态Bean的的 remote 接口。接口。package cn.edu.ujn.ejb.test.impl;import cn.edu.ujn.ejb.test.HelloEjb;StatelessRemote(HelloEjb.class)public class HelloEjbBean implements HelloEjb public String hello(String name) / TODO Auto-generated method stubreturn name+:hello EJB!;41例子:开发一个会话bean 打包发布到打包发布到JBoss中去中去(copy到到JBoss的的serverdefaultdeploy目录下目录下)。42例子:开发一个会话bean 我们写一个我们写一个client来测试该来测试该EJB 首先把首先把JBoss的的client目录下所有的目录下所有的jar包添加到该工程包添加到该工程的的classpath中中 然后新建一个测试类:然后新建一个测试类:TestClient.javapackage test;/省略掉importpublic class TestClient public static void main(String args) Properties props= new Properties();props.setProperty(java.naming.factory.initial,org.jnp.interfaces.NamingContextFactory);props.setProperty(java.naming.provider.url, localhost:1099);InitialContext ctx;try ctx= new InitialContext(props);HelloEjb helloejb=(HelloEjb)ctx.lookup(HelloEjbBean/remote);System.out.println(helloejb.hello(刘鹍); catch (NamingException e)System.out.println(e.getMessage();43例子:开发一个会话bean 着重说一下着重说一下Jboss EJB JNDI名称默认的命名规则:名称默认的命名规则:1)如果)如果 EJB 打包进后缀为打包进后缀为*.ear的的 JavaEE发布文件,默认的发布文件,默认的 JNDI路径名称是路径名称是访问本地接口:访问本地接口:EAR-FILE-BASE-NAME/EJB-CLASS-NAME/local访问远程接口:访问远程接口:EAR-FILE-BASE-NAME/EJB-CLASS-NAME/remote例:例:EJB HelloEjb打包进名为打包进名为HelloEjb.ear的的JavaEE应用,访问它远程接口的应用,访问它远程接口的 JNDI名是:名是:HelloEjb/HelloEjbBean/remote2)如果)如果 EJB 应用打包成后缀为应用打包成后缀为*.jar的发布文件的发布文件, 默认的默认的 JNDI路径名称是路径名称是访问本地接口:访问本地接口:EJB-CLASS-NAME/local访问远程接口:访问远程接口:EJB-CLASS-NAME/remote例:例: HelloEjb 应用打包成应用打包成 HelloEjb.jar 文件,访问它远程接口的文件,访问它远程接口的 JNDI名称是:名称是: HelloEjbBean/remote另外有一点要注意:另外有一点要注意:EJB-CLASS-NAME 是不带包名的,如是不带包名的,如 cn.edu.ujn.test.HelloEjbBean只需取只需取HelloEjbBean。44例子:开发一个会话bean 运行结果:运行结果: 下面我们再看一个只存在下面我们再看一个只存在 Local接口的无状态接口的无状态 SessionBean,新建,新建HelloEjbLocalBean.java,同样实,同样实现现HelloEjb这个接口。这个接口。package cn.edu.ujn.ejb.test.impl;import javax.ejb.Local;import javax.ejb.Stateless;import cn.edu.ujn.ejb.test.HelloEjb;StatelessLocal(HelloEjb.class)public class HelloEjbLocalBean implements HelloEjb public String hello(String name) return name+:hello Local Stateless EJB!;45例子:开发一个会话bean新建一个新建一个index.jsp 46例子:开发一个会话bean 通过通过eclipse把该把该web project也部署到也部署到JBoss中去中去 通过浏览器访问该通过浏览器访问该jsp页面,结果如下:页面,结果如下:47例子:开发一个会话bean 思考:思考:Spring跟跟EJB的的bean管理思想对比管理思想对比 Springxml管理管理 EJBJNDI管理管理 得到一个得到一个bean的实例:的实例:Spring这样得到:这样得到: EJB这样得到:这样得到: ApplicationContext ctx = new FileSystemXmlApplicationContext(src/applicationContext.xml); Human human = null; human = (Human) ctx.getBean(chinese); human.speak(); InitialContext ctx= new InitialContext(props);HelloEjb helloejb=(HelloEjb)ctx.lookup(HelloEjbLocalBean/local);48例子:开发一个会话bean 下面我们来开发一个有状态的会话下面我们来开发一个有状态的会话bean: 我们用课本上做加法的例子(适当修改)我们用课本上做加法的例子(适当修改) 首先新建接口首先新建接口Add.java,该接口必须实现,该接口必须实现Serializable接口,接口,并实现该接口:并实现该接口:package cn.edu.ujn.ejb.test;import java.io.Serializable;public interface Add extends Serializablepublic int doAdd(int i,int j);public int getTotal();package cn.edu.ujn.ejb.test.impl;import javax.ejb.Remote;import javax.ejb.Stateful;import cn.edu.ujn.ejb.test.Add;StatefulRemote(Add.class)public class AddBean implements Add private int total =0;private int addresult =0;public int doAdd(int i, int j) addresult = i+j;return addresult;public int getTotal()total =total+addresult;return total;49例子:开发一个会话bean新建一个新建一个client测试类测试类TestStateful.javapublic static void main(String args) / TODO Auto-generated method stubProperties props= new Properties();props.setProperty(java.naming.factory.initial,org.jnp.interfaces.NamingContextFactory);props.setProperty(java.naming.provider.url, localhost:1099);props.setProperty(java.naming.factory.url.pkgs, org.jboss.naming);InitialContext ctx;try ctx= new InitialContext(props);Add addejb=(Add)ctx.lookup(AddBean/remote);System.out.println(addresult:+addejb.doAdd(1, 2);System.out.println(total:+addejb.getTotal();System.out.println(-);Add addejb1=(Add)ctx.lookup(AddBean/remote);System.out.println(addresult:+addejb1.doAdd(3, 4);System.out.println(total:+addejb1.getTotal(); catch (NamingException e)System.out.println(e.getMessage();50例子:开发一个会话bean 把把EJB打包,部署到打包,部署到JBoss的的serverdefaultdeploy目目录下录下 运行结果如下:运行结果如下:51济南大学信息学院济南大学信息学院 刘鹍刘鹍52回顾:EJBJAR、WAR和和EAREJB: 32+153回顾:EJB会话会话bean调用调用 InitialContext LookupInitialContext ctx= new InitialContext(props);HelloEjb helloejb=(HelloEjb)ctx.lookup(HelloEjbLocalBean/local);54回顾:EJB JNDI Java Naming and Directory Interface 为开发人员提供了查找和访问各种命名和目录服务的通用、为开发人员提供了查找和访问各种命名和目录服务的通用、统一的方式。借助于统一的方式。借助于JNDI提供的接口,能够通过名字定位提供的接口,能够通过名字定位用户、机器、网络、对象服务等。用户、机器、网络、对象服务等。 NamingDNS Directory简单的简单的RDBMS JNDI的主要用途:的主要用途: 使用使用JNDI获得对获得对JAVA事务事务API中的中的UserTransaction接口接口的引用的引用 借助于借助于JNDI,连接到资源工厂,比如,连接到资源工厂,比如JDBC、JMS等。等。 在在EJB组件中,借助于组件中,借助于JNDI查找其他的查找其他的EJB组件组件55回顾:EJBjavax.naming.Context(interface)其中INITIAL_CONTEXT_FACTORY 和PROVIDER_URL 。javax.naming.Naming(interface)javax.naming.InitialContext(class)其中lookup()、list()、bind() 、createSubcontext()、unbind() Java.util.Propertes(class)其中setProperties()和getProperties()、list()/设置初始化上下文的参数,主要是设置设置初始化上下文的参数,主要是设置JNDI驱动的类名驱动的类名/java.naming.factory.initial和提供命名服务的的和提供命名服务的的URL -java.naming.provider.url,/ java.naming.factory.initial的值因提供的值因提供JNDI服务器的不同而不同,服务器的不同而不同,/java.naming.provider.url的值包括提供命名服务的主机地址和端口号。的值包括提供命名服务的主机地址和端口号。Properties p=new Properties();p.setProperty(java.naming.factory.initial, org.jnp.interfaces.NamingContextFactory);p.setProperty(java.naming.provider.url, localhost:1099);/ 初始化上下文环境,生成一个上下文实例初始化上下文环境,生成一个上下文实例InitialContext jndiContext = new InitialContext(p);Object lookupObject=jndiContext.lookup(“jndiname”);56回顾:EJB 着重说一下着重说一下Jboss EJB JNDI名称默认的命名规则:名称默认的命名规则:1)如果)如果 EJB 打包进后缀为打包进后缀为*.ear的的 JavaEE发布文件,默认的发布文件,默认的 JNDI路径名称是路径名称是访问本地接口:访问本地接口:EAR-FILE-BASE-NAME/EJB-CLASS-NAME/local访问远程接口:访问远程接口:EAR-FILE-BASE-NAME/EJB-CLASS-NAME/remote例:例:EJB HelloEjb打包进名为打包进名为HelloEjb.ear的的JavaEE应用,访问它远程接口的应用,访问它远程接口的 JNDI名是:名是:HelloEjb/HelloEjbBean/remote2)如果)如果 EJB 应用打包成后缀为应用打包成后缀为*.jar的发布文件的发布文件, 默认的默认的 JNDI路径名称是路径名称是访问本地接口:访问本地接口:EJB-CLASS-NAME/local访问远程接口:访问远程接口:EJB-CLASS-NAME/remote例:例: HelloEjb 应用打包成应用打包成 HelloEjb.jar 文件,访问它远程接口的文件,访问它远程接口的 JNDI名称是:名称是: HelloEjbBean/remote另外有一点要注意:另外有一点要注意:EJB-CLASS-NAME 是不带包名的,如是不带包名的,如 cn.edu.ujn.test.HelloEjbBean只需取只需取HelloEjbBean。578.1 EJB3.0概述概述 8.2 会话会话Bean 8.3 消息驱动消息驱动Bean588.3.1 为什么要使用消息为什么要使用消息8.3.2 Java消息服务消息服务8.3.3 集成集成JMS和和EJB8.3.4 开发消息开发消息Bean8.3.5 消息事务消息事务*8.3.6 集群消息集群消息*8.3.7 负载均衡负载均衡*598.3.1 为什么要使用消息当服务器需要耗费较长的时间(几小时或着有时当服务器需要耗费较长的时间(几小时或着有时甚至是几天)来对这些请求作出响应。客户端程甚至是几天)来对这些请求作出响应。客户端程序(应用)要与服务器连接并耗费如此长的时间序(应用)要与服务器连接并耗费如此长的时间来等待结果,这是毫无意义的。因此通信应该是来等待结果,这是毫无意义的。因此通信应该是异步发生的。异步发生的。消息系统的运行机制:一旦请求被提交,它就被消息系统的运行机制:一旦请求被提交,它就被放置在队列中,同时客户端与服务器断开连接。放置在队列中,同时客户端与服务器断开连接。然后服务器从指定的队列中选出请求进行处理,然后服务器从指定的队列中选出请求进行处理,并将处理得到的消息放置在另一个消息队列里。并将处理得到的消息放置在另一个消息队列里。最后,客户端程序从这个队列中选出处理结果,最后,客户端程序从这个队列中选出处理结果,获得响应。获得响应。608.3.2 Java消息服务Java消息服务(消息服务(Java Message Service,JMS)是一个是一个Java API,它定义了消息的客户程序如,它定义了消息的客户程序如何以一种标准化的形式与底层的消息服务提供者何以一种标准化的形式与底层的消息服务提供者交互。交互。JMS提供了一种接口,底层消息服务提供提供了一种接口,底层消息服务提供者通过该接口向客户程序提供者通过该接口向客户程序提供 JMS消息服务。消息服务。JMS提供了点对点消息模式(提供了点对点消息模式(Point-to-Point)和发布和发布-订阅消息模式(订阅消息模式(Publish-Subscribe)。)。 618.3.3 集成JMS和EJB会话会话 Bean可以发送可以发送 JMS 消息并同步接收消息并同步接收 JMS 消息,但不是异步方式。为避免占用服务器资源,消息,但不是异步方式。为避免占用服务器资源,可能希望在服务器端组件中使用异步接收。要异可能希望在服务器端组件中使用异步接收。要异步接收消息,就使用消息驱动型步接收消息,就使用消息驱动型 Bean。消息驱动消息驱动bean大大地简化了创建一个大大地简化了创建一个JMS使用使用者,创建和配置一个者,创建和配置一个JMS消息使用者这些功能都消息使用者这些功能都交由交由EJB容器来做了。开发人员只需简单地实现容器来做了。开发人员只需简单地实现消息驱动消息驱动bean的接口,配置给的接口,配置给EJB服务器,用服务器,用来创建一个接收消息的商业逻辑部件。来创建一个接收消息的商业逻辑部件。628.3.4 开发消息Bean消息驱动消息驱动Bean的业务接口已经被定义,对于使的业务接口已经被定义,对于使用用JMS来说那就是来说那就是MessageListener接口,这接口,这个接口定义了个接口定义了OnMessage方法。在之前所有的方法。在之前所有的EJB规范中,强制要求必须实现规范中,强制要求必须实现MessageDrivenBean接口,在接口,在EJB3.0中可以实中可以实现也可以不实现。但实现类必须使用现也可以不实现。但实现类必须使用MessageDriven注释。注释。开发消息开发消息Bean需要通过需要通过MessageDriven的注释,的注释,完成实现类的开发。完成实现类的开发。638.3.4 开发消息Bean开发一个消息驱动开发一个消息驱动Bean新建一个新建一个EJB Project64 新建一个新建一个MDB类,实现类,实现MessageListener接口,类型选接口,类型选择择Queue (Point-to-Point)8.3.4 开发消息Bean65 完成完成HelloMDB.java的代码的代码8.3.4 开发消息BeanMessageDriven(activationConfig = ActivationConfigProperty(propertyName = acknowledgeMode, propertyValue = Auto-acknowledge),ActivationConfigProperty(propertyName = destinationType, propertyValue = javax.jms.Queue),ActivationConfigProperty(propertyName = destination, propertyValue = queue/myQueue) )public class HelloMDB implements MessageListener public void onMessage(Message msg) try if (msg instanceof TextMessage) TextMessage tmsg = (TextMessage) msg;String content = tmsg.getText();System.out.println(content); catch (Exception e) e.printStackTrace();66 修改修改jbossmq-destinations-service.xml(该文件在(该文件在jboss安装目录安装目录serverdefaultdeployjms下)下) 打包,发布该消息驱动打包,发布该消息驱动bean8.3.4 开发消息Bean678.3.4 开发消息Bean 注意注意:设置:设置Queue可以不在可以不在 jbossmq-destinations-service.xml文件中,也可以放在自己的文件中,也可以放在自己的EJB中,方法如中,方法如下:在下:在META-INF下新建下新建test-service.xml queue/myQueue jboss.mq:service=DestinationManager 688.3.4 开发消息Bean 补充:补充:META-INF中的配置文件中的配置文件698.3.4 开发消息Bean ejb-jar.xml例子:例子:HelloEjbBeanHelloEjbBean708.3.4 开发消息Bean *-service.xml queue/myQueue jboss.mq:service=DestinationManager 718.3.4 开发消息Bean jboss.xmlHelloEjbBeanhelloEjb/remote72 测试该消息驱动测试该消息驱动Bean,新建测试类,新建测试类TestMDB.java8.3.4 开发消息Beanpublic static void main(String args) QueueConnection conn= null;QueueSession session= null;Properties props= new Properties();props.setProperty(java.naming.factory.initial, org.jnp.interfaces.NamingContextFactory);props.setProperty(java.naming.provider.url, localhost:1099);props.setProperty(java.naming.factory.url.pkgs, org.jboss.naming:org.jnp.interfaces);try InitialContext ctx= new InitialContext(props);QueueConnectionFactory factory=(QueueConnectionFactory)ctx.lookup(ConnectionFactory);conn=factory.createQueueConnection();session =conn.createQueueSession(false,QueueSession.AUTO_ACKNOWLEDGE);Destination destination=(Queue)ctx.lookup(queue/myQueue);MessageProducer producer=session.createProducer(destination);TextMessage msg=session.createTextMessage(这是我的第一个这是我的第一个MessageDrivenBean!);producer.send(msg); catch (Exception e) / TODO Auto-generated catch blocke.printStackTrace();finallytry session.close();conn.close(); catch (JMSException e)e.printStackTrace();73 运行结果:运行结果: 下面我们传递一下对象,新建一个对象下面我们传递一下对象,新建一个对象User.java,该对,该对象要实现象要实现Serializable接口。接口。8.3.4 开发消息Bean74User.java代码:代码:8.3.4 开发消息Beanpublic class User implements Serializable private String name;/姓名姓名private String address;/地址地址public String getName() return name;public void setName(String name) this.name = name;public String getAddress() return address;public void setAddress(String address) this.address = address;75修改修改HelloMDB.java8.3.4 开发消息Beanpublic class HelloMDB implements MessageListener public void onMessage(Message msg) try if (msg instanceof TextMessage) TextMessage tmsg = (TextMessage) msg;String content = tmsg.getText();System.out.println(content); else if(msg instanceof ObjectMessage)ObjectMessage omsg=(ObjectMessage)msg;User me=(User)omsg.getObject();String content=Name:+me.getName()+ |Address:+me.getAddress();System.out.println(content); catch (Exception e) e.printStackTrace();76 新建测试类新建测试类QueueTestObject.java8.3.4 开发消息Beanpublic static void main(String args) / TODO Auto-generated method stubQueueConnection conn= null;QueueSession session= null;try InitialContext ctx= new InitialContext();QueueConnectionFactory factory=(QueueConnectionFactory)ctx.lookup(ConnectionFactory);conn=factory.createQueueConnection();session =conn.createQueueSession(false,QueueSession.AUTO_ACKNOWLEDGE);Destination destination=(Queue)ctx.lookup(queue/myQueue);MessageProducer producer=session.createProducer(destination);User me = new User();me.setName(刘鹍刘鹍);me.setAddress(济南大学信息学院济南大学信息学院);producer.send(session.createObjectMessage(me); catch (Exception e) e.printStackTrace();finallytry session.close();conn.close(); catch (JMSException e)e.printStackTrace();778.3.4 开发消息Bean 下面我们来看一个下面我们来看一个topic的例子:的例子: 新建一个新建一个HelloMDBTopicBean.java,类型选择,类型选择Topic788.3.4 开发消息Bean HelloMDBTopicBean.java代码如下代码如下MessageDriven(mappedName = jms/HelloMDBTopicBean, activationConfig = ActivationConfigProperty(propertyName = acknowledgeMode, propertyValue = Auto-acknowledge),ActivationConfigProperty(propertyName = destinationType, propertyValue = javax.jms.Topic),ActivationConfigProperty(propertyName = subscriptionDurability, propertyValue = Durable),ActivationConfigProperty(propertyName = clientId, propertyValue = HelloMDBTopicBean),ActivationConfigProperty(propertyName = subscriptionName, propertyValue = HelloMDBTopicBean),ActivationConfigProperty(propertyName=destination,propertyValue=topic/myTopic)public class HelloMDBTopicBean implements Me
展开阅读全文