(转帖)Wiring Your Web Application with Open Source Java(3)

(由admin转自:http://www.onjava.com/pub/a/onjava/2004/04/07/wiringwebapps.html?page=3)

[译者注:欢迎大家直接在这篇译文中修改和完善,并留下你的联系方式。]

Now that we have our container service beans configured and wired together we need to wire our business service object and our DAO object together. Then we need to wire these objects to the transaction manager.

现在我们已经配置了我们的容器服务beans和把它们连在了一起,我们需要把我们的业务服务对象和我们的DAO对象连在一起。然后,我们需要把这些对象和事务manager连起来。

 

Here is what this looks like in the Spring configuration file:

这是在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>

Figure 4 is an overview of what we have wired together. This shows how each object is related and set into other objects by Spring. Compare this with the Spring configuration file in the sample application to see these relationships.

图4是我们已经连在一起的东西的一个概览。它展示了每个对象是怎样被关联的和怎样被Spring设置进其它对象中。把这幅图和Spring配置文件在示例应用中对比看它们之间的关系。

Figure 4. This is how Spring will assemble the beans based on this configuration.

图4:这是Spring怎样将在这个配置的基础上装配beans。

This example uses a TransactionProxyFactoryBean, which has a setter for a transaction manager that we have already defined. This is a convenience object that knows how to deal with declarative transaction handling and your service objects. You can define how transactions are handled through the transactionAttributes property, which defines patterns for method names, and how they participate in a transaction. For more information about configuring isolation levels and commits or rollbacks on a transaction see TransactionAttributeEditor.

这个例子使用一个TransactionProxyFactoryBean,它有一个为我们已经定义了的事务管理者准备的setter。这是一个方便的对象,它知道怎样处理声明的事务操作和你的服务对象。你可以通过transactionAttributes属性定义事务怎样被处理,transactionAttributes属性为方法名定义模式和它们怎样参与进一个事务。获得更多的关于在一个事务上配置隔离层和提交或回滚看TransactionAttributeEditor。

The class TransactionProxyFactoryBean also has a setter for a target, which will be a reference to our business service object called orderTarget. The orderTarget bean defines which business service class to use and it has a property which refers to setOrderDAO(). This property will populate the orderDAO bean that is our DAO object to communicate with our persistence layer.

TransactionProxyFactoryBean类也有一个为一个target的setter,target将是一个到我们的叫作orderTarget的业务服务对象的引用。 orderTarget bean定义使用哪个业务服务对象和有一个指向setOrderDAO()的属性。这个属性orderDAO bean将居于其中,orderDAO bean是我们的和持久层交流的DAO对象。

One more note about Spring and beans is that beans can operate in two modes. These are defined as singleton and prototype. The default mode for a bean is singleton that means that one shared instance of the bean will be managed. This is used for stateless operations like a stateless session bean would provide. The prototype mode allows new instances of the bean to be create when the bean is served through Spring. You should only use prototype mode when each user needs their own copy of the bean.

还有一个关于Spring和bean要注意的是bean能以两种模式运作。这两种模式被定义为singleton和prototype.为一个bean默认的模式是singleton,意味着一个共享的bean的实例将被管理。这是用于像一个无状态会话bean将提供的无状态操作。prototype模式允许当bean被通过Spring服务时新的bean的实例被创建。你应当仅仅在每一个用户需要他们自己的bean的拷贝时使用prototype模式。

Providing a Service Locator

Now that we have wired up our services with our DAO we need to expose our services to other layers. This is generally used from code in a layer such as UI that uses Struts or Swing. An easy way to handle this is with a service locator patterned class to return resources from a Spring context. This can also be done directly through Spring by referencing the bean ID.

提供一个服务定位器

  现在我们已经把我们的服务和我们的DAO连起来了,我们需要暴露我们的服务给其它层。这通常被从在一个像在使用Struts或Swing的用户界面的层里的代码使用。一个处理这个容易的方法是使用一个服务定位器模式的类来从一个Spring上下文中返回资源。这也能通过Spring引用bean ID被直接完成。

Here is an example of how a service locator can be configured in a Struts Action:

这儿是一个服务定位器怎样能被配置在一个Struts Action中的示例:

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 Layer Configuration

The UI Layer for the example application uses the Struts framework. Here we will discuss what is related to Struts when layering an application. Let's begin by examining an Action configuration within the struts-config.xml file.

用户界面层配置

  示例应用的用户界面层使用Struts框架。这儿我们将讨论当分层一个应用时和Struts相关的东西。让我们从检查在struts-config.xml文件里的一个Action配置开始。

  

<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>

The SaveNewOrder Action is used to persist an order that the user submitted from the UI layer. This is a typical Struts Action; however, notice the exception configuration for this action. These exceptions are also configured in the Spring configuration file, applicationContext-hibernate.xml, for our business service objects in the transactionAttributes property. When these exceptions get thrown back from the business layer we can handle them appropriately in our UI. The first exception, OrderException, will be used by this action when there is a failure saving the order object in the persistence layer. This will cause the transaction to rollback and propagate the exception back through the business object to the Struts layer. The OrderMinimumAmountException will also be handled in a transaction within the business object logic that fails when the order placed does not meet the minimum order amount. Again, the transaction will rollback and this exception can be handled properly by the UI layer.

SaveNewOrder Action被用来持久化一个用户从用户界面层提交的订单。这是一个典型的Struts Action;然而,注意这个action的异常配置。这些异常为在transactionAttributes属性里的我们的业务服务对象也被配置在Spring配置文件里,applicationContext-hibernate.xml。当这些异常被从业务层掷回我们能在我们的用户界面里恰当的处理它们。第一个异常,OrderException,当在持久层里有一个保存订单对象失败时将被这个action使用。这当引起事务回滚和通过业务对象传递异常回Struts层。OrderMinimumAmountException在业务对象逻辑里的一个事务因为提交的订单达不到最小订单数量而失败也将被处理。然后,事务将回滚和这个异常能被用户界面层恰当的处理。

[注:由admin翻译上述部分2005年12月31日22:59分;由***在***修改了上述部分;由***在***修改了上述部分...请自行填写,以便联系]

The last wiring step is to allow our presentation layer to interact with our business layer. This is done by using the service locator that was previously discussed. The service layer acts as an interface to our business logic and persistence layer. Here is how the SaveNewOrder Action in Struts might use a service locator to invoke a business method:

最后一个连接步骤是允许我们的表现层和我们的业务层交互。这可以通过使用前面讨论的服务定位器来完成。服务层扮演一个到我们的业务逻辑层和持久层的接口。这儿是 在Struts中的SaveNewOrder Action怎样可能使用一个服务定位器调用一个业务方法:

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");

}

Conclusion

This article covers a lot of ground in terms of technology and architecture. The main concept to take away is how to better separate your application, user interface, persistence logic, and any other application layer you require. Doing this will decouple your code, allow new code components to be added, and make your application more maintainable in the future. The technologies covered here address specific problems well. However, by using this type of architecture you can replace application layers with other technologies. For example, you might not want to use Hibernate for persistence. Since you are coding to interfaces in your DAO objects it should be apparent to you how you might use another technology or framework, such as iBATIS, as a substitute. Or you might want to replace your UI layer with a different framework than Struts. Switching UI layer implementations should not directly affect your business logic or your persistence layer. Replacing your persistence layer should not affect your UI logic or business service layer. Wiring a web application is not a trivial task but it can be made easier to deal with by decoupling your application layers and wiring it together with suitable frameworks.

结论

这篇文章按照技术和架构覆盖了许多话题。从中取出的主要思想是怎样更好的分离你所需要的应用层、用户界面层、持久逻辑层、和其它任何应用层。这样做将解耦你的代码,允许新的代码组件被加入,使你的应用在将来更加可维护。这里覆盖的技术较好的解决特定的问题。然而,使用这种架构你能用其它的技术代替应用层。例如,你也许不想使用Hibernate持久化。因为你在你的DAO对象中编码到接口,你可能怎样使用其它的技术或框架,比如 iBATIS,作为一个替代是显而易见的。或者你可能用不同于Struts的框架替代你的UI层。改变UI层的实现不会直接影响你的业务逻辑层或者你的持久层。替换你的持久层应该不会影响你的UI逻辑或业务服务层。连接一个web应用不是一个小的任务,但是,靠解耦你的各应用层和用适当的框架组成它,它能变得更容易处理。

Mark Eagle is a Senior Software Engineer at MATRIX Resources, Inc. in Atlanta, GA. 

Mark Eagle 是一位在MATRIX智囊团的高级软件工程师, Inc. in Atlanta, GA。

[注:由admin翻译完全文第一遍于2006年1月1日9:59分;由***在***修改了上述部分;由***在***修改了上述部分...请自行填写,以便联系

全文:

(转帖)Wiring Your Web Application with Open Source Java(1) (1篇) http://www.learndiary.com/disDiaryContentAction.do?goalID=1408

(转帖)Wiring Your Web Application with Open Source Java(2) (1篇)http://www.learndiary.com/disDiaryContentAction.do?goalID=1409

(转帖)Wiring Your Web Application with Open Source Java(3) (1篇)http://www.learndiary.com/disDiaryContentAction.do?goalID=1410]

Author: test

供游客使用的测试帐号

One thought on “(转帖)Wiring Your Web Application with Open Source Java(3)”

  1. (为预防误操作,特此备份。因为学习日记的session设置为20分钟如果没有动作就会清除当前用户连接信息,要求重新登录。因此,你超过20分钟没有保存的东西就有可能丢失,所以写东西请20分钟内保存一次)

     日记标题 (转帖)Wiring Your Web Application with Open Source Java(3)  作者: guest  创建时间: 2005-12-28 21:04:44  最近更新: 2005-12-31 23:00:08  编辑 我要评论  

    内容

    (由admin转自:http://www.onjava.com/pub/a/onjava/2004/04/07/wiringwebapps.html?page=3)

    Now that we have our container service beans configured and wired together we need to wire our business service object and our DAO object together. Then we need to wire these objects to the transaction manager.

    现在我们已经配置了我们的容器服务beans和把它们连在了一起,我们需要把我们的业务服务对象和我们的DAO对象连在一起。然后,我们需要把这些对象和事务manager连起来。

      

    Here is what this looks like in the Spring configuration file:

    这是在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>

    Figure 4 is an overview of what we have wired together. This shows how each object is related and set into other objects by Spring. Compare this with the Spring configuration file in the sample application to see these relationships.

    图4是我们已经连在一起的东西的一个概览。它展示了每个对象是怎样被关联的和怎样被Spring设置进其它对象中。把这幅图和Spring配置文件在示例应用中对比看它们之间的关系。

    Figure 4. This is how Spring will assemble the beans based on this configuration.

    图4:这是Spring怎样将在这个配置的基础上装配beans。

    This example uses a TransactionProxyFactoryBean, which has a setter for a transaction manager that we have already defined. This is a convenience object that knows how to deal with declarative transaction handling and your service objects. You can define how transactions are handled through the transactionAttributes property, which defines patterns for method names, and how they participate in a transaction. For more information about configuring isolation levels and commits or rollbacks on a transaction see TransactionAttributeEditor.

    这个例子使用一个TransactionProxyFactoryBean,它有一个为我们已经定义了的事务管理者准备的setter。这是一个方便的对象,它知道怎样处理声明的事务操作和你的服务对象。你可以通过transactionAttributes属性定义事务怎样被处理,transactionAttributes属性为方法名定义模式和它们怎样参与进一个事务。获得更多的关于在一个事务上配置隔离层和提交或回滚看TransactionAttributeEditor。

    The class TransactionProxyFactoryBean also has a setter for a target, which will be a reference to our business service object called orderTarget. The orderTarget bean defines which business service class to use and it has a property which refers to setOrderDAO(). This property will populate the orderDAO bean that is our DAO object to communicate with our persistence layer.

    TransactionProxyFactoryBean类也有一个为一个target的setter,target将是一个到我们的叫作orderTarget的业务服务对象的引用。 orderTarget bean定义使用哪个业务服务对象和有一个指向setOrderDAO()的属性。这个属性orderDAO bean将居于其中,orderDAO bean是我们的和持久层交流的DAO对象。

    One more note about Spring and beans is that beans can operate in two modes. These are defined as singleton and prototype. The default mode for a bean is singleton that means that one shared instance of the bean will be managed. This is used for stateless operations like a stateless session bean would provide. The prototype mode allows new instances of the bean to be create when the bean is served through Spring. You should only use prototype mode when each user needs their own copy of the bean.

    还有一个关于Spring和bean要注意的是bean能以两种模式运作。这两种模式被定义为singleton和prototype.为一个bean默认的模式是singleton,意味着一个共享的bean的实例将被管理。这是用于像一个无状态会话bean将提供的无状态操作。prototype模式允许当bean被通过Spring服务时新的bean的实例被创建。你应当仅仅在每一个用户需要他们自己的bean的拷贝时使用prototype模式。

    Providing a Service Locator

    Now that we have wired up our services with our DAO we need to expose our services to other layers. This is generally used from code in a layer such as UI that uses Struts or Swing. An easy way to handle this is with a service locator patterned class to return resources from a Spring context. This can also be done directly through Spring by referencing the bean ID.

    提供一个服务定位器

      现在我们已经把我们的服务和我们的DAO连起来了,我们需要暴露我们的服务给其它层。这通常被从在一个像在使用Struts或Swing的用户界面的层里的代码使用。一个处理这个容易的方法是使用一个服务定位器模式的类来从一个Spring上下文中返回资源。这也能通过Spring引用bean ID被直接完成。

    Here is an example of how a service locator can be configured in a Struts Action:

    这儿是一个服务定位器怎样能被配置在一个Struts Action中的示例:

    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 Layer Configuration

    The UI Layer for the example application uses the Struts framework. Here we will discuss what is related to Struts when layering an application. Let's begin by examining an Action configuration within the struts-config.xml file.

    用户界面层配置

      示例应用的用户界面层使用Struts框架。这儿我们将讨论当分层一个应用时和Struts相关的东西。让我们从检查在struts-config.xml文件里的一个Action配置开始。

      

    <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>

    The SaveNewOrder Action is used to persist an order that the user submitted from the UI layer. This is a typical Struts Action; however, notice the exception configuration for this action. These exceptions are also configured in the Spring configuration file, applicationContext-hibernate.xml, for our business service objects in the transactionAttributes property. When these exceptions get thrown back from the business layer we can handle them appropriately in our UI. The first exception, OrderException, will be used by this action when there is a failure saving the order object in the persistence layer. This will cause the transaction to rollback and propagate the exception back through the business object to the Struts layer. The OrderMinimumAmountException will also be handled in a transaction within the business object logic that fails when the order placed does not meet the minimum order amount. Again, the transaction will rollback and this exception can be handled properly by the UI layer.

    SaveNewOrder Action被用来持久化一个用户从用户界面层提交的订单。这是一个典型的Struts Action;然而,注意这个action的异常配置。这些异常为在transactionAttributes属性里的我们的业务服务对象也被配置在Spring配置文件里,applicationContext-hibernate.xml。当这些异常被从业务层掷回我们能在我们的用户界面里恰当的处理它们。第一个异常,OrderException,当在持久层里有一个保存订单对象失败时将被这个action使用。这当引起事务回滚和通过业务对象传递异常回Struts层。OrderMinimumAmountException在业务对象逻辑里的一个事务因为提交的订单达不到最小订单数量而失败也将被处理。然后,事务将回滚和这个异常能被用户界面层恰当的处理。

    [注:由admin翻译上述部分2005年12月31日22:59分;由***在***修改了上述部分;由***在***修改了上述部分...请自行填写,以便联系]

    The last wiring step is to allow our presentation layer to interact with our business layer. This is done by using the service locator that was previously discussed. The service layer acts as an interface to our business logic and persistence layer. Here is how the SaveNewOrder Action in Struts might use a service locator to invoke a business method:

    最后一个连接步骤是允许我们的表现层和我们的业务层交互。这可以通过使用前面讨论的服务定位器来完成。服务层扮演一个到我们的业务逻辑层和持久层的接口。这儿是 在Struts中的SaveNewOrder Action怎样可能使用一个服务定位器调用一个业务方法:

    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");

    }

    Conclusion

    This article covers a lot of ground in terms of technology and architecture. The main concept to take away is how to better separate your application, user interface, persistence logic, and any other application layer you require. Doing this will decouple your code, allow new code components to be added, and make your application more maintainable in the future. The technologies covered here address specific problems well. However, by using this type of architecture you can replace application layers with other technologies. For example, you might not want to use Hibernate for persistence. Since you are coding to interfaces in your DAO objects it should be apparent to you how you might use another technology or framework, such as iBATIS, as a substitute. Or you might want to replace your UI layer with a different framework than Struts. Switching UI layer implementations should not directly affect your business logic or your persistence layer. Replacing your persistence layer should not affect your UI logic or business service layer. Wiring a web application is not a trivial task but it can be made easier to deal with by decoupling your application layers and wiring it together with suitable frameworks.

    结论

    这篇文章按照技术和架构覆盖了许多话题。从中取出的主要思想是怎样更好的分离你所需要的应用层、用户界面层、持久逻辑层、和其它任何应用层。这样做将解耦你的代码,允许新的代码组件被加入,使你的应用在将来更加可维护。这里覆盖的技术较好的解决特定的问题。然而,使用这种架构你能用其它的技术代替应用层。例如,你也许不想使用Hibernate持久化。因为你在你的DAO对象中编码到接口,你可能怎样使用其它的技术或框架,比如 iBATIS,作为一个替代是显而易见的。或者你可能用不同于Struts的框架替代你的UI层。改变UI层的实现不会直接影响你的业务逻辑层或者你的持久层。替换你的持久层应该不会影响你的UI逻辑或业务服务层。连接一个web应用不是一个小的任务,但是,靠解耦你的各应用层和用适当的框架组成它,它能变得更容易处理。

    Mark Eagle is a Senior Software Engineer at MATRIX Resources, Inc. in Atlanta, GA.

    Mark Eagle 是一位在MATRIX智囊团的高级软件工程师, Inc. in Atlanta, GA。

    [注:由admin翻译完全文第一遍于2006年1月1日9:59分;由***在***修改了上述部分;由***在***修改了上述部分...请自行填写,以便联系

    全文:

    (转帖)Wiring Your Web Application with Open Source Java(1) (1篇) http://www.learndiary.com/disDiaryContentAction.do?goalID=1408

    (转帖)Wiring Your Web Application with Open Source Java(2) (1篇)http://www.learndiary.com/disDiaryContentAction.do?goalID=1409

    (转帖)Wiring Your Web Application with Open Source Java(3) (1篇)http://www.learndiary.com/disDiaryContentAction.do?goalID=1410] 

    相关资源

    http://www.onjava.com/pub/a/onjava/2004/04/07/wiringwebapps.html?page=3&nbsp;

Comments are closed.