Spring+EJB-程序员宅基地

技术标签: AOP  iBATIS  EJB  Spring  Bean  

近日闲来无事,结合平时项目开发使用EJB2.x过程中带来的种种不便,决定结合Spring深入总结和研究下EJB开发和调用方面技术,主要包括三个方面:

 

1、事务控制

在Struts2+EJB2+Spring2+Ibatis的技术架构中,有三个地方可以进行事务控制

1)通过EJB2进行全局事务控制,EJB的事务控制分为两种:容器管理事务和Bean管理事务

使用EJB容器管理事务默认启用的是JTA事务,且是基于EJB方法的事务控制,要求在EJB方法包含完成一个业务且需要进行事务控制的各种操作,下边给出一个完整实例。

示例1(将事务完全交由ejb容器进行管理):

Spring的applicationContext.xml文件配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">

	<!-- 配置远程JNDI数据源-->
	<bean id="jndiDataSource" class="org.springframework.jndi.JndiObjectFactoryBean" scope="singleton">
		<property name="jndiName" value="xpDS" />
		<property name="jndiEnvironment">
			<props>
				<prop key="java.naming.factory.initial">weblogic.jndi.WLInitialContextFactory</prop>
				<prop key="java.naming.provider.url">t3://127.0.0.1:7001</prop>
				<prop key="java.naming.security.principal">weblogic</prop>
				<prop key="java.naming.security.credentials">weblogic</prop>
			</props>
		</property>
	</bean>
                <!-- ibatis sqlMapClient -->
	<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
		<property name="configLocation" value="classpath:sql-map-config.xml"/>
		<property name="dataSource" ref="jndiDataSource"/>
	</bean>
                <!-- 引入bo配置文件 -->
	<import resource="classpath:/config/dmtab.xml" />
</beans>

 

 

在Spring的applicationContext.xml文件中未进行任何关于事务管理方面的配置

 

EJB方法代码:

public class HelloBean implements javax.ejb.SessionBean {

...

                public String saveDM_DWLX(DM_DWLX param) {
		DM_DWLX temp = new DM_DWLX();
		temp.setDWLX_DM("89");
		temp.setDWLX_MC("政府机关");
		boDM_DWLX.insertDM_DWLX(temp);//保证能够成功插入数据库
		boDM_DWLX.insertDM_DWLX(param);//模拟插入失败情况
		return null;
	}

...

}

 注意:这里的两次插入操作都是在ejb方法中进行的,如果将这两次插入操作移植到boDM_DWLX.insertDM_DWLX(DM_DWLX param)方法中完成,那么事务就不能正常回滚了。因此,通过ejb控制事务时,ejb方法就变成了业务方法,封装了一个业务对应的各种操作,和项目技术架构中使用ejb只作为facade和实现分布式的应用相违背,而且,每当业务发生变化都需要修改EJB,为系统修改造成极大的不方便。

 

ejb-jar.xml文件配置:

<?xml version="1.0" encoding="UTF-8"?>

<ejb-jar id="ejb-jar_1" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd" version="2.1">

   <description</description>
   <display-name>EJBTest</display-name>

   <enterprise-beans>      
      <!-- Session Beans -->
      <session id="Session_Hello">
         <description><![CDATA[An EJB named Hello]]></description>
         <display-name>Hello</display-name>

         <ejb-name>Hello</ejb-name>

         <home>net.xp.service.ejb.HelloHome</home>
         <remote>net.xp.service.ejb.Hello</remote>
         <local-home>net.xp.service.ejb.HelloLocalHome</local-home>
         <local>net.xp.service.ejb.HelloLocal</local>
         <ejb-class>net.xp.service.ejb.HelloBean</ejb-class>
         <session-type>Stateless</session-type>
         <transaction-type>Container</transaction-type><!--注意:此处选择的是容器管理事务-->

      </session>
   </enterprise-beans>
   <container-transaction><!--容器事务属性配置(必须的,否则事务将无法控制)-->
      <description></description>
      <method>
        <description></description>
        <ejb-name>Hello</ejb-name>
        <method-name>*</method-name>
      </method>
      <trans-attribute>Required</trans-attribute>
   </container-transaction>
   ...

</ejb-jar>

 

客户端测试代码:

public static void main(String[] args) throws Exception {
		Properties p = new Properties();
		p.put("java.naming.factory.initial", "weblogic.jndi.WLInitialContextFactory");
		p.put("java.naming.provider.url","t3://127.0.0.1:7001");
		InitialContext ctx = new InitialContext(p);
		Object obj = ctx.lookup("Hello");
		HelloHome home = (HelloHome)PortableRemoteObject.narrow(obj, HelloHome.class);
		Hello hello = home.create();
		
		DM_DWLX model = new DM_DWLX();
		model.setDWLX_DM("AAa");//模拟字段长度过长异常
		model.setDWLX_MC("AA");
		hello.saveDM_DWLX(model);
}

 

测试结果:

在ejb方法saveDM_DWLX中,第一次插入操作成功,但第二次插入操作失败情况下,事务成功回滚

 

2)通过Spring2的声明式事务在业务层进行事务控制

Spring提供了两种事务管理方式,即编程式事务和声明式事务,这里主要记录使用声明式事务的配置

 

Spring声明式事务配置代码:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">

	<!-- 配置远程JNDI数据源-->
	<bean id="jndiDataSource" class="org.springframework.jndi.JndiObjectFactoryBean" scope="singleton">
		<property name="jndiName" value="ds" />
		<property name="jndiEnvironment">
			<props>
				<prop key="java.naming.factory.initial">weblogic.jndi.WLInitialContextFactory</prop>
				<prop key="java.naming.provider.url">t3://127.0.0.1:7001</prop>
				<prop key="java.naming.security.principal">weblogic</prop>
				<prop key="java.naming.security.credentials">weblogic</prop>
			</props>
		</property>
	</bean>
	 
	<!-- ibatis sqlMapClient -->
	<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
		<property name="configLocation" value="classpath:sql-map-config.xml"/>
		<property name="dataSource" ref="jndiDataSource"/>
	</bean>
	<!-- 事务管理器 -->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="jndiDataSource"/>
	</bean>
                <!--jta事务管理器,需要进行全局事务时配置,使用jta事务,要求上面的jndi datasource配置成XA DataSource
                <bean id="transactionManager" class="org.springframework.transaction.jta.WebLogicJtaTransactionManager">
	</bean>
	
	-->
                <!--aop配置,这里主要设置对bo包下的类和业务方法进行事务控制-->
	<aop:config>
		<aop:pointcut id="defaultServiceOperation" expression="execution(* net.xp.service.bo..*.*(..))"/>
		<aop:advisor pointcut-ref="defaultServiceOperation" advice-ref="defaultTxAdvice"/>
	</aop:config>
    <!--事务通知,针对不同方法配置事务属性-->	
    <tx:advice id="defaultTxAdvice" transaction-manager="transactionManager">-->
	<!-- <tx:advice id="defaultTxAdvice">
        <tx:attributes>
            <tx:method name="get*" read-only="true" rollback-for="Exception"/>
            <tx:method name="select*" read-only="true" rollback-for="Exception"/>
            <tx:method name="insert*" propagation="REQUIRED" rollback-for="Exception"/>
            <tx:method name="delete*" propagation="REQUIRED" rollback-for="Exception"/>
            <tx:method name="save*" propagation="REQUIRED" rollback-for="Exception"/>
            <tx:method name="update*" propagation="REQUIRED" rollback-for="Exception"/>
            <tx:method name="make*" propagation="REQUIRED" rollback-for="Exception"/>
        </tx:attributes>
    </tx:advice>
	
	
	<!-- 引入bo配置文件 -->
	<import resource="classpath:/config/dmtab.xml" />
</beans>

 

使用该配置,事务将在bo层进行控制,符合在业务层进行事务控制的要求,且配置和应用简单,推荐使用该方案进行项目中的事务控制

 

3)通过IBatis对DAO层的事务进行控制

 

2、基于Spring的EJB开发

虽然Spring提供了很多帮助实现EJB的类,但实现起来那叫一个麻烦,引用Spring官方文档翻译后中的一段文字:

 

“与不使用Spring方式的EJB客户端相比,Spring的EJB客户端有一个额外的好处。通常如果要想能随意的在本地和远程EJB调用之间切换EJB客户端代码,是会产生问题的。这是因为远程接口的方法需要声明他们抛出的RemoteException方法,然后客户端代码必须处理这种异常,但是本地接口的方法却不需要这样。如果要把针对本地EJB的代码改为访问远程EJB,就需要修改客户端代码,增加处理远程异常的代码,反之要么保留这些用不上的远程异常处理代码要么就需要进行修改以去除这些异常处理代码。使用Spring的远程EJB代理,我们就不再需要在业务方法接口和EJB的实现代码中声明要抛出的RemoteException,而是定义一个相似的远程接口,唯一不同就是它抛出的是RemoteException, 然后交给代理对象去动态的协调这两个接口。也就是说,客户端代码不再需要与 RemoteException这个checked exception打交道,实际上在EJB调用中被抛出的RemoteException都将被

以unchecked exception RemoteAccessException的方式重新抛出,它是RuntimeException的一个子类。这样目标服务就可以在本地EJB或远程EJB(甚至POJO)之间随意地切换,客户端不需要关心甚至根本不会觉察到这种切换。当然,这些都是可选的,没有什么阻止你在你的业务接口中声明RemoteExceptions异常。”

 

刚开始看到这段文字的确让我感到一种久违的兴奋,但经过编写代码实践却发现根本不是这么回事,实现本地EJB时客户端的确不需要捕获任何异常,但是实现远程EJB时客户端仍然要捕获RemoteException,在官方文档中只提供了本地EJB调用的部分代码,并没有提供远程EJB调用的代码,突然感觉有种被忽悠的感觉,在网上找了很多文章,只有问的,却没见到有回答的,真是让人不解~~

 

如果有哪位高人知道,可以给我回复,分享你的理解,在此先谢过

 

 

3、EJB本地接口和远程接口调用

 

 EJB远程接口调用就不说了,主要说说EJB本地接口调用吧,以前在项目中都使用的是远程接口调用,从来没有使用本地接口调用,想着简单,就随便写了点代码试验一把,不试不知道,一试吓一跳,居然碰了一鼻子的灰,一直报NameNotFoundException。最终将用于调用EJB本地接口的Servlet和ejb打包成EAR包部署后测试成功,一直不理解为什么将web和ejb分别以war和jar方式部署在WebLogic的同一个domain下就不行了呢,呵呵,还得等待好心的高人给予解答~~

推荐一篇相关的文章http://www.iteye.com/topic/270490 供大家参考

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/javaRwx/article/details/83813676

智能推荐

稀疏编码的数学基础与理论分析-程序员宅基地

文章浏览阅读290次,点赞8次,收藏10次。1.背景介绍稀疏编码是一种用于处理稀疏数据的编码技术,其主要应用于信息传输、存储和处理等领域。稀疏数据是指数据中大部分元素为零或近似于零的数据,例如文本、图像、音频、视频等。稀疏编码的核心思想是将稀疏数据表示为非零元素和它们对应的位置信息,从而减少存储空间和计算复杂度。稀疏编码的研究起源于1990年代,随着大数据时代的到来,稀疏编码技术的应用范围和影响力不断扩大。目前,稀疏编码已经成为计算...

EasyGBS国标流媒体服务器GB28181国标方案安装使用文档-程序员宅基地

文章浏览阅读217次。EasyGBS - GB28181 国标方案安装使用文档下载安装包下载,正式使用需商业授权, 功能一致在线演示在线API架构图EasySIPCMSSIP 中心信令服务, 单节点, 自带一个 Redis Server, 随 EasySIPCMS 自启动, 不需要手动运行EasySIPSMSSIP 流媒体服务, 根..._easygbs-windows-2.6.0-23042316使用文档

【Web】记录巅峰极客2023 BabyURL题目复现——Jackson原生链_原生jackson 反序列化链子-程序员宅基地

文章浏览阅读1.2k次,点赞27次,收藏7次。2023巅峰极客 BabyURL之前AliyunCTF Bypassit I这题考查了这样一条链子:其实就是Jackson的原生反序列化利用今天复现的这题也是大同小异,一起来整一下。_原生jackson 反序列化链子

一文搞懂SpringCloud,详解干货,做好笔记_spring cloud-程序员宅基地

文章浏览阅读734次,点赞9次,收藏7次。微服务架构简单的说就是将单体应用进一步拆分,拆分成更小的服务,每个服务都是一个可以独立运行的项目。这么多小服务,如何管理他们?(服务治理 注册中心[服务注册 发现 剔除])这么多小服务,他们之间如何通讯?这么多小服务,客户端怎么访问他们?(网关)这么多小服务,一旦出现问题了,应该如何自处理?(容错)这么多小服务,一旦出现问题了,应该如何排错?(链路追踪)对于上面的问题,是任何一个微服务设计者都不能绕过去的,因此大部分的微服务产品都针对每一个问题提供了相应的组件来解决它们。_spring cloud

Js实现图片点击切换与轮播-程序员宅基地

文章浏览阅读5.9k次,点赞6次,收藏20次。Js实现图片点击切换与轮播图片点击切换<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title></title> <script type="text/ja..._点击图片进行轮播图切换

tensorflow-gpu版本安装教程(过程详细)_tensorflow gpu版本安装-程序员宅基地

文章浏览阅读10w+次,点赞245次,收藏1.5k次。在开始安装前,如果你的电脑装过tensorflow,请先把他们卸载干净,包括依赖的包(tensorflow-estimator、tensorboard、tensorflow、keras-applications、keras-preprocessing),不然后续安装了tensorflow-gpu可能会出现找不到cuda的问题。cuda、cudnn。..._tensorflow gpu版本安装

随便推点

物联网时代 权限滥用漏洞的攻击及防御-程序员宅基地

文章浏览阅读243次。0x00 简介权限滥用漏洞一般归类于逻辑问题,是指服务端功能开放过多或权限限制不严格,导致攻击者可以通过直接或间接调用的方式达到攻击效果。随着物联网时代的到来,这种漏洞已经屡见不鲜,各种漏洞组合利用也是千奇百怪、五花八门,这里总结漏洞是为了更好地应对和预防,如有不妥之处还请业内人士多多指教。0x01 背景2014年4月,在比特币飞涨的时代某网站曾经..._使用物联网漏洞的使用者

Visual Odometry and Depth Calculation--Epipolar Geometry--Direct Method--PnP_normalized plane coordinates-程序员宅基地

文章浏览阅读786次。A. Epipolar geometry and triangulationThe epipolar geometry mainly adopts the feature point method, such as SIFT, SURF and ORB, etc. to obtain the feature points corresponding to two frames of images. As shown in Figure 1, let the first image be ​ and th_normalized plane coordinates

开放信息抽取(OIE)系统(三)-- 第二代开放信息抽取系统(人工规则, rule-based, 先抽取关系)_语义角色增强的关系抽取-程序员宅基地

文章浏览阅读708次,点赞2次,收藏3次。开放信息抽取(OIE)系统(三)-- 第二代开放信息抽取系统(人工规则, rule-based, 先关系再实体)一.第二代开放信息抽取系统背景​ 第一代开放信息抽取系统(Open Information Extraction, OIE, learning-based, 自学习, 先抽取实体)通常抽取大量冗余信息,为了消除这些冗余信息,诞生了第二代开放信息抽取系统。二.第二代开放信息抽取系统历史第二代开放信息抽取系统着眼于解决第一代系统的三大问题: 大量非信息性提取(即省略关键信息的提取)、_语义角色增强的关系抽取

10个顶尖响应式HTML5网页_html欢迎页面-程序员宅基地

文章浏览阅读1.1w次,点赞6次,收藏51次。快速完成网页设计,10个顶尖响应式HTML5网页模板助你一臂之力为了寻找一个优质的网页模板,网页设计师和开发者往往可能会花上大半天的时间。不过幸运的是,现在的网页设计师和开发人员已经开始共享HTML5,Bootstrap和CSS3中的免费网页模板资源。鉴于网站模板的灵活性和强大的功能,现在广大设计师和开发者对html5网站的实际需求日益增长。为了造福大众,Mockplus的小伙伴整理了2018年最..._html欢迎页面

计算机二级 考试科目,2018全国计算机等级考试调整,一、二级都增加了考试科目...-程序员宅基地

文章浏览阅读282次。原标题:2018全国计算机等级考试调整,一、二级都增加了考试科目全国计算机等级考试将于9月15-17日举行。在备考的最后冲刺阶段,小编为大家整理了今年新公布的全国计算机等级考试调整方案,希望对备考的小伙伴有所帮助,快随小编往下看吧!从2018年3月开始,全国计算机等级考试实施2018版考试大纲,并按新体系开考各个考试级别。具体调整内容如下:一、考试级别及科目1.一级新增“网络安全素质教育”科目(代..._计算机二级增报科目什么意思

conan简单使用_apt install conan-程序员宅基地

文章浏览阅读240次。conan简单使用。_apt install conan