下面案例使用的環境
-------------1.jboss 的安裝
http://www.jboss.org/jbossas/downloads
jboss 的啟動?? jboss/bin/run.bat?
停止服務? 使用個 ctrl+c 就可以了
什么是EJB???
會話bean
實體bean
消息驅動bean
//----遠程調用 EJB的過程
///EJB 容器對會話bean的管理方式
//----------------EJB中? 怎么樣使用其他 EJB
//---- EJB中的一些注解說明
--定義 本地和遠程 接口類
//開發的時候 需要先加入 jboss安裝路徑下 client 中的jar
開發好項目后, 選擇好文件后? 將項目打成 jar 放入到 jboss 安裝目錄下的
E:\jboss-5.0.0.GA\server\default\deploy
HelloWorld.java
HelloWorldLocal.java
Other.java
//遠程 和 本地 接口實現類?
HelloWorldBean.java
OtherBean.java
-->使用 Ant 編譯發布后 就可以 在jboss 后臺空中中查看 發布到 接口 (下面有介紹怎么查看)
客戶端 client 開發 訪問遠程接口的客戶端
客戶端 client 開發 訪問本地接口的客戶端
//注意? 注意 下面的 web項目 添加 對上面 ejb3.0 項目的引用? 否則 jsp頁面會報錯?
//編寫好后將香項目 打成 war的包 發布到? server\default\deploy下
////----------? ANT 的 使用
提高工作效率?? 幫助 我們編譯 打包? 發布運行? 卸載
在項目根目錄下 添加一個 build.xml
然后配置?
在? 中查看 jndi 名稱
//---jboss 默認生成的JNDI 名稱
myeclipse.10.1
jdk1.6.0_17
jboss-6.0.0.Final
JAXWS2.2.7-20120813
-------------1.jboss 的安裝
http://www.jboss.org/jbossas/downloads
-------------jboss
要配置jdk
JAVAHOME
CLASSPATH
端口 8080 1099
findstr不是內部命令 外部命令
%SystemRoot%\system32;%SystemRoot%;
環境配置
JBOSS_HOME=d:\JBOSS\jboss-4.2.2.GA
PATH=$PATH;%JBOSS_HOME%\bin;
jboss 的啟動?? jboss/bin/run.bat?
停止服務? 使用個 ctrl+c 就可以了
什么是EJB???
EJB (Enterprise JavaBean)是一個標準的分布式業應用服務器端組件.
EJB實際上是用于編寫業務層代碼.他為我們提供了很多服務,如事務管理,多用戶安全,持久化.分布式.
EJB 主要使用于大型企業,因為一般大型企業都有多個信息系統,而這些系統中的信息都是相互關聯的,因此為了避免業務功能重復開發,所以我們將一些業務給獨立出來,讓這多個信息系統共享一個業務中心.這樣我們開發應用就需要具備分布式的能力.因此我們采用EJB
如果不需要開發分布式應用完全可以采用spring來開發.
優點: 使用EJB架構編寫的應用
是可以伸的 事務性,多用戶安全,的.
EJB3.0 運行的環境
jdk5.0 以上
jboss 4.2 以上 :javaEE應用服務器所占據的市場份額第一.
weblogic 10以上: 在商業市場上占有率第一
sun applicatioin server 9.0 以上
oralce application server 10 以上:如果數據庫是oracle
apusic引用服務器 中國開發的.
Glassfish:開源的javaEE服務器, 對JavaEE規范支持的非常好, 運行性能比較高,發展實際較短.
會話bean
負責和客戶端的交互,是編寫業務邏輯的地方,在會話bean中可以通過jdbc直接遭挫數據庫,但是大多數情況下都是過實體bean來完成對數據庫的額操作
1.無狀態會話bean
平常,我們使用最多的無狀態bean因為它的bean 的實例,可以供多個用戶使用,所以它的性能高,正因為一個bean實例可以被多個用戶使用,那么前一個用戶設置的值有可能被后一個用戶所修改,所以它無法正確保存某個用戶設置的值,因為是無狀態的.
2.有轉臺會話bean
有狀態bean平常使用的不多, 因為他的一個bean 實例只能供一個用戶使用個,所以要為每一個用戶創建一個實例,所以性能開銷比較大,正因為他的實例,只被一個用戶使用,那么用戶設置是不會背其他用戶所 修改,所以可以正確保存用戶設置過的值,因此是有狀態的.
實體bean
它實際上屬于java持久規范 簡稱JPA里的技術,JPA的出現主要是為了簡化現有的持久化開發工作和整合ORM 技術.借宿現在在Hibernate toplink 等 ORM框架各自為營的局面,用于實現O/R映射,負責將數據庫中的表記錄映射為內存中的Entity對象,
消息驅動bean
它是專門用于一部處理java 消息的組件,具有處理大量并發消息的能力,它基于JMS消息,只能接收客戶端發送的JMS消息然后處理。MDB實際上是一個異步的無狀態Session Bean,客戶端調用MDB后無需等待,立刻返回,MDB將異步處理客戶請求。這適合于需要異步處理請求的場合,比如訂單處理
//----遠程調用 EJB的過程
首先 客戶端需要與EBJ建立起 socket 通信;
在通信管道上他們之間需要來回發送IIOP協議信息; (Internet Inter-ORB Protocol(互聯網內部對象請求代理協議),它是一個用于CORBA 2.0及兼容平臺上的協議)實現互操作性的協議,由不同語言編寫的分布式程序在因特網中可以實現彼此的交流溝通,公用對象請求代理程序結構(Common Object Request Broker Architecture,CORBA)中至關重要的一個部分
因為數據要在在網絡上進行傳輸, 所以存放數據的 java對象必須要進行序列化
在這個過程中我們看到 ,網絡通信的開銷, 協議解析的開銷 ,對象序列化的開銷.
A: (遠程接口 )
客戶端 和 EJB 容器不在一個 同一機器上
1.可以看出 EJB容器是 一個 重量級容器 所以 初始化 需要比較長的時間
2.EJB 是分布式技術,他允許客戶端 與 EJB應用不在同一機器上,所以 這樣開銷也是必然的
B .(本地接口 ) 不注解的時候 默認為 本地接口
客戶端 和 EJB 容器在一個 同一機器上 這樣 是不是就可以 減少了 網絡 通信 協議解析的開銷呢 ??
1.是滴,會減少 , 此時 他們 就跑到了 JVM 內存中了,他們之間完全可以通過內存進行交互. 所以此時 就需要 "本地接口了".
客戶端 和 EJB應用 發布在同一個jboss 我們就認為 在同一個JVM 內
///EJB 容器對會話bean的管理方式
1.無狀態 使用
@Stateless 用戶可以共享
EJB 容器會對 這個bean使用個實例池技術管理bean
實例池 和 數據源技術 原理相同,
比如數據源里面的連接 沒有空閑時候, 必須等連接使用完后才能使用.
這個實例 只有當一個用戶使用完后,才能被其他用戶使用. 可以使用最少的實例數 來為用戶服務.
2.有狀態 使用 (購物車)
@Stateful 會為每個用戶創建單獨的一個bean實例
EJB 容器會對 這個bean 使用 激活(activation) 管理bean
//鈍化
如果用戶 在一定時間內沒有使用
這段時間 < 會話超時 設置的時間 ==> 系統會講 用戶的這個會話信息保存到 磁盤里面
//激活
如果用戶又開始訪問 < 會話超時 設置的時間 ==> 此時 會將磁盤上的會話信息(釋放內存等資源) 又被還原到 內存中 此時用戶又可以繼續訪問了
//超時
如果用戶又開始訪問 > 會話超時 設置的時間
//----------------EJB中? 怎么樣使用其他 EJB
第一種: 使用 查找的方式
InitialContext ctx=new InitialContext();
Other other=(Other)ctx.lookup("OtherBean/local");
第二種: 使用 注解的方式
@EJB
例如:
public class HelloWorldBean implements HelloWorld,HelloWorldLocal {
@EJB(beanName="OtherBean") Other other; // 如果這個接口 有多個 實現類 就出現錯 誤;此時就需要 beanName=就可以設置成需要的那個
public String sayHello(String name) {
return name+"說:你好,"+other.sayMe();
}
}
//---- EJB中的一些注解說明
1.指明為無狀態的會話bean
@Stateless
2.指明為有狀態的會話bean
@Stateful
3指明為遠程接口 @Remote(HelloWorld.class)
@Remote(HelloWorld.class) //如果發布在同一機器上 就優先使用本地接口 否則 使用 遠程接口
4.指明 本地接口
@Local(HelloWorldLocal.class)
5.修改 類的 EJB 名稱
@Stateless(name="xxx") 可以將這個類的EJB名稱 修改為xxx
6.使用其他EJB 類
@EJB Other1 other;
@EJB(beanName="OtherBean") Other other; // 如果這個接口 有多個 實現類 就出現錯誤;此時就需要 beanName=就可以設置成需要的那個
7.使用EJB自帶的服務
@Resource TimerService timerService; //使用 EJB 的定時服務
8.如果要使用 數據源
@Resource(mappedName="java:xxx") DataSource datasource; //mappedName 就是java類的 jndi名稱
--定義 本地和遠程 接口類
//開發的時候 需要先加入 jboss安裝路徑下 client 中的jar
開發好項目后, 選擇好文件后? 將項目打成 jar 放入到 jboss 安裝目錄下的
E:\jboss-5.0.0.GA\server\default\deploy
HelloWorld.java
HelloWorldLocal.java
Other.java
package com.sh.ebj3;
//遠程接口
public interface HelloWorld {
public String sayHello(String name);
}
package com.sh.ebj3;
//本地接口
public interface HelloWorldLocal extends HelloWorld {
}
package com.sh.ebj3;
//其他bean
public interface Other {
public String sayMe();
}
//遠程 和 本地 接口實現類?
HelloWorldBean.java
package com.sh.ejb3.impl;
import javax.annotation.Resource;
import javax.ejb.EJB;
import javax.ejb.Local;
import javax.ejb.Remote;
import javax.ejb.Stateful;
import javax.ejb.TimerService;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import com.sh.ebj3.HelloWorld;
import com.sh.ebj3.HelloWorldLocal;
import com.sh.ebj3.Other;
//指明為無狀態的會話bean @Stateless
@Stateful
//指明為遠程接口 @Remote(HelloWorld.class)
@Remote(HelloWorld.class) //如果發布在同一機器上 就優先使用本地接口 否則 使用 遠程接口
//指明 本地接口
@Local(HelloWorldLocal.class)
public class HelloWorldBean implements HelloWorld,HelloWorldLocal {
@EJB(beanName="OtherBean") Other other; // 如果這個接口 有多個 實現類 就出現錯誤;此時就需要 beanName=就可以設置成需要的那個
//如果要使用 EJB里面的 定時服務 此時只能使用 不能使用 @EJB 服務
@Resource TimerService timerService; //使用 EJB 的定時服務
//如果要使用 數據源 數據庫可以減少數據庫連接的創建數量 ,因為 數據庫連接對象的創建是很耗性能的 .
@Resource(mappedName="java:xxx") DataSource datasource; //mappedName 就是java類的 jndi名稱
private static int times=1;
@Override
public String sayHello(String name) {
// TODO Auto-generated method stub
try {
times++;
InitialContext ctx=new InitialContext();
Other other=(Other)ctx.lookup("OtherBean/local");
System.out.println(times);
return name+"說:你好,"+other.sayMe();
} catch (NamingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
}
OtherBean.java
package com.sh.ejb3.impl;
import javax.ejb.Stateless;
import com.sh.ebj3.Other;
@Stateless//@Stateless(name="xxx") 可以將這個類的EJB名稱 修改為xxx
public class OtherBean implements Other {
@Override
public String sayMe() {
// TODO Auto-generated method stub
return "other";
}
}
-->使用 Ant 編譯發布后 就可以 在jboss 后臺空中中查看 發布到 接口 (下面有介紹怎么查看)
客戶端 client 開發 訪問遠程接口的客戶端
package com.sh.test;
import java.util.Properties;
import javax.naming.InitialContext;
import com.sh.ebj3.HelloWorld;
public class EJBClient {
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");*/
/*如果訪問的是sun公司的服務器
props.setProperty("java.naming.factory.initial", "com.sun.enterprice.naming.SeriaIInitContextFactory");
props.setProperty("java.naming.provider.url", "localhost:3700");
*/
try {
//不采用硬編碼 就可以直接 添加 一個jndi.properties 講上面的配置寫入進入
InitialContext ctx=new InitialContext();//InitialContext(props);
HelloWorld helloworld=(HelloWorld)ctx.lookup("HelloWorldBean/remote");
System.out.println(helloworld.sayHello("佛山"));
} catch (Exception e) {
e.printStackTrace();
}
}
}
客戶端 client 開發 訪問本地接口的客戶端
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ page import="javax.naming.*,com.sh.ebj3.*" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<%
try {
//不采用硬編碼 就可以直接 添加 一個jndi.properties
InitialContext ctx=new InitialContext();//InitialContext(props);
HelloWorldLocal helloworld=(HelloWorldLocal)ctx.lookup("HelloWorldBean/local");
out.println(helloworld.sayHello("佛山詠春派"));
} catch (Exception e) {
e.printStackTrace();
}
%>
<body>
This is my JSP page. <br>
</body>
</html>
//注意? 注意 下面的 web項目 添加 對上面 ejb3.0 項目的引用? 否則 jsp頁面會報錯?
//編寫好后將香項目 打成 war的包 發布到? server\default\deploy下
////----------? ANT 的 使用
提高工作效率?? 幫助 我們編譯 打包? 發布運行? 卸載
在項目根目錄下 添加一個 build.xml
然后配置?
<?xml version="1.0" encoding="UTF-8"?>
<!-- ======================================================================
2013-2-25 下午1:53:33
project
description
Bin
====================================================================== -->
<project name="HelloWorld" basedir=".">
<description>
description
</description>
<!-- 設置項目原目錄 -->
<property name="src.dir" value="${basedir}\src" />
<!-- 獲取環境變量 -->
<property environment="env"/>
<property name="jboss.home" value="${env.JBOSS_HOME}"/>
<property name="jboss.server.config" value="default"/>
<property name="build.dir" value="${basedir}\build"/>
<!-- 引入 jboss client 下的 所有jar -->
<path id="build.classpath">
<fileset dir="${jboss.home}\client">
<include name="*.jar"/>
</fileset>
<!-- 講編譯過后的路徑加入到 path中去 方便 接口和實現的引用 -->
<pathelement location="${build.dir}"/>
</path>
<target name="prepare" description="創建build目錄">
<delete dir="${build.dir}"/>
<mkdir dir="${build.dir}"/>
</target>
<!-- - - - - - - - - - - - - - - - - -
target: compile
- - - - - - - - - - - - - - - - - -->
<target name="compile" depends="prepare" description="編譯">
<javac srcdir="${src.dir}" destdir="${build.dir}" includeantruntime="false">
<classpath refid="build.classpath"/>
</javac>
</target>
<!-- =================================
target: ejbjar
================================= -->
<target name="ejbjar" depends="compile" description="創建EJB發布包">
<jar jarfile="${basedir}\${ant.project.name}.jar">
<fileset dir="${build.dir}">
<include name="**/*.class"/>
</fileset>
</jar>
</target>
<!-- =================================
target: deploy
================================= -->
<target name="deploy" depends="ejbjar" description="發布EJB">
<copy file="${basedir}\${ant.project.name}.jar" todir="${jboss.home}\server\${jboss.server.config}\deploy"/>
</target>
<!-- - - - - - - - - - - - - - - - - -
target: undeploy
- - - - - - - - - - - - - - - - - -->
<target name="undeploy" description="卸載EJB">
<delete file="${jboss.home}\server\${jboss.server.config}\deploy\${ant.project.name}.jar"/>
</target>
</project>
<!--//如果注意 編譯中的 includeantruntime="false" 的配置 否則 會報錯
如果 剛配置JBOSS_HOME 則需要重啟 IDE -->
在? 中查看 jndi 名稱
localhost:8080 --->JMX控制臺 --> service=JNDIView (jboss) -->list -->
Global JNDI Namespace
+- UserTransactionSessionFactory (proxy: $Proxy82 implements interface org.jboss.tm.usertx.interfaces.UserTransactionSessionFactory)
+- UUIDKeyGeneratorFactory (class: org.jboss.ejb.plugins.keygenerator.uuid.UUIDKeyGeneratorFactory)
//找到了
+- HelloWorldBean (class: org.jnp.interfaces.NamingContext)
| +- remote (class: Proxy for: com.sh.ebj3.HelloWorld)
| +- remote-com.sh.ebj3.HelloWorld (class: Proxy for: com.sh.ebj3.HelloWorld)
如果有問題 可以看 導入的jar 環境變量的設置
//---jboss 默認生成的JNDI 名稱
當EJB發布到jboss時候
默認的命名規則為
1.如果 EJB 作為模塊打包進后綴名我*.ear 的javaEE 企業應用文件,默認的全局JNDI 是
本地接口 EAR-FILE-BASE-NAME/EJB-CLASS-NAME/local
遠程接口 EAR-FILE-BASE-NAME/EJB-CLASS-NAME/remote
例如 講 HelloWorld 應用作為模塊打包進名為 aaaa.ear 的企業文件 那他的 遠程接口的JDNI的名稱就是 aaaa/HelloWorldBean/remote --HelloWroldBean 為HelloWorld 的實現類
2.如果講EJB應用打包成后綴為*.jar 的模塊文件,默認的全局JNDI名稱是
本地接口 : EJB-CLASS-NAME/local
遠程接口 : EJB-CLASS-NAME/remote
例如 講 HelloWorld 應用作為模塊打包進名為 aaaa.jar 的企業文件 那他的
遠程接口的JDNI的名稱就是:
HelloWorldBean/remote --HelloWroldBean 為HelloWorld 的實現類
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

