上一篇博客介绍了EJB基本概念:会话Bean 和 消息驱动Bean,在ITOO项目中主要是应用EJB 会话Bean,故接下来的博客将总结整理 会话Bean在项目中的应用。
EJB中使用Session Bean进行开发,是以接口-实现的形式进行开发,这同我们在一般系统中进行解耦,调用接口以达到层与层之间解耦是相同的开发方式。但与众不同之处在于,EJB的接口分为本地接口和远程接口,通过@Local 和@Remote 注解分别进行标识,目的在于该会话Bean 在建立之后,确定该Bean 中的接口是为本地提供实现还是用于远程调用。
1、业务接口
Session Bean开发中应至少有一个业务接口(本地Local /远程 Remote均可)
2、接口实现
Session Bean的具体实现类不能是抽象类,或final修饰的最终类,该实现类必须实现该业务接口和接口中所有方法。
通过上面的介绍,开发一个无状态的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组件,供别的模块调用。
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 都被设置成无状态的。