




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
企业级应用开发liuku回忆:Struts2、Hibernate和Spring整合应用分层架构模式添加Spring开发能力添加Hibernate开发能力生成Hibernate所需的POJO类和映射文件映射文件在Spring配置文件中注册开发DAO层继承HibernateDaoSupport类super.getHibernateTemplate()Spring配置文件中注入sessionFactory开发Service层依赖注入实现WEB层Action类〔action类+spring配置文件+struts配置文件〕过滤器〔过滤器类+struts配置文件〕数据校验〔xml+命名+位置〕分页〔Pager类+DAO层+Action层+JSP〕第3讲基于EJB的企业级信息系统开发技术第7章
JSF应用第8章开发EJB3.0应用第9章JAVA持久API第7章
JSF应用第7章
JSF应用ServletAPI请求/响应模型收集HTML页信息servlet执行业务逻辑在HTML上显示结果HTMLServlet业务
逻辑第7章
JSF应用ServletAPI缺点维护问题:HTML嵌入servlet代码第7章
JSF应用JavaServerPages体系结构优于ServletAPI模型-视图-控制器(MVC)模式:表示层与业务逻辑层别离代码重用易于维护JSPJSPJSPServletJavaBeanEJBWeb效劳视图控制器模型第7章
JSF应用Struts2Struts是MVC设计模型的开放源代码Struts是通过一组Java类和JSP标签库实现的Struts有助于管理Web应用开发和维护,加快开发过程第7章
JSF应用Web应用开发截至目前,JavaWeb技术已被公认为具有:移植性扩展性灵活性可用于构建大型企业解决方案但不适于快速应用开发(RAD)缩短学习过程构建中小企业〔SMB〕解决方案第7章
JSF应用——学习要点1.JSF简介2.第一个JSF程序3.ManagedBean4.JSF标签第7章
JSF应用JSF简介7.1JSF简介JavaServerFaces:JavaServerFaces(JSF)技术是构建Web应用的框架JSF将Web应用框架开发推进了一步,以ServletAPI和JSP技术为根底功能性体系结构更理想,RAD,便于维护ServletAPIJSP/ServletAPIJSFStruts7.1JSF简介JSF增强了JSP/ServletAPI更多内置Java类更多标签库采用IBM工具提高操作能力ServletAPIJSP/ServletAPIStruts增加内置功能JSF7.1JSF简介7.1JSF简介JSF与StrutsJSF与Struts功能上有局部重叠JSF是一个更完整的模型开发团队对Struts和JSF有不同的设计目标IBM工具和中间件都支持JSF与Struts,但更侧重JSF数据库JavaBeanFacesServletEJB模型视图控制器JSPs7.1JSF简介JSF特点:可以通过一组标准的、可重用的效劳器端组件来创立用户界面。提供了一组JSP标签以访问这些组件。在表单重新显示时,透明的保存状态信息并重新填充表单。提供了实现自定义组件的框架。封装了事件处理和组建呈现,以便可以使用标准的JSF组件或自定义组件来支持除HTML之外的标记语言。让工具开发商可以开发针对标准WEB应用开发程序框架的IDE。7.1JSF简介JSF技术组成一组用于表示用户界面组件并管理其状态、处理事件和验证输入的JavaAPI,这些API支持国际化和可访问性。一个用于JSP页面中表示JSF组件的自定义标签库。补充:典型的JavaEE应用系统层次结构补充:JavaEE容器基于组件和平台独立的JavaEE使分层的企业分布式应用程序容易开发,因为各种应用的功能逻辑被封装在可重用的JavaEE组件中。另外JavaEE效劳器以容器的形式为所有JavaEE组件提供底层公共效劳,因此您不必再为这些底层公共效劳伤脑筋,而可以专注于解决应用系统的商业问题。容器〔Container〕是组件和支持组件功能的底层特定平台〔如数据库、分布式的网络环境及Java虚拟机等〕之间的接口。在运行Web组件、企业Bean组件或者JavaEE客户端组件之前,您必须将它们装配到一个JavaEE应用程序中,并部署它们到容器中。补充:JavaEE容器JavaEE的容器类型补充:JavaEE应用打包与部署JAR/WAR/EAR文件格式JAR是Java技术中的一种与平台无关的文件格式,它允许将许多文件组合成一个压缩文件。JAR文件格式以流行的
ZIP文件格式为根底。与
ZIP文件不同的是,JAR文件不仅用于压缩和发布,而且还用于部署和封装库、组件和插件程序,并可被像编译器和
JVM这样的工具直接使用。在
JAR中包含特殊的文件,如
manifests和部署描述符,用来指示工具如何处理特定的
JAR。补充:JavaEE应用打包与部署JAR/WAR/EAR文件格式WAR和EAR文件也是Java技术中的一种与平台无关的文件格式,也同样允许将许多文件组合成一个压缩文件。与JAR文件不同的是,WAR文件除了可以组合JSP文件和servlet类文件等web组件程序文件之外,还可以包含GIF文件、静态HTML文件等多种其它类型的文件。EAR文件那么主要用于由多个JavaEE应用模块所构成的一个完整应用程序的打包,其可以包含多个JAR文件和WAR文件。从打包粒度上讲,按由小至大的顺序排列,分别是JAR、WAR和EAR。补充:JavaEE应用打包与部署JAR、WAR和EAR文件的一般目录结构补充:JavaEE应用开发角色企业Bean开发者提供企业Bean的EJBJAR文件Web组件开发者的工作任务是提供WAR文件JavaEE应用程序客户端开发者也提供一个JAR文件应用程序组装者将从组件开发者获得的组件文件装配成一个JavaEE应用程序EAR文件。应用程序部署者和系统管理员配置和部署JavaEE应用程序,在程序运行时管理计算机和网络结构,并且监控运行时环境。包括设置事务控制、平安属性和指定数据库连接。补充:JavaEE应用效劳器补充:JavaEE应用效劳器SunGlassFish金蝶ApusicJBoss第8章开发EJB3.0应用8.1EJB3.0概述8.2会话Bean8.3消息驱动Bean8.1EJB3.0概述EnterpriseJavaBeans(EJB)是一种效劳器端的软件组件模型,是J2EE的根底和最重要的局部。如今开发电于商务平台已大量使用组件技术,这是因为组件技术提供了效劳器上的自治、企业级和分布式功能,并帮助开发者在不同颗粒度级别上定义和封装系统功能。8.1.1传统的EJB引入EnterpriseJavaBeans〔EJB〕是为了构建分布式组件。最初,该技术承诺可以解决CORBA的所有问题并降低其复杂性。作为J2EE的核心,EJB经历了几次较大的修订,并参加了许多特性,因而变得臃肿起来。随着EJB标准的相继发布,它还变得越来越复杂了。由于其复杂性和本身庞大的体系,传统的EJB技术被喻为一头笨重的大象。理解分布式EJB分布式特点:8.1.2EJB3.0简介Domorewithlesswork——JavaEE5的正式宣言在JavaEE5中采用了EJB3.0技术标准实现的EJB技术在这方面作出了改进的努力。EJB3.0减轻了开发人员进行底层开发的工作量,它取消或最小化了很多〔以前这些是必须实现〕回调方法的实现,并且降低了实体Bean及O/R映射模型的复杂性。
EJB3.0标准与JavaPersistence1.0的标准紧密结合,借鉴了轻量级企业数据对象的很多优点,将JavaPersistence1.0的标准运用到EJB3.0的EntityBean中,大大提高了EntityBean的开发效率,也使EntityBean更加通用、简洁、轻巧。32+18.1.3EJB3.0中的Bean类型EJB3.0中的组件分为三个主要类别:会话Bean消息驱动Bean实体Bean根据Bean处理状态、事务和持久性的方式这些类别还可以进一步细分。会话Bean可分为无状态会话Bean和有状态会话Bean实体Bean可分为CMP〔ContainerMangementPersitence〕方式的实体Bean和BMP(BeanMangementPersitence)方式的实体Bean。第8章开发EJB3.0应用8.1EJB3.0概述8.2会话Bean8.3消息驱动Bean8.2会话Bean8.2.1会话Bean的生命周期8.2.2无状态会话Bean8.2.3有状态会话Bean8.2.4会话Bean实例8.2.5将会话Bean发布为web效劳8.2.1会话Bean的生命周期如果是无状态无状态sessionbean,其生命周期如下:1〕当bean实例不存在时,容器调用bean类的newInstance()方法,开始bean的生命周期。2〕接着,容器调用bean的setSessionContext()方法,进而调用ejbCreate()方法。此时,bean就创立完毕,其方法可供调用了。3〕当容器不需要该bean实例的时候,容器调用bean的ejbRemove()方法,删除该实例。8.2.1会话Bean的生命周期而有状态sessionbean的生命周期那么复杂一些,因为涉及到钝化、激活和事务,其生命周期如下:1〕当客户调用create(args)时,容器调用newInstance()方法,剩下来的创立过程同无状态sessionbean。2〕有状态sessionbean的方法执行分为事务与非事务两种情况。3〕钝化与激活。bean长久没有被操作时,容器会决定该bean是否应该被钝化。钝化后一段时间仍然没有被操作,容器会将其从存储介质中删除。假设钝化后被调用,容器会激活该bean,让其重新载入内存。4〕当容器不需要该bean实例的时候,容器调用ejbRemove()方法,删除该实例。8.2.2无状态会话Bean无状态会话Bean是这样一种EJB,其效劳的业务过程只需要单个业务方法即可完成。由于它们不需维护客户多个方法调用间的会话状态,因此它是无状态的。在每次方法调用结束后,EJB容器可能会销毁无状态会话Bean实例,或者实例化新的实例,或者去除掉上次方法调用中的相关信息。当然,EJB容器还可能保存前一会话Bean实例,并且供其他所有客户使用,从而实现同一会话Bean实例的重用,至于具体的实现策略那么与具体EJB容器相关。8.2.3有状态会话Bean有状态会话Bean是这样一种EJB,即其效劳的业务过程能够延伸到多个方法请求或者事务中。为完成这种业务过程,有状态会话Bean需要为单个客户保存状态信息。如果在方法调用期间有状态会话Bean的状态发生改变,那么这种改变必须反映到同一客户的随后调用中。8.2.4会话Bean实例在EJB3.0标准中,写一个无状态会话Bean(StatelessSessionBean)只需要为一个普通的Java类加上@Stateless注释〔annotation〕就可以了。这个Bean可以实现某个业务接口〔BusinessInterface〕也可以不实现它。8.2.5将会话Bean发布为web效劳在EJB2.1就规定了无状态会话Bean〔StatelessSessionBean〕对WebService的支持,而在EJB3.0中运用注释〔annotation〕就可以轻松把一个无状态会话Bean发布为Web效劳。需要注意的是:只有无状态会话Bean可以发布成WebService;要暴露给Web效劳客户端的业务方法必须是public的;Bean类可以通过@WebService注释的endpointInterface元素实现一个ServiceEndpointInterface(SEI),但这不是必须的,如果没有这样一个endpointInterface,SEI也能被隐含定义。例子:开发一个会话bean例子:开发一个会话bean首先我们先定义一个接口:HelloEjb.java然后实现该接口:HelloEjbB.ujn.ejb.test;public
interfaceHelloEjb{ public
Stringhello(Stringname);}.ujn.ejb.test.impl;.ujn.ejb.test.HelloEjb;publicclassHelloEjbBeanimplementsHelloEjb{publicStringhello(Stringname){ //TODOAuto-generatedmethodstub
returnname+":helloEJB!";}}例子:开发一个会话bean刚刚的实现类只是一个普通的Java类,并不是EJB。下面我们给实现类参加两个注释@Stateless,@Remote,第一个注释定义这是一个无状态会话Bean,第二个注释指明这个无状态Bean的remote接口。.ujn.ejb.test.impl;.ujn.ejb.test.HelloEjb;@Stateless@Remote(HelloEjb.class)publicclassHelloEjbBeanimplementsHelloEjb{publicStringhello(Stringname){ //TODOAuto-generatedmethodstub
returnname+":helloEJB!";}}例子:开发一个会话bean打包发布到JBoss中去(copy到JBoss的\server\default\deploy目录下)。例子:开发一个会话bean我们写一个client来测试该EJB首先把JBoss的client目录下所有的jar包添加到该工程的classpath中然后新建一个测试类:TestClient.javapackagetest;//省略掉importpublicclassTestClient{publicstaticvoidmain(String[]args){ Propertiesprops=newProperties(); props.setProperty("java.naming.factory.initial","erfaces.NamingContextFactory"); props.setProperty("vider.url","localhost:1099"); InitialContextctx; try{ ctx=newInitialContext(props); HelloEjbhelloejb=(HelloEjb)ctx.lookup("HelloEjbBean/remote"); System.out.println(helloejb.hello("刘鹍")); }catch(NamingExceptione){ System.out.println(e.getMessage()); }}}例子:开发一个会话bean着重说一下JbossEJBJNDI名称默认的命名规那么:1〕如果EJB打包进后缀为*.ear的JavaEE发布文件,默认的JNDI路径名称是访问本地接口:EAR-访问远程接口:EAR-例:EJBHelloEjb打包进名为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是不带包名的,如.ujn.test.HelloEjbBean只需取HelloEjbBean。例子:开发一个会话bean运行结果:下面我们再看一个只存在Local接口的无状态SessionBean,新建HelloEjbLocalBean.java,同样实现HelloEjb这个接口。packag.ujn.ejb.test.impl;importjavax.ejb.Local;importjavax.ejb.Stateless;impor.ujn.ejb.test.HelloEjb;@Stateless@Local(HelloEjb.class)publicclassHelloEjbLocalBeanimplementsHelloEjb{ publicStringhello(Stringname){ returnname+":helloLocalStatelessEJB!"; }}例子:开发一个会话bean新建一个index.jsp<%@pagelanguage="java"import="java.util.*"pageEncoding="UTF-8"%><%@pageimport="javax.naming.*,.ujn.ejb.test.HelloEjb"%><!DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML4.01Transitional//EN"><html><body><% Propertiesprops=newProperties(); props.setProperty("java.naming.factory.initial","erfaces.NamingContextFactory"); props.setProperty("vider.url","localhost:1099"); props.setProperty("java.naming.factory.url.pkgs","org.jboss.naming"); InitialContextctx; try{ ctx=newInitialContext(props); HelloEjbhelloejb=(HelloEjb)ctx.lookup("HelloEjbLocalBean/local"); out.println(helloejb.hello("刘鹍")); }catch(NamingExceptione){ System.out.println(e.getMessage()); }%></body></html>例子:开发一个会话bean通过eclipse把该webproject也部署到JBoss中去通过浏览器访问该jsp页面,结果如下:例子:开发一个会话bean思考:Spring跟EJB的bean管理思想比照Springxml管理EJBJNDI管理得到一个bean的实例:
Spring这样得到:
EJB这样得到:…
ApplicationContextctx=new("src/applicationContext.xml"); Humanhuman=null; human=(Human)ctx.getBean("chinese"); human.speak();……
InitialContextctx=newInitialContext(props); HelloEjbhelloejb=(HelloEjb)ctx.lookup("HelloEjbLocalBean/local");…例子:开发一个会话bean下面我们来开发一个有状态的会话bean:我们用课本上做加法的例子〔适当修改〕首先新建接口Add.java,该接口必须实现Serializable接口,并实现该接口:packag.ujn.ejb.test;importjava.io.Serializable;publicinterfaceAddextendsSerializable{publicintdoAdd(inti,intj);publicintgetTotal();}packag.ujn.ejb.test.impl;importjavax.ejb.Remote;importjavax.ejb.Stateful;impor.ujn.ejb.test.Add;@Stateful@Remote(Add.class)publicclassAddBeanimplementsAdd{ privateinttotal=0; privateintaddresult=0; publicintdoAdd(inti,intj){ addresult=i+j; returnaddresult; } publicintgetTotal(){ total=total+addresult; returntotal; }}例子:开发一个会话bean新建一个client测试类TestStateful.java…publicstaticvoidmain(String[]args){//TODOAuto-generatedmethodstub Propertiesprops=newProperties(); props.setProperty("java.naming.factory.initial","erfaces.NamingContextFactory"); props.setProperty("vider.url","localhost:1099"); props.setProperty("java.naming.factory.url.pkgs","org.jboss.naming"); InitialContextctx; try{ ctx=newInitialContext(props); Addaddejb=(Add)ctx.lookup("AddBean/remote"); System.out.println("addresult:"+addejb.doAdd(1,2)); System.out.println("total:"+addejb.getTotal()); System.out.println(""); Addaddejb1=(Add)ctx.lookup("AddBean/remote"); System.out.println("addresult:"+addejb1.doAdd(3,4)); System.out.println("total:"+addejb1.getTotal()); }catch(NamingExceptione){ System.out.println(e.getMessage()); }}…例子:开发一个会话bean把EJB打包,部署到JBoss的\server\default\deploy目录下运行结果如下:企业级应用开发济南大学信息学院刘鹍liuku回忆:EJBJAR、WAR和EAREJB:32+1会话BeanSLSBSFSB会话Bean部署回忆:EJB会话bean调用InitialContextLookup与Spring比照Bean的管理方式SLSB、SFSB与Spring中对应…
InitialContextctx=newInitialContext(props); HelloEjbhelloejb=(HelloEjb)ctx.lookup("HelloEjbLocalBean/local");…回忆:EJBJNDIJavaNamingandDirectoryInterface为开发人员提供了查找和访问各种命名和目录效劳的通用、统一的方式。借助于JNDI提供的接口,能够通过名字定位用户、机器、网络、对象效劳等。NamingDNSDirectory简单的RDBMSJNDI的主要用途:使用JNDI获得对JAVA事务API中的UserTransaction接口的引用借助于JNDI,连接到资源工厂,比方JDBC、JMS等。在EJB组件中,借助于JNDI查找其他的EJB组件回忆:EJBJNDI编程:JNDI类Javax.naming.Context〔interface〕
其中INITIAL_CONTEXT_FACTORY
和PROVIDER_URLJavax.naming.Naming〔interface〕Javax.naming.InitialContext〔class〕
其中lookup〔〕、list〔〕、bind()、createSubcontext()、unbind〔〕
Java.util.Propertes〔class〕
其中setProperties〔〕和getProperties〔〕、list〔〕回忆:EJBJNDI编程:设置JNDI访问环境信息
在进行JNDI查找前,我们必须设置应用效劳器的上下文信息,主要是设置JNDI驱动的类名〔java.naming.factory.initial〕和命名效劳提供者的URL〔vider.url〕。java.naming.factory.initial或Context.INITIAL_CONTEXT_FACTORY:环境属性名,用于指定InitialContext工厂〔作者称它为JNDI驱动更容易理解〕,它类似于JDBC指定数据库驱动类。因为本例子连接的是JbossNS〔命名效劳的实现者〕,所以使用Jboss提供的驱动类:erfaces.NamingContextFvider.url或Context.PROVIDER_URL:环境属性名,包含提供命名效劳的主机地址和端口号。它类似于JDBC指定数据库的连接URL。连接到JbossNS的URL格式为:jnp://host:port,该URL的“jnp:〞局部是指使用的协议,JBoss使用的是基于Socket/RMI的协议。host为主机的地址,port为JNDI效劳的端口。除了host之外,其他局部都是可以不写的。回忆:EJBJNDI编程:编程过程补充:JNDI的所有配置信息可以保存在perties中。//设置初始化上下文的参数,主要是设置JNDI驱动的类名//Java.naming.factory.initial和提供命名效劳的的URL-Jvider.url,//Java.naming.factory.initial的值因提供JNDI效劳器的不同而不同,//Jvider.url的值包括提供命名效劳的主机地址和端口号。Propertiesp=newProperties();p.setProperty("Java.naming.factory.initial","erfaces.NamingContextFactory");p.setProperty("Jvider.url","localhost:1099");//初始化上下文环境,生成一个上下文实例InitialContextjndiContext=newInitialContext(p);ObjectlookupObject=jndiContext.lookup(“jndiname〞);回忆:EJB强调一下JbossEJBJNDI名称默认的命名规那么:1〕如果EJB打包进后缀为*.ear的JavaEE发布文件,默认的JNDI路径名称是访问本地接口:EAR-访问远程接口:EAR-例:EJBHelloEjb打包进名为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是不带包名的,如.ujn.test.HelloEjbBean只需取HelloEjbBean。第8章开发EJB3.0应用8.1EJB3.0概述8.2会话Bean8.3消息驱动Bean8.3消息驱动Bean8.3.1为什么要使用消息8.3.2Java消息效劳8.3.3集成JMS和EJB8.3.4开发消息Bean8.3.1为什么要使用消息当效劳器需要消耗较长的时间〔几小时或着有时甚至是几天〕来对这些请求作出响应。客户端程序〔应用〕要与效劳器连接并消耗如此长的时间来等待结果,这是毫无意义的。因此通信应该是异步发生的。动机:异步松耦合可靠性播送面向消息8.3.1为什么要使用消息消息系统的运行机制:一旦请求被提交,它就被放置在队列中,同时客户端与效劳器断开连接。然后效劳器从指定的队列中选出请求进行处理,并将处理得到的消息放置在另一个消息队列里。最后,客户端程序从这个队列中选出处理结果,获得响应。8.3.2Java消息效劳Java消息效劳〔JavaMessageService,JMS〕是一个JavaAPI,它定义了消息的客户程序如何以一种标准化的形式与底层的消息效劳提供者交互。JMS提供了一种接口,底层消息效劳提供者通过该接口向客户程序提供JMS消息效劳。JMS提供了点对点消息模式〔Point-to-Point〕和发布-订阅消息模式〔Publish-Subscribe〕。
8.3.2Java消息效劳消息处理的类型:发布/订阅点对多注册者注册到一定的Topic,发布者将消息分发到订阅者点对点通过消息队列实现Producer1Producer2TopicConsumer1Consumer2Producer1Producer2QueueConsumer18.3.3集成JMS和EJB会话Bean可以发送JMS消息并同步接收JMS消息,但不是异步方式。为防止占用效劳器资源,可能希望在效劳器端组件中使用异步接收。要异步接收消息,就使用消息驱动型Bean。异步接收8.3.4开发消息Bean消息驱动Bean的业务接口已经被定义,对于使用JMS来说那就是MessageListener接口,这个接口定义了OnMessage方法。EJB2.0:强制要求必须实现MessageDrivenBean接口。EJB3.0:可以实现也可以不实现,但实现类必须使用MessageDriven注释。EJB3.0中开发消息驱动Bean:实现MessageListener接口,实现OnMessage方法。使用MessageDriven注释。8.3.4开发消息Bean8.3.4开发消息Bean开发一个消息驱动Bean新建一个EJBProject新建一个MDB类,实现MessageListener接口,类型选择Queue〔Point-to-Point〕8.3.4开发消息Bean完成HelloMDB.java的代码8.3.4开发消息Bean……@MessageDriven(activationConfig={ @ActivationConfigProperty(propertyName="acknowledgeMode",propertyValue="Auto-acknowledge"), @ActivationConfigProperty(propertyName="destinationType",propertyValue="javax.jms.Queue"), @ActivationConfigProperty(propertyName="destination",propertyValue="queue/myQueue")
})publicclassHelloMDBimplementsMessageListener{ publicvoidonMessage(Messagemsg){
try{ if(msginstanceofTextMessage){ TextMessagetmsg=(TextMessage)msg; Stringcontent=tmsg.getText(); System.out.println(content); } }catch(Exceptione){ e.printStackTrace(); } }}修改jbossmq-destinations-service.xml〔该文件在jboss安装目录\server\default\deploy\jms下〕打包,发布该消息驱动bean8.3.4开发消息Bean<mbeancode="org.jboss.mq.server.jmx.Queue" name="jboss.mq.destination:service=Queue,name=myQueue"><dependsoptional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends></mbean>测试该消息驱动Bean,新建测试类TestMDB.java8.3.4开发消息Beanpublicstaticvoidmain(String[]args){QueueConnectionconn=null;QueueSessionsession=null;Propertiesprops=newProperties();props.setProperty("java.naming.factory.initial","erfaces.NamingContextFactory");props.setProperty("vider.url","localhost:1099");props.setProperty("java.naming.factory.url.pkgs","org.jboss.naming:erfaces");try{InitialContextctx=newInitialContext(props);QueueConnectionFactoryfactory=(QueueConnectionFactory)ctx.lookup("ConnectionFactory");conn=factory.createQueueConnection();session=conn.createQueueSession(false,QueueSession.AUTO_ACKNOWLEDGE);Destinationdestination=(Queue)ctx.lookup("queue/myQueue");MessageProducerproducer=session.createProducer(destination);TextMessagemsg=session.createTextMessage("这是我的第一个MessageDrivenBean!");producer.send(msg);}catch(Exceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}finally{try{session.close();conn.close();}catch(JMSExceptione){e.printStackTrace();}}}运行结果:8.3.4开发消息Bean8.3.4开发消息Bean注意:设置Queue可以不在jbossmq-destinations-service.xml文件中,也可以放在自己的EJB中,方法如下:在META-INF下新建test-service.xml<?xmlversion="1.0"encoding="UTF-8"?><server><mbeancode="org.jboss.mq.server.jmx.Queue"name="jboss.mq.destination:service=Queue,name=myQueue"><attributename="JNDJName">queue/myQueue</attribute><dependsoptional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends></mbean></server>8.3.4开发消息Bean补充:META-INF中的配置文件ejb-jar.xml配置EJB的mappedName,默认通过注释指定。*-service.xml配置消息到达的目标地址。jboss.xml为EJB指定JNDI名称,默认JBoss会自动生成JNDI名称。8.3.4开发消息Beanejb-jar.xml例子:8.3.4开发消息Bean*-service.xml<?xmlversion="1.0"encoding="UTF-8"?><server><mbeancode="org.jboss.mq.server.jmx.Queue"name="jboss.mq.destination:service=Queue,name=myQueue"><attributename="JNDJName">queue/myQueue</attribute><dependsoptional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends></mbean></server>8.3.4开发消息Beanjboss.xml下面我们传递一下对象,新建一个对象User.java,该对象要实现Serializable接口。8.3.4开发消息BeanUser.java代码:8.3.4开发消息BeanpublicclassUserimplementsSerializable{privateStringname;//姓名privateStringaddress;//地址publicStringgetName(){returnname;}publicvoidsetName(Stringname){=name;}publicStringgetAddress(){returnaddress;}publicvoidsetAddress(Stringaddress){this.address=address;}}修改HelloMDB.java8.3.4开发消息Bean……publicclassHelloMDBimplementsMessageListener{ publicvoidonMessage(Messagemsg){ try{ if(msginstanceofTextMessage){ TextMessagetmsg=(TextMessage)msg; Stringcontent=tmsg.getText(); System.out.println(content); }elseif(msginstanceofObjectMessage){ ObjectMessageomsg=(ObjectMessage)msg; Userme=(User)omsg.getObject(); Stringcontent="Name:"+me.getName()+"||Address:"+me.getAddress(); System.out.println(content); } }catch(Exceptione){ e.printStackTrace(); } }}新建测试类QueueTestObject.java8.3.4开发消息Beanpublicstaticvoidmain(String[]args){//TODOAuto-generatedmethodstubQueueConnectionconn=null;QueueSessionsession=null;try{ InitialContextctx=newInitialContext(); QueueConnectionFactory factory=(QueueConnectionFactory)ctx.lookup("ConnectionFactory"); conn=factory.createQueueConnection(); session=conn.createQueueSession(false,QueueSession.AUTO_ACKNOWLEDGE); Destinationdestination=(Queue)ctx.lookup("queue/myQueue"); MessageProducerproducer=session.createProducer(destination);
Userme=newUser(); me.setName("刘鹍"); me.setAddress("济南大学信息学院"); producer.send(session.createObjectMessage(me));}catch(Exceptione){ e.printStackTrace();}finally{ try{ session.close(); conn.close(); }catch(JMSExceptione){ e.printStackTrace(); }}}8.3.4开发消息Bean下面我们来看一个topic的例子:新建一个HelloMDBTopicBean.java,类型选择Topic8.3.4开发消息BeanHelloMDBTopicBean.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")})publicclassHelloMDBTopicBeanimplementsMessageListener{ publicvoidonMessage(Messagemessage){
try{ TextMessagetopicmsg=(TextMessage)message; Stringcontent=topicmsg.getText(); System.out.println(this.getClass().getName()+":"+content); }catch(Exceptione){ e.printStackTrace(); } }}8.3.4开发消息Bean在META-INF的test-service.xml中配置该消息到达的目标地址打包,部署<mbeancode="org.jboss.mq.server.jmx.Topic"name="jboss.mq.destination:service=Topic,name=myTopic"> <attributename="JNDIName">topic/myTopic</attribute> <dependsoptional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager </depends></mbean>8.3.4开发消息Bean测试类:TestMDBTopic.javapublicstaticvoidmain(String[]args){TopicConnectionconn=null;TopicSessionsession=null;try{ InitialContextctx=newInitialContext(); TopicConnectionFactoryfactory=(TopicConnectionFactory)ctx.lookup("TopicConnectionFactory"); conn=factory.createTopicConnection(); session=conn.createTopicSession(false,TopicSession.AUTO_ACKNOWLEDGE); Destinationdestination=(Topic)ctx.lookup("topic/myTopic"); MessageProducerproducer=session.createProducer(destination); TextMessagemsg=session.createTextMessage("你好TopicMDB!"); producer.send(msg);}catch(Exceptione){System.out.println(e.getMessage());}finally{ try{ session.close(); conn.close(); }catch(JMSExceptione){ e.printStackTrace(); }}}8.3.4开发消息Bean运行结果:8.3.4开发消息Bean企业级应用开发济南大学信息学院刘鹍liuku回忆:消息驱动Bean消息驱动Bean异步接收第9章JAVA持久API学习要点:实体Bean实体类实体的生命周期事务处理直接操纵实体数据并发访问和锁查找实体和QueryAPI命名查询EJB-QL语言第9章JAVA持久API9.1Java持久化API概述9.2数据库同步9.1Java持久化API概述9.1.1实体Bean9.1.2实体类9.1.3实体的生命周期9.1.4事务处理9.1.1实体Bean实体Bean有着一组属性并且每个属性与数据库表中的每个字段一一对应。公开get和set方法供外界访问。每一个属性对应数据库表中的一个字段,这样一个Bean实例就对应了表中的一条记录。并不是固定的一个实例对应一条记录。9.1.1实体Bean保持实体Bean可以手工完成持久化操作可以让EJB容器完成持久化操作实体bean和会话bean的比较实体bean不允许保存每个客户端的信息。会话bean允许保存客户端的状态信息。实体bean允许保存记录的,会话bean既可以保存客户端的信息又可以保存数据库记录的信息。会话bean也不能提供在相同或不同的EJB类调用间进行全局的事务控制。实体Bean的分类1〕CMP类型的实体Bean2〕BMP类型的实体Bean9.1.2实体类实体类用于表示数据库中的表,实体类的编写主要确定如下信息:该实体与数据库中的哪个表对应;实体类中的属性与表中的哪个字段对应;实体类中的哪个属性是主键。9.1.2实体类编写实体类的主要知识点声明该类为实体类:@Entity声明该实体类与哪个表对应:@Table(name="userinfo")声明该实体类与表中的哪个列对应,如:声明主键,如:@Column(name="userid",nullable=false)
privateStringuserid;
@Column(name="username",nullable=false)
privateStringusername;
@Column(name="userpass",nullable=false)
privateStringuserpass;
@Column(name="usertype",nullable=false)privatecharusertype;
@Id@GeneratedValue(strategy=GenerationType.AUTO)9.1.3实体的生命周期受管新建删除分离new()persist()persist()remove()终止PersistenceContextmerge()第9章JAVA持久API9.1Java持久化API概述9.2数据库同步9.2数据库同步9.2.1直接操纵实体数据9.2.3查找实体和QueryAPI9.2.4命名查询9.2.5EJB-QL语言9.2.1直接操纵实体数据实体数据RDBMS实体持久化提供者O/RMapping现有应用直接修改数据库9.2.2并发访问和锁借助于事务隔离总是能够保护对RDBMS数据的并发访问。正确使用事务,应用便不用考虑有关并发控制方面的设计问题。如果应用没有做任何特殊处理,那么实体将会受到容器管理事务的保护,并且事务能够使用到持久化提供者和EJB容器事务效劳提供的隔离级别。事务隔离级别要适宜Serializable——性能下降,死锁ReadUnCommitted——数据不一致,应用行为不正确ReadCommitted——不能防止不可重复读和幻影读RepeatableRead——不能防止幻影读9.2.2并发访问和锁JPA定义了用于处理并发访问实体的两个重要特征:使用version属性实现乐观锁写数据时探测是否存在写操作冲突与Subversion比照不能防止不可重复读和幻影读的发生显式读锁和写锁9.2.2并发访问和锁脏读表9-1
出现在事务T2中的脏读T1T2account=manager.find(Account.class,1234);//更新account.withdraw(100,000);manager.flush()//查找和读数据account=manager.find(Account.class,1234);System.out.printIn(account.balance);//触发回滚thrownewRuntimeException();9.2.2并发访问和锁不可重复读T1T2Account=manager.find(Account.class,1234);Account.withdraw(100,000);Queryquery=manager.createQuery(“SelectafromAccountaWHEREa.balance>1000〞);System.out.printIn(“Got〞+query.getResultList().size()+“records.〞)//…System.out.printIn(“Got〞+query.getResultList().size()+“records.〞)图9-3
出现在事务T2中的不可重复读9.2.3查找实体和QueryAPIfind()操作的方法签名。EntityManagerAPI的使用步骤:从EntityManager获得javax.persistence.Query实例。自定义Query实例。比方,设置查询参数、控制结果集的大小。执行查询。使用EJB-QL和SQL创立查询的EntityManager操作:/**通过主键进行查找*/public<T>Tfind(Class<T>entityClass,ObjectprimaryKey);/**创立执行EJBQL语句的Query*/publicQuerycreateQuery(StringejbqlString);/**创立执行原生SQL语句的Query*/publicQuerycreateNativeQuery(StringsqlString);9.2.3查找实体和QueryAPI从数据库中返回所有Account实体的简单EJB-QL查询实例。重载createNativeQuery()方法。将SQL结果集数据映射到实体,从而返回给客户。publicList<Account>listAccounts(){Queryquery=manager.createQuery("SELECTaFROMAccounta");returnquery.getResultList();}publicQuerycreateNativeQuery(StringsqlString,ClassresultClass);publicQuerycreateNativeQuery(StringsqlString,StringresultSetMapping);9.2.4命名查询可能需要在整个持久化单元中使用单个查询语句,或者需要为部署者或管理员提供变更查询语句的便利,这时我们可以使用静态查询〔StaticQuery〕,静态查询也被称之为命名查询〔NamedQuery〕。9.2.4命名查询从外部的命名查询字符串创立Query对象,需要使用EntityManager提供的如下操作。在调用createNamedQuery之前,开发者必须定义好相应的命名查询。比方,在如下给出的listAccounts()方法中使用了这一操作。/**创立命名查询〔EJBQL或原生SQL〕*/publicQuerycreateNamedQuery(Stringname);publicList<Account>listAccounts(){Queryquery=manager.createNamedQuery("findThem");returnquery.getResultList();}9.2.5EJB-QL语言EJB-QL用来在CMP类型的EJB中描述finders和select方法。设计这种语言的目的是严格地描绘内存对象的查询,而不是数据库的查询。但是EJB-QL的语法与SQL非常相似。它有三个根本语句:SELECT、FROM、WHERE。通过这几个语句可以实现各种各样的组合。9.2.5EJB-QL语言常用语法:当处理一个select方法时,返回类型(SELECT语句)可以不用是OBJECT(x)。可以为任意类型的任意值。例如如下:
SELECTOBJECT(variable)FROMabstractSchemaName[AS]variable[WHEREvaluecomparisonvalue]SELECT[DISTINCT]valueFROMabstractSchemaName[AS]variable[WHERE...]回忆:Hibernate开发步骤:导入JAR包+hibernate.cfg.xmlPOJO类映射文件:*.hbm.xml,需要在hibernate.cfg.xml中声明DAO层接口和实现类目录结构〔参考〕WEB-INF/classes/hibernate.cfg.xml*.model.pojo类+*
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 提升团队协作的Python试题及答案
- 计算机一级Photoshop学习分享试题及答案
- 理解Delphi编程的社区支持与贡献试题及答案
- 提升自信心的试题及答案建议
- 计算机二级Delphi模块试题及答案解析
- 财务细节中的逻辑考量试题及答案
- 轻松掌握22025年计算机二级试题及答案
- 2025年实际应用试题及答案分析
- 计算机二级MySQL课程评估试题及答案
- 2025年Msoffice备考心得试题及答案
- 火爆世界的DeepSeek(时政猜想)-2025年中考道德与法治时政热点专练 (解析版)
- 车险代理合同
- 2024年盐城工学院辅导员考试真题
- 全球农业经济的试题及答案
- 2025年高考历史三轮复习之宋元时期
- 高校实验室安全教育与培训措施
- 2025年安徽省C20教育联盟中考一模物理试题(原卷版+解析版)
- 小区违章装修培训
- 疫情防控消毒培训课件
- GB/T 45355-2025无压埋地排污、排水用聚乙烯(PE)管道系统
- 公司统计管理制度
评论
0/150
提交评论