读书人

EJB3.0实业bean

发布时间: 2012-12-26 14:39:29 作者: rapoo

EJB3.0实体bean

6.5 持久化实体管理器EntityManager
EntityManager 是用来对实体Bean进行操作的辅助类。他可以用来产生/删除持久化的实体Bean,通过主键查找
实体bean,也可以通过EJB3 QL语言查找满足条件的实体Bean。EntityManager 的获取前面已经介绍过,可以通
过@PersistenceContext注释由EJB容器动态注入,例:
@PersistenceContext(unitName="foshanshop")
EntityManager em;
下面介绍EntityManager 常用的API
6.5.1 Entity 获取find()
如果知道Entity的唯一标示符,我们可以用find()方法来获得Entity。
@PersistenceContext
protected EntityManager em;

Person person = em.find(Person.class, Integer.valueOf(personid));
6.5.2 添加persist()
保存Entity 到数据库。
@PersistenceContext
protected EntityManager em;

Person person = new Person();
Jboss EJB3.0实例教程
版权所有:黎活明
person.setName(name);
//把数据保存进数据库中
em.persist(person);
6.5.3 更新Merge()
把Entity 更新到数据库。
@PersistenceContext
protected EntityManager em;

Person person = em.find(Person.class, Integer.valueOf(personid));
//更新数据
em.merge (person);
6.5.4 删除Remove()
把Entity从到数据库中删除。
@PersistenceContext
protected EntityManager em;

Person person = em.find(Person.class, Integer.valueOf(personid));
//如果级联关系cascade=CascadeType.ALL,在删除person时候,也会把级联对象删除。把cascade
属性设为cascade=CascadeType.REMOVE 有同样的效果。
em.remove (person);
6.5.5 执行EJB3 QL 操作createQuery()
@PersistenceContext
protected EntityManager em;

Query query = em.createQuery("select p from Person p where p. name=’黎明’");
List result = query.getResultList();
Iterator iterator = result.iterator();
while( iterator.hasNext() ){
//处理Person
}

// 执行更新语句
Query query = em.createQuery("update Person as p set p.name =?1 where p. personid=?2");
query.setParameter(1, “黎明” );
query.setParameter(2, new Integer(1) );
Jboss EJB3.0实例教程
版权所有:黎活明
int result = query.executeUpdate(); //影响的记录数

// 执行更新语句
Query query = em.createQuery("delete from Person");
int result = query.executeUpdate(); //影响的记录数

6.6 关系/对象映射
6.6.1 映射的表名或列名与数据库保留字同名时的处理
如果应用采用的数据库是Mysql,当映射的表名或列名与数据库保留字同名时,Hibernate 转绎成的SQL 在执行
时将会出错。
如:
@Entity
@Table(name = "Order")
public class Order implements Serializable {
表名Order 与排序保留字 “Order“相同,导致SQL语法出错。
针对上面的情况,作者在Hibernate 文档中没有找到相关的解决方案。在此作者采用了一种变通的方法来解决此
问题。该方法针对具体数据库,不利于数据库移植。建议大家在不得已的情况下使用。
可以用``字符把Order 括起来。如下:
@Entity
@Table(name = "`Order`")
public class Order implements Serializable {
列名与保留字同名的处理方法如上,如列名为group
@Column(name = "`group`")
public String getGroup() {
return group;
}
如果数据库是Sqlserver 可以用 [] 把表名或列名括起来。Sqlserver 不加[]也能执行成功,建议在出错的情况下使
用[]。
6.6.2 一对多及多对一映射
现实应用中存在很多一对多的情况,如一项订单中存在一个或多个订购项。下面就以订单为例介绍存在一对多及
多对一双向关系的实体bean 开发。
需要映射的数据库表
orders
字段名称 字段类型属性 描述
orderid Int 订单号
amount float 订单金额
createdate datetime 订单创建日期
Jboss EJB3.0实例教程
版权所有:黎活明
orderitems
字段名称 字段类型属性 描述
id Int 订单项ID
productname Varchar(255) 订购产品名称
price float 产品价格
order_id Int 订单号
双向一对多关系,一是关系维护端(owner side),多是关系被维护端(inverse side)。在关系被维护端建立外
键列指向关系维护端的主键列。
Order.java
//author:lihuoming
package com.foshanshop.ejb3.bean;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Date;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;
@SuppressWarnings("serial")
@Entity
@Table(name = "Orders")
public class Order implements Serializable {
private Integer orderid;
private Float amount;
private Set<OrderItem> orderItems = new HashSet<OrderItem>();
private Date createdate;
@Id
@GeneratedValue
public Integer getOrderid() {
return orderid;
}
public void setOrderid(Integer orderid) {
this.orderid = orderid;
}
public Float getAmount() {
return amount;
}
Jboss EJB3.0实例教程
版权所有:黎活明
public void setAmount(Float amount) {
this.amount = amount;
}
@OneToMany(mappedBy="order",cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@OrderBy(value = "id ASC")
public Set<OrderItem> getOrderItems() {
return orderItems;
}
public void setOrderItems(Set<OrderItem> orderItems) {
this.orderItems = orderItems;
}
public Date getCreatedate() {
return createdate;
}
public void setCreatedate(Date createdate) {
this.createdate = createdate;
}
public void addOrderItem(OrderItem orderitem) {
if (!this.orderItems.contains(orderitem)) {
this.orderItems.add(orderitem);
orderitem.setOrder(this);
}
}
public void removeOrderItem(OrderItem orderitem) {
orderitem.setOrder(null);
this.orderItems.remove(orderitem);
}
}
上面声明一个Set 变量orderItems 用来存放多个OrderItem 对象, 注释
@OneToMany(mappedBy="order",cascade = CascadeType.ALL, fetch = FetchType.LAZY)指明Order与OrderItem
关联关系为一对多关系,下面是@OneToMany 注释的属性介绍:
1>targetEntity
Class 类型的属性。
定义关系类的类型,默认是该成员属性对应的类类型,所以通常不需要提供定义。
2>mappedBy
String 类型的属性。
定义类之间的双向关系。如果类之间是单向关系,不需要提供定义,如果类和类之间形成双向关系,我们就需要
使用这个属性进行定义,否则可能引起数据一致性的问题。
Jboss EJB3.0实例教程
版权所有:黎活明
3>cascade
CascadeType[]类型。
该属性定义类和类之间的级联关系。定义的级联关系将被容器视为对当前类对象及其关联类对象采取相同的操
作,而且这种关系是递归调用的。举个例子:Order 和OrderItem 有级联关系,那么删除Order 时将同时删除它
所对应的OrderItem对象。而如果OrderItem还和其他的对象之间有级联关系,那么这样的操作会一直递归执行
下去。
cascade 的值只能从CascadeType.PERSIST(级联新建)、CascadeType.REMOVE(级联删除)、CascadeType.REFRESH
(级联刷新)、CascadeType.MERGE(级联更新)中选择一个或多个。还有一个选择是使用CascadeType.ALL,表
示选择全部四项。
4>fatch
FetchType 类型的属性。
可选择项包括:FetchType.EAGER和FetchType.LAZY。前者表示关系类(本例是OrderItem类)在主类(本例是Order
类)加载的时候同时加载,后者表示关系类在被访问时才加载。默认值是FetchType. LAZY。
@OrderBy(value = "id ASC")注释指明加载OrderItem 时按id 的升序排序
addOrderItem 和removeOrderItem 方法用来添加/删除订单项。
OrderItem.java
//author:lihuoming
package com.foshanshop.ejb3.bean;
import java.io.Serializable;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@SuppressWarnings("serial")
@Entity
@Table(name = "OrderItems")
public class OrderItem implements Serializable {
private Integer id;
private String productname;
private Float price;
private Order order;
public OrderItem() {
}
public OrderItem(String productname, Float price) {
this.productname = productname;
Jboss EJB3.0实例教程
版权所有:黎活明
this.price = price;
}
@Id
@GeneratedValue
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getProductname() {
return productname;
}
public void setProductname(String productname) {
this.productname = productname;
}
public Float getPrice() {
return price;
}
public void setPrice(Float price) {
this.price = price;
}
@ManyToOne(cascade=CascadeType.ALL,optional=false)
@JoinColumn(name = "order_id")
public Order getOrder() {
return order;
}
public void setOrder(Order order) {
this.order = order;
}
}
注释@ManyToOne指明OrderItem和Order之间为多对一关系,多个OrderItem实例关联的都是同一个Order对象。
@ManyToOne注释有四个属性:targetEntity、cascade、fetch 和optional,前三个属性的具体含义和@OneToMany
注释的同名属性相同,但@ManyToOne 注释的fetch 属性默认值是FetchType.EAGER。
optional 属性是定义该关联类对是否必须存在,值为false 时,关联类双方都必须存在,如果关系被维护端不存
在,查询的结果为null。值为true 时, 关系被维护端可以不存在,查询的结果仍然会返回关系维护端,在关系
维护端中指向关系被维护端的属性为null。optional属性的默认值是true。举个例:某项订单(Order)中没有订
单项(OrderItem),如果optional 属性设置为false,获取该项订单(Order)时,得到的结果为null,如果optional
属性设置为true,仍然可以获取该项订单,但订单中指向订单项的属性为null。实际上在解释Order 与OrderItem
的关系成SQL时,optional属性指定了他们的联接关系optional=false 联接关系为inner join, optional=true
Jboss EJB3.0实例教程
版权所有:黎活明
联接关系为left join。
@JoinColumn(name = "order_id")注释指定OrderItem 映射表的order_id 列作为外键与Order 映射表的主键列
关联。
为了使用上面的实体Bean,我们定义一个Session Bean作为他的使用者。下面是Session Bean 的业务接口,他
定义了三个业务方法insertOrder,getOrderByID 和getAllOrder,三个方法的业务功能是:
insertOrder 添加一个订单(带两个订单项)进数据库
getOrderByID 获取指定订单号的订单
getAllOrder 获取所有订单
下面是Session Bean 的业务接口及实现类
OrderDAO.java
//author:lihuoming
package com.foshanshop.ejb3;
import java.util.List;
import com.foshanshop.ejb3.bean.Order;
public interface OrderDAO {
public void insertOrder();
public Order getOrderByID(Integer orderid);
public List getAllOrder();
}
OrderDAOBean.java
//author:lihuoming
package com.foshanshop.ejb3.impl;
import java.util.Date;
import java.util.List;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import com.foshanshop.ejb3.OrderDAO;
import com.foshanshop.ejb3.bean.Order;
import com.foshanshop.ejb3.bean.OrderItem;
@Stateless
@Remote ({OrderDAO.class})
public class OrderDAOBean implements OrderDAO {
@PersistenceContext
protected EntityManager em;
public void insertOrder(){
Order order = new Order();
order.setCreatedate(new Date());
Jboss EJB3.0实例教程
版权所有:黎活明
order.addOrderItem(new OrderItem("笔记本电脑", new Float(13200.5)));
order.addOrderItem(new OrderItem("U盘", new Float(620)));
order.setAmount(new Float(13200.5+620));
em.persist(order);
}
public Order getOrderByID(Integer orderid) {
Order order = em.find(Order.class, orderid);
order.getOrderItems().size();
//因为是延迟加载,通过执行size()这种方式获取订单下的所有订单项
return order;
}
public List getAllOrder() {
Query query = em.createQuery("select o from Order o inner join fetch o.orderItems order by
o.orderid");
List result = query.getResultList();
return result;
}
}
上面有一点需要强调:当业务方法需要把一个实体Bean作为参数返回给客户端时,除了实体Bean 本身需要实现
Serializable 接口之外,如果关联类(OrderItem)是延迟加载,还需在返回实体Bean之前通过访问关联类的方式
加载关联类。否则在客户端访问关联类时将会抛出加载例外。另外不管是否延迟加载,通过join fetch 关联语
句都可显式加载关联类,如业务方法getAllOrder 。
下面是Session Bean 的JSP 客户端代码:
OneToManyTest.jsp
<%@ page contentType="text/html; charset=GBK"%>
<%@ page import="com.foshanshop.ejb3.OrderDAO,
com.foshanshop.ejb3.bean.*,
javax.naming.*,
java.util.*"%>
<%
Properties props = new Properties();
props.setProperty("java.naming.factory.initial",
"org.jnp.interfaces.NamingContextFactory");
props.setProperty("java.naming.provider.url", "localhost:1099");
props.setProperty("java.naming.factory.url.pkgs", "org.jboss.naming");
InitialContext ctx = new InitialContext(props);
try {
OrderDAO orderdao = (OrderDAO) ctx.lookup("OrderDAOBean/remote");
orderdao.insertOrder();
/*
Order order = orderdao.getOrderByID(new Integer(1));
Jboss EJB3.0实例教程
版权所有:黎活明
out.println("订单总费用:"+ order.getAmount() +"<br>==============订单项
=================<br>");
if (order!=null){
Iterator iterator = order.getOrderItems().iterator();
while (iterator.hasNext()){
OrderItem SubOrder = (OrderItem) iterator.next();
out.println("订购产品:"+ SubOrder.getProductname() +"<br>");
}
}else{
out.println("没有找到相关订单");
}
*/
List list = orderdao.getAllOrder();
if (list!=null){
Integer orderid = null;
for(int i=0; i<list.size();i++){
Order od = (Order) list.get(i);
if (od!=null){
if (!od.getOrderid().equals(orderid)){
orderid = od.getOrderid();
out.println("==============订单号:"+ od.getOrderid()
+"=================<br>");
Iterator iterator = od.getOrderItems().iterator();
while (iterator.hasNext()){
OrderItem SubOrder = (OrderItem) iterator.next();
out.println("订购产品:"+ SubOrder.getProductname() +"<br>");
}
}
}
}
}else{
out.println("获取不到订单列表");
}
} catch (Exception e) {
out.println(e.getMessage());
}
%>
本例子的EJB 源代码在OneToMany 文件夹(源代码下载:http://www.foshanshop.net/),项目中使用到的类库在
上级目录lib文件夹下。要发布本例子EJB (确保配置了环境变量JBOSS_HOME 及启动了Jboss),你可以执行Ant
的deploy 任务。例子使用的数据源配置文件是mysql-ds.xml,你可以在下载的文件中找到。数据库名为
foshanshop
本例子的客户端代码在EJBTest 文件夹,要发布客户端应用,你可以执行Ant 的deploy 任务。通过
http://localhost:8080/EJBTest/OneToManyTest.jsp 访问客户端。
Jboss EJB3.0实例教程
版权所有:黎活明
6.6.3 一对一映射
一个人(Person)只有唯一的身份证号 (IDCard),Person 与IDCard 是一对一关系。下面就以他们为例介绍存在
一对一关系的实体Bean开发过程
需要映射的数据库表
person
字段名称 字段类型属性 描述
personid (主键) Int(11) not null 人员ID
PersonName Varchar(32) not null 姓名
sex Tinyint(1) not null 性别
age Smallint(6) not null 年龄
birthday Datetime null 出生日期
idcard
字段名称 字段类型属性 描述
id (主键) Int(11) not null 流水号
cardno Varchar(18) not null 身份证号
Person_ID Int(11) not null 作为外键指向person 表的
personid
一对一关系需要在关系维护端(owner side)的@OneToOne注释中定义mappedBy 属性。在关系被维护端(inverse
side)建立外键列指向关系维护端的主键列。
下面是关系维护端Person.java 的源代码:
//author:lihuoming
package com.foshanshop.ejb3.bean;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;
@SuppressWarnings("serial")
@Entity
@Table(name = "Person")
public class Person implements Serializable{
private Integer personid;
private String name;
private boolean sex;
Jboss EJB3.0实例教程
版权所有:黎活明
private Short age;
private Date birthday;
private IDCard idcard;
@Id
@GeneratedValue
public Integer getPersonid() {
return personid;
}
public void setPersonid(Integer personid) {
this.personid = personid;
}
@Column(name = "PersonName",nullable=false,length=32)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Column(nullable=false)
public boolean getSex() {
return sex;
}
public void setSex(boolean sex) {
this.sex = sex;
}
@Column(nullable=false)
public Short getAge() {
return age;
}
public void setAge(Short age) {
this.age = age;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
Jboss EJB3.0实例教程
版权所有:黎活明
@OneToOne(optional = true,cascade = CascadeType.ALL, mappedBy = "person")
public IDCard getIdcard() {
return idcard;
}
public void setIdcard(IDCard idcard) {
this.idcard = idcard;
}
}
@OneToOne 注释指明Person 与IDCard为一对一关系,@OneToOne 注释五个属性:targetEntity、cascade、fetch、
optional 和mappedBy, 前四个属性的具体含义与@ManyToOne 注释的同名属性一一对应,请大家参考前面章节中
的内容,fetch 属性默认值是FetchType.EAGER。mappedBy 属性的具体含义与@OneToMany 注释的同名属性相同。
上面的optional = true 设置idcard 属性可以为null,也就是允讦没有身份证,未成年人就是没有身份证的。
IDCard.java
//author:lihuoming
package com.foshanshop.ejb3.bean;
import java.io.Serializable;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;
@SuppressWarnings("serial")
@Entity
@Table(name = "IDCard")
public class IDCard implements Serializable{
private Integer id;
private String cardno;
private Person person;
public IDCard() {
}
public IDCard(String cardno) {
this.cardno = cardno;
}
@Id
@GeneratedValue
public Integer getId() {
return id;
Jboss EJB3.0实例教程
版权所有:黎活明
}
public void setId(Integer id) {
this.id = id;
}
@Column(nullable=false,length=18,unique = true)
public String getCardno() {
return cardno;
}
public void setCardno(String cardno) {
this.cardno = cardno;
}
@OneToOne(optional = false, cascade = CascadeType.ALL)
@JoinColumn(name = "Person_ID", referencedColumnName = "personid",unique = true)
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
}
@OneToOne 注释指明IDCard 与Person 为一对一关系,IDCard 是关系被维护端,optional = false 设置person
属性值不能为null,也就是身份证必须有对应的主人。@JoinColumn(name = "Person_ID", referencedColumnName
= "personid",unique = true)指明IDCard 对应表的Person_ID 列作为外键与Person 对应表的personid列进行
关联, unique = true 指明Person_ID 列的值不可重复。
为了使用上面的实体Bean,我们定义一个Session Bean作为他的使用者。下面是Session Bean 的业务接口,他
定义了四个业务方法insertPerson,getPersonByID,updatePersonInfo 和deletePerson, 四个方法的业务功能
是:
insertPerson 添加一个人员(带一个身份证)进数据库
getPersonByID 获取指定编号的人员
updatePersonInfo 更新人名及身份证号
deletePerson 删除人员,连同其身份证一起删除
下面是Session Bean 的业务接口及实现类
OneToOneDAO.java
//author:lihuoming
package com.foshanshop.ejb3;
import java.util.Date;
import com.foshanshop.ejb3.bean.Person;
public interface OneToOneDAO {
public void insertPerson(String name, boolean sex,short age, Date birthday,String cardID);
public Person getPersonByID(Integer orderid);
public void updatePersonInfo(Integer personid, String newname, String newIDcard);
Jboss EJB3.0实例教程
版权所有:黎活明
public void deletePerson(Integer personid);
}
OneToOneDAOBean.java
package com.foshanshop.ejb3.impl;
import java.util.Date;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import com.foshanshop.ejb3.OneToOneDAO;
import com.foshanshop.ejb3.bean.IDCard;
import com.foshanshop.ejb3.bean.Person;
@Stateless
@Remote ({OneToOneDAO.class})
public class OneToOneDAOBean implements OneToOneDAO {
@PersistenceContext
protected EntityManager em;
public void insertPerson(String name, boolean sex,short age, Date birthday,String cardID) {
Person person = new Person();
person.setName(name);
person.setSex(sex);
person.setAge(Short.valueOf(age));
person.setBirthday(birthday);
IDCard idcard = new IDCard(cardID);
idcard.setPerson(person);
person.setIdcard(idcard);
em.persist(person);
}
public Person getPersonByID(Integer personid) {
Person person = em.find(Person.class, personid);
return person;
}
public void updatePersonInfo(Integer personid, String newname, String newIDcard) {
Person person = em.find(Person.class, personid);
if (person!=null) {
person.setName(newname);
if (person.getIdcard()!=null){
Jboss EJB3.0实例教程
版权所有:黎活明
person.getIdcard().setCardno(newIDcard);
}
em.merge(person);
}
}
public void deletePerson(Integer personid) {
Person person = em.find(Person.class, personid);
if (person!=null) em.remove(person);
}
}
下面是Session Bean 的JSP 客户端代码:
OneToOneTest.jsp
<%@ page contentType="text/html; charset=GBK"%>
<%@ page import="com.foshanshop.ejb3.OneToOneDAO,
com.foshanshop.ejb3.bean.*,
javax.naming.*,
java.util.Date,
java.text.SimpleDateFormat,
java.util.*"%>
<%
Properties props = new Properties();
props.setProperty("java.naming.factory.initial",
"org.jnp.interfaces.NamingContextFactory");
props.setProperty("java.naming.provider.url", "localhost:1099");
props.setProperty("java.naming.factory.url.pkgs", "org.jboss.naming");
InitialContext ctx = new InitialContext(props);
try {
String outformate = "<font color=blue>CMD>>Out>></font> ";
OneToOneDAO oneToonedao = (OneToOneDAO) ctx.lookup("OneToOneDAOBean/remote");
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat formatter1 = new SimpleDateFormat("MMddhhmmss");
String endno = formatter1.format(new Date()).toString();
oneToonedao.insertPerson("黎活明", true, (short)26,formatter.parse("1980-9-30"),
"44011"+endno);
//添加时请注意,身份证号不要重复,因为数据库字段身份证号是唯一的
Person person = oneToonedao.getPersonByID(new Integer(1));
if (person!=null){
out.println(outformate +"寻找编号为1的人员<br>");
out.println("姓名:"+ person.getName() +" 身份证:"+
person.getIdcard().getCardno() +"<br>");
}else{
Jboss EJB3.0实例教程
版权所有:黎活明
out.println("没有找到编号为1的人员<br>");
}
out.println(outformate +"更新编号为1的人员的姓名为李明,身份证号为33012" +endno
+"<br>");
oneToonedao.updatePersonInfo(new Integer(1), "李明", "33012" +endno);
out.println("================删除编号为3的人员==============<br>");
oneToonedao.deletePerson(new Integer(3));
} catch (Exception e) {
out.println(e.getMessage());
}
%>
本例子的EJB 源代码在OneToOne 文件夹(源代码下载:http://www.foshanshop.net/),项目中使用到的类库在
上级目录lib文件夹下。要发布本例子EJB (确保配置了环境变量JBOSS_HOME 及启动了Jboss),你可以执行Ant
的deploy 任务。例子使用的数据源配置文件是mysql-ds.xml,你可以在下载的文件中找到。数据库名为
foshanshop
注意:在发布本例子EJB时,请御载前面带有Person类的例子 (如: EntityBean.jar),否则会引起类型冲突。
本例子的客户端代码在EJBTest 文件夹,要发布客户端应用,你可以执行Ant 的deploy 任务。通过
http://localhost:8080/EJBTest/OneToOneTest.jsp 访问客户端。

读书人网 >编程

热点推荐