1.前言
上一篇博客,通过实例讲解,分析了一下EJB中SessionBean的两种状态,这篇博客来深入的分析一下EJB中的远程客户端和本地客户端的区别。
2.什么是远程客户端和本地客户端
2.1、在本地客户端中,客户端与其调用的EJB对象在同一个JVM进程中
2.2、在远程客户端中,客户端与其调用的EJB对象不在同一个JVM进程中
2.3、打个比方,假设同一台机器,安装了一个JVM,一个JBOSS应用服务器,下面启动一个JBOSS应用服务器,另外编写一个包含main方法的java类,并编译以及运行,那么此时一共有几个JVM进程呢?或者编写一个javaWeb项目,部署到JBOSS中,此时又有几个JVM进程呢?
2.4、远程客户端有如下特性
1.它可以运行在跟企业Bean不同的机器或者不同的JVM进程中
2.它可以是WEB组件、应用客户端、或者其他的企业Bean
3.对远程客户端来说,企业Bean的位置是透明的
4.为了创建一个能够被远程客户端访问的企业Bean,必须用@Remote注解来定义这些企业Bean
3.传值OR传址
下面通过一个DEMO来展示一下,远程调用和本地调用的传参数上的差别
1.EJBProject创建
创建一个User对象
<span style="font-size:18px;">package com.test; import java.io.Serializable; public class User implements Serializable { private int id; private String userName; private String Password; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return Password; } public void setPassword(String password) { Password = password; } } </span>
创建远程调用接口
<span style="font-size:18px;">package com.test; public interface UserManager { public void addUser(User user); } </span>
创建远程调用实现
<span style="font-size:18px;">package com.test; import javax.ejb.Local; import javax.ejb.Remote; import javax.ejb.Stateless; @Stateless @Local public class UserManagerImpl implements UserManager { public void addUser(User user) { System.out.println("User{username=}"+user.getUserName()+"已经被成功的保存"); user.setId(10); } } </span>
2.远程调用测试创建一个测试类
<span style="font-size:18px;">package com.test; import javax.naming.InitialContext; import javax.naming.NamingException; public class UserManagerClient { public static void main(String[] args) throws NamingException { InitialContext context=new InitialContext(); UserManager userManager=(UserManager)context.lookup("UserManagerImpl/remote"); User use=new User(); use.setUserName("张三"); use.setPassword("zhangsan"); userManager.addUser(use); System.out.println(use.getId()); } } </span>
运行结果如下
3.创建本地调用测试
创建一个JAVAwebProject项目,并把项目部署到同一个JBOSS中
<span style="font-size:18px;"><%@ page language="java" import="java.util.*,javax.naming.*,com.test.*" pageEncoding="GBK"%> <% 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"> </head> <body> <% InitialContext context=new InitialContext(); UserManager userManager=(UserManager)context.lookup("UserManagerImpl/local"); User use=new User(); use.setUserName("张三"); use.setPassword("zhangsan"); userManager.addUser(use); out.print(use.getId()); %> </body> </html> </span>
运行测试
4.小结
1.通过上述测试,得出结论,EJB在远程调用时采用的是传地址的形式,而本地调用时传的是值得形式
2.如果是本地调用的话,本地就不要使用JNDI文件了,因为如果是本地调用的话,就出在同一个环境中了,那些依赖包也就不需要了
3.如果是远程调用的话,对象必须是可以序列化的
4.远程接口定义的三种方式
例如一个EJB04Bean,实现了4个接口
第一种方式@Stateless (name= "ejb04beanname" )
@Remote(value={Ejb04Interface01.class, Ejb04Interface02.class })
@Local(value={Ejb04Interface03. class})
第二种方式
依据注解的规则,如果一个注解只定义了一个属性,而且这个属性的名称为value,则value可以直接省略,直接写值就可以了
@Remote({Ejb04Interface01.class, Ejb04Interface02.class })
@Local({Ejb04Interface03.class})
第三种方式
也可以不用再EJB实现类中定义访问方式,而是将访问方式(@remote或者@local这些注解直接定义到接口上)
一般都采用第一种方式