EJB学习笔记01,了解企业级开发!
来源:互联网 发布:淘宝预售如何合并付款 编辑:程序博客网 时间:2024/05/23 00:02
有状态/无状态 SessionBean 和消息驱动Bean
EJB主要的使用场合就是在数据分布的情况下,并且对事务的支持也要考虑多数据源,也就是跨容器的自动全局性事务,在EJB3中这种事务类型是CMT(容器管理事务)。还有另外一种事务类型,即BMT(Bean管理事务),也就是程序员用代码的方式来管理事务,相比CMT事务来讲,BMT的功能有限。
下面以实例的方式来介绍EJB3主要的核心组件:
1. 会话Bean (Session Bean)
2. 消息驱动Bean (Message Driven Bean)
先来看看学习EJB3需要掌握的一些基本知识:
1.EJB3 大量使用注解,这是在JDK5.0 中的技术,当然也可以使用XML文件来进行EJB3组件的配置,关于注解和XML 的选择可谓是仁者见仁,智者见智,并没有一个准确的答案,官方着力推进的方法还是使用注解。
2.EJB3 用JTA (Java Transactoin API) 来规范事务的模型,这样就可以在跨数据源时达到全局性事务的处理。
3.使用EJB3可以在任何实现JavaEE 技术的容器中进行部署,因为EJB3是一个标准和规范。
4.EJB3也有类似Spring 框架的AOP 和 IOC 技术,如果有 struts + hibernate + spring 技术的使用经验,那么理解EJB3将会变得非常简单。
5.在EJB3中,实体Bean 带有注解,以匹配类中的属性和表中字段进行ORM映射。
14.1.1 Java EE体系结构
Java EE 应用框架 由不同的组件组成,映射到实际的开发中,也就是由不同的技术来组成JavaEE的体系结构(典型的javaEE体系结构客户端+业务层+数据库),所以JavaEE 体系是1个集大成者,不管是开源的技术还是商业的框架都能很好的在符合 Java EE 标准的容器中运行。
14.1.2容器的概念
如果开发过JSP/Servlet类型的项目,那么大多数使用的服务器肯定是Tomcat,Tomcat就是1种Web类型的容器,俗称:Web容器,Web容器主要负责request请求和response响应对象处理,并且将这些处理进行分发,通过解析无状态的http 协议来达到浏览器客户端与服务器之间的交互。那么在EJB3技术中,还有1种容器,叫做JavaEE容器。
javaEE容器模糊点说就是在网上经常看到的软件,像Weblogic,JBoss,Websphere,GlasshFish等,其实JavaEE容器真正的意义是实现Java EE标准接口,提供EJB运行,开发,部署,调试等功能的环境,由于实现JavaEE 标准接口的厂商不同,所以会出现类似像Weblogic,JBoss,Websphere,GlasshFish 等这样的软件。
Java EE 容器中的EJB 容器通过对Enterprise JavaBean 进行处理,来达到对服务器端商业组件功能的封装实现,EJB 技术发布了基于分布式的标准框架,使各个厂商有自己的跨容器,远程或本地功能的实现。
JavaEE 容器主要包含3种结构:
(1) Web容器 (2)EJB容器 (3)持久化容器
使用不同的技术也是在不同的容器中运行,像servlet运行在web容器,无状态/有状态 Enterprise JavaEean 运行在EJB 容器中,而与ORM映射有关的实体类运行在持久化容器中。
14.2有状态 SessionBean 和无状态 SessionBean
回话Bean 是EJB3的核心组件,也是使用EJB3必须要用到的技术,EJB3已经将会话Bean的使用复杂度降到了很低,可以说,用非常简单的代码,就可以实现使用会话Bean来完成分布式业务服务的功能。
14.2.1 SessionBean 有什么作用
会话Bean(Session Bean)就有处理复杂业务逻辑的功能,相当于MVC模式的M层。大多数对事务的处理,以及持久化的功能都是在会话Bean中完成的,它是将软件的功能进行逻辑上的集成,在使用EJB3的过程中,可以使用会话Bean来将业务功能的接口进行暴漏,以便通过远程或本地服务的方式被调用。
14.2.2 SessionBean的种类
在EJB3中,会话Bean主要分为2种
1.无状态会话:不保存客户端应用程序的会话状态,有点类似于Web技术中http协议,其实它真正的实现是在Java EE容器中有一个无状态会话Bean实例池pool,在这个pool池中存放无状态会话Bean,池中的所有无状态会话Bean都是为客户端所共享,有些类似于JDBC中的Connection pool 的含义,所以使用完就放回池中,那么无状态会话Bean也有点"http协议时无状态"的味道了。
2.有状态会话:而有状态会话则是像web技术中的session对象,可以在服务器端保存客户端的会话状态。
14.2.3 在MyEclipse中无状态SessionBean的创建
14.2.7 调用远程Remote类型的 StatelessBean实验
前面的章节创建的是Local本地类型的无状态的SessionBean,现在要做一个跨JVM容器的调用Remote远程无状态SessionBean的实例。
1.首先创建企业级项目,添加EJB模块支持(注意,不添加JPA标准支持,将checkbox勾去掉)
2.新建远程类型的无状态SessionBean(注意要将 Create Interface 类型选择为Remote!)
3 业务方法,在这里需要注意的是,要在@Stateless 加入mappedName 属性,mappedName 属性值代表在 weblogic中注册JNDI节点的名称。
package publicInterface;
import javax.ejb.Remote;
@Remote
public interface UserinfoServiceRemote {
public void xyz();
}
package publicInterface;
import javax.ejb.Stateless;
@Stateless(mappedName = "zzzzzzzzzzzzzzzzzzz")
public class UserinfoService implements UserinfoServiceRemote {
public void xyz() {
System.out.println("run xyz method !");
}
}
4 将企业级项目部署到weblogic, 并且以ear 文件格式进行发布。
5 下一步就要再单独调的创建一个web项目去调用这个远程的无状态的SessionBean
项目示例如下:
package controller;
public class tt extends HttpServlet {
Public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
Properties props = new Properties();
props.setProperty(Context.INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.WLInitialContextFactory");
props.setProperty(Context.PROVIDER_URL, "t3://localhost:7001");
props.setProperty(Context.SECURITY_PRINCIPAL, "weblogic");
props.setProperty(Context.SECURITY_CREDENTIALS, "12345678");
Context context = new InitialContext(props);
UserinfoServiceRemote remote = (UserinfoServiceRemote) context
.lookup("zzzzzzzzzzzzzzzzzzz#publicInterface.UserinfoServiceRemote");
remote.xyz();
context.close();
} catch (NamingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
14.2.8无状态SessionBean 的回调函数和生命周期
无状态SessionBean 的回调函数有2种:
@PostConstruct + @PreDestroy
说起无状态SessionBean 的回调函数就要一同介绍一下与它息息相关的生命周期,无状态SessionBean的生命周期只有2个状态:
1.不存在(does not exist)状态代表实例在内存中还没有创建
2.无状态SessionBean中的方法在池中准备被调用(method-ready pool)状态实例已经被创建,并且放入实例池中等待被调用,
根据Java EE 容器的不同,有些Java EE容器在启动时就创建一些无状态SessionBean ,并且放入实例池,
这和容器的实现有很大的区别。
其中从does not exist 状态转换到 method-ready pool 状态需要执行大体3个步骤:
1.容器会调用Class类的newInstance()方法来构造一个无状态SessionBean的实例,所以可以有一个无参的构造函数,如果没有无参的构造函数,
则使用系统默认的构造函数。
2.容器将其它的资源注入进这个无状态SessionBean中。
3.容器自动执行带有@PostConstruct 注解无参,不抛出异常,无返回值的任何名称的方法,每个类只允许定义1个@PostContruct方法,并且这个方法只被调用1次。
经过上面的3个步骤无状态SessionBean 就进入了method-ready pool 状态,准备供外部进行调用了,无状态SessionBean是线程安全的,所以访问量非常大时也能保证
每个无状态SessionBean的线程安全,直到执行完本请求的业务方法后,再被其它的请求所调用,或者由于SessionBean数量不够,由容器再创建一些无状态的SessionBean.
被调用结束后,无状态SessionBean 转为method-ready pool 状态。
4.当容器中空闲无状态SessionBean 的数目过多,或大量的无状态SessionBean 占用太多的系统资源,则Java EE 容器自动调用带有@PreDestroy注解的无参,
不抛出异常,无返回值的任何名称的方法,每1个类只允许定义1个@PreDestroy方法,并且这个方法只被调用1次,它是在由method-ready pool 到 does not exist
状态时被调用,调用后被垃圾回收器所回收,释放内存资源。
下面一起来做一个实验:创建时添加EJB 和 WEB 模块,但不需要添加JPA 支持,然后在EJB 模块中创建无状态SessionBean。。
ejb1testEJB
TestRemote.java
import java.io.IOException;
import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.syz.testLocal;
public class test extends HttpServlet {
@EJB
testLocal tl;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
tl.sayHello();
}
TestLocal.java
package com.syz;
import javax.ejb.Local;
@Local
public interface testLocal {
public void sayHello();
}
}
Test.java
package com.syz;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.Stateless;
@Stateless
public class test implements testLocal, testRemote {
public test() {
System.out.println("你好我是构造!!");
}
public void sayHello() {
try {
System.out.println("Begin 你好我是EJB");
Thread.sleep(10000);
System.out.println("End 你好我是EJB");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@PostConstruct
public void postConstruct() {
System.out.println("postConstruct");
}
@PreDestroy
public void preDestroy() {
System.out.println("preDestroy");
}
}
ejb1testWeb
import java.io.IOException;
import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.syz.testLocal;
public class test extends HttpServlet {
@EJB
testLocal tl;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
tl.sayHello();
}
}
14.2.9 无状态SessionBean 实例变量值保留的问题与无状态SessionBean实例池
无状态的SessionBean 在使用全局变量时有1个特性,比如1个无状态SessionBean,类名称为TestSessionBean,类TestSessionBean 中有1个全局变量是username,那么:
1.用户1第一次使用这个TestSessionBean 时对username的值进行赋值了
2.而用户2也使用这个TestSessionBean 时取到的还是用户1对username变量赋的值
为什么会有这种情况呢?其实这里面的机制是因为 Java EE 容器预先将一定数目的无状态SessionBean放入一个实例池中,每次执行无状态SessionBean 时从实例池取出一个实例,并不是重新new 创建出一个对象,一起来做一个实例,看看无状态SessionBean全局变量的特性。
14.2.10 什么是有状态SessionBean
有过web开发经验的盆友都会第一时间想到HttpSession,HttpSession会话对象可以在服务器端以sessionid为标识记录客户端的用户信息,这种在服务器端记录客户端用户信息的功能,就称为"有状态"功能 EJB3也能实现这种有状态的机制,称为"有状态SessionBean"
使用有状态SessionBean的主要目的就是使每个用户有自己的有状态SessionBean,它和实例池中将无状态SessionBean 做共享的特性是相反,有状态SessionBean 不做共享,1个客户有1个自己的有状态SessionBean,比如购物车,每个人有自己的购物车。
14.2.11 有状态SessionBean 的创建与状态特性
注意:将Stateful 选中,意味着将要创建的是有状态的SessionBean,并且有状态SessionBean的类型是Local本地访问。
package com.syz;
import javax.ejb.Local;
@Local
public interface CartServiceLocal {
public void add();
public int getSize();
public void del();
}
package com.syz;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.Stateful;
@Stateful
public class CartService implements CartServiceLocal {
private List list = new ArrayList();
public void add() {
list.add("= =");
}
public void del() {
list.remove(0);
}
public int getSize() {
return list.size();
}
}
test2Web
import java.io.IOException;
import javax.ejb.EJB;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.syz.CartServiceLocal;
public class test extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Object o = request.getSession().getAttribute("CartService");
if (o == null) {
try {
System.out.println("第一次运行");
Context c = new InitialContext();
CartServiceLocal cs = (CartServiceLocal) c
.lookup("java:comp/env/CartService");
cs.add();
request.getSession().setAttribute("CartService", cs);
System.out.println(cs.getSize());
} catch (NamingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
System.out.println("不是第一次运行");
CartServiceLocal cs = (CartServiceLocal) o;
cs.add();
System.out.println(cs.getSize());
request.getSession().setAttribute("CartService", cs);
}
}
}
- EJB学习笔记01,了解企业级开发!
- EJB学习之企业级开发初步
- EJB-01:企业级开发背景知识
- 企业级EJB开发实例
- Java企业级开发:Spring学习笔记
- 【J2EE】企业级项目开发总结--EJB篇
- 菜鸟Java学习笔记01--了解JDK开发环境
- EJB学习笔记
- Weblogic EJB 学习笔记
- EJB学习笔记
- EJB学习笔记
- EJB学习笔记
- EJB学习笔记(1)
- EJB学习笔记(2)
- EJB学习笔记(3)
- EJB学习笔记(4)
- EJB学习笔记--体系结构
- EJB学习笔记(JNDI)
- 诡异的 "密码取回" 邮件问题
- js 继承
- 【甘道夫】Hadoop2.4.1尝鲜部署+完整版配置文件
- POJ_3190_Stall Reservations
- PAT数组-11. 猴子选大王(20)
- EJB学习笔记01,了解企业级开发!
- linux虚拟机上网配置
- jQuery源码分析——jQuery对象怎么来的
- HashMap遍历方式
- Java插入时对时间的保存
- mongodb中obj()使用问题
- HDU 2066 一个人的旅行(Dijkstra)
- word ladder
- bzoj1189 [HNOI2007]紧急疏散evacuate