EJB 会话bean and Jboss JNDI

11 篇文章 0 订阅
下面案例使用的环境

myeclipse.10.1

jdk1.6.0_17

jboss-6.0.0.Final

JAXWS2.2.7-20120813


[size=medium][b]
-------------1.jboss 的安装[/b][/size]
[url]http://www.jboss.org/jbossas/downloads[/url]


-------------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 就可以了

[b]
什么是EJB???[/b]


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将异步处理客户请求。这适合于需要异步处理请求的场合,比如订单处理



[size=medium][b]//----远程调用 EJB的过程[/b][/size]

首先 客户端需要与EBJ建立起 socket 通信;
在通信管道上他们之间需要来回发送IIOP协议信息; (Internet Inter-ORB Protocol(互联网内部对象请求代理协议),它是一个用于CORBA 2.0及兼容平台上的协议)实现互操作性的协议,由不同语言编写的分布式程序在因特网中可以实现彼此的交流沟通,公用对象请求代理程序结构(Common Object Request Broker Architecture,CORBA)中至关重要的一个部分
因为数据要在在网络上进行传输, 所以存放数据的 java对象必须要进行序列化

[img]http://dl.iteye.com/upload/attachment/0080/8184/8e56e39b-02ea-3758-8f4b-c28405849cf3.jpg[/img]


在这个过程中我们看到 ,网络通信的开销, 协议解析的开销 ,对象序列化的开销.

A: (远程接口 )
客户端 和 EJB 容器不在一个 同一机器上

1.可以看出 EJB容器是 一个 重量级容器 所以 初始化 需要比较长的时间

2.EJB 是分布式技术,他允许客户端 与 EJB应用不在同一机器上,所以 这样开销也是必然的

B .(本地接口 ) 不注解的时候 默认为 本地接口
客户端 和 EJB 容器在一个 同一机器上 这样 是不是就可以 减少了 网络 通信 协议解析的开销呢 ??

1.是滴,会减少 , 此时 他们 就跑到了 JVM 内存中了,他们之间完全可以通过内存进行交互. 所以此时 就需要 "本地接口了".

客户端 和 EJB应用 发布在同一个jboss 我们就认为 在同一个JVM 内



[size=medium][b]///EJB 容器对会话bean的管理方式[/b][/size]

1.无状态 使用
@Stateless 用户可以共享
EJB 容器会对 这个bean使用个实例池技术管理bean

实例池 和 数据源技术 原理相同,
比如数据源里面的连接 没有空闲时候, 必须等连接使用完后才能使用.

这个实例 只有当一个用户使用完后,才能被其他用户使用. 可以使用最少的实例数 来为用户服务.


2.有状态 使用 (购物车)
@Stateful 会为每个用户创建单独的一个bean实例
EJB 容器会对 这个bean 使用 激活(activation) 管理bean
//钝化
如果用户 在一定时间内没有使用
这段时间 < 会话超时 设置的时间 ==> 系统会讲 用户的这个会话信息保存到 磁盘里面
//激活
如果用户又开始访问 < 会话超时 设置的时间 ==> 此时 会将磁盘上的会话信息(释放内存等资源) 又被还原到 内存中 此时用户又可以继续访问了

//超时
如果用户又开始访问 > 会话超时 设置的时间




[size=medium][b]//----------------EJB中 怎么样使用其他 EJB[/b][/size]

第一种: 使用 查找的方式
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();
}
}



[size=medium][b]//---- EJB中的一些注解说明[/b][/size]

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名称



[img]http://dl.iteye.com/upload/attachment/0080/9260/97320ab0-5eaa-3bf8-a212-3a62edf92ad8.jpg[/img]


--定义 本地和远程 接口类
//开发的时候 需要先加入 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();
}



[size=medium][b]//远程 和 本地 接口实现类 [/b][/size]
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 后台空中中查看 发布到 接口 (下面有介绍怎么查看)


[size=medium][b]
客户端 client 开发 访问远程接口的客户端[/b][/size]

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();
}

}
}


[size=medium][b]
客户端 client 开发 访问本地接口的客户端[/b][/size]

<%@ 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下


[size=medium][b]---------- ANT 的 使用
提高工作效率 帮助 我们编译 打包 发布运行 卸载[/b][/size]

在项目根目录下 添加一个 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 -->


[size=medium][b]在 中查看 jndi 名称 [/b][/size]
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 环境变量的设置


[size=medium][b]//---jboss 默认生成的JNDI 名称[/b][/size]
当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 的实现类
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值