• Re: 使用开源Java框架开发WEB应用(转载)

    (四)

    提供一个服务定位器(Providing a Service Locator)

    既然我们已经将我们的Serices和DAO搭配起来了。我们需要把我们的Service显示到其他

    层。 这个通常是在Struts或者Swing这层里编码。一个简单方法就是用 服务定位器返回

    给Spring context 。当然,可以通过直接调用Spring中的Bean来做。

    下面是一个Struts Actin 中的服务定位器的一个例子。

    public abstract class BaseAction extends Action {

    private IOrderService orderService;

    public void setServlet(ActionServlet

    actionServlet) {

    super.setServlet(actionServlet);

    ServletContext servletContext =

    actionServlet.getServletContext();

    WebApplicationContext wac =

    WebApplicationContextUtils.

    getRequiredWebApplicationContext(

    servletContext);

    this.orderService = (IOrderService)

    wac.getBean("orderService");

    }

    protected IOrderService getOrderService() {

    return orderService;

    }

    }

    UI 层配置 (UI Layer Configuration)

    这个例子里UI层 使用了Struts framework. 这里我们要讲述一下在给程序分层的时候,

    哪些是和Struts部分的。我们就从一个Struts-config.xml文件中的Action的配置信息

    开始吧。

    struts-config.xml file.

    <action path="/SaveNewOrder"

    type="com.meagle.action.SaveOrderAction"

    name="OrderForm"

    scope="request"

    validate="true"

    input="/NewOrder.jsp">

    <display-name>Save New Order</display-name>

    <exception key="error.order.save"

    path="/NewOrder.jsp"

    scope="request"

    type="com.meagle.exception.OrderException"/>

    <exception key="error.order.not.enough.money"

    path="/NewOrder.jsp"

    scope="request"

    type="com.

    meagle.

    exception.

    OrderMinimumAmountException"/>

    <forward name="success" path="/ViewOrder.jsp"/>

    <forward name="failure" path="/NewOrder.jsp"/>

    </action>

    SaveNewOrder 这个Action是用来持久化UI层里的表单提交过来Order的。这是Struts中

    一个很典型的Action;  注意观察这个Action中exception配置,这些Exceptions也在Sp

    ring 配置文件(applicationContext-hibernate.xml)中配置了(就在 business servi

    ce object 的transactionAttributes属性里)。 当异常在业务层被被抛出时,我们可

    以控制他们,并适当的显示给UI层。

    第一个异常,OrderException,在持久层保存order对象失败的时候被触发。这将导致事

    物回滚并且通过BO把异常回传到Struts这一层。

    第二个异常,OrderMinimumAmountException也同第一个一样。

    搭配整和的最后一步 通过是让你显示层和业务层相结合。这个已经被服务定位器(ser

    vice locator)实现了(前面讨论过了), 这里服务层作为一个接口提供给我们的业务

    逻辑和持久层。

    SaveNewOrder Action 在Struts中用一个服务定位器(service locator)来调用执行业

    务方法的。 方法代码如下:

    public ActionForward execute(

    Actionmapping mapping,

    ActionForm form,

    javax.servlet.http.HttpServletRequest request,

    javax.servlet.http.HttpServletResponse response)

    throws java.lang.Exception {

    OrderForm oForm = (OrderForm) form;

    // Use the form to build an Order object that

    // can be saved in the persistence layer.

    // See the full source code in the sample app.

    // Obtain the wired business service object

    // from the service locator configuration

    // in BaseAction.

    // Delegate the save to the service layer and

    // further upstream to save the Order object.

    getOrderService().saveNewOrder(order);

    oForm.setOrder(order);

    ActionMessages messages = new ActionMessages();

    messages.add(

    ActionMessages.GLOBAL_MESSAGE,

    new ActionMessage(

    "message.order.saved.successfully"));

    saveMessages(request, messages);

    return mapping.findForward("success");

    }

    总结

    这篇文章在技术和构架方面掩盖了很多低层的基础信息, 文章的主要的意图在

    于让你意识到如何给你应用程序分层。  分层可以“解耦”你的代码——允许新的组件

    被添加进来,而且让你的代码易于维护。  这里用到的技术只是专注于把“解偶”做好

    。 不管怎样,使用这样的构架可以让你用其他技术代替现在的层。 例如,你可能不使

    用Hibernate实现持久化。既然你在DAO中面向接口的编程的,所以你完全可以用iBATIS

    来代替。或者,你也可能想用Struts外的其他的技术或者框架替换现在的UI层(转换久

    层,实现层并不应该直接影响到你的业务逻辑和业务服务层)。 用适当的框架搭建你的

    Web应用,其实也不是一件烦琐的工作,更主要的是它“解耦”了你程序中的各个层。

    后记:

    看完这篇文章后,只是觉得很喜欢,于是就翻译了,当然同时也准备着挨大家扔

    来的鸡蛋:)。

    这篇文章里并没有太多的技术细节,和详细的步骤。如果你从未使用过这些框架

    而在运行实例程序遇上困难的话,可以到CSDN论坛Java Open Source版发贴,我一定会

    详细解答的(啊哦,这不算做广告吧?),

    文章是从一个构架的角度讲述了如何搭配现有的开源框架进行分层,  有太多的

    术语我都不知道怎么表达,而且可能有很多语句存在错误。如果影响了你的阅读,请你

    直接点原文地址,我同时也象你说声抱歉。

    作者简介:Mark Eagle 高级软件工程师,亚特兰大。

    翻    译:Totodo(zhangli@telecomjs.com) 软件工程师

    参考:

    Struts:http://jakarta.apache.org/struts/index.html

    Spring: http://www.springframework.org

    Hibernate: http://www.hibernate.org

    http://www.hibernate.org.cn

    关于控制反转IOC和依赖注射:http://www.martinfowler.com/articles/injection.ht

    ml

    作者Blog:http://blog.csdn.net/totodo/

    【 在 diaochong (充实的雕虫~~小猪) 的大作中提到: 】

    : 下面是HibernateSessionFactory 和  HibernateTransactionManager:的配置:

    : <bean id="mySessionFactory"

    :        class="org.springframework.orm.hibernate.

    : ...................

    2004-08-11
  • Re: 使用开源Java框架开发WEB应用(转载)

    (三)

    下面是HibernateSessionFactory 和  HibernateTransactionManager:的配置:

    <bean id="mySessionFactory"

    class="org.springframework.orm.hibernate.

    LocalSessionFactoryBean">

    <property name="mappingResources">

    <list>

    <value>

    com/meagle/bo/Order.hbm.xml

    </value>

    <value>

    com/meagle/bo/OrderLineItem.hbm.xml

    </value>

    </list>

    </property>

    <property name="hibernateProperties">

    <props>

    <prop key="hibernate.dialect">

    net.sf.hibernate.dialect.MySQLDialect

    </prop>

    <prop key="hibernate.show_sql">

    false

    </prop>

    <prop key="hibernate.proxool.xml">

    C:/MyWebApps/.../WEB-INF/proxool.xml

    </prop>

    <prop key="hibernate.proxool.pool_alias">

    spring

    </prop>

    </props>

    </property>

    </bean>

    <!-- Transaction manager for a single Hibernate

    SessionFactory (alternative to JTA) -->

    <bean id="myTransactionManager"

    class="org.

    springframework.

    orm.

    hibernate.

    HibernateTransactionManager">

    <property name="sessionFactory">

    <ref local="mySessionFactory"/>

    </property>

    </bean>

    可以看出:每个对象都可以在Spring 配置信息中用<bean>标签引用。在这里,mySessi

    onFactory引用了HibernateSessionFactory,而myTransactionManager引用了Hibernat

    eTransactionManage。  注意代码中myTransactionManger Bean有个sessionFactory属

    性。  HibernateTransactionManager有个sessionFactory setter 和 getter方法,这

    是用来在Spring启动的时候实现“依赖注入” (dependency injection)的。  在ses

    sionFactory 属性里 引用mySessionFactory。这两个对象在Spring容器初始化后就被组

    装了起来了。 这样的搭配让你从 单例(singleton objects)和工厂(factories)中

    解放了出来,降低了代码的维护代价。 mySessionFactory.的两个属性,分别是用来注

    入mappingResources 和 hibernatePropertes的。通常,如果你在Spring之外使用Hibe

    rnate,这样的设置应该放在hibernate.cfg.xml中的。 不管怎样,Spring提供了一个便捷

    的方式-----在Spring内部配置中并入了Hibernate的配置。 如果要得到更多的信息,可

    以查阅Spring API。

    既然我们已经组装配置好了Service Beans,就需要把Business Service Object和 DAO

    也组装起来,并把这些对象配到一个事务管理器(transaction manager)里。

    在Spring中的配置信息:

    <!-- ORDER SERVICE -->

    <bean id="orderService"

    class="org.

    springframework.

    transaction.

    interceptor.

    TransactionProxyFactoryBean">

    <property name="transactionManager">

    <ref local="myTransactionManager"/>

    </property>

    <property name="target">

    <ref local="orderTarget"/>

    </property>

    <property name="transactionAttributes">

    <props>

    <prop key="find*">

    PROPAGATION_REQUIRED,readOnly,-OrderException

    </prop>

    <prop key="save*">

    PROPAGATION_REQUIRED,-OrderException

    </prop>

    </props>

    </property>

    </bean>

    <!-- ORDER TARGET PRIMARY BUSINESS OBJECT:

    Hibernate implementation -->

    <bean id="orderTarget"

    class="com.

    meagle.

    service.

    spring.

    OrderServiceSpringImpl">

    <property name="orderDAO">

    <ref local="orderDAO"/>

    </property>

    </bean>

    <!-- ORDER DAO OBJECT -->

    <bean id="orderDAO"

    class="com.

    meagle.

    service.

    dao.

    hibernate.

    OrderHibernateDAO">

    <property name="sessionFactory">

    <ref local="mySessionFactory"/>

    </property>

    </bean>

    图4 是我们对象搭建的一个提纲。 从中可以看出,每个对象都联系着Spring,并且能通

    过Spring注入到其他对象。把它与Spring的配置文件比较,观察他们之间的关系

    图 4. Spring就是这样基于配置文件,将各个Bean搭建在一起。

    这个例子使用一个TransactionProxyFactoryBean,它定义了一个setTransactionManag

    er()。 这对象很有用,他能很方便的处理你申明的事物还有Service Object。    你可

    以通过transactionAttributes属性来定义怎样处理。 想知道更多还是参考Transactio

    nAttributeEditor吧。

    TransactionProxyFactoryBean 还有个setter. 这会被我们 Business service object

    (orderTarget)引用, orderTarget定义了 业务服务层,并且它还有个属性,由setO

    rderDAO()引用。这个属性

    Spring 和Bean 的还有一点要注意的: bean可以以用两种方式创造。 这些都在单例模

    式(Sington)和原型模式(propotype)中定义了。  默认的方式是singleton,这意味

    着共享的实例将被束缚。 而原形模式是在Spring用到bean的时候允许新建实例的。当每

    个用户需要得到他们自己Bean的Copy时,你应该仅使用prototype模式。(更多的请参考

    设计模式中的单例模式和原形模式)

    【 在 diaochong (充实的雕虫~~小猪) 的大作中提到: 】

    : 一个简单例子

    : 既然我们已经从全局上理解这些组件。 现在就让我们开始实践吧。 我们还是用 Strut

    : s,Spring 和Hibernate。这三个框架已经被描述够多了,这里就不重复介绍了。 这篇

    : ...................

    2004-08-11
  • Re: 使用开源Java框架开发WEB应用(转载)

    (二)

    一个简单例子

    既然我们已经从全局上理解这些组件。 现在就让我们开始实践吧。 我们还是用 Strut

    s,Spring 和Hibernate。这三个框架已经被描述够多了,这里就不重复介绍了。 这篇

    文章举例指导你如何使用这三个框架整合开发, 并向你揭示 一个请求是如何贯穿于各个

    层的。(从用户的加入一个Order到数据库,显示;进而更新、删除)。

    从这里可以下载到程序程序原代码(download)

    既然每个层是互相作用的,我们就先来创建domain objects。首先,我们要在这些Obje

    ct中要确定那些是需要持久化的,哪些是提供给business logic,那些是显示接口的设

    计。  下一步,我们将配置我们的持久层并且定义好Hibernate的OR mappings。然后定

    义好Business Objects。有了这些组成部分之后,我们将 使用Spring把这些连接起来。

    最后,我们提供给Spring一个持久层,从这个持久层里我们可以知道它是如何与业务逻

    辑层(business service layer)通信的,以及它是怎样处理其他层抛出的异常的。。

    域对象层(Domain Object Layer)

    这层是编码的着手点,我们的编码就从这层开始。 例子中Order 与OrderItem 是一个O

    ne—To—Many的关系。 下面就是Domain Object Layer的两个对象:

    ·     com.meagle.bo.Order.java: 包含了一个Order的概要信息

    ·     com.meagle.bo.OrderLineItem.java: 包含了Order的详细信息

    好好考虑怎你的package命名,这反应出了你是怎样分层的。 例如 domain objects在程

    序中可能打包在com.meagle.bo内。  更详细一点将打包在com. meagle.bo的子目录下面

    。business logic应该从com.meagle.serice开始打包,而DAO 对象应该位于com.meagl

    e.service.dao.hibernate。反应Forms和Actions的 持久对象(presentation classes

    ) 应该分别放在 com.meagle.action和com.meagle.forms包。 准确的给包命名使得你

    的classes很好分割并且易于维护,并且在你添加新的classes时,能使得程序结构上保

    持上下一致。

    持久层的配置(Persistence Layer Configuration)

    建立Hibernate的持久层 需要好几个步骤。 第一步让我们把BO持久化。 既然Hibernat

    e是通过POJO工作的, 因此Order和 OrderLineItem对象需要给所有的fileds 加上gett

    er,setter方法。 Hibernate通过XML文件来映射(OR)对象,以下两个xml文件分别映射了

    Order 和OrderItem对象。(这里有个叫XDoclet工具可以自动生成你的XML影射文件)

    Order.hbm.xml

    OrderLineItem.hbm.xml

    你可以在WebContent/WEB-INF/classes/com/meagle/bo目录下找到这些xml文件。Hiber

    nate的 SessionFactory 是用来告诉程序 应该与哪个数据库通信,该使用哪个连接池或

    使用了DataSource, 应该加载哪些持久对象。而Session接口是用来完成Selecting,S

    aving,Delete和Updating这些操作。 后面的我们将讲述SessionFactory和Session是怎

    样设置的。

    业务层的配置(Business Layer Configuration)

    既然我们已经有了domain objects,接下来我们就要business service objects了,用

    他们来执行程序的logic,调用持久层,得到UI层的requests,处理transactions,并且控

    制exceptions。 为了将这些连接起来并且易于管理,我们将使用面向方面的 SpringFr

    amework。 Spring 提供了 控制倒置(inversion of control 0==IoC)和注射依赖设置

    (setter dependency injection)这些方式(可供选择),用XML文件将对象连接起来

    。 IoC是一个简单概念(它允许一个对象在上层接受其他对象的创建),用IoC这种方式

    让你的对象从创建中释放了出来,降低了偶合度。

    这里是一个没有使用IoC的对象创建的例子,它有很高偶合度。

    图 2.没有使用 IoC.    A 创建了 B 和 C

    而这里是一个使用IoC的例子,这种方式允许对象在高层可以创建并进入另外一个对象,

    所以这样可以直接被执行。

    图 3. 对象使用了 IoC。 A 包含了接受B,C的 setter方法 , 这同样达到了 由A创建B,

    C的目的。

    建立我们的业务服务对象(Building Our Business Service Objects)

    Business Object中的Setter方法接受的是接口,这样我们可以很松散的定义对象实现,

    然后注入。 在我们的案例中,我们将用一个business service object接收一个DAO,用

    它来控制domain objects的持久化。  由于在这个例子中使用了Hibernate,我们可以很

    方便的用其他持久框架实现 同时通知Spring 有新的DAO可以使用了。

    在面向接口的编程中,你会明白 “注射依赖”模式是怎样松散耦合你的业务逻辑和持久

    机制的:)。

    下面是一个接口business service object,DAO代码片段:

    public interface IOrderService {

    public abstract Order saveNewOrder(Order order)

    throws OrderException,

    OrderMinimumAmountException;

    public abstract List findOrderByUser(

    String user)

    throws OrderException;

    public abstract Order findOrderById(int id)

    throws OrderException;

    public abstract void setOrderDAO(

    IOrderDAO orderDAO);

    }

    注意到这段代码里有一个 setOrderDao(),它就是一个DAO Object设置方法(注射器

    )。 但这里并没有一个getOrderDao的方法,这不必要,因为你并不会在外部访问这个

    orderDao。这个DAO Objecte将被调用,和我们的persistence layer 通信。我们将用S

    pring把DAO Object 和 business service object搭配起来的。因为我们是面向接口编

    程的,所以并不需要将实现类紧密的耦合在一起。

    接下去我们开始我们的DAO的实现类进行编码。 既然Spring已经有对Hibernate的支持,

    那这个例子就直接继承HibernateDaoSupport类了,这个类很有用,我们可以参考Hiber

    nateTemplate(它主要是针对HibernateDaoSupport的一个用法,译注:具体可以查看S

    rping 的API)。 下面是这个DAO接口代码:

    public interface IOrderDAO {

    public abstract Order findOrderById(

    final int id);

    public abstract List findOrdersPlaceByUser(

    final String placedBy);

    public abstract Order saveOrder(

    final Order order);

    }

    我们仍然要给我们持久层组装很多关联的对象,这里包含了HibernateSessionFactory

    和TransactionManager。 Spring 提供了一个  HibernateTransactionManager,他用线

    程捆绑了一个Hibernate Session,用它来支持transactions(请查看ThreadLocal) 。

    【 在 diaochong (充实的雕虫~~小猪) 的大作中提到: 】

    : 本文转载自CSDN文档中心,刊登在<开发高手>2004年6月期

    : 使用open source产品组装你的web应用架构(一)

    : 其实,就算用Java建造一个不是很烦琐的web应用,也不是件轻松的事情。 在构架的一

    : ...................

    2004-08-11
  • 使用开源Java框架开发WEB应用(转载)

    本文转载自CSDN文档中心,刊登在<开发高手>2004年6月期

    使用open source产品组装你的web应用架构

    (一)

    其实,就算用Java建造一个不是很烦琐的web应用,也不是件轻松的事情。 在构架的一

    开始就有很多事情要考虑。 从高处看,摆在开发者面前有很多问题:要考虑是怎样建立

    用户接口?在哪里处理业务逻辑? 怎样持久化的数据。 而这三层构架中,每一层都有

    他们要仔细考虑的。 各个层该使用什么技术? 怎样的设计能松散耦合还能灵活改变?

    怎样替换某个层而不影响整体构架?应用程序如何做各种级别的业务处理(比如事务处

    理)?

    构架一个Web应用需要弄明白好多问题。 幸运的是,已经有不少开发者已经遇到过这类

    问题,并且建立了处理这类问题的框架。 一个好框架具备以下几点: 减轻开发者处理

    复杂的问题的负担(“不重复发明轮子”); 内部有良好的扩展; 并且有一个支持它

    的强大的用户团体。  好的构架一般有针对性的处理某一类问题,并且能将它做好(Do

    One Thing well)。 然而,你的程序中有几个层可能需要使用特定的框架,已经完成

    的UI(用户接口) 并不代表你也可以把你的业务逻辑和持久逻辑偶合到你的UI部分。  举

    个例子, 你不该在一个Controller(控制器)里面写JDBC代码作为你的业务逻辑, 这不

    是控制器应该提供的。  一个UI 控制器应该委派给其它给在UI范围之外的轻量级组件。

    好的框架应该能指导代码如何分布。 更重要的是,框架能把开发者从编码中解放出来

    ,使他们能专心于应用程序的逻辑(这对客户来说很重要)。

    这篇文章将讨论怎样结合几种著名的框架来使得你的应用程序做到松弛耦合。

    如何建立你的架构,并且怎样让你的各个应用层保持一致。?如何整合框架以便让每个

    层在以一种松散偶合的方式彼此作用而不用管低层的技术细节?这对我们来说真是一种

    挑战。  这里讨论一个整合框架的策略( 使用3 种受欢迎的开源框架)  :表示层我们用

    Struts; 业务层我们用Spring;而持久层则用Hibernate。 你也可以用其他FrameWork

    替换只要能得到同样的效果。 见图1 (框架组合示意图)

    应用程序的分层

    大部分的Web应用在职责上至少能被分成4层。 这四层是:presentation(描述),per

    sistence(持久),business(业务)和domain model(域模块)。每个层在处理程序

    上都应该有一项明确的责任, 而不应该在功能上与其它层混合,并且每个层要与其它层

    分开的,但要给他们之间放一个通信接口。   我们就从介绍各个层开始,讨论一下这些

    层应该提供什么,不应该提供什么。

    表示层(The Presentation Layer)

    一般来讲,一个典型的Web应用的的末端应该是表示层。 很多Java发者也理解Struts所

    提供的。 象业务逻辑之类的被打包到org.apache.struts.Action., 因此,我们很赞成

    使用Struts这样的框架。

    下面是Struts所负责的:

    *  管理用户的请求,做出相应的响应。

    *  提供一个Controller ,委派调用业务逻辑和其它上层处理。

    *  处理异常,抛给Struts Action

    *  为显示提供一个模型

    *  UI验证。

    以下条款,不该在Struts显示层的编码中经常出现。 它们与显示层无关的。

    * 直接的与数据库通信,例如JDBC调用。

    * 与你应用程序相关联的业务逻辑以及校验。

    * 事物管理。

    在表示层引入这些代码,则会带来高偶合和麻烦的维护。

    持久层(The Persistence Layer)

    典型的Web应用的另一个末端是持久层。这里通常是程序最容易失控的地方。开发者总是

    低估构建他们自己的持久框架的挑战性。系统内部的持续层不但需要大量调试时间,而

    且还经常缺少功能使之变得难以控制,这是持久层的通病。 还好有几个ORM开源框架很

    好的解决了这类问题。尤其是Hibernate。 Hibernate为java提供了OR持久化机制和查询

    服务, 它还给已经熟悉SQL和JDBC API 的Java开发者一个学习桥梁,他们学习起来很方

    便。 Hibernate的持久对象是基于POJO和Java collections。此外,使用Hibernate并不

    妨碍你正在使用的IDE。

    请看下面的条目,你在持久层编码中需要了解的。

    *  查询对象的相关信息的语句。 Hibernate通过一个OO查询语言(HQL)或者正则表达

    的API来完成查询。  HQL非常类似于SQL-- 只是把SQL里的table和columns用Object和它

    的fields代替。 你需要学习一些新的HQL语言; 不管怎样,他们容易理解而文档也做的

    很好。 HQL是一种对象查询的自然语言,花很小的代价就能学习它。

    *  如何存储,更新,删除数据库记录。

    *  象Hibernate这类的高级ORM框架支持大部分主流数据库,并且他们支持 Parent/chi

    ld关系,事物处理,继承和多态。

    业务层(The Business Layer)

    一个典型Web应用的中间部分是业务层或者服务层。 从编码的视角来看,这层是最

    容易被忽视的一层。 而我们却往往在UI层或持久层周围看到这些业务处理的代码,这其

    实是不正确的,因为它导致了程序代码的紧密偶合,这样一来,随着时间推移这些代码

    很难维护。幸好,针对这一问题有好几种Frameworks存在。 最受欢迎的两个框架是Spr

    ing和PicoContainer。 这些为也被称为microcontainers,他们能让你很好的把对象搭

    配起来。 这两个框架都着手于‘依赖注射’(dependency injection)(还有我们知道的

    ‘控制反转’Inversion of Control=IoC)这样的简单概念。 这篇文章将关注于Spring

    的注射(译注:通过一个给定参数的Setter方法来构造Bean,有所不同于Factory), Sp

    ring还提供了Setter Injection(type2),Constructor Injection(type3)等方式供我们

    选择。  Spring把程序中所涉及到包含业务逻辑和Dao的Objects——例如transaction

    management handler(事物管理控制)、Object Factoris(对象工厂)、service objec

    ts(服务组件)——都通过XML来配置联系起来。

    后面我们会举个例子来揭示一下Spring 是怎样运用这些概念。

    业务层所负责的如下:

    * 处理应用程序的 业务逻辑和业务校验

    * 管理事物

    * 允许与其它层相互作用的接口

    * 管理业务层级别的对象的依赖。

    * 在显示层和持久层之间增加了一个灵活的机制,使得他们不直接的联系在一起。

    * 通过揭示 从显示层到业务层之间的Context来得到business services。

    * 管理程序的执行(从业务层到持久层)。

    域模块层(The Domain Model Layer )

    既然我们致力于的是一个不是很复杂的Web的应用, 我们需要一个对象集合,让它在不

    同层之间移动的。  域模块层由实际需求中的业务对象组成 比如, OrderLineItem , P

    roduct等等。 开发者在这层 不用管那些DTOs,仅关注domain object即可。 例如,Hi

    bernate允许你将数据库中的信息存放入对象(domain objects),这样你可以在连接断

    开的情况下把这些数据显示到UI层。 而那些对象也可以返回给持续层,从而在数据库里

    更新。 而且,你不必把对象转化成DTOs(这可能似的它在不同层之间的在传输过程中丢

    失),这个模型使得Java开发者能很自然运用OO,而不需要附加的编码。

    2004-08-11
  • Re: 蔚蓝竞争简析

    前两次在蔚蓝定书觉的不如以前省心了,尤其配送站取消了后

    【 在 danielsdk (sdk) 的大作中提到: 】

    : 从业态来说, 当当,卓越,蔚蓝同属网上书店。

    : 互联网商业是无疆界的, 当当,卓越起步较早,

    : 又有强大的资本储备,是否意味着蔚蓝一定无法同他们竞争吗?

    : ...................

    2004-08-06
  • Re: xmlspy 2004用网上的注册码怎么不好用?

    这点最关键

    【 在 edor (edor) 的大作中提到: 】

    : 补充一个,要离线注册。

    2004-07-31
  • 昨天在学院一楼会议室捡了100元钱

    晚上捡的,应该是白天用过会议室的老师或者学生掉的。

    失主请快来117室第一个位子找我,否则明天下午就不在了,

    八月才能回来。

    2004-07-17
  • Re: 网格的杂谈

    按照网格提出的构想,已经不是技术能解决得了得问题了。

    首先提高网络带宽是根本;

    其次普及科学界和普通用户的计算机使用水平。

    【 在 winberg (洪福齐天) 的大作中提到: 】

    : 这些困惑也许是网格的规模还太小的缘故

    : 如果网格发展到了一定程度,网格服务极大丰富,需要解决一个问题,可能

    : 并不一定是计算问题,也许网格的好处久体现出来了,

    : ...................

    2004-07-15
  • Re: [公告]j2ee项目征集

    足球经理的online提议不错,新浪前一阵的那个bug太多了。

    我想这个小的项目,

    应该还是选取能够体现J2EE技术特点的项目。

    最好先把大致需要达到的技术目的,

    还有主要的参与者能够基本确定一个范围。

    进度,开发方式都有一个大致的设想。

    还需要大家群策群力啊

    【 在 cataract (大猩猩·小兔子的守护神) 的大作中提到: 】

    : 要说专业其实哪个不专业呢?都要了解业务模型吧。

    : 对不熟悉的人来说,都是要学习的。

    : 我认为游戏在这方面还至少有个感觉上的认识。

    : ...................

    2004-07-15
  • [合集] 自动增长类型在ejb中怎么处理

    ☆─────────────────────────────────────☆

     wsed (糊涂龙) 于  (Sun Jun 27 13:53:58 2004)  提到:

    请指教

    ☆─────────────────────────────────────☆

     wupher (刺猬) 于  (Sun Jun 27 21:59:42 2004)  提到:

    插NULL就可以了吧。

    ☆─────────────────────────────────────☆

     ma3r (艾菲尔) 于  (Mon Jun 28 08:43:39 2004)  提到:

    我记得不行。JBuilder 里有地方设的。

    【 在 wupher (刺猬) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     diaochong (充实的雕虫~~小猪) 于  (Tue Jun 29 10:01:34 2004)  提到:

    要是主键肯定不行。

    自己用点技巧可以解决,比如在什么地方记录一下。

    EJB是否有支持就不清楚了。

    【 在 wupher (刺猬) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     sykis (无名) 于  (Tue Jun 29 11:10:07 2004)  提到:

    建议不要使用自动增长类型,那样无法取得生成的id

    自己写一个生成唯一id的类比较好,Java Enterprise Best Practices那本书上有个不错的解决方案

    【 在 wsed (糊涂龙) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     wupher (刺猬) 于  (Tue Jun 29 12:55:40 2004)  提到:

    或者采用数据库提供的函数生成ID亦可,

    采用EJB的话,TSS上有相关模式可以参考,亦可见EJB Patterns上面的记述。

    【 在 sykis (无名) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     lww209 (后来) 于  (Tue Jun 29 16:41:30 2004)  提到:

    法1,在数据库中将你要自动增长的属性的设一个种子,例如在SQL2000中,在企业管理器中就可以设,设置"标识"为"是",标识种子为1,增量为1,如果你用jbuilder的话,你可以在EJB Moudule DD Editor中有一个选项是Automatic primary key generation 中的Enable选为是,就可以自动增长了!

    法2,在建立一个表,这个表可以设置2个属性,一个作为主键,另一个属性是一直都在变的量,写一个方法让其每次调用都加1,在与你的需要的实体bean作关联,什么的都可以!

    你看行不行,我以前用过!你试试吧!

    【 在 wsed (糊涂龙) 的大作中提到: 】

    : 请指教

    : 插NULL就可以了吧。

    : 插NULL就可以了吧。

    : 请指教

    : 建议不要使用自动增长类型,那样无法取得生成的id

    : 自己写一个生成唯一id的类比较好,Java Enterprise Best Practices那本书上有个不错的解决方案

    2004-06-30
  • Re: 周日回趟学校,和本科的哥们一起吃饭看球

    27日中午考过试,睡了一觉,和MM匆匆登上去天大的校车(在清华西北门东边的车棚)。

    6点半不到,就到了天大东门。第一印象是东门不让进车了,花圃不见了!!!改成一个喷泉广场,居然能够看到北洋大学堂。MM第一次去,颇为欣喜学校的景色,尤其是敬业湖的水。宿舍的兄弟已经在北洋广场等着我们了,大家又一年不见了,一眼看见还是有点兴奋的。

    寒暄过后去东门外气象台道吃炖骨头,又打车去避风堂打牌看球。我们大胜,呵呵,很

    高兴;捷克队又奉献了三个精彩的进球。早上5点多出来去永强豆浆坊,当年考研时去过多次的地方吃了顿早点,感觉豆浆没有以前好喝了。

    大家在一起转了转看了看学校的晨景,很多老太太在北洋广场跳舞,还有不少人在科学楼外打太极。居然一个我们系97的师兄也在练,印象中他以前就是学院里有名的太极师徒之一。和宿舍的同学分别后,在爱晚湖边看到了当年的电力系统老师,真高兴,和他说了会话。然户在北洋大学堂见了我的一个好朋友,年级的科研型高手,他直博两年了,变化不小,成熟了不少。送我们出了东门。感觉学校里正在基建,路上比较脏,美中不足。

    和MM去了水上公园,门票太ft了,居然要25,我记得当年是10元。我们走了一会,困的不行了,在一个岛上亭子里睡了一会,真香。醒来后继续走发现动物园居然要门票了!更加ft。掉头回,本来以为要扫兴而归了,居然发现了去水上东门的一路好景,以前我也没有去过的,呵呵,猛拍了几十张照片。

    中午去南开外面的狗不理快餐吃了午饭,坐8路车去东站。8路车和50路都改成新车了。坐火车回北京,到了清华3点多了,整整去了24小时,基本没有睡觉。去游泳馆舒舒服服的泡了泡,洗个澡睡了,知道今天早上9点。现在坐在实验室里还感觉有点耳鸣呢,呵呵。

    现在知道,在天大,之所以有亲切感,不仅因为是母校,还因为有多年的好朋友和恩师。

    【 在 windend (长江水) 的大作中提到: 】

    : 现在这个版面的精华区里有啊

    : 两校交流里面

    2004-06-29
  • 大家觉得这样干合理吗

    项目头让我把WSDL的东西全部解开,

    然后放到关系数据库里面去。

    为了做这个事情,设计了8,9张表。

    比如binding一张表,bingding里面的operation又是一张表。

    有人这么干吗?有什么合理的建议方法吗

    2004-06-16
  • TJU校友diaochong报到

    我的id:

    diaochong

    我在天大bbs(任意)的id:

    diaochong

    我在天大的年级 专业:

    98级电气工程

    我现在所在地:

    清华大学15号楼

    要对天大说的话  :):

    您好,母校

    2004-06-10
  • [合集] EJB初学者问

    ☆─────────────────────────────────────☆

     fansle (首席泡面专家) 于  (Tue Jun  1 11:32:11 2004)  提到:

    第一个问题:interface采用remote和local的区别

    local是不是只能在同一个应用服务器里面使用,而remote都可以?

    第二个问题:sessionbean的Stateful表现在哪里

    按照相同的参数create的远程接口的2个实例是不是同一个?

    ☆─────────────────────────────────────☆

     pwlazy (swing) 于  (Tue Jun  1 15:43:27 2004)  提到:

    个人理解如下:

    1)remote是一般指客户与服务在不同的机器上

    ,当然布置在相同的机器上也是可以的,local指两者在同一个jvm中

    2)状态表现在:状态bean包含了一些状态数据(与特定用户相关),每个与ejbobject相连的bean都不一样,而且状态bean存在一个激活与钝化的问题,此时将会保存或取出相应的状态数据。。。

    ☆─────────────────────────────────────☆

     fansle (首席泡面专家) 于  (Tue Jun  1 17:13:44 2004)  提到:

    我要在2个servlet里面使用同一个有状态的sessionbean的话,怎么取得对这个sessionbean实例的引用?

    我原本以为是只要create()的参数的值是一样的,比如我在servlet1里面create("test")在servlet2里面也create("test")得到的是同一个实例,测试了一下好像不是这回事,请指教

    【 在 pwlazy (swing) 的大作中提到: 】

    ☆─────────────────────────────────────☆

     pwlazy (swing) 于  (Tue Jun  1 17:32:39 2004)  提到:

    个人理解如下:

    1)客户端不可能取得sessionbean的引用(j2ee规范也不许这么做),只能取得将sessionbean包装起来的ejbobject的stub,或者说引用吧

    2)如果两个servlet需取得同一个ejbobject得引用,也许需要两者通信

    3)同时采用create(“test”),返回的是两个ejboject的引用,至于这两个ejbobject是否包装了同一个session bean,很难讲,这要依靠容器的算法,不过这似乎并不重要

    【 在 fansle (首席泡面专家) 的大作中提到: 】

    【 在 fansle (首席泡面专家) 的大作中提到: 】

    : 第一个问题:interface采用remote和local的区别

    : local是不是只能在同一个应用服务器里面使用,而remote都可以?

    : 第二个问题:sessionbean的Stateful表现在哪里

    : ...................

    : 个人理解如下:

    : 1)remote是一般指客户与服务在不同的机器上

    : ,当然布置在相同的机器上也是可以的,local指两者在同一个jvm中

    : ...................

    : 我要在2个servlet里面使用同一个有状态的sessionbean的话,怎么取得对这个sessionbean实例的引用?

    : 我原本以为是只要create()的参数的值是一样的,比如我在servlet1里面create("test")在servlet2里面也create("test")得到的是同一个实例,测试了一下好像不是这回事,请指教

    2004-06-03
  • Sun的一个认证消息

    http://gceclub.sun.com.cn/event/apec-hcb/index.html

    2004-06-01
  • Re: Java开发教程--qyjohn版 [7]

    顶一个。

    怪不得最近都不去room了,不知道数据有没有上去,我觉得人气

    比以前好了一些了

    【 在 qyjohn (Sweet Potato -- 清扬婉兮,适我愿兮) 的大作中提到: 】

    : 作业7:一个简单的多用户游戏的加强版

    : 在开始教程7 之前我需要向各位网友道个歉,这个星期单位里

    : 事情比较多,没有能够及时地将这个教程的内容贴上来。不过

    : ...................

    2004-05-28
  • Re: 问个有关EJB-QL的简单问题

    like后面写成:

    concat(concat(%,?1),%)试试,忘了参数是否有引号

    【 在 zengweixiong (雄哥) 的大作中提到: 】

    :     我现在么模糊查询,我得语句是SELECT OBJECT(O) FROM ExhibBoothInfo AS O WHERE O.boothName LIKE '%?1%'。其中?1是输入的参数。请问我这个语句错在那儿?怎么老的不到答案?

    :     如果SELECT OBJECT(O) FROM ExhibBoothInfo AS O WHERE O.boothName=?1我却能够得完全匹配查询的答案

    :     谁帮我解答一下?谢谢

    : ...................

    2004-05-23
  • [合集] 请问如何在jsp下实现打印报表的功能?(多谢!)

    ☆─────────────────────────────────────☆

     zhangbin (zhangbin ) 于  (Wed May 19 20:49:42 2004)  提到:

    做一个大作业,实现的功能是可以把报表输出到文件中,可以预览报表、打印报表等。由于第一次做,没有一点思路,望指点一下。多谢!!!

    ☆─────────────────────────────────────☆

     oosky (j2ee) 于  (Wed May 19 21:07:17 2004)  提到:

    jfreereport

    可能会对你有帮助。

    www.jfree.org

    ☆─────────────────────────────────────☆

     Kun (发呆鱼~..佛克西西) 于  (Wed May 19 23:15:41 2004)  提到:

    jexcelapi

    poi

    【 在 zhangbin (zhangbin ) 的大作中提到: 】

    【 在 zhangbin (zhangbin ) 的大作中提到: 】

    : 做一个大作业,实现的功能是可以把报表输出到文件中,可以预览报表、打印报表等。由于第一次做,没有一点思路,望指点一下。多谢!!!

    : 做一个大作业,实现的功能是可以把报表输出到文件中,可以预览报表、打印报表等。由于第一次做,没有一点思路,望指点一下。多谢!!!

    2004-05-20
  • Re: 求助:WEBLOGIC SERVER7的配置中定义连接数据库属性的问题!�

    name随便起,

    其他只用设URL,Driver Name,properties三项,用户名密码写到properties里面,类似

    user=sa

    password=123

    剩下的不用设了

    【 在 happyCarol (新鲜多一点) 的大作中提到: 】

    : WEBLOGIC SERVER7的配置中已经启动服务器,进入http://localhost:7001/console这个页面后,开始

    : 定义连接属性的时候,我是这样填的

    : Name: MyJDBC Connection Pool

    : ...................

    2004-05-19
  • 【原创】雕虫学习笔记系列之四(EJB设计模式)
    loading ...
    loading ...

    雕虫学习笔记系列

    之四

    diaochong

    2004-5-18

    Session Facade模式与DTO

    正如别的设计模式一样,EJB设计模式是用来解决开发EJB过程中的常见的问题,提供给开发人员好的经验总结。目前来说,可能用的最多的就是会话外观模式(Session Facade)和数据传送对象模式(DTO)了。使用这两种模式组成的架构体系,至少可以保证一个严格区分的,整洁的业务层次逻辑,同时提高了层间工作效率,为一个成功的J2EE应用打下了坚实的基础。

    在介绍具体的模式之前,我们先设想这样的一个具体应用:我们需要为一个大学的图书馆搭建一套系统,至少具有图书管理(包括图书查询,图书登记),借阅管理(借书,还书),和用户管理(增,删,查)三部分功能,要求要用三层架构,采用EJB技术来实现。一般的考虑在后台数据库中,会至少建三张表,一张UserInfo存放用户信息,一张存放BookInfo存放书目信息,一张LendInfo存放借阅信息。

    会话外观(Session Facade)描述如下:将实体bean层包装在一个称为会话外观的会话bean层中,客户端只能访问会话bean而不是实体bean。

    考虑一次借书用例过程:首先我们先查找表示用户的实体bean,验证用户身份,和已经借书数量,确实是否还能借书;其次查找图书信息的实体bean,获取图书编号,并将数量减1;最后查找借阅信息的实体bean,将借书信息写入。在这个过程中,我们至少需要3+n次网络调用:三个用来查找适当的实体bean,其他N个用来具体操作。于是问题就出来了,第一是负载较大的时候扩展性极度降低,第二是开启的多个实体bean事务相互独立,一旦出现故障,会造成某本书已经被借出而借阅信息没有增加记录这种类似的恶劣冲突情况。

    采用会话外观模式可以解决上述问题。会话外观通常是用无状态会话bean来实现的,当然如果用到会话bean中多个方法调用才能解决一个用例并且会话状态需要保存的话,需要用有状态的会话bean。通过提供给客户端一个可访问点――会话bean层,我们做到了:客户端完全隐藏了存在于服务器端的对象模型;强制一个用例在一次网络中调用执行;并且构建了完整的事务逻辑。

    再考虑我们的借书用例。现在我们多了一个无状态sessionbean――bookOper,其中有了一个方法专门处理借书――borrow(userpk,bookpk),在此方法中,完成上述的操作。因为bookOper是与各个实体bean统一部署的,可以在其内部硬编码通过实体bean的localhome接口直接与实体bean通信。执行这个用例的网络开销减少到了只有一个调用,就是客户端对bookOper的调用;同时通过对bookOper的部署描述文件中的事务属性设置<trans-attribute>Required</trans-attribute>,使得整个用例包含在同一个事务中。

    进一步来看,在这个图书馆应用中包含了更多的用例,使用会话外观模式,可以在创建会话bean时将具有相同的功能的用例聚集在同一个bean中。比如在刚才的bookOper,可以拥有borrow(借书),select(查询),booking(预约)等操作,还可以再建立一个userOper,里面封装个关于关于用户信息的操作。也就是说,会话外观模式为我们提供了一个搭建J2EE系统的标准构架。

    总之,使用Session Facade 模式有下列好处:

    降低网络开销,提供粗粒度访问;

    严格分离业务逻辑和表示层逻辑;

    集中化事务控制;

    降低耦合,提高可管理性;

    有良好的复用性;

    良好的可维护性;

    清晰的动词-名词分离

    提供统一接口,向客户端提供更少的远程接口。

    使用Session Facade模式也应注意下列问题:

    不要创建会话bean的万能类,把所有的用例都放到一个会话bean中,将导致产生一个臃肿的会话bean。

    不要把实体bean的逻辑放到了会话bean中,大部分会话bean的功能只是简单的指代给恰当的实体bean。

    不要在外观中过于重复业务逻辑,在项目变的越来越大的时候,可以把重复的逻辑提取出来置于一个经常使用的bean中或是简单的java类中。

    三  DTO模式

    继续考虑我们的图书馆系统,需要查询书的信息,比如作者,出版社,ID号,数量等等。如果用实体bean提供了若干的get方法来取得我们需要的各个字段的值的话,就产生了网络间大量细粒度的数据交换的情况,造成网络性能下降,效率问题也显现出来。该方法如下面的上图所示:

    数据传送对象(DTO)模式解决了客户端和服务器交换批量数据而不产生多个细粒度网络调用的问题。构建一个成为数据传送对象的普通的可序列化的Java类,通过生成该类的对象,在一个网络可传送包中封装了批量的数据。如上面的下图所示。

    回到图书馆系统。可以构建一个下列形式的DTO类:

    import java.io.Serializable;

    public class bookDTO implements Serializable{

    private String bookName;

    private int bookID;

    private String author;

    ……

    public String getBookName();

    public int getbookID();

    public String getAuthor();

    ……

    }

    这样,当我们需要查询服务器端的数据时,通过将数据封装在dto中,客户端可以在一个网络调用中获得它需要的所有数据。同样,当需要更新服务器端的数据时,也可以创建一个封装了服务器端执行更新所必需的所有信息的dto,并将其传给服务器端(通常时fa&ccedil;ade session)处理。

    关于数据传送对象的最后一个问题就是,需要设计多少个dto,每个dto封装多少数据。在项目开始,客户端和服务器端的开发人员需要坐下来认真考虑这个问题,并达成一致。刚开始,这个问题肯定也不会考虑的很清楚,有个简单的处理方法就是就先让一个dto对应一个实体bean(也可以对应多个)吧。总之,dto解决了粒度问题,但它合适的粒度也需要设计者的经验和实际的应用来评断。

    参考书目:

    《EJB设计模式》

    《J2EE核心模式》

    2004-05-18