英语原文共 9 页,剩余内容已隐藏,支付完成后下载完整资料
通过post-EJB j2ee Web应用程序架构进行远足,第二部分
作者:Kontantin Laufer
这是关于Web应用程序开发的偶然系列的第二篇文章。第一部分,发表于2005年9月/10月问题(“通过后EJB J2EE Web应用程序架构进行远征”,第7卷,第5期,第80-88页),重点关注构成用户界面的上层;在这里,我专注于较低层。
我首先介绍了典型的Enterprise Java Bean(EJB)Java2企业版(J2EE)Web应用程序体系结构的蓝图(参见图1)。几个功能和非功能需求驱动这样的架构,并且它们已经变得相对标准。
在这个体系结构中,我们查看了我们运行的示例-线性回归在一组持久点上的核心功能-然后通过连续的用户界面层向上移动,包括动态行为,演示,国际化,导航,布局和视觉样式。在加息期间,我们研究了每一层的典型技术。
在本文中,我们将介绍应用程序的隐形内部。具体来说,我检查业务服务对象,对象关系映射,轻量级容器(用于无痛地连接各个部分),安全性和并发性。我们的最终目标是促进可靠,灵活和高效的基于服务器的Web应用程序的开发。
图1 架构蓝图
业务服务对象
我们的示例的核心功能是维护一组点(包括添加,编辑和删除它们)并对当前集执行线性回归。我们可以以服务接口的形式对此功能进行建模,如图2所示,以及一个或多个服务实现。
正如我们在上一篇文章中看到的,用户交互采用循环周期的形式:通过与输入表示元素交互,用户触发服务方法的调用。那个服务方法的结果是预先的通过输出表示元素向用户发送。调用哪种服务方法通常取决于用户输入和应用程序动态行为中当前用户界面状态的组合。
作为我们的第一步,我们必须实现服务接口。虽然我们最终期望在最底层的持久层中找到关系数据库,但我们不希望服务实现直接与该层交互。这种关注点分离使我们具有更强的稳健性和灵活性。因此,我们针对存储我们当前点集的(被动)数据访问对象(DAO)的接口PointDAO实现(活动)服务对象DefaultRegressionService,并且因为每个点都有一个颜色,所以我们允许的颜色值列表。
我们稍后会担心如何实现DAO以及如何告诉服务对象。推迟这两个问题让我们将服务对象保持为普通的旧Java对象(POJO),甚至不需要知道它是在J2EE servlet容器(如Apache Tomcat)内运行的Web应用程序的一部分(http:// tomcat) .apache.org)。这意味着其他用户界面(例如命令行界面(CLI))可以使用相同的服务对象。
图2 服务接口
生成的服务实现基于DAO构建,在某些情况下,简单地以另一个名称公开DAO方法或在被动DAO方法之上提供重要的活动功能:
public class DefaultRegressionService implements RegressionService {
private PointDAO dao;
public void setPointDAO(PointDAO dao) {
this.dao = dao;
}
public void reset() {
dao.init();
}
public void addPoint(
double x, double y, String color) {
dao.create(x, y, color);
}
public Point getPoint(int id) {
return dao.find(id);
}
public RegressionResult getResult() {
final Collection points = dao.findAll();
//~25 lines of code to compute the regression
return new RegressionResult() {/*... */};
}
public void removePoint(int id) {
dao.remove(id);
}
public void editPoint(
int id, double x, double y, String color) {
dao.update(id, x, y, color);
}
public Collection getColors() {
return dao.findColors();
}
}
由于此层中的其他实体只是接口,因此图2中的类图已经显示了要查看的所有内容,因此无需显示额外的代码。
数据模型和持久性
如前所述,DAO管理点和有效颜色的集合。以下界面捕获以下职责:
public interface PointDAO {
/** Initializes the database tables. */
void init();
/** Creates a point object. */
Point create(double x, double y, String color);
/** Finds a point given a unique id. */
Point find(int id);
/** Returns all point objects. */
Collection findAll();
/** Removes the point with the given id. */
void remove(int id);
/** Updates the point with the given id. */
void update(int id, double x, double y,String color);
/** Returns all known colors. */
Collection findColors();
}
由DAO管理的点对象是图2中所示的Point接口的合适实现的实例。我们选择调用此实现类De-faultPoint;除了接口中的getter方法之外,此类还具有修改现有点实例所需的setter方法。颜色由简单的Color类表示,该类使用字符串表示特定颜色。
DAO实施选择
我们的DAO实现的工作是通过将它们映射到关系数据库中的表来实现POJO的DefaultPoint和Color持久化。这可以通过以下两种方式之一发生:
(1)使用Java数据库连接(JDBC)API直接实现DAO。这条路线要求开发人员用笨拙的构造编写许多低级代码,这些构造从面向对象的角度来看并不自然。更糟糕的是,由于结构化查询语言(SQL)方言的微小差异关系型数据库
(2)在数据库供应商之间,生成的DAO不太可能是可移植的。使用对象关系映射(ORM)技术,如实体EJB,Java数据对象(JDO)或Hibernate(www.hibernate.org)。这条路线允许开发人员以声明方式表达POJO和关系数据库表之间的映射,使他们免于编写低级JDBC代码,并使交换数据库供应商变得微不足道。
在本文中,我们将重点放在广泛使用的Hibernate上。ture,高性能,开源的对象关系映射器,对开发人员来说非常自然且面向对象。
使用对象关系映射
基于Hibernate的数据模型的核心是Hibernate映射,它将POJO映射到关系持久存储。在下面的映射中,DefaultPoint类映射到具有自动增量ID列的POINTS表以及与点的属性对应的列;Color类映射到COLORS表,其中一列对应于字符串值颜色属性。property元素表示标量值,而many-to-one元素表示引用:
lt;hibernate-mappinggt;
lt;class name=points.hib.DefaultPoint”
table=POINTS”gt;
lt;id name='id' column='ID' type='int'gt;
lt;generator class='native/'gt;
lt;/idgt;
lt;property name='x” column='X” type='double'/gt;
lt;property name='y' column='Y' type='double'/gt;
lt;many-to-one name='realColor' column='COLOR'/gt;
lt;/classgt;
lt;class name='points.hib.Color' table='COLORS'gt;
lt;id name='name' column='NAME' type='string'gt;
lt;generator class='assigned'/gt;
lt;/idgt;
lt;/classgt;
lt;/hibernate-mappinggt;
Hibernate附带了各种转换工具,可以独立方式或以编程方式调用。特别是,Hibernate可以从映射创建数据库模式,因此无需手动执行此操作。请注意参考值如何在结果模式中被约束为外键:
CREATE TABLE COLORS(
NAME VARCHAR(255) NOT NULL PRIMARY KEY
)
CREATE TABLE POINTS(
ID INTEGER
GENERATED BY DEFAULT AS IDENTITY(START WITH 1)
NOT NULL PRIMARY KEY,
X DOUBLE,
Y DOUBLE,
COLOR VARCHAR(255),
CONSTRAINT FOREIGN KEY(COLOR)
REFERENCES COLORS(NAME)
)
Hibernate提供了用于创建,选择,修改和删除映射对象的Java方法,这些方法自动转换为映射产生的数据库表上的SQL查询。我们将在DAO的实现中广泛使用它们(下一节)。
产生的DAO实施
现在我们可以实现基于Hibernate的DAO,如下所示
public class PlainHibernatePointDAO implements PointDAO {
//...
public Point find(final int id) {
Session session = ConnectionFactory.getInstance().getSession();
try {
return (Point) session.get(Point.class, id);
} catch (HibernateException e) {
System.err.println('Hibernate Exception' e.getMessage());
throw new RuntimeException(e);
} finally {
if (session != null) {
try {
session.close();
} catch (HibernateException e) {
System.err.println('Hibernate Error' e.getMessage());
throw new RuntimeException(e);
}
}
}
}
public Collection findAll() {
//...
// need join fetch to initialize subobjects
Query query = session.createQuery(
'from points.hib.DefaultPoint as p' 'join fetch p.realColor');
return query.list();
//...
}
}
大多数生成的实现方法看起来非常相似:获取会话对象,然后调用一个方法来操作对应于特定行的对象,或者在Hibernate查询语言(HQL)中提交查询,这是一个高级别的供应商 - SQL的独立抽象(查看findAll方法作为HQL的一个例子)。美学上没有吸引力且难以维护的是每个方法中20行样板异常处理代码,只有一行非常重要:
return (Point) session.get(Point.class, id);
对于访问会话对象所需的类似样板连接工厂,此实现还需要超过130行代码。幸运的是,正如我们所
剩余内容已隐藏,支付完成后下载完整资料
资料编号:[19684],资料为PDF文档或Word文档,PDF文档可免费转换为Word
课题毕业论文、文献综述、任务书、外文翻译、程序设计、图纸设计等资料可联系客服协助查找。