上一篇博客介绍了EJB基本概念:会话Bean 和 消息驱动Bean,在ITOO项目中主要是应用EJB 会话Bean,故接下来的博客将总结整理 会话Bean在项目中的应用。
EJB中使用Session Bean进行开发,是以接口-实现的形式进行开发,这同我们在一般系统中进行解耦,调用接口以达到层与层之间解耦是相同的开发方式。但与众不同之处在于,EJB的接口分为本地接口和远程接口,通过@Local 和@Remote 注解分别进行标识,目的在于该会话Bean 在建立之后,确定该Bean 中的接口是为本地提供实现还是用于远程调用。
一、先看一下EJB3中的Session Bean应该遵循如下设计规范:
1、业务接口
Session Bean开发中应至少有一个业务接口(本地Local /远程 Remote均可)
2、接口实现
Session Bean的具体实现类不能是抽象类,或final修饰的最终类,该实现类必须实现该业务接口和接口中所有方法。
二、开发远程调用的Session Bean
通过上面的介绍,开发一个无状态的Session Bean由三个步骤完成:
1、开发一个或多个业务接口,通过@Local 和@Remote 标识接口状态
这里的注解可以在接口处注明
@Remote()
public interface Hello()
{
public String Hello(String name);
}
或是在实现类注明,此时需要在注解中指定接口名称
@Remote(Hello.class)
@Stateless(mapperName="Hello")
{
public class HelloImpl implements Hello()
{
.........
}
}
2、开发接口的实现
3、客户端调用接口
客户端调用原理:通过JNDI查找该EJB的引用之后,调用该接口实现即可。
在ITOO_JC系统中,开发了众多远程调用的Session Bean,以StudentBean实现为例。
@Stateless(name = "studentBeanImpl")
@Remote(StudentBean.class)
@TransactionManagement(TransactionManagementType.CONTAINER)
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class StudentBeanImpl extends BaseBeanImpl<Student> implements
StudentBean {
// ClassesBean 的访问地址
private String classesBeanUrl = "itoo-basic-institution-ear/itoo-basic-
institution-core-0.0.1-SNAPSHOT/classesBeanImpl!
com.tgb.itoo.basic.service.ClassesBean";
// InstitutionBean 的访问地址
private String institutionBeanUrl = "itoo-basic-institution-ear/itoo-basic-
institution-core-0.0.1-SNAPSHOT/InstitutionBeanImpl!
com.tgb.itoo.basic.service.InstitutionBean";
// 本系统接口
private String teacherBeanUrl = "itoo-basic-teacher-ear/itoo-basic-teacher-
core-0.0.1-SNAPSHOT/TeacherBeanImpl!com.tgb.itoo.basic.service.TeacherBean";
/**
* 依赖注入name为"studentEaoImpl"的EJB组件
*/
@EJB(beanName = "studentEaoImpl")
private StudentEao studentEao;
/**
* 根据List<String> ids批量查询,返回List<Map>
*/
@Override
public List<Map<Serializable, Serializable>> queryListByStudentIds(
List<String> ids, String dataBaseName) {
EntityToMap entityToMap = new EntityToMap();
List<Map<Serializable, Serializable>> listStudentInfo = new
ArrayList<Map<Serializable, Serializable>>();
List<Student> listStudent = new ArrayList<Student>();
// 根据ids集合查询出实体
listStudent = studentEao.queryByList(ids, dataBaseName);
// 实体转换为Map
listStudentInfo = entityToMap.entityToMap(listStudent);
return listStudentInfo;
}
通过编译,将class文件打成jar包后,就开发完成了一个简单的、可远程调用、无状态的Session Bean。本实例为远程调用的无状态EJB Session Bean,@local 和@Stateful用法与远程无状态Session Bean完全一样。
需要注意的是:本地调用Session Bean时,如果需要使用一个wen应用调用该EJB组件,就必须将该Session Bean相关的接口、实现和web程序打到同一个Ear文件中。这也是在ITOO项目中有web(MVC)、core(service实现+eao接口实现)和Ear,三层,jenkins构建时也以core web ear 的顺序分别将三层打包形成jar、jar、ear包,其他线引用时在pom文件中配置依赖jar,这个jar 或者ear、便是打成包的EJB组件,供别的模块调用。
三、EJB注解
1、关于注解@Remote专门用于修改支持远程调用的EJB,可以修饰接口,也可修饰Bean实现类,修饰实现类注意在括号中注明(接口名称.class)。
2、@Local 和@Remote的用法几乎完全一样,@Local 修饰的EJB只允许本地调用。
3、@Stateless 专门用于修饰无状态的EJB实现类,使用该注解可指定一个mapperName属性,用于为该EJB实现类指定名称,EJB容器会根据该名称生成JNDI名。对于有状态、无状态的会话Bean在上篇博客介绍了它的原理,对于开发人员而言,只是注解选择的问题,其他编码完全一样。
但在选择是需注意,EJB容器能很轻松的管理无状态的Session Bean,无需为为每一个调用该bean 的客户端都分配一个EJB实例,维护会话关联状态,大大减少了创建实例的系统开销。所以在ITOO项目中很容易发现, 多数SessionBean 都被设置成无状态的。