EJB——会话bean(一)

       会话bean的目的是建模业务处理或者操作,特别是系统用户能察觉到的。会话bean是EJB中最容易但也最通用的部分。
会话bean有两种类型:无状态类型和有状态类型。
无状态bean
   
   
package com.ejb3inaction.actionbazaar.buslogic;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import com.ejb3inaction.actionbazaar.persistence.Bid;
@Stateless//将POJO标记为会话bean
public class PlaceBidBean implements PlaceBid {
···
public PlaceBidBean(){}
public Bid addBid(Bid bid) {
System.out.println("Adding bid, bidder ID=" + bid.getBidderId()
+ ", item ID=" + bid.getItemId() + ", bid amount="
+ bid.getBidPrice() + ".");
return save(bid);
}
···
}
}
···
package ejb3inaction.example.buslogic;
 
import javax.ejb.Local;
import ejb3inaction.example.persistence.Bid;
 
@Local//将EJB业务接口标记为本地的
public interface PlaceBid {
Bid addBid(Bid bid);
}
        这段代码中值得注意的特性是两个EJB 3注解:@Stateless和@Local。无状态会话bean用于建模可以一次性完成的操作或处理。
  • @Stateless注解通知EJB容器这个bean是无状态会话bean。容器自动的为bean提供这些服务并发控制、线程安全、池化和事务管理。此外,你可以添加适用于无状态bean的其他服务,比如透明安全和拦截器。
  • @ Local注解通知容器可以通过接口访问PlaceBid EJB。因为EJB和servlet通常在同一个应用程序中协同操作,所以这种方式非常好。另一种方式是,你可以使用@Remote注解标记接口。在Java远程方法调用(RMI)的控制下提供对@Remote进行远程访问,这是从Java客户端进行远程访问的理想方式。
       如果非Java客户端(如.NET应用程序)需要访问EJB,可以在接口或bean类上使用@WebService注解,从而启动基于Web服务的远程访问。
无状态bean客户端
客户端调用上面的PlaceBid EJB,可能从JSP或servlet中调用,假设是在servlet中调用,代码如下:
   
   
package ejb3inaction.example.buslogic;
import javax.ejb.EJB;
import ejb3inaction.example.persistence.Bid;
 
 
public class PlaceBidClient {
@EJB//注入PlaceBid EJB的实例
private static PlaceBid placeBid;
public static void main(String [] args) {
try {
Bid bid = new Bid();
bid.setBidderId("npanda");
bid.setItemId(Long.valueOf(100));
bid.setBidPrice(20000.40);
 
System.out.println("Bid Successful, BidId Received is:" +placeBid.addBid(bid).getBidId());
} catch (Exception ex) {
ex.printStackTrace();
}
}
 
}
        当servlet容器第一次加载servlet发现@EJB注解时,它将在幕后查找PlaceBid EJB并把placeBid变量设置为可获得的EJB引用。如果有必要,容器会通过RMI远程查找EJB。
PlaceBid无状态bean的一个有意思的地方就是只要每次调用addBid方法并导致创建新的记录时,客户端不关心bean的内部状态。完全不需要无状态bean保证其任何实例变量的值在任意两次调用之间是相同的,这就是无状态的意义。
有状态bean
        与无状态bean不同,有状态bean保证客户端可以设置bean的内部状态,希望在任意次调用之间维护状态。容器确保通过在幕后进行一下两个重要的操作来达到目的。
  • 首先,容器确保客户端可以跨越一次以上的方法调用访问分配到容器的bean,比如打电话,如果你在给定的时间(此时间就是会话)内给技术支持打电话的次数超过1次,它能确保你和同一个客服代表通话。
  • 其次,容器确保在会话过程中维护bean实例的变量值,无需你编写任何会话维护代码。
        举一个订单处理的例子,购物订单处理流程是添加商品,设置商品信息,确认订单,我们建一个类PlaceOrderBean,从Web层依次调用addItem、setShippingInfo、setBillingInfo和confirmOrder方法,对用户在每个步骤中的操作做出响应。除了 confirmOrder方法之外,其他方法都是将用户输入保存到有状态实例变量中。 confirmOrder方法使用会话中积累的数据进行如下操作:把完成的订单保存到数据库中,并进行账单处理,把账单id返回给用户确认。代码如下:
   
   
package com.ejb3inaction.actionbazaar.buslogic;
 
import java.util.ArrayList;
import java.util.List;
import javax.ejb.*;
 
@Stateful//使用POJO有状态
public class PlaceOrderBean implements PlaceOrder {
private Long bidderId;
private List<Long> items;
private ShippingInfo shippingInfo;
private BillingInfo billingInfo;
 
public PlaceOrderBean() {
items = new ArrayList<Long>();
}
 
public void setBidderId(Long bidderId) {
this.bidderId = bidderId;
}
 
public void addItem(Long itemId) {
items.add(itemId);
}
 
public void setShippingInfo(ShippingInfo shippingInfo) {
this.shippingInfo = shippingInfo;
}
 
public void setBillingInfo(BillingInfo billingInfo) {
this.billingInfo = billingInfo;
}
 
@Remove//包含删除方法
public Long confirmOrder() {
Order order = new Order();
order.setBidderId(bidderId);
order.setItems(items);
order.setShippingInfo(shippingInfo);
order.setBillingInfo(billingInfo);
saveOrder(order);
billOrder(order);
return order.getOrderId();
}
···
}
···
package com.ejb3inaction.actionbazaar.buslogic;
 
import javax.ejb.Remote;
 
@Remote//定义远程业务接口
public interface PlaceOrder {
void setBidderId(Long bidderId);
void addItem(Long itemId);
void setShippingInfo(ShippingInfo shippingInfo);
void setBillingInfo(BillingInfo billingInfo);
Long confirmOrder();
}
       从代码上看,开发无状态和有状态bean的区别不大。但是容器在处理bean和客户端之间关系以及存储在bean实例变量中的值等方面的区别是很大到。
       @Remove注解也很重要。此注解是可选的,但是对服务器的性能来说,它很重要。此注解用于标记有状态bean建模的工作流的结束。例子中我们通知容器调用confirmOrder方法之后就不在需要维护与客户端的bean会话。如果我们没有通知容器哪个方法用于标记工作流的结束,那么在容器安全的使会话超时之前,他就会等待很长时间。因为有状态bean保证在会话的过程中被指派给客户端,这可能意味着在很长的时间周期内,大量“孤立”状态数据在消耗宝贵的服务器资源!
有状态bean客户端
   
   
package com.ejb3inaction.example.buslogic;
 
import javax.ejb.EJB;
 
public class PlaceOrderClient {
@EJB//注入EJB的实例
private static PlaceOrder placeOrder;
 
public static void main(String[] args) {
try {
Context context = new InitialContext();
placeOrder = (PlaceOrder) context.lookup("chapter2/"
+ PlaceOrderBean.class.getSimpleName() + "/remote");
 
System.out.println("Exercising PlaceOrder EJB...");
placeOrder.setBidderId(new Long(100));
placeOrder.addItem(new Long(200));
placeOrder.addItem(new Long(201));
placeOrder.setShippingInfo(new ShippingInfo("123 My Sweet Home",
"My City", "My State"));
placeOrder.setBillingInfo(new BillingInfo("VISA", "123456789",
"0708"));
Long orderId = placeOrder.confirmOrder();
System.out.println("Added Order: " + orderId);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
       除了客户可以安全的假设即使EJB在远程应用程序服务器上也可以维护状态之外,使用无状态和有状态bean的客户代码之间没有区别。值得注意的是,在有状态客户端中@EJB注解把远程EJB注入到独立客户端中。这是通过应用程序客户端容器(application client container,ACC)中运行客户端完成的。
       任何具有main方法的Java类都可以运行在ACC之内。但是,通常情况下,应用程序客户端打包在JAR文件中,此文件必须在Manifest文件中包含Main-Class。可选方式是,JAR文件可以包含部署描述文件(application-client.xml)和jndi.properties,它们包含连接在远程EJB容器的环境属性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值