<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    2006年9月8日

    struts2 基礎(chǔ)

    1. action extends ActionSupport abstract class, because it already provide some default operation(input, createErrorMessage).
    2. property is set by reflect to action, and pass to jsp(jsp is filled with these properties, jsp is a servlet, what it returned to user is HTML file)
    3. static validate happened in action method(override ActionSupport method), dynamic validation happened in action layer.
    4. change dynamic property file value in this way : thankyou=Thank you for registerling %{personBean.firstName}, Resource file can be deployed in action layer, package layer and global layer
    5. exception can be configured in bellow way:  <global-exception-mappings>
       <exception-mapping exception="org.apache.struts.register.exceptions.SecurityBreachException" result="securityerror" />
        <exception-mapping exception="java.lang.Exception" result="error" />
         </global-exception-mappings>
       
        <global-results>
              <result name="securityerror">/securityerror.jsp</result>
         <result name="error">/error.jsp</result>
         </global-results>
    6. Wildcard Method Selection: flexible but not useful(<action name="*Person" class="org.apache.struts.tutorials.wildcardmethod.action.PersonAction" method="{1}">)
    7. integrate spring & struts 2 way: use spring plugin, main point is who to maintain action creation(spring || action), better choice is spring, you can enjoy great function of spring.
    8. Add Convention Plugin to so that you can use annotation
    9. intercepter can be configured in action level and package level.

    posted @ 2011-03-29 12:07 Sheldon Sun 閱讀(238) | 評(píng)論 (0)編輯 收藏

    轉(zhuǎn):用Spring快速開(kāi)發(fā)jms應(yīng)用(JBOSS服務(wù)器)

    異步進(jìn)程通信是面向服務(wù)架構(gòu)(SOA)一個(gè)重要的組成部分,因?yàn)槠髽I(yè)里很多系統(tǒng)通信,特別是與外部組織間的通信,實(shí)質(zhì)上都是異步的。Java消息服務(wù)(JMS)是用于編寫使用異步消息傳遞的JEE應(yīng)用程序的API。傳統(tǒng)的使用JMS API進(jìn)行消息傳遞的實(shí)現(xiàn)包括多個(gè)步驟,例如JNDI查詢隊(duì)列連接工廠和Queue資源,在實(shí)際發(fā)送和接收消息前創(chuàng)建一個(gè)JMS會(huì)話。

       Spring框架則簡(jiǎn)化了使用JEE組件(包括JMS)的任務(wù)。它提供的模板機(jī)制隱藏了典型的JMS實(shí)現(xiàn)的細(xì)節(jié),這樣開(kāi)發(fā)人員可以集中精力放在處理消息的實(shí)際工作中,而不用擔(dān)心如何去創(chuàng)建,訪問(wèn)或清除JMS資源。

       本文將對(duì)Spring JMS API作一個(gè)概述,并通過(guò)一個(gè)運(yùn)行在JBoss MQ服務(wù)器上的web例程來(lái)介紹如何使用Spring JMS API來(lái)異步處理(發(fā)送和接收)消息。我將通過(guò)傳統(tǒng)JMS實(shí)現(xiàn)和Spring JMS實(shí)現(xiàn)兩者間的比較,來(lái)展示使用Spring JMS處理消息是如何的簡(jiǎn)單和靈活。

    異步消息傳遞和面向服務(wù)架構(gòu)

      在現(xiàn)實(shí)中,大多數(shù)web請(qǐng)求都是同步處理的。例如,當(dāng)用戶要登入一個(gè)網(wǎng)站,首先輸入用戶名和密碼,然后服務(wù)器驗(yàn)證登錄合法性。如果驗(yàn)證成功,程序?qū)⒃试S該用戶進(jìn)入網(wǎng)站。這里,登錄請(qǐng)求在從客戶端接收以后被即時(shí)處理了。信用卡驗(yàn)證是另一個(gè)同步處理的例子;只有服務(wù)器證實(shí)輸入的信用卡號(hào)是有效的,同時(shí)客戶在帳戶上有足夠的存款,客戶才被允許繼續(xù)操作。但是讓我們思考一下在順序處理系統(tǒng)上的支付結(jié)算步驟。一旦系統(tǒng)證實(shí)該用戶信用卡的信息是準(zhǔn)確的,并且在帳戶上有足夠的資金,就不必等到所有的支付細(xì)節(jié)落實(shí)、轉(zhuǎn)賬完成。支付結(jié)算可以異步方式進(jìn)行,這樣客戶可以繼續(xù)進(jìn)行核查操作。

       需要比典型同步請(qǐng)求耗費(fèi)更長(zhǎng)時(shí)間的請(qǐng)求,可以使用異步處理。另一個(gè)異步處理的例子是,在本地貸款處理程序中,提交至自動(dòng)承銷系統(tǒng)(AUS)的信用請(qǐng)求處理過(guò)程。當(dāng)借方提交貸款申請(qǐng)后,抵押公司會(huì)向AUS發(fā)送請(qǐng)求,以獲取信用歷史記錄。由于這個(gè)請(qǐng)求要求得到全面而又詳細(xì)的信用報(bào)告,包括借方現(xiàn)今和過(guò)去的帳戶,最近的付款和其他財(cái)務(wù)資料,服務(wù)器需要耗費(fèi)較長(zhǎng)的時(shí)間(幾小時(shí)或著有時(shí)甚至是幾天)來(lái)對(duì)這些請(qǐng)求作出響應(yīng)。客戶端程序(應(yīng)用)要與服務(wù)器連接并耗費(fèi)如此長(zhǎng)的時(shí)間來(lái)等待結(jié)果,這是毫無(wú)意義的。因此通信應(yīng)該是異步發(fā)生的;也就是,一旦請(qǐng)求被提交,它就被放置在隊(duì)列中,同時(shí)客戶端與服務(wù)器斷開(kāi)連接。然后AUS服務(wù)從指定的隊(duì)列中選出請(qǐng)求進(jìn)行處理,并將處理得到的消息放置在另一個(gè)消息隊(duì)列里。最后,客戶端程序從這個(gè)隊(duì)列中選出處理結(jié)果,緊接著處理這個(gè)信用歷史數(shù)據(jù)。

    JMS

       如果您使用過(guò)JMS代碼,您會(huì)發(fā)現(xiàn)它與JDBC或JCA很像。它所包含的樣本代碼創(chuàng)建或JMS資源對(duì)象回溯,使得每一次您需要寫一個(gè)新類來(lái)發(fā)送和接收消息時(shí),都具有更好的代碼密集性和重復(fù)性。以下序列顯示了傳統(tǒng)JMS實(shí)現(xiàn)所包括的步驟:

    1. 創(chuàng)建JNDI初始上下文(context)。
    2. 從JNDI上下文獲取一個(gè)隊(duì)列連接工廠。
    3. 從隊(duì)列連接工廠中獲取一個(gè)Quene。
    4. 創(chuàng)建一個(gè)Session對(duì)象。
    5. 創(chuàng)建一個(gè)發(fā)送者(sender)或接收者(receiver)對(duì)象。
    6. 使用步驟5創(chuàng)建的發(fā)送者或接收者對(duì)象發(fā)送或接收消息。
    7. 處理完消息后,關(guān)閉所有JMS資源。

    您可以看到,步驟6是處理消息的唯一地方。其他步驟都只是管理與實(shí)際業(yè)務(wù)要求無(wú)關(guān)的JMS資源,但是開(kāi)發(fā)人員必須編寫并維護(hù)這些額外步驟的代碼。

    Spring JMS

       Spring框架提供了一個(gè)模板機(jī)制來(lái)隱藏Java APIs的細(xì)節(jié)。JEE開(kāi)發(fā)人員可以使用JDBCTemplate和JNDITemplate類來(lái)分別訪問(wèn)后臺(tái)數(shù)據(jù)庫(kù)和JEE資源(數(shù)據(jù)源,連接池)。JMS也不例外。Spring提供JMSTemplate類,因此開(kāi)發(fā)人員不用為一個(gè)JMS實(shí)現(xiàn)去編寫樣本代碼。接下來(lái)是在開(kāi)發(fā)JMS應(yīng)用程序時(shí)Spring所具有一些的優(yōu)勢(shì)。

    1. 提供JMS抽象API,簡(jiǎn)化了訪問(wèn)目標(biāo)(隊(duì)列或主題)和向指定目標(biāo)發(fā)布消息時(shí)JMS的使用。
    2. JEE開(kāi)發(fā)人員不需要關(guān)心JMS不同版本(例如JMS 1.0.2與JMS 1.1)之間的差異。
    3. 開(kāi)發(fā)人員不必專門處理JMS異常,因?yàn)镾pring為所有JMS異常提供了一個(gè)未經(jīng)檢查的異常,并在JMS代碼中重新拋出。

    示例程序

            說(shuō)明:因?yàn)橹皇菫榱搜菔救绾问褂胹pring編寫jms的應(yīng)用,所以本例沒(méi)有什么實(shí)際用途。

            程序功能:MessageProducer.java根據(jù)一用戶信息產(chǎn)生一個(gè)消息發(fā)送到 JMS Provider;由MessageConsumer.java接收。

    1.在Jboss里配置XML文件創(chuàng)建一個(gè)新的JMS provider。
    打開(kāi)位于%JBOSS_HOME%server\default\deploy\jms文件夾下的jbossmq-destinations-service.xml文件,加入以下代碼片斷:
     <!--  Register User Send/Receive Queue  -->
     <mbean code="org.jboss.mq.server.jmx.Queue"
       name="jboss.mq.destination:service=Queue,name=registerUserQueue">
       <depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
     </mbean>
     <!--  Register User Send/Receive Topic  -->
     <mbean code="org.jboss.mq.server.jmx.Topic"
      name="jboss.mq.destination:service=Topic,name=registerUserTopic">
       <depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
     </mbean>
    2.在spring的配置文件中配置JMS組件的具體細(xì)節(jié)。
     (1)JNDI上下文是取得JMS資源的起始位置,因此首先我們要配置JNDI模板:
        <!-- JNDI上下文(它是取得JMS資源的起始位置) -->
       <bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
        <property name="environment">
         <props>
          <prop key="java.naming.factory.initial">
           org.jnp.interfaces.NamingContextFactory
          </prop>
          <prop key="java.naming.provider.url">localhost</prop>
          <prop key="java.naming.factory.url.pkgs">
           org.jnp.interfaces:org.jboss.naming
          </prop>
         </props>
        </property>
       </bean>
       注意:此JNDI模板用到了org.jnp.interfaces.NamingContextFactory所以要把%JBOSS_HOME%\client下的jbossall-client.jar加到你的項(xiàng)目的classpath中。
    (2)配置連接工廠:
       <!-- JMS連接工廠 -->
         <bean id="jmsConnectionFactory"class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiTemplate">
         <ref bean="jndiTemplate" />
        </property>
        <property name="jndiName">
         <value>XAConnectionFactory</value>
        </property>
       </bean>
       注意:XAConnectionFactory這個(gè)JNDI名字是在%JBOSS_HOME%server\default\deploy\jms文件夾下的jms-ds.xml中定義的(它是由JBoss指定的)。
     (3)配置JmsTemplate組件。在例程中我們使用JmsTemplate102。同時(shí)使用defaultDestination屬性來(lái)指定JMS目標(biāo)。
      <!-- JMS模板配置 -->
      <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate102">
       <property name="connectionFactory" ref="jmsConnectionFactory" />
       <property name="defaultDestination" ref="destination" />
       <property name="pubSubDomain">
        <value>true</value>
       </property>
       <!-- 等待消息的時(shí)間(ms) -->
       <property name="receiveTimeout">
             <value>30000</value>
          </property>
      </bean>
      注意:如果使用topic-subscribe(主題訂閱)模式,該模板的pubSubDomain屬性值為true;若使用PToP(點(diǎn)對(duì)點(diǎn))模式,pubSubDomain屬性值為false或不配置該屬性。
     (4)定義一個(gè)JMS目標(biāo)來(lái)發(fā)送和接收消息:
      <bean id="destination" class="org.springframework.jndi.JndiObjectFactoryBean">
       <property name="jndiTemplate">
        <ref bean="jndiTemplate" />
       </property>
       <property name="jndiName">
        <value>topic/registerUserTopic</value>
       </property>
      </bean>
     (5)配置發(fā)送者和接收者組件:
      <!-- 消息發(fā)布者 -->
      <bean id="msgProducer" class="com.boco.jms.MessageProducer">
       <property name="jmsTemplate" ref="jmsTemplate" />
      </bean>
      <!-- 消息接收者 -->
      <bean id="msgConsumer" class="com.boco.jms.MessageConsumer">
       <property name="jmsTemplate" ref="jmsTemplate" />
      </bean>
    3.相應(yīng)的類:
     (1). User對(duì)象。
       /**
       *  User.java
       *  created on Jul 2, 2006
       *  Copyrights 2006 BOCO,Inc. All rights reserved.
       */
      package com.boco.dto;
      
      import java.io.Serializable;
      
      /**
       * desc: 用戶信息 Bean
       * @author qiujy
       */
      public class User {
       private int id;
       private String username;
       private String password;
       private String email;
       
       public User(){}
       
       //以下為Getter,setter方法略
       ......
      }
      
     (2).消息生產(chǎn)者:
       /**
       *  MessageProducer.java
       *  created on Jul 22, 2006
       *  Copyrights 2006 BOCO,Inc. All rights reserved.
       */
      package com.boco.jms;
      
      import javax.jms.JMSException;
      import javax.jms.MapMessage;
      import javax.jms.Message;
      import javax.jms.Session;
      
      import org.springframework.jms.core.JmsTemplate;
      import org.springframework.jms.core.MessageCreator;
      
      import com.boco.dto.User;
      
      /**
       * desc:消息生產(chǎn)者
       * @author qiujy
       *
       */
      public class MessageProducer {
       /** JMS模板 */
       private JmsTemplate jmsTemplate;
       
       public void setJmsTemplate(JmsTemplate jmsTemplate){
        this.jmsTemplate = jmsTemplate;
       }
       
       public void sendMessage(final User user){
        //調(diào)用模板的send來(lái)發(fā)送消息
        jmsTemplate.send(new MessageCreator(){
      
         public Message createMessage(Session session) throws JMSException {
          //構(gòu)造一個(gè)要發(fā)送的消息
          MapMessage message = session.createMapMessage();
           message.setInt("id", user.getId());
           message.setString("username", user.getUsername());
           message.setString("password", user.getPassword());
           message.setString("email", user.getEmail());
          System.out.println("send success!!");
          return message;
         }
        });
       }
      }
      
     (3).消息消費(fèi)者:
      /**
       *  MessageConsumer.java
       *  created on Jul 22, 2006
       *  Copyrights 2006 BOCO,Inc. All rights reserved.
       */
      package com.boco.jms;
      
      import javax.jms.JMSException;
      import javax.jms.MapMessage;
      
      import org.springframework.jms.core.JmsTemplate;
      
      import com.boco.dto.User;
      
      /**
       * desc:消息消費(fèi)者
       * @author qiujy
       *
       */
      public class MessageConsumer {
       /** JMS模板 */
       private JmsTemplate jmsTemplate;
       
       public void setJmsTemplate(JmsTemplate jmsTemplate){
        this.jmsTemplate = jmsTemplate;
       }
       
       public User receiveMessage(){
        //參數(shù)為Destination的JNDI名字去掉前面的模式類型標(biāo)識(shí)
        //MapMessage msg = (MapMessage)jmsTemplate.receive("registerUserQueue");
        MapMessage msg = (MapMessage)jmsTemplate.receive("registerUserTopic");
        User user = new User();
        
        try {
         user.setId(msg.getInt("id"));
         user.setUsername(msg.getString("username"));
         user.setPassword(msg.getString("password"));
         user.setEmail(msg.getString("email"));
        } catch (JMSException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
        }
        
        return user;
       }
      }

     (4).測(cè)試用例:
       //======== 生產(chǎn)者測(cè)試用例 ===============
       /**
       *  TestMsgProducer.java
       *  created on Jul 22, 2006
       *  Copyrights 2006 BOCO,Inc. All rights reserved.
       */
      package com.boco.jms;
      
      import junit.framework.TestCase;
      
      import org.springframework.context.ApplicationContext;
      import org.springframework.context.support.ClassPathXmlApplicationContext;
      
      import com.boco.dto.User;
      
      /**
       * desc:
       * @author qiujy
       *
       */
      public class TestMsgProducer extends TestCase {
      
       private ApplicationContext context;
       /**
        * @param arg0
        */
       public TestMsgProducer(String arg0) {
        super(arg0);
        context = new ClassPathXmlApplicationContext("applicationContext_jms.xml");
       }
      
       /* (non-Javadoc)
        * @see junit.framework.TestCase#setUp()
        */
       protected void setUp() throws Exception {
        super.setUp();
       }
      
       /* (non-Javadoc)
        * @see junit.framework.TestCase#tearDown()
        */
       protected void tearDown() throws Exception {
        super.tearDown();
       }
      
       /**
        * Test method for {@link com.boco.jms.MessageProducer#sendMessage(com.boco.dto.User)}.
        */
       public void testSendMessage() {
        User user = new User();
        user.setId(132);
        user.setUsername("JMSTest");
        user.setPassword("password");
        user.setEmail("support@boco.com.cn");
        
        MessageProducer producer = (MessageProducer)context.getBean("msgProducer");
        
        producer.sendMessage(user);
        
       }
      
      }

      //============ 消費(fèi)者測(cè)試用例 ===============
      /**
       *  TestMsgConsumer.java
       *  created on Jul 22, 2006
       *  Copyrights 2006 BOCO,Inc. All rights reserved.
       */
      package com.boco.jms;
      
      import junit.framework.TestCase;
      
      import org.springframework.context.ApplicationContext;
      import org.springframework.context.support.ClassPathXmlApplicationContext;
      
      import com.boco.dto.User;
      
      /**
       * desc:
       * @author qiujy
       *
       */
      public class TestMsgConsumer extends TestCase {
       private ApplicationContext context;
       /**
        * @param arg0
        */
       public TestMsgConsumer(String arg0) {
        super(arg0);
        context = new ClassPathXmlApplicationContext("applicationContext_jms.xml");
       }
      
       /* (non-Javadoc)
        * @see junit.framework.TestCase#setUp()
        */
       protected void setUp() throws Exception {
        super.setUp();
       }
      
       /* (non-Javadoc)
        * @see junit.framework.TestCase#tearDown()
        */
       protected void tearDown() throws Exception {
        super.tearDown();
       }
      
       /**
        * Test method for {@link com.boco.jms.MessageConsumer#receiveMessage()}.
        */
       public void testReceiveMessage() {
        MessageConsumer consumer = (MessageConsumer)context.getBean("msgConsumer");
        User user = consumer.receiveMessage();
        assertNotNull(user);
        System.out.println( "id========" + user.getId()
            + "\nname======" + user.getUsername()
            + "\npassword==" + user.getPassword()
            + "\nemail=====" + user.getEmail());
       }
      
      }

    posted @ 2011-03-23 14:49 Sheldon Sun 閱讀(269) | 評(píng)論 (0)編輯 收藏

    concurrent

    AVA后臺(tái)程序設(shè)計(jì)及UTIL.CONCURRENT包的應(yīng)用


    摘要 : 在很多軟件項(xiàng)目中,JAVA語(yǔ)言常常被用來(lái)開(kāi)發(fā)后臺(tái)服務(wù)程序。線程池技術(shù)是提高這類程序性能的一個(gè)重要手段。在實(shí)踐中,該技術(shù)已經(jīng)被廣泛的使用。本文首先 對(duì)設(shè)計(jì)后臺(tái)服務(wù)程序通常需要考慮的問(wèn)題進(jìn)行了基本的論述,隨后介紹了JAVA線程池的原理、使用和其他一些相關(guān)問(wèn)題,最后對(duì)功能強(qiáng)大的JAVA開(kāi)放源碼線 程池包util.concurrent 在實(shí)際編程中的應(yīng)用進(jìn)行了詳細(xì)介紹。
    關(guān)鍵字: JAVA;線程池;后臺(tái)服務(wù)程序;util.concurrent



    1 引言
    在軟件項(xiàng)目開(kāi)發(fā)中,許多后臺(tái)服務(wù)程序的處理動(dòng)作流程都具有一個(gè)相同點(diǎn),就是:接受客戶端發(fā)來(lái)的請(qǐng)求,對(duì)請(qǐng)求進(jìn)行一些相關(guān)的處理,最后將處理結(jié)果返回給客戶 端。這些請(qǐng)求的來(lái)源和方式可能會(huì)各不相同,但是它們常常都有一個(gè)共同點(diǎn):數(shù)量巨大,處理時(shí)間短。這類服務(wù)器在實(shí)際應(yīng)用中具有較大的普遍性,如web服務(wù) 器,短信服務(wù)器,DNS服務(wù)器等等。因此,研究如何提高此類后臺(tái)程序的性能,如何保證服務(wù)器的穩(wěn)定性以及安全性都具有重要的實(shí)用價(jià)值。

    2 后臺(tái)服務(wù)程序設(shè)計(jì)
    2.1 關(guān)于設(shè)計(jì)原型
    構(gòu)建服務(wù)器應(yīng)用程序的一個(gè)簡(jiǎn)單的模型是:?jiǎn)?dòng)一個(gè)無(wú)限循環(huán),循環(huán)里放一個(gè)監(jiān)聽(tīng)線程監(jiān)聽(tīng)某個(gè)地址端口。每當(dāng)一個(gè)請(qǐng)求到達(dá)就創(chuàng)建一個(gè)新線程,然后新線程為請(qǐng)求服務(wù),監(jiān)聽(tīng)線程返回繼續(xù)監(jiān)聽(tīng)。
    簡(jiǎn)單舉例如下:
    import java.net.*;
    public class MyServer extends Thread{
    public void run(){
    try{
    ServerSocket server=null;
    Socket clientconnection=null;
    server = new ServerSocket(8008);//監(jiān)聽(tīng)某地址端口對(duì)
    while(true){進(jìn)入無(wú)限循環(huán)
    clientconnection =server.accept();//收取請(qǐng)求
    new ServeRequest(clientconnection).start();//啟動(dòng)一個(gè)新服務(wù)線程進(jìn)行服務(wù)
    ……
    }
    }catch(Exception e){
    System.err.println("Unable to start serve listen:"+e.getMessage());
    e.printStackTrace();
    }
    }
    }
    實(shí)際上,這只是個(gè)簡(jiǎn)單的原型,如果試圖部署以這種方式運(yùn)行的服務(wù)器應(yīng)用程序,那么這種方法的嚴(yán)重不足就很明顯。
    首先,為每個(gè)請(qǐng)求創(chuàng)建一個(gè)新線程的開(kāi)銷很大,為每個(gè)請(qǐng)求創(chuàng)建新線程的服務(wù)器在創(chuàng)建和銷毀線程上花費(fèi)的時(shí)間和消耗的系統(tǒng)資源, 往往有時(shí)候要比花在處理實(shí)際的用戶請(qǐng)求的時(shí)間和資源更多。在Java中更是如此,虛擬機(jī)將試圖跟蹤每一個(gè)對(duì)象,以便能夠在對(duì)象銷毀后進(jìn)行垃圾回收。所以提 高服務(wù)程序效率的一個(gè)手段就是盡可能減少創(chuàng)建和銷毀對(duì)象的次數(shù)。這樣綜合看來(lái),系統(tǒng)的性能瓶頸就在于線程的創(chuàng)建開(kāi)銷。
    其次,除了創(chuàng)建和銷毀線程的開(kāi)銷之外,活動(dòng)的線程也消耗系統(tǒng)資源。在一個(gè) JVM 里創(chuàng)建太多的線程可能會(huì)導(dǎo)致系統(tǒng)由于過(guò)度消耗內(nèi)存而用完內(nèi)存或“切換過(guò)度”。為了防止資源不足,服務(wù)器應(yīng)用程序需要一些辦法來(lái)限制任何給定時(shí)刻運(yùn)行的處理 線程數(shù)目,以防止服務(wù)器被“壓死”的情況發(fā)生。所以在設(shè)計(jì)后臺(tái)程序的時(shí)候,一般需要提前根據(jù)服務(wù)器的內(nèi)存、CPU等硬件情況設(shè)定一個(gè)線程數(shù)量的上限值。
    如果創(chuàng)建和銷毀線程的時(shí)間相對(duì)于服務(wù)時(shí)間占用的比例較大,那末假設(shè)在一個(gè)較短的時(shí)間內(nèi)有成千上萬(wàn)的請(qǐng)求到達(dá),想象一下,服務(wù)器的時(shí)間和資源將會(huì)大量的花在 創(chuàng)建和銷毀線程上,而真正用于處理請(qǐng)求的時(shí)間卻相對(duì)較少,這種情況下,服務(wù)器性能瓶頸就在于創(chuàng)建和銷毀線程的時(shí)間。按照這個(gè)模型寫一個(gè)簡(jiǎn)單的程序測(cè)試一下 即可看出,由于篇幅關(guān)系,此處略。如果把(服務(wù)時(shí)間/創(chuàng)建和銷毀線程的時(shí)間)作為衡量服務(wù)器性能的一個(gè)參數(shù),那末這個(gè)比值越大,服務(wù)器的性能就越高。
    應(yīng)此,解決此類問(wèn)題的實(shí)質(zhì)就是盡量減少創(chuàng)建和銷毀線程的時(shí)間,把服務(wù)器的資源盡可能多地用到處理請(qǐng)求上來(lái),從而發(fā)揮多線程的優(yōu)點(diǎn)(并發(fā)),避免多線程的缺點(diǎn)(創(chuàng)建和銷毀的時(shí)空開(kāi)銷)。
    線程池為線程生命周期開(kāi)銷問(wèn)題和資源不足問(wèn)題提供了解決方案。通過(guò)對(duì)多個(gè)任務(wù)重用線程,線程創(chuàng)建的開(kāi)銷被分?jǐn)偟搅硕鄠€(gè)任務(wù)上。其好處是,因?yàn)樵谡?qǐng)求到達(dá)時(shí) 線程已經(jīng)存在,所以無(wú)意中也消除了線程創(chuàng)建所帶來(lái)的延遲。這樣,就可以立即為請(qǐng)求服務(wù),使應(yīng)用程序響應(yīng)更快。而且,通過(guò)適當(dāng)?shù)卣{(diào)整線程池中的線程數(shù)目,也 就是當(dāng)請(qǐng)求的數(shù)目超過(guò)某個(gè)閾值時(shí),就強(qiáng)制其它任何新到的請(qǐng)求一直等待,直到獲得一個(gè)線程來(lái)處理為止,從而可以防止資源不足。

    3    JAVA線程池原理
    3.1 原理以及實(shí)現(xiàn)
    在實(shí)踐中,關(guān)于線程池的實(shí)現(xiàn)常常有不同的方法,但是它們的基本思路大都是相似的:服務(wù)器預(yù)先存放一定數(shù)目的“熱”的線程,并發(fā)程序需要使用線程的時(shí)候,從 服務(wù)器取用一條已經(jīng)創(chuàng)建好的線程(如果線程池為空則等待),使用該線程對(duì)請(qǐng)求服務(wù),使用結(jié)束后,該線程并不刪除,而是返回線程池中,以備復(fù)用,這樣可以避 免對(duì)每一個(gè)請(qǐng)求都生成和刪除線程的昂貴操作。
    一個(gè)比較簡(jiǎn)單的線程池至少應(yīng)包含線程池管理器、工作線程、任務(wù)隊(duì)列、任務(wù)接口等部分。其中線程池管理器(ThreadPool Manager)的作用是創(chuàng)建、銷毀并管理線程池,將工作線程放入線程池中;工作線程是一個(gè)可以循環(huán)執(zhí)行任務(wù)的線程,在沒(méi)有任務(wù)時(shí)進(jìn)行等待;任務(wù)隊(duì)列的作 用是提供一種緩沖機(jī)制,將沒(méi)有處理的任務(wù)放在任務(wù)隊(duì)列中;任務(wù)接口是每個(gè)任務(wù)必須實(shí)現(xiàn)的接口,主要用來(lái)規(guī)定任務(wù)的入口、任務(wù)執(zhí)行完后的收尾工作、任務(wù)的執(zhí) 行狀態(tài)等,工作線程通過(guò)該接口調(diào)度任務(wù)的執(zhí)行。下面的代碼實(shí)現(xiàn)了創(chuàng)建一個(gè)線程池:
    public class ThreadPool
    { 
    private Stack threadpool = new Stack();
    private int poolSize;
    private int currSize=0;
    public void setSize(int n)
    { 
    poolSize = n;
    }
    public void run()
    {
    for(int i=0;i

    (發(fā)帖時(shí)間:2003-11-30 11:55:56) 
    ---岑心 J

    回復(fù)(1): 

    4.2    框架與結(jié)構(gòu)
    下面讓我們來(lái)看看util.concurrent的框架結(jié)構(gòu)。關(guān)于這個(gè)工具包概述的e文原版鏈接地址是http: //gee.cs.oswego.edu/dl/cpjslides/util.pdf。該工具包主要包括三大部分:同步、通道和線程池執(zhí)行器。第一部分 主要是用來(lái)定制鎖,資源管理,其他的同步用途;通道則主要是為緩沖和隊(duì)列服務(wù)的;線程池執(zhí)行器則提供了一組完善的復(fù)雜的線程池實(shí)現(xiàn)。
    --主要的結(jié)構(gòu)如下圖所示

    4.2.1 Sync
    acquire/release協(xié)議的主要接口
    - 用來(lái)定制鎖,資源管理,其他的同步用途
    - 高層抽象接口
    - 沒(méi)有區(qū)分不同的加鎖用法

    實(shí)現(xiàn)
    -Mutex, ReentrantLock, Latch, CountDown,Semaphore, WaiterPreferenceSemaphore, FIFOSemaphore, PrioritySemaphore
    還有,有幾個(gè)簡(jiǎn)單的實(shí)現(xiàn),例如ObservableSync, LayeredSync

    舉例:如果我們要在程序中獲得一獨(dú)占鎖,可以用如下簡(jiǎn)單方式:
    try {
    lock.acquire();
    try {
    action();
    }
    finally {
    lock.release();
    }
    }catch(Exception e){
    }

    程序中,使用lock對(duì)象的acquire()方法獲得一獨(dú)占鎖,然后執(zhí)行您的操作,鎖用完后,使用release()方法釋放之即可。呵呵,簡(jiǎn)單吧,想 想看,如果您親自撰寫?yīng)氄兼i,大概會(huì)考慮到哪些問(wèn)題?如果關(guān)鍵的鎖得不到怎末辦?用起來(lái)是不是會(huì)復(fù)雜很多?而現(xiàn)在,以往的很多細(xì)節(jié)和特殊異常情況在這里都 無(wú)需多考慮,您盡可以把精力花在解決您的應(yīng)用問(wèn)題上去。

    4.2.2 通道(Channel)
    為緩沖,隊(duì)列等服務(wù)的主接口

    具體實(shí)現(xiàn)
    LinkedQueue, BoundedLinkedQueue,BoundedBuffer, BoundedPriorityQueue, SynchronousChannel, Slot

    通道例子
    class Service { // ...
    final Channel msgQ = new LinkedQueue();
    public void serve() throws InterruptedException {
    String status = doService();
    msgQ.put(status);
    }
    public Service() { // start background thread
    Runnable logger = new Runnable() {
    public void run() {
    try {
    for(;;)
    System.out.println(msqQ.take());
    }
    catch(InterruptedException ie) {} }
    };
    new Thread(logger).start();
    }
    }
    在后臺(tái)服務(wù)器中,緩沖和隊(duì)列都是最常用到的。試想,如果對(duì)所有遠(yuǎn)端的請(qǐng)求不排個(gè)隊(duì)列,讓它們一擁而上的去爭(zhēng)奪cpu、內(nèi)存、資源,那服務(wù)器瞬間不當(dāng)?shù)舨殴帧6谶@里,成熟的隊(duì)列和緩沖實(shí)現(xiàn)已經(jīng)提供,您只需要對(duì)其進(jìn)行正確初始化并使用即可,大大縮短了開(kāi)發(fā)時(shí)間。

    4.2.3執(zhí)行器(Executor)
    Executor是這里最重要、也是我們往往最終寫程序要用到的,下面重點(diǎn)對(duì)其進(jìn)行介紹。
    類似線程的類的主接口
    - 線程池
    - 輕量級(jí)運(yùn)行框架
    - 可以定制調(diào)度算法

    只需要支持execute(Runnable r)
    - 同Thread.start類似

    實(shí)現(xiàn)
    - PooledExecutor, ThreadedExecutor, QueuedExecutor, FJTaskRunnerGroup

    PooledExecutor(線程池執(zhí)行器)是個(gè)最常用到的類,以它為例:
    可修改得屬性如下:
    - 任務(wù)隊(duì)列的類型
    - 最大線程數(shù)
    - 最小線程數(shù)
    - 預(yù)熱(預(yù)分配)和立即(分配)線程
    - 保持活躍直到工作線程結(jié)束
    -- 以后如果需要可能被一個(gè)新的代替
    - 飽和(Saturation)協(xié)議
    -- 阻塞,丟棄,生產(chǎn)者運(yùn)行,等等

    可不要小看上面這數(shù)條屬性,對(duì)這些屬性的設(shè)置完全可以等同于您自己撰寫的線程池的成百上千行代碼。下面以筆者撰寫過(guò)得一個(gè)GIS服務(wù)器為例:
    該GIS服務(wù)器是一個(gè)典型的“請(qǐng)求-服務(wù)”類型的服務(wù)器,遵循后端程序設(shè)計(jì)的一般框架。首先對(duì)所有的請(qǐng)求按照先來(lái)先服務(wù)排入一個(gè)請(qǐng)求隊(duì)列,如果瞬間到達(dá)的 請(qǐng)求超過(guò)了請(qǐng)求隊(duì)列的容量,則將溢出的請(qǐng)求轉(zhuǎn)移至一個(gè)臨時(shí)隊(duì)列。如果臨時(shí)隊(duì)列也排滿了,則對(duì)以后達(dá)到的請(qǐng)求給予一個(gè)“服務(wù)器忙”的提示后將其簡(jiǎn)單拋棄。這 個(gè)就夠忙活一陣的了。
    然后,結(jié)合鏈表結(jié)構(gòu)實(shí)現(xiàn)一個(gè)線程池,給池一個(gè)初始容量。如果該池滿,以x2的策略將池的容量動(dòng)態(tài)增加一倍,依此類推,直到總線程數(shù)服務(wù)達(dá)到系統(tǒng)能力上限, 之后線程池容量不在增加,所有請(qǐng)求將等待一個(gè)空余的返回線程。每從池中得到一個(gè)線程,該線程就開(kāi)始最請(qǐng)求進(jìn)行GIS信息的服務(wù),如取坐標(biāo)、取地圖,等等。 服務(wù)完成后,該線程返回線程池繼續(xù)為請(qǐng)求隊(duì)列離地后續(xù)請(qǐng)求服務(wù),周而復(fù)始。當(dāng)時(shí)用矢量鏈表來(lái)暫存請(qǐng)求,用wait()、 notify() 和 synchronized等原語(yǔ)結(jié)合矢量鏈表實(shí)現(xiàn)線程池,總共約600行程序,而且在運(yùn)行時(shí)間較長(zhǎng)的情況下服務(wù)器不穩(wěn)定,線程池被取用的線程有異常消失的 情況發(fā)生。而使用util.concurrent相關(guān)類之后,僅用了幾十行程序就完成了相同的工作而且服務(wù)器運(yùn)行穩(wěn)定,線程池沒(méi)有丟失線程的情況發(fā)生。由 此可見(jiàn)util.concurrent包極大的提高了開(kāi)發(fā)效率,為項(xiàng)目節(jié)省了大量的時(shí)間。
    使用PooledExecutor例子
    import java.net.*;
    /**
    *

    Title:


    *

    Description: 負(fù)責(zé)初始化線程池以及啟動(dòng)服務(wù)器


    *

    Copyright: Copyright (c) 2003


    *

    Company:


    * @author not attributable
    * @version 1.0
    */
    public class MainServer {
    //初始化常量
    public static final int MAX_CLIENT=100; //系統(tǒng)最大同時(shí)服務(wù)客戶數(shù)
    //初始化線程池
    public static final PooledExecutor pool =
    new PooledExecutor(new BoundedBuffer(10), MAX_CLIENT); //chanel容量為10,
    //在這里為線程池初始化了一個(gè)
    //長(zhǎng)度為10的任務(wù)緩沖隊(duì)列。

    public MainServer() {
    //設(shè)置線程池運(yùn)行參數(shù)
    pool.setMinimumPoolSize(5); //設(shè)置線程池初始容量為5個(gè)線程
    pool.discardOldestWhenBlocked();//對(duì)于超出隊(duì)列的請(qǐng)求,使用了拋棄策略。
    pool.createThreads(2); //在線程池啟動(dòng)的時(shí)候,初始化了具有一定生命周期的2個(gè)“熱”線程
    }

    public static void main(String[] args) {
    MainServer MainServer1 = new MainServer();
    new HTTPListener().start();//啟動(dòng)服務(wù)器監(jiān)聽(tīng)和處理線程
    new manageServer().start();//啟動(dòng)管理線程
    }
    }

    類HTTPListener
    import java.net.*;
    /**
    *

    Title:


    *

    Description: 負(fù)責(zé)監(jiān)聽(tīng)端口以及將任務(wù)交給線程池處理


    *

    Copyright: Copyright (c) 2003


    *

    Company:


    * @author not attributable
    * @version 1.0
    */

    public class HTTPListener extends Thread{
    public HTTPListener() {
    }
    public void run(){
    try{
    ServerSocket server=null;
    Socket clientconnection=null;
    server = new ServerSocket(8008);//服務(wù)套接字監(jiān)聽(tīng)某地址端口對(duì)
    while(true){//無(wú)限循環(huán)
    clientconnection =server.accept();
    System.out.println("Client connected in!");
    //使用線程池啟動(dòng)服務(wù)
    MainServer.pool.execute(new HTTPRequest(clientconnection));//如果收到一個(gè)請(qǐng)求,則從線程池中取一個(gè)線程進(jìn)行服務(wù),任務(wù)完成后,該線程自動(dòng)返還線程池
    }
    }catch(Exception e){
    System.err.println("Unable to start serve listen:"+e.getMessage());
    e.printStackTrace();
    }
    }
    }

    關(guān)于util.concurrent工具包就有選擇的介紹到這,更詳細(xì)的信息可以閱讀這些java源代碼的API文檔。Doug Lea是個(gè)很具有“open”精神的作者,他將util.concurrent工具包的java源代碼全部公布出來(lái),有興趣的讀者可以下載這些源代碼并細(xì) 細(xì)品味。 

    5    結(jié)束語(yǔ)
    以上內(nèi)容介紹了線程池基本原理以及設(shè)計(jì)后臺(tái)服務(wù)程序應(yīng)考慮到的問(wèn)題,并結(jié)合實(shí)例詳細(xì)介紹了重要的多線程開(kāi)發(fā)工具包util.concurrent的構(gòu)架和使用。結(jié)合使用已有完善的開(kāi)發(fā)包,后端服務(wù)程序的開(kāi)發(fā)周期將大大縮短,同時(shí)程序性能也有了保障。

    posted @ 2011-03-23 13:25 Sheldon Sun 閱讀(248) | 評(píng)論 (0)編輯 收藏

    JAVA事務(wù),JTA,JDBC,JDO,DAO,JNDI概念

    引用http://dyldragon.javaeye.com/blog/789374

    一、什么是Java事務(wù)

    通常的觀念認(rèn)為,事務(wù)僅與數(shù)據(jù)庫(kù)相關(guān)。 
    事務(wù)必須服從ISO/IEC所制定的ACID原則。

    ACID是原子性(atomicity)、一致性(consistency)、隔離性(isolation)和持久性(durability)的縮寫。

    事務(wù)的原子性表示事務(wù)執(zhí)行過(guò)程中的任何失敗都將導(dǎo)致事務(wù)所做的任何修改失效。

    一致性表示當(dāng)事務(wù)執(zhí)行失敗時(shí),所有被該事務(wù)影響的數(shù)據(jù)都應(yīng)該恢復(fù)到事務(wù)執(zhí)行前的狀態(tài)。

    隔離性表示在事務(wù)執(zhí)行過(guò)程中對(duì)數(shù)據(jù)的修改,在事務(wù)提交之前對(duì)其他事務(wù)不可見(jiàn)。

    持久性表示已提交的數(shù)據(jù)在事務(wù)執(zhí)行失敗時(shí),數(shù)據(jù)的狀態(tài)都應(yīng)該正確。


         
    通俗的理解,事務(wù)是一組原子操作單元,從數(shù)據(jù)庫(kù)角度說(shuō),就是一組SQL指令,要么全部執(zhí)行成功,若因?yàn)槟硞€(gè)原因其中一條指令執(zhí)行有錯(cuò)誤,則撤銷先前執(zhí)行過(guò)的所有指令。更簡(jiǎn)答的說(shuō)就是:要么全部執(zhí)行成功,要么撤銷不執(zhí)行。


    既然事務(wù)的概念從數(shù)據(jù)庫(kù)而來(lái),那Java事務(wù)是什么?之間有什么聯(lián)系?  實(shí)際上,一個(gè)Java應(yīng)用系統(tǒng),如果要操作數(shù)據(jù)庫(kù),則通過(guò)JDBC來(lái)實(shí)現(xiàn)的。增加、修改、刪除都是通過(guò)相應(yīng)方法間接來(lái)實(shí)現(xiàn)的,事務(wù)的控制也相應(yīng)轉(zhuǎn)移到Java程序代碼中。因此,數(shù)據(jù)庫(kù)操作的事務(wù)習(xí)慣上就稱為Java事務(wù)。


    二、為什么需要事務(wù)

    事務(wù)是為解決數(shù)據(jù)安全操作提出的,事務(wù)控制實(shí)際上就是控制數(shù)據(jù)的安全訪問(wèn)。具一個(gè)簡(jiǎn)單例子:比如銀行轉(zhuǎn)帳業(yè)務(wù),賬戶A要將自己賬戶上的1000 元轉(zhuǎn)到B賬戶下面,A賬戶余額首先要減去1000元,然后B賬戶要增加1000元。假如在中間網(wǎng)絡(luò)出現(xiàn)了問(wèn)題,A賬戶減去1000元已經(jīng)結(jié)束,B因?yàn)榫W(wǎng)絡(luò)中斷而操作失敗,那么整個(gè)業(yè)務(wù)失敗,必須做出控制,要求A賬戶轉(zhuǎn)帳業(yè)務(wù)撤銷。這才能保證業(yè)務(wù)的正確性,完成這個(gè)操走就需要事務(wù),將A賬戶資金減少和B賬戶資金增加方到一個(gè)事務(wù)里面,要么全部執(zhí)行成功,要么操作全部撤銷,這樣就保持了數(shù)據(jù)的安全性。


    三、Java事務(wù)的類型 
        Java 
    事務(wù)的類型有三種:JDBC事務(wù)、JTA(Java Transaction API)事務(wù)、容器事務(wù)。 
    1
    JDBC事務(wù) 
    JDBC 
    事務(wù)是用 Connection 對(duì)象控制的。JDBC Connection 接口( java.sql.Connection )提供了兩種事務(wù)模式:自動(dòng)提交和手工提交。 java.sql.Connection 提供了以下控制事務(wù)的方法:

    public void setAutoCommit(boolean) 
    public boolean getAutoCommit() 
    public void commit() 
    public void rollback() 
    使用 JDBC 事務(wù)界定時(shí),您可以將多個(gè) SQL 語(yǔ)句結(jié)合到一個(gè)事務(wù)中。JDBC 事務(wù)的一個(gè)缺點(diǎn)是事務(wù)的范圍局限于一個(gè)數(shù)據(jù)庫(kù)連接。一個(gè) JDBC 事務(wù)不能跨越多個(gè)數(shù)據(jù)庫(kù)。 
    2
    JTA(Java Transaction API)事務(wù) 
        JTA 
    是一種高層的,與實(shí)現(xiàn)無(wú)關(guān)的,與協(xié)議無(wú)關(guān)的API,應(yīng)用程序和應(yīng)用服務(wù)器可以使用JTA來(lái)訪問(wèn)事務(wù)。 
    JTA
    允許應(yīng)用程序執(zhí)行分布式事務(wù)處理--在兩個(gè)或多個(gè)網(wǎng)絡(luò)計(jì)算機(jī)資源上訪問(wèn)并且更新數(shù)據(jù),這些數(shù)據(jù)可以分布在多個(gè)數(shù)據(jù)庫(kù)上。JDBC驅(qū)動(dòng)程序的JTA支持極大地增強(qiáng)了數(shù)據(jù)訪問(wèn)能力。 
    如果計(jì)劃用 JTA 界定事務(wù),那么就需要有一個(gè)實(shí)現(xiàn) javax.sql.XADataSource  javax.sql.XAConnection  javax.sql.XAResource接口的 JDBC 驅(qū)動(dòng)程序。一個(gè)實(shí)現(xiàn)了這些接口的驅(qū)動(dòng)程序?qū)⒖梢詤⑴c JTA 事務(wù)。一個(gè) XADataSource 對(duì)象就是一個(gè)XAConnection 對(duì)象的工廠。 XAConnection s 是參與 JTA 事務(wù)的 JDBC 連接。 
    您將需要用應(yīng)用服務(wù)器的管理工具設(shè)置 XADataSource 。從應(yīng)用服務(wù)器和 JDBC 驅(qū)動(dòng)程序的文檔中可以了解到相關(guān)的指導(dǎo)。 
    J2EE 
    應(yīng)用程序用 JNDI 查詢數(shù)據(jù)源。一旦應(yīng)用程序找到了數(shù)據(jù)源對(duì)象,它就調(diào)用 javax.sql.DataSource.getConnection() 以獲得到數(shù)據(jù)庫(kù)的連接。 
         XA 
    連接與非 XA 連接不同。一定要記住 XA 連接參與了 JTA 事務(wù)。這意味著 XA 連接不支持 JDBC 的自動(dòng)提交功能。同時(shí),應(yīng)用程序一定不要對(duì) XA 連接調(diào)用 java.sql.Connection.commit() 或者 java.sql.Connection.rollback() 。相反,應(yīng)用程序應(yīng)該使用 UserTransaction.begin() UserTransaction.commit()  serTransaction.rollback() 

    3、容器事務(wù) 
         
    容器事務(wù)主要是J2EE應(yīng)用服務(wù)器提供的,容器事務(wù)大多是基于JTA完成,這是一個(gè)基于JNDI的,相當(dāng)復(fù)雜的API實(shí)現(xiàn)。相對(duì)編碼實(shí)現(xiàn)JTA 事務(wù)管理,我們可以通過(guò)EJB容器提供的容器事務(wù)管理機(jī)制(CMT)完成同一個(gè)功能,這項(xiàng)功能由J2EE應(yīng)用服務(wù)器提供。這使得我們可以簡(jiǎn)單的指定將哪個(gè)方法加入事務(wù),一旦指定,容器將負(fù)責(zé)事務(wù)管理任務(wù)。這是我們土建的解決方式,因?yàn)橥ㄟ^(guò)這種方式我們可以將事務(wù)代碼排除在邏輯編碼之外,同時(shí)將所有困難交給 J2EE容器去解決。使用EJB CMT的另外一個(gè)好處就是程序員無(wú)需關(guān)心JTA API的編碼,不過(guò),理論上我們必須使用EJB 
    四、三種事務(wù)差異 
    1
    JDBC事務(wù)控制的局限性在一個(gè)數(shù)據(jù)庫(kù)連接內(nèi),但是其使用簡(jiǎn)單。 
    2
    JTA事務(wù)的功能強(qiáng)大,事務(wù)可以跨越多個(gè)數(shù)據(jù)庫(kù)或多個(gè)DAO,使用也比較復(fù)雜。 
    3
    、容器事務(wù),主要指的是J2EE應(yīng)用服務(wù)器提供的事務(wù)管理,局限于EJB應(yīng)用使用。 


    JTA

    Java事務(wù)API(JTA;Java Transaction API)和它的同胞Java事務(wù)服務(wù)(JTS;Java Transaction Service),為J2EE平臺(tái)提供了分布式事務(wù)服務(wù)。一個(gè)分布式事務(wù)(distributed transaction)包括一個(gè)事務(wù)管理器(transaction manager)和一個(gè)或多個(gè)資源管理器(resource manager)。一個(gè)資源管理器(resource manager)是任意類型的持久化數(shù)據(jù)存儲(chǔ)。事務(wù)管理器(transaction manager)承擔(dān)著所有事務(wù)參與單元者的相互通訊的責(zé)任。下圖顯示了事務(wù)管理器和資源管理的間的關(guān)系。


    JTA事務(wù)比JDBC事務(wù)更強(qiáng)大。一個(gè)JTA事務(wù)可以有多個(gè)參與者,而一個(gè)JDBC事務(wù)則被限定在一個(gè)單一的數(shù)據(jù)庫(kù)連接。下列任一個(gè)Java平臺(tái)的組件都可以參與到一個(gè)JTA事務(wù)中:

    JDBC連接

    • JDO PersistenceManager 對(duì)象
    • JMS 隊(duì)列
    • JMS 主題
    • 企業(yè)JavaBeans(EJB)
    • 一個(gè)用J2EE Connector Architecture 規(guī)范編譯的資源分配器。


    DAO

    DAO是Data Access Object數(shù)據(jù)訪問(wèn)接口,數(shù)據(jù)訪問(wèn):顧名思義就是與數(shù)據(jù)庫(kù)打交道。夾在業(yè)務(wù)邏輯與數(shù)據(jù)庫(kù)資源中間。對(duì)數(shù)據(jù)庫(kù)進(jìn)行CURD(增刪查改操作)。

     

      在核心J2EE模式中是這樣介紹DAO模式的:為了建立一個(gè)健壯的J2EE應(yīng)用,應(yīng)該將所有對(duì)數(shù)據(jù)源的訪問(wèn)操作抽象封裝在一個(gè)公共API中。用程序設(shè)計(jì)的語(yǔ)言來(lái)說(shuō),就是建立一個(gè)接口,接口中定義了此應(yīng)用程序中將會(huì)用到的所有事務(wù)方法。在這個(gè)應(yīng)用程序中,當(dāng)需要和數(shù)據(jù)源進(jìn)行交互的時(shí)候則使用這個(gè)接口,并且編寫一個(gè)單獨(dú)的類來(lái)實(shí)現(xiàn)這個(gè)接口在邏輯上對(duì)應(yīng)這個(gè)特定的數(shù)據(jù)存儲(chǔ)。


    JDBC

    JDBC(Java Data Base Connectivity,java數(shù)據(jù)庫(kù)連接)是一種用于執(zhí)行SQL語(yǔ)句的Java API,可以為多種關(guān)系數(shù)據(jù)庫(kù)提供統(tǒng)一訪問(wèn),它由一組用Java語(yǔ)言編寫的類和接口組成。JDBC為工具/數(shù)據(jù)庫(kù)開(kāi)發(fā)人員提供了一個(gè)標(biāo)準(zhǔn)的API,據(jù)此可以構(gòu)建更高級(jí)的工具和接口,使數(shù)據(jù)庫(kù)開(kāi)發(fā)人員能夠用純 Java API 編寫數(shù)據(jù)庫(kù)應(yīng)用程序,同時(shí),JDBC也是個(gè)商標(biāo)名。

     

    有了JDBC,向各種關(guān)系數(shù)據(jù)發(fā)送SQL語(yǔ)句就是一件很容易的事。換言之,有了JDBC API,就不必為訪問(wèn)Sybase數(shù)據(jù)庫(kù)專門寫一個(gè)程序,為訪問(wèn)Oracle數(shù)據(jù)庫(kù)又專門寫一個(gè)程序,或?yàn)樵L問(wèn)Informix數(shù)據(jù)庫(kù)又編寫另一個(gè)程序等等,程序員只需用JDBC API寫一個(gè)程序就夠了,它可向相應(yīng)數(shù)據(jù)庫(kù)發(fā)送SQL調(diào)用。同時(shí),將Java語(yǔ)言和JDBC結(jié)合起來(lái)使程序員不必為不同的平臺(tái)編寫不同的應(yīng)用程序,只須寫一遍程序就可以讓它在任何平臺(tái)上運(yùn)行,這也是Java語(yǔ)言“編寫一次,處處運(yùn)行”的優(yōu)勢(shì)。


    簡(jiǎn)單地說(shuō),JDBC 可做三件事:與數(shù)據(jù)庫(kù)建立連接、發(fā)送 操作數(shù)據(jù)庫(kù)的語(yǔ)句并處理結(jié)果。


    JDO

    JDO(Java Data Object )是一個(gè)JAVA用于存取某種數(shù)據(jù)倉(cāng)庫(kù)中的對(duì)象的標(biāo)準(zhǔn)化API。JDO提供了透明的對(duì)象存儲(chǔ),因此對(duì)開(kāi)發(fā)人員來(lái)說(shuō),存儲(chǔ)數(shù)據(jù)對(duì)象完全不需要額外的代碼(如JDBC API的使用)。這些繁瑣的例行工作已經(jīng)轉(zhuǎn)移到JDO產(chǎn)品提供商身上,使開(kāi)發(fā)人員解脫出來(lái),從而集中時(shí)間和精力在業(yè)務(wù)邏輯上。另外,JDO很靈活,因?yàn)樗梢栽谌魏螖?shù)據(jù)底層上運(yùn)行。JDBC只是面向關(guān)系數(shù)據(jù)庫(kù)(RDBMS)JDO更通用,提供到任何數(shù)據(jù)底層的存儲(chǔ)功能,比如關(guān)系數(shù)據(jù)庫(kù)、文件、XML以及對(duì)象數(shù)據(jù)庫(kù)(ODBMS)等等,使得應(yīng)用可移植性更強(qiáng)。


    JNDI

    英文全稱是:Java Naming and Directory Interface

    術(shù)語(yǔ)解釋:一組幫助做多個(gè)命名和目錄服務(wù)接口的API。

    JNDI(Java Naming and Directory Interface)是SUN公司提供的一種標(biāo)準(zhǔn)的Java命名系統(tǒng)接口,JNDI提供統(tǒng)一的客戶端API,通過(guò)不同的訪問(wèn)提供者接口JNDI SPI的實(shí)現(xiàn),由管理者將JNDI API映射為特定的命名服務(wù)和目錄系統(tǒng),使得Java應(yīng)用程序可以和這些命名服務(wù)和目錄服務(wù)之間進(jìn)行交互。集群JNDI實(shí)現(xiàn)了高可靠性JNDI[8],通過(guò)服務(wù)器的集群,保證了JNDI的負(fù)載平衡和錯(cuò)誤恢復(fù)。在全局共享的方式下,集群中的一個(gè)應(yīng)用服務(wù)器保證本地JNDI樹(shù)的獨(dú)立性,并擁有全局的JNDI樹(shù)。每個(gè)應(yīng)用服務(wù)器在把部署的服務(wù)對(duì)象綁定到自己本地的JNDI樹(shù)的同時(shí),還綁定到一個(gè)共享的全局JNDI樹(shù),實(shí)現(xiàn)全局JNDI和自身JNDI的聯(lián)系。


     

    JNDI(Java Naming and Directory Interface)是一個(gè)應(yīng)用程序設(shè)計(jì)的API,為開(kāi)發(fā)人員提供了查找和訪問(wèn)各種

     

    命名和目錄服務(wù)的通用、統(tǒng)一的接口,類似JDBC都是構(gòu)建在抽象層上。

     

    JNDI可訪問(wèn)的現(xiàn)有的目錄及服務(wù)有:DNS、XNam 、Novell目錄服務(wù)、LDAP(Lightweight Directory Access Protocol 輕型目錄訪問(wèn)協(xié)議)、 CORBA對(duì)象服務(wù)、文件系統(tǒng)、Windows XP/2000/NT/Me/9x的注冊(cè)表、RMI、

     


     

    DSML v1&v2、NIS。

     


    JNDI與JDBC

    JNDI提供了一種統(tǒng)一的方式,可以用在網(wǎng)絡(luò)上查找和訪問(wèn)服務(wù)。通過(guò)指定一個(gè)資源名稱,該名稱對(duì)應(yīng)于數(shù)據(jù)庫(kù)或命名服務(wù)中的一個(gè)記錄,同時(shí)返回?cái)?shù)據(jù)庫(kù)連接建立所必須的信息。

    JNDI主要有兩部分組成:應(yīng)用程序編輯接口和服務(wù)供應(yīng)商接口。應(yīng)用程序編程接口提供了Java應(yīng)用程序訪問(wèn)各種命名和目錄服務(wù)的功能,服務(wù)供應(yīng)商接口提供了任意一種服務(wù)的供應(yīng)商使用的功能。

     

     

    Java代碼  收藏代碼
    1. try{  
    2.   Context cntxt = new InitialContext();  
    3.   DataSource ds = (DataSource) cntxt.lookup("jdbc/dpt");  
    4. }  
    5.   catch(NamingException ne){  
    6.   ...  
    7. }  

    posted @ 2011-03-22 17:35 Sheldon Sun 閱讀(1130) | 評(píng)論 (1)編輯 收藏

    Restart

    From now, i will restart my blog , try to record sth of my life, including some thoughts and research results of technology, the only little hope is that the blog can leave my memory of life, as time flying, when i open it , i can get something.

    Technology - Hibernate collection:
    Maybe i used to write sth related before.
    Several points as follows:
    1. Define interface as property, for Hibernate will use its own implementation during runtime.
    2. <key> element is used to identiry foreign key for specified table.
    3. <element> and <composite-element> is used for value type definition while <one-to-many> and <many-to-many> is used for entities type.
    4. indexed-collections contain : map, list, index is used to record position for certain record in the container.<map-key> for map while <index-list> for list.
    Next two items is for bidirection:
    5. inverse can be set in either sides for many-to-many relation.
    6. For one-to-many,  many sides will mantain relationship between object. exception happened when many side is index container.in this situation, it is not a completely "bidirectoinal".

    7. Sort is done in memory while order by is down in DB.
    8. <Bag> is used when property is defined as list, but <index-list> is not welcome.
    9. <idbag> is a list which can generate an id for primary key.

    posted @ 2008-06-11 18:27 Sheldon Sun 閱讀(507) | 評(píng)論 (0)編輯 收藏

    Interpret and command pattern

    解釋器模式:
    編譯器用的比較多。
    針對(duì)某一特定語(yǔ)法的分析, 解釋, 并進(jìn)行處理!
    E.g: Expression = expression1 | expression2 | repeatableExpresson|Literal
    針對(duì)整個(gè)Expression, 分析出其每個(gè)組成的expresion1, expression2, 對(duì)每個(gè)分析出的結(jié)果, 都有相應(yīng)的處理類! 并初始化出處理類的實(shí)例進(jìn)行處理!
    Literal代表元數(shù)據(jù) !
    如果對(duì)一個(gè)汽車組件的各個(gè)生產(chǎn)廠商進(jìn)行解釋器模式分析的話: 汽車 = 輪胎 + 發(fā)動(dòng)機(jī) + 框架 那么首先建立一個(gè)分析程序,分析汽車的組成, 并針對(duì)每個(gè)部件初始化一個(gè)不見(jiàn)對(duì)應(yīng)的對(duì)象, 來(lái)匹配該部件! 并調(diào)用部件的特有方法, 處理部件, 返回生產(chǎn)廠家的名稱!

    這個(gè)例子好失敗, Interpret 模式優(yōu)點(diǎn)在表達(dá)式的租成有很多模塊, 每個(gè)模塊重復(fù)的包含其他模塊的情況下, 達(dá)到代碼重用的目的! 所以除了正則表達(dá)式, 編譯器以外, 暫時(shí)想不出什么好的例子來(lái)!

    命令行模式:
    Struts 應(yīng)用是典型的命令行模式。
    1。 把請(qǐng)求參數(shù)話。
    2。 對(duì)每個(gè)請(qǐng)求配置相應(yīng)的處理類。處理類有統(tǒng)一的接口。
    3。 配置請(qǐng)求與處理類的對(duì)應(yīng)關(guān)系。
    4。 調(diào)用處理類統(tǒng)一接口。

    沒(méi)什么好說(shuō)的!




    今天比較凡, 感覺(jué)自己職業(yè)發(fā)展已經(jīng)到達(dá)了一個(gè)瓶頸, 不知道怎么發(fā)展才好!
    感覺(jué)自己交流能力比較差, 大家在一起的時(shí)候都是聽(tīng)別人說(shuō)! 自己很少發(fā)言, 做編碼已經(jīng)感覺(jué)沒(méi)有太大意思了, 因?yàn)楝F(xiàn)在的公司只注重結(jié)果, 不看中代碼的質(zhì)量,開(kāi)發(fā)出來(lái)很容易, 但開(kāi)發(fā)好的代碼很難! 周圍的同事開(kāi)發(fā)出來(lái)代碼的水平比我都差很多, 也一樣通過(guò), 搞得自己想提高自己都沒(méi)有動(dòng)力!
    想提高一下交流能力, 不知道轉(zhuǎn)行做QA會(huì)不會(huì)有點(diǎn)改善, 或者還家公司?
    比較迷茫!

    posted @ 2007-11-22 16:56 Sheldon Sun 閱讀(302) | 評(píng)論 (0)編輯 收藏

    Chain of responsibility

    剛才看了看職責(zé)鏈模式, 沒(méi)什么概念, 腦袋還是比較混亂! 把思路寫出來(lái)!

    職責(zé)鏈主要是為了一個(gè)請(qǐng)求, 可能有很多個(gè)處理者, 這些處理者數(shù)目并不固定而設(shè)計(jì)的!

    對(duì)每種處理, 都會(huì)有一個(gè)處理類來(lái)對(duì)應(yīng)! 沒(méi)個(gè)具體的處理類都會(huì)有一個(gè)后繼: succor, 這個(gè)后繼比處理類更廣泛! 如果當(dāng)前的處理類可以處理改請(qǐng)求, 則處理,否則使用后繼的處理方法!

    感覺(jué)最關(guān)鍵的一點(diǎn)就是對(duì)后繼者的定義, 那為什么不用繼承機(jī)制呢???

    posted @ 2007-11-21 16:49 Sheldon Sun 閱讀(339) | 評(píng)論 (1)編輯 收藏

    Validate xml

    package testSchema;

    import java.io.IOException;
    import java.io.InputStream;
    import java.io.Serializable;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Map;

    import org.apache.commons.codec.binary.Base64;
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.dom4j.Document;
    import org.dom4j.DocumentException;
    import org.dom4j.DocumentHelper;
    import org.dom4j.Element;
    import org.dom4j.Namespace;
    import org.dom4j.io.SAXReader;
    import org.dom4j.tree.DefaultNamespace;

    import org.iso_relax.verifier.Schema;
    import org.iso_relax.verifier.Verifier;
    import org.iso_relax.verifier.VerifierConfigurationException;
    import org.iso_relax.verifier.VerifierFactory;
    import org.iso_relax.verifier.VerifierFilter;
    import org.xml.sax.EntityResolver;
    import org.xml.sax.ErrorHandler;
    import org.xml.sax.InputSource;
    import org.xml.sax.SAXException;
    import org.xml.sax.SAXParseException;

    import com.sun.msv.verifier.jarv.TheFactoryImpl;

    public class ValidateXML {
       
        public Document validate(InputStream stream, String xsdName) throws IOException{
       
        Document result = null;
        InputStream xmlStream = stream;
        InputStream schemaStream = this.getClass().getResourceAsStream(xsdName);
        SAXReader reader;
        try {
            reader = createSAXReader(schemaStream);
            result = reader.read(xmlStream);
            xmlStream.close();
            schemaStream.close();
        } catch (DocumentException e) {
            System.out.println("Validate failed !");
            e.printStackTrace();           
        } catch(IOException e) {
            System.out.println("Xsd file does not exist !");
            e.printStackTrace();           
        }
        catch (Exception e) {
            System.out.println("Xsd file format error !");
            e.printStackTrace();
        }
       
        return result;
    }

    private SAXReader createSAXReader(InputStream xsdStream) throws VerifierConfigurationException, SAXException, IOException {
        VerifierFactory factory = new TheFactoryImpl();
    Schema schema = factory.compileSchema(xsdStream);

    Verifier verifier = schema.newVerifier();
    verifier.setErrorHandler(new ErrorHandler() {
        public void error(SAXParseException e) {
        System.out.println("ERROR: " + e);
        }

        public void fatalError(SAXParseException e) {
        System.out.println("FATAL: " + e);
        }

        public void warning(SAXParseException e) {
        System.out.println("WARNING: " + e);
        }
    });

    // now install the verifying filter
    VerifierFilter filter = verifier.getVerifierFilter();
    SAXReader reader = new SAXReader();
    reader.setXMLFilter(filter);
    return reader;
    }


    public static void main(String[] args) throws IOException {
        ValidateXML validateXML = new ValidateXML();
    //    InputStream schemaStream = validateXML.getClass().getResourceAsStream("Response.xml");
    //    validateXML.validate(schemaStream, "BAK-Response.xsd");
        validateXML.validateByDtd("hibernate-configuration-3.0.dtd", "src\\testSchema\\hibernate.cfg.xml");
    }

    public Document validateByDtd(String dtdFile, String xmlFile) {
        List errors = new ArrayList();
        SAXReader saxReader = new SAXReader();
        saxReader.setEntityResolver(new DTDEntityResolver(dtdFile));
        saxReader.setErrorHandler(new ErrorLogger(xmlFile, errors));
        saxReader.setValidation(true);
        Document doc = null;
        try {
        doc = saxReader.read(xmlFile);
        } catch (DocumentException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        }
       
        return doc;
    }

    public static class ErrorLogger implements ErrorHandler {
        private String file;
        private List errors;
        ErrorLogger(String file, List errors) {
            this.file=file;
            this.errors = errors;
        }
        public void error(SAXParseException error) {
            System.err.println( "Error parsing XML: " + file + '(' + error.getLineNumber() + ") " + error.getMessage() );
            errors.add(error);
        }
        public void fatalError(SAXParseException error) {
            System.err.println(error);
        }
        public void warning(SAXParseException warn) {
            System.err.println( "Warning parsing XML: " + file + '(' + warn.getLineNumber() + ") " + warn.getMessage() );
        }
    }


    public static class DTDEntityResolver implements EntityResolver, Serializable {

        private static final Log log = LogFactory.getLog( DTDEntityResolver.class );

       
        private String dtdFile;
        public DTDEntityResolver(String dtdFile) {
            this.dtdFile = dtdFile;
        }
        public InputSource resolveEntity(String publicId, String systemId) {
            if ( systemId != null ) {
                InputStream dtdStream = this.getClass().getResourceAsStream(dtdFile);
                InputSource source = new InputSource( dtdStream );
                source.setPublicId( publicId );
                source.setSystemId( systemId );
                       
                return source;
            }
            // use default behavior
            return null;
        }

    }

    }

    posted @ 2007-08-08 09:53 Sheldon Sun 閱讀(579) | 評(píng)論 (0)編輯 收藏

    Hibernate - Component

    1. Component is value type, can not shared between entities, dont own identifier!
    2. Declaration for mapping under component element.
    3. When storing in set(or other collection type), use composite-element.
    4. When using as primary key, use composite-id.
    5. Dynamic component.



    posted @ 2007-06-19 09:31 Sheldon Sun 閱讀(302) | 評(píng)論 (0)編輯 收藏

    Hibernate - Persistent class

    1. Hibernate recommand persisten class as a standard javabean naming convention, but not required, Hibernate can access fileds directory too.
    But a no-argument constuctor is requeried for hibernate to instiante an object of the class by refection.

    2. Indentifier property if optional too, but needed if we want to use the full feature set of hibernate, for hibernate will distinguish object by identifiers while some special operation. e.g:  merge(), saveOrUpdate.

    3. Equals() and hasdCode() mehtod is recommanded to implenent when you want to store persisntent class in a Set or manipulate object span sessions.

    4. There are other 2 ways to define enity object except java class, Map and xml, the defect maybe can not do compile check, metrit is more flexisble than java.

    5. Tuplizier!!!!

    Hibernate integrated with J2EE infrastructure:
    Two main point:
    1. Hidden Configuration.config().buildSessionFacotory operation.
    2. Bound session factory to jndi namespace through many way. e.g: MBean
     

    posted @ 2007-06-14 11:12 Sheldon Sun 閱讀(558) | 評(píng)論 (0)編輯 收藏

    Inheritance strategy

    There are three kinds of basic strategies for inheritence mapping:
    1. table per hierarchy.
    2. table per subclass.
    3. table per concreteclass.

    Table structure maybe the root reason to determine which kind strategy will be used.

    Table per hierarchy:
    With subclass element.
    A discriminator column will be used to distinguish subclass.
    Limitation: no not null constraint on sub class's property.
    Fault: redandance data will be generated.

    Table per subclass:
    With joined-class elment.
    There are tables for super class and each subclass, for every subclass, key elemnt is used to referenced to super class's primary key, and all common properties will be stored in super table. The relation between super table and sub table is one-to-one.
    Fault: complex table structure.


    Table per concrete class:
    With union-class elemnt.
    Super class responsible for genrate id and all common properties wich will stored in sub table.
    Fault: redandance data will be generated.
    Limitation: all common column should used the same column name for the properties are defined in super class.

    posted @ 2007-06-01 10:55 Sheldon Sun 閱讀(255) | 評(píng)論 (0)編輯 收藏

    HbmBinder

    Walks an XML mapping document and produces the Hibernate configuration-time metamodel (the classes in the mapping package)


     

    1. parse "extend" attribute of subclass, unionclass, joinedclass which defined under <hibernate-mapping> element.

    2. parse "meta" data element.

    3. parse other subclass of root element.

    posted @ 2007-05-30 12:57 Sheldon Sun 閱讀(153) | 評(píng)論 (0)編輯 收藏

    Hibernate filter

    1. Hibernate filter is used to give a definition condition in xml mapping files.
    2. Ever session want to use it must enable the filter with name first.
    3. filter is defined in xml with elment <filter-def> under <hibernate-mapping>, used <filter> element under <class> element.
    4. give certain sql condition attribute either in <filter-def> or <filter>.
    5. Support value to filter parameters in application.



    The main purpose is to support global filter.

    posted @ 2007-05-24 13:20 Sheldon Sun 閱讀(436) | 評(píng)論 (0)編輯 收藏

    Hibernate query

    1. session.createSqlQuery(), in purpose to increase performance, execute sql directly. addScalar() method is used to sepcify type of columns, add entity to return certain entity instance.
    2. session.getNamedQuery(), execute query defined in mapping files with <sql-query> element, the query can be a defined sql sentence or a procedure, property type and entity type can also be specifid by certain elment.
    3. update, detelet, insert sql can be defined in xml mapping files also.


    The finaly purpose of the query is to enchance performance.

    posted @ 2007-05-24 12:51 Sheldon Sun 閱讀(333) | 評(píng)論 (0)編輯 收藏

    Hibernate Criteria

    1. Usage org.hibernage.Criteria interface is to compose criterians included in org.hibernate.criteria package.
    2. Criteria interface inherit org.hibernate.criteria.CriterianSpecification, which only defined some mode value, e.g: flushmode, cach mode, maybe not a good implemnt.
    3. Criterian was implemnt by org.hibernate.impl.criteriaImpl and created by org.hibernate.impl.SessionImplementor, translate class name and sesson to criterian.
    4. Typical usage: session.createCriteria(class).add(Restriction.xx()).list;
    5. Restriction is factory of org.hibernate.criteria.Criteriaon implementation.

    Architecture : Define top level interface to compose low lever sub interface, easy to extense and maintain.

    posted @ 2007-05-24 10:55 Sheldon Sun 閱讀(277) | 評(píng)論 (0)編輯 收藏

    Hibernate - Environment

    There are 2 kinds of factory : factory level and System level, factory responsible for every factory instance, System for all facotrys, (only 2 system factory property).
    Evironment got properties for /hibernate.properties first, and then from System.getProperties() to ovrride old one!

    Totally, Evironment represents properties.

    posted @ 2007-05-22 13:57 Sheldon Sun 閱讀(111) | 評(píng)論 (0)編輯 收藏

    Collection mappings

    1. Use interface type.
    2. Ordered type collection has index sub-element.
    3. Key element indicates the foreign key referred to entity own the collection.
    4. "element" or "composite element" element is used to specify value type contained in collection.
    5. "many-to-many" or "one-to-many" elmeent is used to sepcify referred type contained in collection.
    6. one-to-many need not an intervening table.(foreign key)

    posted @ 2007-05-22 11:12 Sheldon Sun 閱讀(111) | 評(píng)論 (0)編輯 收藏

    Persisitent object

    Hard requirenment:
    1. No-argument construct , package visiblity, usde instantiate object by Constructor.newInstance().

    Option requirement:
    1. Pojo.
    2. Implement hashCode and equals for two resons :
        1) Object will be store in a set property.
        2) Instance span to sesssion scope, make a detached object persistent again, will call equals, for java indentify(==) and db indentify(pk) is not available for the condition(object doest not have identify before persistent),

    Note: hashCode generation should not use indentify proeprty  of object.

    posted @ 2007-05-17 08:51 Sheldon Sun 閱讀(240) | 評(píng)論 (0)編輯 收藏

    Hibernate configuration

    Hibernate configuration object is the core and starttime class , initiate it and call its config() method to initial sessionFactory.
    Configuration get properties, mapping , etc information through two ways:
    1. Config file: hibernate.propeties, system, hibernate.cfg.xml(optional, name changed Configuration.doConfig(*.cfg.xml)).
    2. Method: Configuration.addSource, addProperties...

    So config files is only a way of configuration to get config info.



    posted @ 2007-05-16 15:00 Sheldon Sun 閱讀(232) | 評(píng)論 (0)編輯 收藏

    0516_2

    Configuration: the class instantiate a sessionng factory, it works as follow:
    1. Get properties for Enviroment.java. Environment get properties from hibernate.properties and System, System propertie is prior to hibernate.properties when name is equal.
    2. Configuration.config will read hibernate.cfg.xml to get more properties and mapping files.


    During last two steps, it will some util class in org.hibernate.util to help handle file.

    3. Generate ConnectionProvider by its all properties.


    posted @ 2007-05-16 09:17 Sheldon Sun 閱讀(122) | 評(píng)論 (0)編輯 收藏

    0516_1

    1. Update make a detached object persistent.
    2. Config mapping relating in mapping files make query as object oriented.
    3. For many-to-many relation relationship, middle table store link to two tables.
    4. Key element is identify the column of middle table.
    5. Db operation happend at the end of a unit work ---- session flush.
    6. For value type, "element" will replace "many-to-many" in set element(acturally, for all java object, hibernate take it as a value type), value type can not shared by more than one instance.
    7. All bi-directional associations need one side as inverse. bi-direction means both sides of mapping mentain relations of middle table, inverse side is a mirror of the other side, during save or update, the other side will handle.

    posted @ 2007-05-16 08:52 Sheldon Sun 閱讀(166) | 評(píng)論 (0)編輯 收藏

    session

    1. batch insert/update session.flush session.clear
    2. statlesssession

    posted @ 2007-05-15 13:34 Sheldon Sun 閱讀(80) | 評(píng)論 (0)編輯 收藏

    Mapping for inheritance

    There are three main kinds of mapping for inheritance:
    1. table per class hirachy, for each subclass, use discriminator to distinguish different data, subclass specific property can not be null, only one table.
    2. table per subclass, there is a common table for super class, subclass table reference to super table through primary key, add relationship between tables.
    3. table per concrete class, generate too much redandance data, pk was generated by super class.


    some mix mapping is available.



    posted @ 2007-05-14 13:41 Sheldon Sun 閱讀(133) | 評(píng)論 (0)編輯 收藏

    hibernate ref1

    1. Entity name: can be used query.
    2. Way of define mapping: xml, xdoclet, annotation.
    3. Gerated properties: timestamp, version, and property can be generated. Types as follows :
    never: default value.
    always: generated when insert and update.
    insert: only geneated when create data, won't change when updated it later.
    4. Create db schema can be written in xml file.

    posted @ 2007-05-14 10:20 Sheldon Sun 閱讀(112) | 評(píng)論 (0)編輯 收藏

    Hibernate reference

    1. lite archetecture: application handle connection and transaction, use niminum hibernate api.
    2. full scream architecture: application will ingore underlying jdbc, jta apis, hibernate hold it.
    3. Persistent object stats: persistence, transient and detached.
    4. Session factory: a cache of compiled configuration files for single db, thread-safed, factory of session and client of connectionProvider, an optional cache of data for process, cluster layer.
    5. Session: represent a conversation between application and db, factory of transaction. wrapped conncetion.
    6. Transatcion: specify automic unit of work.
    7. Context session: hibernateUtil class, for certain application, the scope of current is different, have different context concept. (need more research!)
    8. Configration: store xml to java, can got it through specify xml, java class and proeprties.
    9. Hibernate mapping: mapping java type to SQL type.
    10. Custome mapping type: implement UserType or CompsiteUserType, can define short name, chould get certain value of property by key value.(useless)
    11. Entity and Value: entity can be shared by more than one persistent class as reference.


    posted @ 2007-05-14 09:45 Sheldon Sun 閱讀(247) | 評(píng)論 (0)編輯 收藏

    再論Singleton模式

    Singleton模式可能是應(yīng)用最廣泛的模式之一了, 但有些錯(cuò)誤的應(yīng)用。
    ?Singleton的實(shí)現(xiàn): 有兩種方式, 如下:
    1. class Test { public static final Test instance = new Test(); private Test() {} }
    ?2. class Test { private static final Test instance = new Test(); private Test() {} public static Test getInstance() { return instance; } } 這兩種方法都要求構(gòu)造器是私有的, 這樣就可以防止該類外的對(duì)象創(chuàng)建新的TEST對(duì)象。 但相對(duì)而言, 推薦使用第二種方法, 因?yàn)槠涓哂徐`活性,當(dāng)我們改變創(chuàng)建對(duì)象的方式的時(shí)候, 不需要改動(dòng)客戶代碼。 第一種方法較第二種有一點(diǎn)完全可以忽略不計(jì)的效率的提高。
    ?但應(yīng)避免如下代碼實(shí)現(xiàn)Singleton: class Test { private static Test singleton = null; private Test() {} public Test getSingleton() { if(singleton == null) { singleton = new Test(); } return singleton; } } 因?yàn)閲?yán)格上講, 這并不能完全實(shí)現(xiàn)Singleton模式,而且會(huì)導(dǎo)致程序出錯(cuò), 這同著名的線程問(wèn)題--DCL實(shí)效的原理是完全一樣的:
    JVM創(chuàng)建對(duì)象的過(guò)程可以分為幾個(gè)步驟:創(chuàng)建空間, 把所有的變量賦值位默認(rèn)值, 初始化。。。 當(dāng)有兩個(gè)線程A和B同事進(jìn)入該方法, A先執(zhí)行, A創(chuàng)建Test實(shí)例的空間, 這時(shí),因?yàn)镃PU的指令流機(jī)制,時(shí)間片段正好輪到B線程, 這時(shí)B判斷singleton是否為NULL, 因?yàn)锳已經(jīng)為Test的實(shí)例分配了空間, 所以JVM認(rèn)為實(shí)例已經(jīng)創(chuàng)建了, B繼續(xù)執(zhí)行, 更糟糕的是B調(diào)用了singleton, 這時(shí)因?yàn)樗](méi)有初始化完全, 所以拋出NullPointerException, 太糟糕了!

    posted @ 2006-10-30 14:10 Sheldon Sun 閱讀(188) | 評(píng)論 (0)編輯 收藏

    Bridge模式 和Composite模式

    Bridge:主要實(shí)現(xiàn)的原理就是把接口 和實(shí)現(xiàn)分離開(kāi)來(lái), 保證他們?cè)賰蓚€(gè)不同的類層次結(jié)構(gòu)。

    用Bridge而不是直接繼承實(shí)現(xiàn)主要有兩個(gè)好處:
    1。 二進(jìn)制兼容。 假設(shè)我們的應(yīng)用程序需要用到format功能, 我們可能有要引用兩個(gè)第三方JAR包, formatInterface.JAR And formatImp.jar, 我們程序可能只引用了formatInterface.jar中的接口, 而formatImpl.jar里是什么我們根本不需要關(guān)心, 因?yàn)樗莊ormatInterface的實(shí)現(xiàn), 所以當(dāng)他改變的時(shí)候, 我們的應(yīng)用程序完全不用重新修改代碼, 編譯。可能我在LINUX下用LINUXFormatImpl.jar, 再WINDOW下use WindowFormatImpl.jar, but Application will never care about it.
    ?2. 接口與實(shí)現(xiàn)的分離, 實(shí)現(xiàn)不一定實(shí)現(xiàn)接口的內(nèi)容, 就是說(shuō)實(shí)現(xiàn)同接口之間不是一一對(duì)應(yīng)的, 實(shí)現(xiàn)可能完成最原子的操作, 而接口通過(guò)持有一個(gè)實(shí)現(xiàn)的應(yīng)用, 組裝這些操作來(lái)實(shí)現(xiàn)接口。 比如說(shuō)接口是createRectangle(), 實(shí)現(xiàn)可能只完成了createLine的操作, 然后有接口來(lái)組裝。


    ?Composite模式則要從全局的角度考慮對(duì)象之間的關(guān)系是否滿足“樹(shù)枝” 與 “樹(shù)葉”的關(guān)系, 如果滿足, 則需要定義一個(gè)樹(shù)枝與樹(shù)葉的集合接口Tree, 既包含樹(shù)枝接口add(tree)和樹(shù)葉接口getColor()。

    posted @ 2006-10-26 19:46 Sheldon Sun 閱讀(155) | 評(píng)論 (0)編輯 收藏

    Synchronize 與 JAVA 內(nèi)存模型

    每個(gè)JAVA對(duì)象都有一把所, 當(dāng)有多個(gè)線程同時(shí)訪問(wèn)共享資源的時(shí)候, 需要Synchronize 來(lái)控制安全性, synchronize 分 synchronize 方法 和synchronize快,使用synchronize塊時(shí), 一定要顯示的獲得該對(duì)象的鎖(如synchronize(object))而方法則不需要。

    ?JAVA 的內(nèi)存模型是對(duì)每一個(gè)進(jìn)程有一個(gè)主內(nèi)存, 每個(gè)線程有自己的內(nèi)存, 他們從主內(nèi)存中取數(shù)據(jù), 然后計(jì)算, 再存入主內(nèi)存中。

    ?并發(fā)問(wèn)題如下:如果多個(gè)線程同事操作同一數(shù)據(jù), A線程從主內(nèi)存中取的I的值為1, 然后進(jìn)行加1操作, 這時(shí)B線程也取I的值, 進(jìn)行加2操作, 然后A存入2到主內(nèi)存中, B也存入, 這樣就覆蓋了A的值(同數(shù)據(jù)庫(kù)中的并發(fā)問(wèn)題一樣)。 解決辦法是用synchronize, 如用synchronized(I)。被synchronize 修飾的方法(塊)把以下三步操作當(dāng)成一個(gè)原子操作:取數(shù)據(jù), 操作數(shù)據(jù), 存數(shù)據(jù)。 我們知道原子操作是不可以被打斷的, 所以其保證了數(shù)據(jù)一致性, 這樣同一時(shí)間只有一個(gè)線程再執(zhí)行, 對(duì)性能有一定的影響。這也是synchronize的第二個(gè)作用:保證統(tǒng)一時(shí)間只有一個(gè)線程再運(yùn)行。 當(dāng)實(shí)現(xiàn)SOCKET連接的時(shí)候經(jīng)常用到.

    ?JAVA中規(guī)定對(duì)非FLOAT, LONG的原始類型的取和存操作為原子操作。 其實(shí)就是對(duì)一個(gè)字(32位)的取,存位原始操作, 因?yàn)镕LOAT, LONG為兩個(gè)字節(jié)的長(zhǎng)度, 所以其取, 存為非原子操作。 如果想把他們也變?yōu)樵硬僮鳎?可以用VOLATILE關(guān)鍵字來(lái)修飾。

    posted @ 2006-10-26 19:19 Sheldon Sun 閱讀(411) | 評(píng)論 (0)編輯 收藏

    java seriliazable

    1. serializable default serialize all field and object net.
    2. Externalizable default deserialize all fields and use writeExternal and readExternal to serialize object. should provide public construct.
    3. serializable interface use private writeObject and private readOjbect to implemnets the same fucntion as Extenalizable interface. (writeDefautObject and readDefaultObject).
    4. Externalizable extends serializable

    posted @ 2006-10-23 20:09 Sheldon Sun 閱讀(163) | 評(píng)論 (0)編輯 收藏

    從學(xué)習(xí)JAVA看學(xué)習(xí)語(yǔ)言

    學(xué)習(xí)java也有幾年的時(shí)間了, 大學(xué)開(kāi)始就一直沒(méi)有斷過(guò), 工作后有專門學(xué)習(xí)了java。 由于對(duì)原理型的知識(shí)比較看重, 所以JAVA基礎(chǔ)學(xué)的比較多, 至今精通不敢說(shuō), 但至少也應(yīng)該算是熟悉了吧! 我認(rèn)為語(yǔ)言的學(xué)習(xí)最簡(jiǎn)單的就是文法學(xué)習(xí), 估計(jì)一般學(xué)習(xí)一周 到兩周就可以使用這種語(yǔ)言編寫程序, 對(duì)于初級(jí)程序員這樣也就足夠了, 但要對(duì)語(yǔ)言有很深的了解:就是對(duì)這個(gè)語(yǔ)言的特性的了解, 把JAVA做例子, 他的所有類繼承自O(shè)BJECT(他的所有方法用途, 作用等等), CLONABLE接口, SERIALIZABEL接口改變了方法的行為,synchronized等等, 這些都是JAVA語(yǔ)言定義的自己的特征, 包括JAVA的性能, 要能高效率的運(yùn)用JAVA, 必須對(duì)對(duì)這些特性有比較深的了解, 還要對(duì)其主要的庫(kù)有一定的了解,比如說(shuō)容器庫(kù), 輸入輸出流。。如果了解這些的話最少也要花費(fèi)1--2年的學(xué)習(xí), 還不一定掌握精髓。 估計(jì)掌握這些知識(shí)的人怎么也應(yīng)該是高級(jí)程序員了。 JAVA學(xué)習(xí)的最高境界應(yīng)該是對(duì)其類庫(kù)的無(wú)比熟悉, 能清楚其內(nèi)在的實(shí)現(xiàn), 如容器類散列桶的實(shí)現(xiàn)方法等等, 以及他們實(shí)現(xiàn)的優(yōu)劣。 能達(dá)到這個(gè)程度的人應(yīng)該寥寥無(wú)幾, 這樣的人一般是有10年JAVA工作經(jīng)驗(yàn)的資深JAVA程序員了。 個(gè)人認(rèn)為學(xué)習(xí)語(yǔ)言也不過(guò)這三個(gè)階段:熟悉語(yǔ)法, 熟悉語(yǔ)言的特性, 精通類庫(kù)。一個(gè)語(yǔ)言成熟與否的標(biāo)志就是他是否有一個(gè)設(shè)計(jì)良好的全面的類庫(kù)。

    posted @ 2006-10-23 11:24 Sheldon Sun 閱讀(198) | 評(píng)論 (0)編輯 收藏

    迭代化開(kāi)發(fā)新問(wèn)題

    http://blog.csdn.net/fuchunyi/archive/2006/10/22/1345708.aspx 這周去拜訪一個(gè)客戶,他們正在實(shí)施RUP,問(wèn)及效果如何,聽(tīng)到了一些關(guān)于迭代化開(kāi)發(fā)的新問(wèn)題。 這位客戶是一家集成商,主要為甲方開(kāi)發(fā)應(yīng)用軟件系統(tǒng)。實(shí)施迭代化開(kāi)發(fā)的主要目的是控制項(xiàng)目風(fēng)險(xiǎn),應(yīng)用項(xiàng)目的最大風(fēng)險(xiǎn)一般都在于需求,采用迭代化可以通過(guò)迭代產(chǎn)生的原型系統(tǒng)來(lái)收集甲方客戶的反饋,從而及早修正對(duì)于客戶需求的誤解。但是開(kāi)發(fā)團(tuán)隊(duì)并沒(méi)有象預(yù)想中那樣收集到甲方的反饋,甲方還是習(xí)慣于用傳統(tǒng)的瀑布模型來(lái)評(píng)價(jià)、驗(yàn)收系統(tǒng),他們并沒(méi)有對(duì)項(xiàng)目過(guò)程中交付的原型系統(tǒng)進(jìn)行認(rèn)真的確認(rèn),所以也沒(méi)有太多的意見(jiàn)反饋給開(kāi)發(fā)團(tuán)隊(duì),很多需求的變更還是要到系統(tǒng)正式驗(yàn)收時(shí)才被提出來(lái)。因?yàn)樵诩追降挠^念中,他們還不太認(rèn)可項(xiàng)目結(jié)束之前所提交的中間結(jié)果。 另外,項(xiàng)目的合同是按照瀑布模型的階段來(lái)簽的,需求分析、概要設(shè)計(jì)、詳細(xì)設(shè)計(jì)、編碼完成、驗(yàn)收測(cè)試是項(xiàng)目回款的里程碑。采用迭代化開(kāi)發(fā)之后,在原定的概要設(shè)計(jì)交付時(shí)間點(diǎn)上,可能需求分析和概要設(shè)計(jì)都只完成了部分的工作,比原定計(jì)劃要晚一些;而詳細(xì)設(shè)計(jì)和編碼工作都已經(jīng)開(kāi)始了一部分,比原定計(jì)劃要提前一些。這樣就不能按照原定時(shí)間點(diǎn)來(lái)要求甲方就需求分析和概要設(shè)計(jì)那部分工作量付款,對(duì)于中國(guó)的集成商而言,項(xiàng)目回款是比合同簽定都要重要的工作。 這些問(wèn)題給我們的經(jīng)驗(yàn)教訓(xùn)是應(yīng)用項(xiàng)目開(kāi)發(fā)采用迭代化開(kāi)發(fā)流程,也需要讓客戶理解這一點(diǎn),項(xiàng)目工作說(shuō)明書中的工作單元內(nèi)容也需要跟迭代化開(kāi)發(fā)流程來(lái)符合。軟件開(kāi)發(fā)流程關(guān)系到所有的涉眾(Stakeholder),僅僅是開(kāi)發(fā)團(tuán)隊(duì)理解并實(shí)施這一流程是不夠的。 還有一個(gè)反饋來(lái)自于很多項(xiàng)目團(tuán)隊(duì),認(rèn)為迭代化開(kāi)發(fā)概念上聽(tīng)起來(lái)很有道理,但在項(xiàng)目中實(shí)施后往往感覺(jué)不到采用這處方法后對(duì)項(xiàng)目有什么太大的幫助。迭代化開(kāi)發(fā)的主要目的在于控制項(xiàng)目風(fēng)險(xiǎn),常見(jiàn)的項(xiàng)目風(fēng)險(xiǎn)如技術(shù)架構(gòu)、客戶需求等等。但是日常工作中的項(xiàng)目往往沒(méi)有太多的風(fēng)險(xiǎn),我們開(kāi)發(fā)的往往是重復(fù)性的項(xiàng)目,電信事業(yè)部做的就是不同運(yùn)營(yíng)商的BOSS項(xiàng)目,社保事業(yè)部就是為不同省份開(kāi)發(fā)社保系統(tǒng),雖然有特殊需求,但系統(tǒng)架構(gòu)和基本需求完全一樣;更多的項(xiàng)目是對(duì)現(xiàn)有系統(tǒng)的維護(hù)性開(kāi)發(fā),實(shí)現(xiàn)客戶提出的變更請(qǐng)求和改正軟件缺陷,一般不會(huì)涉及到系統(tǒng)架構(gòu)的改動(dòng)。在這種類型的項(xiàng)目中,迭代化開(kāi)發(fā)體現(xiàn)的不是對(duì)風(fēng)險(xiǎn)的控制,而是系統(tǒng)增量式開(kāi)發(fā)而不斷給涉眾所帶來(lái)的信心和鼓舞,開(kāi)發(fā)人員可以在較斷的時(shí)間周期內(nèi)看到自己所開(kāi)發(fā)的系統(tǒng)可以“跑”起來(lái)了,客戶則可以看到整個(gè)項(xiàng)目在不斷地往前推進(jìn)。

    posted @ 2006-10-23 08:58 Sheldon Sun 閱讀(174) | 評(píng)論 (0)編輯 收藏

    現(xiàn)在的公務(wù)員...

    媽的, 想起來(lái)就有氣, 現(xiàn)在的公務(wù)員一個(gè)比一個(gè)牛, 本來(lái)應(yīng)該為人民服務(wù), 態(tài)度卻一個(gè)比一個(gè)差....

    最近想辦居住證續(xù)辦, 想打個(gè)電話咨詢一下, 試了N多個(gè), 有的 還好借了告訴你個(gè)號(hào)碼, 讓你去打, 但一直戰(zhàn)線, 更有的那起來(lái)就掛掉, 拿起來(lái)就掛,,,,,,

    TNND!!!!

    posted @ 2006-10-19 22:49 Sheldon Sun 閱讀(222) | 評(píng)論 (1)編輯 收藏

    一個(gè)技術(shù)牛人的悲慘遭遇

    http://www.bcb-tools.com/AuthorNotes.htm

    posted @ 2006-10-16 08:56 Sheldon Sun 閱讀(149) | 評(píng)論 (0)編輯 收藏

    鮑爾默: 軟件互聯(lián)界線模糊 Web服務(wù)離不開(kāi)PC

    http://dotnet.csdn.net/n/20061011/95958.html 微軟首席執(zhí)行官鮑爾默表示,提前部署(on-premise)軟件與通過(guò)互聯(lián)網(wǎng)發(fā)布的服務(wù)之間的界線在日益模糊,微軟正在順應(yīng)這一業(yè)界趨勢(shì)。 鮑爾默在Gartner 的Symposium/ITxpo 會(huì)議上接受了Gartner分析師史密斯和伊馮的采訪。鮑爾默在采訪中說(shuō),許多網(wǎng)站可以被稱作“點(diǎn)擊運(yùn)行”,服務(wù)通過(guò)網(wǎng)站發(fā)布,但在PC上運(yùn)行。 他表示,我認(rèn)為我們正處于一種轉(zhuǎn)型中,軟件正在由前互聯(lián)網(wǎng)時(shí)代發(fā)展到我們所謂的“Live時(shí)代”,網(wǎng)站提供了“點(diǎn)擊運(yùn)行”能力,但軟件仍然需要在PC上運(yùn)行。 由于有大量的臺(tái)式機(jī)和服務(wù)器軟件產(chǎn)品,與Salesforce.com或Google相比,微軟對(duì)托管服務(wù)的態(tài)度還不夠積極。 據(jù)鮑爾默稱,微軟計(jì)劃推出面向消費(fèi)者和企業(yè)客戶的服務(wù)化軟件,提供通過(guò)互聯(lián)網(wǎng)的服務(wù)和企業(yè)防火墻后面的服務(wù)器。 去年,微軟將Windows 和開(kāi)發(fā)者工具部門與負(fù)責(zé)MSN Web 服務(wù)的部門進(jìn)行了整合,它目前正在開(kāi)發(fā)一系列名為L(zhǎng)ive的托管服務(wù),其中一些服務(wù)旨在補(bǔ)充現(xiàn)有的“提前安裝”軟件。 鮑爾默表示,軟件+ 服務(wù)與服務(wù)化軟件之間的差別在于人們是否想利用手機(jī)、PC的處理能力。甚至考查一下目前的互聯(lián)網(wǎng)服務(wù),它們也都使用了客戶端的處理能力,例如AJAX、即時(shí)通訊服務(wù)。 鮑爾默表示,在這一服務(wù)化大潮中,盡管不能永遠(yuǎn)保持第一,但微軟不會(huì)放棄。他說(shuō),我們或許不是第一,但我們?cè)诓粩嗯ΑT谒阉鞣矫嬉彩且粯樱覀儾粫?huì)輕言放棄。

    posted @ 2006-10-12 08:27 Sheldon Sun 閱讀(116) | 評(píng)論 (0)編輯 收藏

    將女友升級(jí)為老婆的時(shí)候發(fā)生的

    親愛(ài)的技術(shù)支持: 我急需您的幫助。我最近將"女朋友7.0"升級(jí)到"妻子1.0",發(fā)現(xiàn)這個(gè)新程序意外地啟動(dòng)了孩子生產(chǎn)程序,而且占用了大量的空間和珍貴的資源。這在產(chǎn)品的使用手冊(cè)中沒(méi)有提到。 此外"妻子1.0"自動(dòng)將自己安裝到其他的所有的程序中,它隨系統(tǒng)同時(shí)啟動(dòng),監(jiān)控整個(gè)系統(tǒng)的狀態(tài)。 "男人夜出2.5"和"高爾夫5.3"無(wú)法再運(yùn)行,一旦運(yùn)行該程序系統(tǒng)即行崩潰。試圖運(yùn)行 "周日足球6.3"經(jīng)常失敗,而"周六購(gòu)物7.1"卻代之運(yùn)行。看來(lái)我無(wú)法保留"妻子1.0",因?yàn)樗臀蚁矚g運(yùn)行的任何程序都不相容。我打算回到"女朋友7.0",可是這個(gè)程序又無(wú)法卸載。 請(qǐng)您幫幫我吧! 喬 給喬的回信: 親愛(ài)的喬:這是個(gè)很普通的問(wèn)題,產(chǎn)生于你對(duì)基本原理的不了解。很多的男人健"女朋友7.0"升級(jí)到"妻子1.0",以為"妻子1.0"是一個(gè)"實(shí)用與娛樂(lè)程序"。然而"妻子1.0"卻是個(gè)操作系統(tǒng),是被設(shè)計(jì)用來(lái)運(yùn)行所有程序的。你不可能清除"妻子1.0",也不可能回到"女朋友7.0",因?yàn)?妻子1.0"的設(shè)計(jì)中不具有這個(gè)功能,無(wú)論是卸載、刪除或是清除已經(jīng)安裝在系統(tǒng)中的這些程序文件,都是不可能的。 有些人曾試圖安裝"女朋友8.0"或者"妻子2.0",結(jié)果是產(chǎn)生了更多的問(wèn)題(參見(jiàn)手冊(cè)中的贍養(yǎng)費(fèi)/孩子的養(yǎng)育/律師費(fèi)用)。我安裝過(guò)"妻子1.0",我建議你保持現(xiàn)在的安裝狀態(tài),妥善解決遇到的困難。 當(dāng)任何錯(cuò)誤或問(wèn)題出現(xiàn)的時(shí)候,不論你認(rèn)為是什么原因引起的,你必須運(yùn)行"C:\我道歉"程序,并且避免使用"退出鍵"。必要時(shí)可能需要運(yùn)行"C:\我道歉"多次,希望最終能使操作系統(tǒng)恢復(fù)到初始狀獺。 "妻子1.0"雖然是一個(gè)需要高保養(yǎng)的程序,但同時(shí)對(duì)人可能是非常有益的。要想充分地利用它,需要買些額外的軟件比如"鮮花2.0"和"巧克力5.0"。不要在任何情況下安裝"秘書(短裙版)",因?yàn)?妻子1.0"不支持這種程序,而且系統(tǒng)多數(shù)時(shí)候肯定會(huì)崩潰。 祝你好運(yùn)!

    posted @ 2006-09-29 16:45 Sheldon Sun 閱讀(137) | 評(píng)論 (0)編輯 收藏

    About life

    Life like a long run contest e.g 3000 meters. sb abort it at 1000 meters. sb abort at 2000 but only ones who finished running are sucessfully. But who will became these ones???

    posted @ 2006-09-29 09:01 Sheldon Sun 閱讀(126) | 評(píng)論 (0)編輯 收藏

    如何在Web應(yīng)用中啟動(dòng)后臺(tái)任務(wù)

    http://www.javaresearch.org/article/showarticle.jsp?column=2&thread=32387 摘要 我們常常在Web應(yīng)用中需要啟動(dòng)一個(gè)自己寫的服務(wù),本文的目的是給你提供一個(gè)解決方案。 原理 本方案的原理是寫一個(gè)實(shí)現(xiàn)了ServletContextListener接口的類,該類中有兩個(gè)方法: public void contextInitialized(ServletContextEvent sce),它是在應(yīng)用啟動(dòng)時(shí)調(diào)用;另一個(gè)方法是:public void contextDestroyed(ServletContextEvent sce),該方法是在應(yīng)用結(jié)束時(shí)調(diào)用。把我們要啟動(dòng)的后臺(tái)應(yīng)用邏輯放在contextInitialized方法中實(shí)現(xiàn);把釋放后臺(tái)應(yīng)用占用資源的工作放在contextDestroyed來(lái)處理。但我們啟動(dòng)的后臺(tái)任務(wù)常常是有要求的,比如時(shí)間,頻率等,我在這里使用了一個(gè)開(kāi)源組件:quartz。 步驟 1.寫業(yè)務(wù)調(diào)用類: // DumbJob.java import org.quartz.*; import java.util.*; public class DumbJob implements Job { public DumbJob() { } public void execute(JobExecutionContext context) throws JobExecutionException { //在這里寫業(yè)務(wù)處理代碼。什么,你不知道?那你別問(wèn)我!!:-< } } 本類的主要功能是由quartz中調(diào)度類按照指定的規(guī)則進(jìn)行調(diào)用執(zhí)行必要的業(yè)務(wù)邏輯。 2.寫調(diào)度類 // TestShedule.java import org.quartz.*; import java.util.*; public class TestShedule{ static SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory(); static Scheduler sched; public static void run()throws Exception{ sched = schedFact.getScheduler(); //獲取調(diào)度管理器 JobDetail jobDetail = new JobDetail("myJob", sched.DEFAULT_GROUP, DumbJob.class);//創(chuàng)建工作 CronTrigger trigger = new CronTrigger("myTrigger","test","0/10 * * * * ?");//創(chuàng)建觸發(fā)器 sched.scheduleJob(jobDetail, trigger); //添加到調(diào)度管理器中 sched.start();//啟動(dòng)調(diào)度管理器 } public static void stop()throws Exception{ sched.shutdown(); } } 本類的目的是設(shè)置調(diào)用規(guī)則,在這里我用了“0/10 * * * * ?”表示每10秒鐘就執(zhí)行一次,有關(guān)表達(dá)式的說(shuō)明請(qǐng)參閱quartz的api文檔。 3.編寫服務(wù)啟動(dòng)類: //ServiceLoader.java import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; public class ServiceLoader implements ServletContextListener { public void contextInitialized(ServletContextEvent sce) { try{ TestShedule.run(); }catch(Exception ex){ System.out.println(ex.getMessage()); } } public void contextDestroyed(ServletContextEvent sce) { try{ TestShedule.stop(); }catch(Exception ex){ System.out.println(ex.getMessage()); } } } 在contextInitialized中調(diào)用TestShedule.run()啟動(dòng)后臺(tái)任務(wù);在contextDestroyed中調(diào)用TestShedule.stop()停止后臺(tái)任務(wù)。 4.部署服務(wù)啟動(dòng)類 在web.xml文件中增加如下一行配置: rootServiceLoader index.html 5.啟動(dòng)web服務(wù)即可。 總結(jié) 其實(shí)實(shí)現(xiàn)這個(gè)功能的方法很多,我在這里是應(yīng)用了ServletContextListener接口和開(kāi)源api quartz,希望能對(duì)你的開(kāi)發(fā)有所幫助。 資源 quartz: http://www.opensymphony.com/quartz ServletContextListener在javax.servlet包中

    posted @ 2006-09-27 16:52 Sheldon Sun 閱讀(239) | 評(píng)論 (0)編輯 收藏

    動(dòng)態(tài)語(yǔ)言,別再說(shuō)不

    http://blog.csdn.net/myan/archive/2006/09/25/1281151.aspx 相信很多人都聽(tīng)過(guò)一個(gè)禪宗故事,說(shuō)是兩個(gè)僧人趕路,趟過(guò)一條小河的時(shí)候,看到一個(gè)漂亮的少婦困于其中,向他們呼救。其中一個(gè)有心施以援手,但想到佛家的色戒,便猶豫起來(lái),不知如何是好。可另一個(gè)和尚卻大大咧咧地沖過(guò)去,抱起少婦,趟過(guò)小河。于是前者的心里就很不舒服,一路上悶悶不語(yǔ),后來(lái)實(shí)在忍不住,就問(wèn)自己的同伴,既然身為佛門中人,怎能不顧清規(guī)戒律,如此輕薄。然而那位和尚卻回過(guò)頭來(lái),淡淡地說(shuō):“我已經(jīng)把她放下了,你還抱著呢?” 也許不太貼切,但是這幾天中外豪杰們圍繞Ruby和Rail爆發(fā)的口水戰(zhàn),讓我不由得想起這個(gè)小故事。 前幾天著名大嘴Joel Spolsky在自己的一畝三分地里對(duì)Ruby進(jìn)行了FUD性的攻擊,引發(fā)互聯(lián)網(wǎng)上一片口水戰(zhàn),Ruby之父matz和Rails之父DHH都卷入其中。似乎是要與此相呼應(yīng),在國(guó)內(nèi)技術(shù)論壇上,這幾天圍繞Ruby的爭(zhēng)論也突然攀登新高峰了。國(guó)外的大氣候和國(guó)內(nèi)的小氣候都有共同特點(diǎn),就是站在傳統(tǒng)技術(shù)立場(chǎng)上的人對(duì)于RoR的火爆看不下去了,首先站出來(lái)發(fā)難,從而引發(fā)Ruby支持者們的回?fù)簦缓箅p方廝殺在一起,連帶旁邊相干不相干的看熱鬧的、拉架的、含沙射影的、慷慨激昂的,瞬間就浩浩蕩蕩,橫無(wú)際涯了。而爭(zhēng)論來(lái)爭(zhēng)論去,無(wú)非還是Ruby的性能問(wèn)題、可用性問(wèn)題、前景問(wèn)題,等等等等。 可能是老生常談了,但倒R派的觀點(diǎn)讓我想起多年前我們這些C++ fans對(duì)Java的鄙視言論。那個(gè)時(shí)候C++程序員們說(shuō),Java只能用來(lái)在頁(yè)面上用applet作一些可笑的小動(dòng)畫,Java只能對(duì)對(duì)火柴棍排序,Java慢得像牛車,Java有內(nèi)存泄露,Java狂耗內(nèi)存,Java愚蠢的弱類型容器可以把鯨魚裝進(jìn)一個(gè)筆筒,Java居然沒(méi)有指針,Java做不了系統(tǒng)程序設(shè)計(jì),Java寫不了操作系統(tǒng),Java解決不了我手頭的超超級(jí)復(fù)雜的巨牛無(wú)比的難題,諸如此類,不一而足。冠冕堂皇的理由可以找出一大籮筐,但大皮襖下面無(wú)非就是一個(gè)“私”字而已。骨子里的想法是,我費(fèi)了好大的牛勁才混了個(gè)C++三品頂戴,你Java一鬧騰,就把我的似錦前程給攪黃了,怎能不妒火中燒,羞憤交加? 可是這些年過(guò)去了,當(dāng)時(shí)我們吐那點(diǎn)酸水起了什么作用了嗎?Java統(tǒng)治了企業(yè)計(jì)算,統(tǒng)治了手機(jī)應(yīng)用開(kāi)發(fā),統(tǒng)治了大學(xué)教育。不但如此,Java在開(kāi)源領(lǐng)域里也如日中天,接Eclipse之威在桌面應(yīng)用中也占了一座大山頭。一些傳統(tǒng)上屬于系統(tǒng)程序的項(xiàng)目,比如編譯器、語(yǔ)法分析器、高性能的服務(wù)器軟件等等,也大量轉(zhuǎn)用Java開(kāi)發(fā)。不錯(cuò),Java還是不能用來(lái)寫F-22戰(zhàn)斗機(jī)的火控系統(tǒng),但是這跟我們這些坐在cubic里寫民用軟件的家伙有個(gè)鬼的關(guān)系!人們對(duì)于簡(jiǎn)單、標(biāo)準(zhǔn)化和生產(chǎn)率的要求不可阻遏地突破了早期對(duì)Java筑起的FUD防線。面對(duì)Java的空前絕后的成功,我們這些當(dāng)年曾經(jīng)對(duì)革命力量翻白眼吐舌頭的家伙,在沉默的面對(duì)現(xiàn)實(shí)之后,已經(jīng)完成了一次觀念上的滌蕩。我們已經(jīng)認(rèn)識(shí)到,技術(shù)的發(fā)展趨勢(shì)是不以個(gè)人利益為轉(zhuǎn)移的,干這行就要有順應(yīng)技術(shù)大潮的勇氣,要有不斷破舊立新的魄力。我覺(jué)得我已經(jīng)放下了曾經(jīng)有的那種盲目的固執(zhí)和一廂情愿。 然而時(shí)間沒(méi)過(guò)多久,隨著Java成長(zhǎng)和騰達(dá)起來(lái)的一代人(其實(shí)不少也就是我的同齡人),又開(kāi)始重蹈覆轍。面對(duì)以Ruby為代表的新興動(dòng)態(tài)語(yǔ)言的蓬勃發(fā)展,他們也有點(diǎn)坐不住了。靠革命起家的人最怕革命,當(dāng)年的下里巴人翻身做主了,搖身一變成闊佬了,就開(kāi)始對(duì)新的革命力量擺譜使臉色,甚至以FUD戰(zhàn)術(shù)加以彈壓了。與當(dāng)年如出一轍,手段還是以攻為守,情緒還是慷慨激昂,筆法還是義正言辭,什么Ruby未經(jīng)驗(yàn)證啦,什么Ruby性能低劣啦,什么Rails可擴(kuò)展性不佳啦,什么Ruby不能解決“大型的”、“復(fù)雜的”、“企業(yè)級(jí)的”、“高性能的”問(wèn)題啦。最要命的是,哪怕自己90%的時(shí)間不過(guò)是在字符串處理,這些闊佬們也還是一致宣稱自己做著世界一流的、大型的、復(fù)雜的、企業(yè)級(jí)的、非Java不可、沒(méi)Java不行、沒(méi)Java就要上吊抹脖子跳樓挖坑的巨牛無(wú)比的大項(xiàng)目,聽(tīng)著讓人心驚肉跳兼之無(wú)比崇敬。你說(shuō)Java還能火幾年?我說(shuō)怎么也得5年!5年?那是上升期!少說(shuō)十年,后面還有平臺(tái)期。你還別不服,反正我退休之前Java說(shuō)什么也別想涼下來(lái),誰(shuí)也別想威脅我的頂戴花翎。企業(yè)級(jí)啊,架構(gòu)師啊,經(jīng)驗(yàn)啊,高手啊,我混成這樣我容易嗎我?誰(shuí)冒出來(lái)我就跟誰(shuí)急,我就用口水淹死他! 可惜,這些大話對(duì)于我這種記性不幸沒(méi)那么差勁的人來(lái)說(shuō),太似曾相識(shí)了,讓我一眼就看出這言論背后的“私”字來(lái)。想來(lái)也真是輪回,當(dāng)年我們C++這一批人放下的東西,原來(lái)你們Java這一批人還抱著呢。不過(guò),技術(shù)的大潮真的是后浪推前浪,往后看吧,我相信,當(dāng)年C++擋不住的東西,今天Java也擋不住。大趨勢(shì)已經(jīng)擺在這了,接不接受、什么時(shí)候接受,那是個(gè)人的問(wèn)題,但是總體的發(fā)展是無(wú)可逆轉(zhuǎn)的。 Ruby的興起,其實(shí)只不過(guò)是一個(gè)積累了幾十年的技術(shù)趨勢(shì)的能量釋放。世界上第二個(gè)程序設(shè)計(jì)語(yǔ)言Lisp及其后續(xù)家族成員都是最最動(dòng)態(tài)的語(yǔ)言。早在七十年代,伴隨著圖形界面的出現(xiàn),Smalltalk就以其純粹的面向?qū)ο蠛图兇獾膭?dòng)態(tài)性獲得有識(shí)之士的認(rèn)可。自1986年代Perl出現(xiàn)以來(lái),大量開(kāi)發(fā)者就認(rèn)識(shí)到,動(dòng)態(tài)語(yǔ)言開(kāi)發(fā)效率高,限制少,能夠自由的表達(dá)思想,輕松完成在傳統(tǒng)語(yǔ)言中非常困難的工作。很多人都預(yù)言動(dòng)態(tài)語(yǔ)言遲早會(huì)成為主流。然而在整個(gè)1990年代,無(wú)論是計(jì)算機(jī)硬件條件還是軟件工程的水平,都還不夠成熟,再加上Perl自身存在一些問(wèn)題,動(dòng)態(tài)語(yǔ)言始終只是作為主流語(yǔ)言的一種有力的補(bǔ)充而存在。2000年之后,PHP大流行,在Web開(kāi)發(fā)領(lǐng)域三分天下有其一。但是PHP本身完全是為Web而做,當(dāng)擴(kuò)展到其他領(lǐng)域時(shí),就凸顯出先天不足的劣勢(shì),因此地主穩(wěn)坐,霸業(yè)難成。直到現(xiàn)在,無(wú)論是硬件條件、軟件開(kāi)發(fā)的方法,還是客觀應(yīng)用環(huán)境都逐漸成熟,在這個(gè)時(shí)候,Ruby借Rails框架贏得廣泛關(guān)注,當(dāng)然不是偶然的現(xiàn)象。在TIOBE全球程序設(shè)計(jì)語(yǔ)言排名表中,Ruby排名一年間跳升15位,而根據(jù)O’Reilly公司對(duì)于圖書市場(chǎng)的統(tǒng)計(jì),Ruby相關(guān)書籍的銷量在2005年增長(zhǎng)15倍的基礎(chǔ)之上,今年又增長(zhǎng)了7倍,已經(jīng)超過(guò)Python和Perl。再看看是誰(shuí)在關(guān)注Ruby,拋開(kāi)一手把Ruby炒熱的“Pragmatic Programmer二人組”Dave Thomas和Andy Hunt不說(shuō),一大批編程老槍都在嘗試或者已經(jīng)轉(zhuǎn)向Ruby,這其中的著名人物包括Robert C. Martin、Martin Fowler、Bruce Tate等。如果這些還不夠令人印象深刻的話,我們應(yīng)該注意一下近期有關(guān)Ruby的一些事件。最近Sun雇用了開(kāi)源項(xiàng)目JRuby的兩名主要開(kāi)發(fā)者,讓他們可以全職開(kāi)發(fā)JRuby,從而正式將Ruby語(yǔ)言搬上JVM。同時(shí),微軟也在上個(gè)月的一次有關(guān).NET語(yǔ)言的技術(shù)會(huì)議上邀請(qǐng)RubyCLR的主要開(kāi)發(fā)者John Lam發(fā)表演講,外界傳言他將加入IronPython開(kāi)發(fā)者Jim Hugunin所在的團(tuán)隊(duì),從而加速Ruby for .NET的開(kāi)發(fā)進(jìn)程。另一個(gè)致力于Rich Internet Application的軟件巨頭Adobe于幾天前剛剛發(fā)布了用以將Flex 2.0整合到Ruby on Rails中的SDK。對(duì)于那些整天盯著巨頭們臉色行事的人來(lái)說(shuō),這些消息就算不是金口玉言,至少也是明確的跡象了吧。 然而,比上面一切都更為重要的是,今天的世界已經(jīng)變了,已經(jīng)不是15年前C++統(tǒng)治一切的那個(gè)世界,也不是10年前Java中彩票的那個(gè)世界,甚至也不是5年前Visual Basic狂練葵花寶典的那個(gè)年代。互聯(lián)網(wǎng)改變了太多的東西,經(jīng)濟(jì)形態(tài)和公司業(yè)務(wù)的形式和途徑都已經(jīng)并且仍在發(fā)生迅速的、根本性的變化。開(kāi)放、互聯(lián)、敏捷、整合、平等、自由、高速、專業(yè),所有這些給我們帶來(lái)了新的經(jīng)濟(jì)運(yùn)行模式,也對(duì)軟件的開(kāi)發(fā)提出了新的要求。Ruby,以及Ruby所代表的一類動(dòng)態(tài)的、自由的程序設(shè)計(jì)語(yǔ)言和開(kāi)發(fā)思想已經(jīng)迎來(lái)了它們的時(shí)代,它們將和其他的科技一起,在下一個(gè)輪回中改變我們的工作,改變我們的生活,改變我們的觀念,直到下下個(gè)輪回將它們掃進(jìn)歷史的功勞簿中為止。 所以,該放下的時(shí)候,就勇敢地放下吧。當(dāng)然,如果想再跟發(fā)展大勢(shì)打一打,那就打一打,反正在技術(shù)進(jìn)步的路上,保守的一方終究是要被解決的。

    posted @ 2006-09-26 08:25 Sheldon Sun 閱讀(126) | 評(píng)論 (0)編輯 收藏

    軟件構(gòu)架師之路

    http://tech.csai.cn/sa/200608111524241005.htm 構(gòu)架師(Architecture)是目前很多軟件企業(yè)最急需的人才,也是一個(gè)軟件企業(yè)中薪水最高的技術(shù)人才。換句話說(shuō),構(gòu)架師是企業(yè)的人力資本,與人力資源相比其能夠通過(guò)構(gòu)架、創(chuàng)新使企業(yè)獲得新的產(chǎn)品、新的市場(chǎng)和新的技術(shù)體系。那么什么是構(gòu)架師、構(gòu)架師的作用、如何定位一個(gè)構(gòu)架師和如何成為一個(gè)構(gòu)架師呢?這是許多企業(yè)、許多程序員朋友希望知道的或希望參與討論的話題內(nèi)容。      我在此拋磚引玉,就上述幾個(gè)問(wèn)題把我的體會(huì)和理解做簡(jiǎn)單闡述。   所謂構(gòu)架師通俗的說(shuō)就是設(shè)計(jì)師、畫圖員、結(jié)構(gòu)設(shè)計(jì)者,這些定義范疇主要用在建筑學(xué)上很容易理解。小時(shí)候到河中玩耍,經(jīng)常干的事就是造橋,步驟如下:1、在沙灘上畫圖;2、選擇形狀好看、大小適合的石頭;3、搭建拱橋。其中我們挑出來(lái)畫圖的那位光PP小孩就是傳說(shuō)中的 “構(gòu)架師”了。   在軟件工程中,構(gòu)架師的作用在于三方面:1、行業(yè)應(yīng)用構(gòu)架,行業(yè)構(gòu)架師往往是行業(yè)專家,了解行業(yè)應(yīng)用需求,其構(gòu)架行為主要是將需求進(jìn)行合理分析布局到應(yīng)用模型中去,偏向于應(yīng)用功能布局;2、應(yīng)用系統(tǒng)技術(shù)體系構(gòu)架,技術(shù)構(gòu)架師往往是技術(shù)高手中的高手,掌握各類技術(shù)體系結(jié)構(gòu)、掌握應(yīng)用設(shè)計(jì)模式,其構(gòu)架行為考慮軟件系統(tǒng)的高效性、復(fù)用性、安全性、可維護(hù)性、靈活性、跨平臺(tái)性等;3、規(guī)范構(gòu)架師是通過(guò)多年磨礪或常年苦思頓悟后把某一類構(gòu)架抽象成一套構(gòu)架規(guī)范,當(dāng)然也有專門研究規(guī)范而培養(yǎng)的規(guī)范構(gòu)架師。他們的產(chǎn)物往往也分為應(yīng)用規(guī)范和技術(shù)規(guī)范兩類。   與建筑學(xué)類似,如果軟件系統(tǒng)沒(méi)有一個(gè)好的構(gòu)架是不可能成為成功的軟件系統(tǒng)的。沒(méi)有圖紙的建筑工地、沒(méi)有設(shè)計(jì)的造橋工程都是不可以想象的混亂世界。建筑工程如是,軟件工程中亦然!   由于國(guó)內(nèi)合格、勝任的軟件構(gòu)架師極為少見(jiàn),直接導(dǎo)致了我國(guó)民族軟件產(chǎn)業(yè)水平的落后。在未來(lái)以信息產(chǎn)業(yè)為主導(dǎo)的社會(huì),信息產(chǎn)業(yè)水平的低下將直接影響國(guó)家核心競(jìng)爭(zhēng)力。究其原因,無(wú)企業(yè)非急功近利、個(gè)人缺乏引導(dǎo)。   企業(yè)的急功近利是有無(wú)法克服的原因的,那就是社會(huì)發(fā)展總體水平。“生存是第一位的,賺錢是第一位的”,多年來(lái)許多客戶抱怨國(guó)內(nèi)的軟件公司無(wú)法信任、系統(tǒng)項(xiàng)目累做累敗、公司越換越差,但因國(guó)外不可能給中國(guó)做應(yīng)用系統(tǒng)項(xiàng)目還不得不找國(guó)內(nèi)軟件公司做。由于人月費(fèi)用低、公司開(kāi)發(fā)成本高,軟件企業(yè)對(duì)于應(yīng)用只能草草了事,拿錢走人(很多公司拿不到后期尾款)。這樣的環(huán)境下,企業(yè)幾乎無(wú)法投入更多資源培養(yǎng)自己的構(gòu)架師,加上眼花繚亂的跳槽風(fēng)氣企業(yè)更是不愿投入……   那么要成為構(gòu)架師的途徑似乎只有現(xiàn)在較為流行的軟件學(xué)院和個(gè)人自我培養(yǎng)了。關(guān)于軟件學(xué)院我接觸過(guò)不少,其宗旨絕大部分都是造就(or打造)企業(yè)需要的軟件構(gòu)架師(or程序員or人才)。教師來(lái)源與企業(yè)、學(xué)員來(lái)源與企業(yè)、人才輸送到企業(yè)是他們辦學(xué)的手段。盡管各個(gè)如雨后春筍般出現(xiàn)的軟件口號(hào)差不多,但除了中科院、清華、北大等大院校可以相信一些之外,恐怕更多的就是為了圈錢賣學(xué)位了事……我有個(gè)朋友二十幾個(gè)人的小公司也想搞軟件學(xué)院:)   構(gòu)架師不是通過(guò)理論學(xué)習(xí)可以搞出來(lái)的,不過(guò)不學(xué)習(xí)相關(guān)知識(shí)那肯定是不行的。參考軟件企業(yè)構(gòu)架師需求、結(jié)合北京網(wǎng)暢公司構(gòu)架師培養(yǎng)計(jì)劃以及目前構(gòu)架師所需知識(shí),我總結(jié)構(gòu)架師自我培養(yǎng)過(guò)程大致如下僅供參考:   1、構(gòu)架師胚胎(程序員)學(xué)習(xí)的知識(shí)是語(yǔ)言基礎(chǔ)、設(shè)計(jì)基礎(chǔ)、通信基礎(chǔ)等,應(yīng)該在大學(xué)完成,內(nèi)容包括 :java、c、c++、uml、RUP、XML、socket通信(通信協(xié)議)——學(xué)習(xí)搭建應(yīng)用系統(tǒng)所必須的原材料。   2、構(gòu)架師萌芽(高級(jí)程序員)學(xué)習(xí)分布式系統(tǒng)、組建等內(nèi)容,可以在大學(xué)或第一年工作時(shí)間接觸,包括 :分布式系統(tǒng)原理、ejb、corba、com/com+、webservice(研究生可以研究網(wǎng)絡(luò)計(jì)算機(jī)、高性能并發(fā)處理等內(nèi)容)   3、構(gòu)架師幼苗(設(shè)計(jì)師)應(yīng)該在掌握上述基礎(chǔ)之上,結(jié)合實(shí)際項(xiàng)目經(jīng)驗(yàn),透徹領(lǐng)會(huì)應(yīng)用設(shè)計(jì)模式,內(nèi)容包括:設(shè)計(jì)模式(c++版本、java版本)、ejb設(shè)計(jì)模式、J2EE構(gòu)架、UDDI、軟件設(shè)計(jì)模式等。在此期間,最好能夠了解軟件工程在實(shí)際項(xiàng)目中的應(yīng)用以及小組開(kāi)發(fā)、團(tuán)隊(duì)管理。   4、軟件構(gòu)架師的正是成型在于機(jī)遇、個(gè)人努力和天賦   軟件構(gòu)架師其實(shí)是一種職位,但一個(gè)程序員在充分掌握軟構(gòu)架師所需的基本技能后,如何得到這樣的機(jī)會(huì)、如何利用所掌握的技能進(jìn)行應(yīng)用的合理構(gòu)架、如何不斷的抽象和歸納自己的構(gòu)架模式、如何深入行業(yè)成為能夠勝任分析、構(gòu)架為一體的精英人才這可不是每個(gè)人都能夠遇上的餡餅……   然而學(xué)海無(wú)涯,精力有限,個(gè)人如何能夠很快將這些所謂的構(gòu)架師知識(shí)掌握?這是秘密,每個(gè)人都有自己的獨(dú)門家傳秘笈就不敢一一暴露了。不過(guò)有一點(diǎn)就是廣泛學(xué)習(xí)的基礎(chǔ)之上一定要根據(jù)個(gè)人興趣、從事領(lǐng)域確定一條自己的主線來(lái)努力

    posted @ 2006-09-26 08:12 Sheldon Sun 閱讀(323) | 評(píng)論 (0)編輯 收藏

    https://jdiameter.dev.java.net/examples.htm

    fasdfasfae

    posted @ 2006-09-25 13:23 Sheldon Sun 閱讀(453) | 評(píng)論 (0)編輯 收藏

    domain-specific languages == DSL

    Null

    posted @ 2006-09-25 09:05 Sheldon Sun 閱讀(106) | 評(píng)論 (0)編輯 收藏

    Martinn Flower's blog

    http://www.martinfowler.com/bliki/

    posted @ 2006-09-25 09:01 Sheldon Sun 閱讀(107) | 評(píng)論 (0)編輯 收藏

    Ruby On Rails與Jdon Framework架構(gòu)比較

    http://java.ccidnet.com/art/297/20060508/547541_1.html 本文試圖比較同屬快速開(kāi)發(fā)性質(zhì)的Ruby on Rails(以下簡(jiǎn)稱RoR)和Jdon Framework(以下簡(jiǎn)稱JF)在架構(gòu)上異同,供大家在實(shí)際架構(gòu)選擇中比較。   RoR 是一個(gè)使用Ruby語(yǔ)言寫就的Web應(yīng)用框架,Ruby語(yǔ)言是類似Python, Smalltalk, PHP和Perl的動(dòng)態(tài)類型語(yǔ)言。從新特點(diǎn)層面看,Ruby on Rails并沒(méi)有提供比其他已經(jīng)存在的Web應(yīng)用框架新的東西,它的唯一特點(diǎn)就是快速開(kāi)發(fā)。RoR大概誕生于2004年6月份。   JF是使用Java語(yǔ)言編寫的、基于Ioc/AOP微容器的快速開(kāi)發(fā)工具。JF是基于JdonSD構(gòu)件庫(kù)增刪改查框架基礎(chǔ)上發(fā)展起來(lái)的,1.0版本是在2004 年12月底完成。當(dāng)時(shí)推出時(shí)很難定位,時(shí)至今日,它應(yīng)該是Ruby on Rails、Spring和JBoss容器三個(gè)概念的一個(gè)中間體。屬于域驅(qū)動(dòng)開(kāi)發(fā)框架(DDDD:omain Driven Development framework )。   JF雖是筆者操作完成,其實(shí)它是國(guó)人網(wǎng)絡(luò)結(jié)晶的開(kāi)源產(chǎn)物,很多需求和思想都來(lái)自Jdon社區(qū)熱情參與者,看到很多初學(xué)者總是為簡(jiǎn)單和靈活做痛苦選擇,為了寫一個(gè)簡(jiǎn)單系統(tǒng),要么走入Jsp+JavaBeans誤區(qū),要么被復(fù)雜技術(shù)配置纏身,忘記業(yè)務(wù)本職工作。JF 推出后,道友提出各種建議甚至猛烈批判,這些都形成了JF發(fā)展動(dòng)力,促進(jìn)JF完善。從用戶出發(fā)的簡(jiǎn)易之道使JF的起點(diǎn)和立意一下和RoR這樣國(guó)外產(chǎn)品走到了一起,下面我們?cè)敿?xì)進(jìn)行一下兩者架構(gòu)比較。 語(yǔ)言之爭(zhēng)   RoR代表的是動(dòng)態(tài)類型語(yǔ)言派別;而Java是一種靜態(tài)類型語(yǔ)言,當(dāng)初Java剛剛誕生時(shí),這種兩種類型派別之爭(zhēng)曾經(jīng)發(fā)生在Java和Smalltalk之間,后來(lái)現(xiàn)實(shí)選擇了Java這樣靜態(tài)類型語(yǔ)言,關(guān)鍵原因時(shí)動(dòng)態(tài)類型語(yǔ)言在編程時(shí)難以找出其一些潛在的語(yǔ)言Bug。   但是,隨著軟件工程中單元測(cè)試的重視,動(dòng)態(tài)類型語(yǔ)言+單元測(cè)試的結(jié)合克服了以上缺憾,從而使得RoR這樣得動(dòng)態(tài)類型語(yǔ)言重新東山再起。   促成RoR受到敏捷工程派別的領(lǐng)域?qū)<遥ㄈ鏜artin Fowler)推崇另外一個(gè)原因是,它被認(rèn)為是一種domain-specific languages(DSL)實(shí)現(xiàn),DSL是一種專門供領(lǐng)域建模專家(也就是系統(tǒng)分析師)使用的語(yǔ)言,這些領(lǐng)域?qū)<也煌诔绦蚋呤郑麄冇幸惶鬃约赫J(rèn)知世界和表達(dá)世界的思維和方式(如UML),因此,他們不感興趣于軟件設(shè)計(jì)細(xì)節(jié),希望軟件能夠按照他們分析設(shè)計(jì)的結(jié)果去運(yùn)行和執(zhí)行就可以了。   其實(shí),DSL并不是一個(gè)全新理念,它已經(jīng)在我們軟件領(lǐng)域中反復(fù)出現(xiàn),例如:我們很多人是關(guān)系數(shù)據(jù)庫(kù)領(lǐng)域?qū)<遥裕M管由O/R Mapping這樣工具出現(xiàn),但是并沒(méi)有改變這些領(lǐng)域?qū)<冶磉_(dá)方式,他們還是使用SQL等嚴(yán)謹(jǐn)?shù)臄?shù)學(xué)思維來(lái)實(shí)現(xiàn)他們的表達(dá)方式。   DSL概念非常好,但是是否有必要重新搞一套DSL語(yǔ)言則涉及很多方面的問(wèn)題,新的語(yǔ)言總會(huì)在實(shí)踐中有新的陷阱,Java經(jīng)過(guò)十多年發(fā)展,成熟和發(fā)展是其特點(diǎn)。   當(dāng)然,別以為RoR頂著DSL新名詞就是一個(gè)非常好的東西,對(duì)其本質(zhì)微詞已經(jīng)不絕于耳,有人認(rèn)為它實(shí)質(zhì)不過(guò)就是1994的Visual FoxPro(Ruby on Rails is a Bloody Square Turd ),提出該觀點(diǎn)的作者認(rèn)為:為什么我們?cè)谝粋€(gè)沒(méi)有重構(gòu)以及調(diào)試支持的編碼環(huán)境中工作?為什么還要重覆以前的痛苦呢?如果你確實(shí)喜歡RoR的ActiveRecord,為什么不用. NET呢?RoR 不是開(kāi)發(fā)Web應(yīng)用平臺(tái), RoR is a cult(RoR是宗教崇拜,筆者注:大概因?yàn)槭且驗(yàn)樗^大師級(jí)的人推薦原因).   無(wú)論如何,讓我們拋開(kāi)爭(zhēng)執(zhí),通過(guò)比較看看RoR一些特點(diǎn)。 多層架構(gòu)   現(xiàn)在多層架構(gòu)已經(jīng)深入人心,多層主要是指表現(xiàn)層MVC、業(yè)務(wù)層和持久層多層分離的體系,由于Java是一個(gè)技術(shù)自由選擇的世界,因此,每個(gè)層面都有不同的具體框架技術(shù)供選擇, 提供選擇是一種好事,但是又可能是一種壞事,需要應(yīng)用者花費(fèi)精力學(xué)習(xí)和研究,這非常類似我們購(gòu)物。   在微軟世界,由于各層框架技術(shù)幾乎都是由一家提供的,所以,.NET就索性將這些框架直接集成到IDE開(kāi)發(fā)工具,對(duì)于有的程序員感覺(jué).NET用起來(lái)很快,將開(kāi)發(fā)工具和框架混合成一體,但這是以綁定為代價(jià)的,甚至有程序員反感Java世界IDE+框架的開(kāi)發(fā)方式,認(rèn)為在開(kāi)發(fā)工具之外還會(huì)多一個(gè)框架,并且認(rèn)為違背KISS(keep it simple and stupid)原則,其實(shí)不然,關(guān)鍵是追求KISS原則的同時(shí),不要使自己受制于某個(gè)廠商或平臺(tái),使自己變得簡(jiǎn)單以及愚蠢 (失去自己作為客戶的上帝位置,被廠商忽視,成為簡(jiǎn)單而愚蠢的人),此為KMSS(keep me simple and stupid)。   在Java世界,多層結(jié)構(gòu)實(shí)現(xiàn)路徑很多,從MVC到持久層框架有各種選擇,例如我們可以使用Struts以及Hibernate組合成一個(gè)J2EE多層 應(yīng)用系統(tǒng)。   Rails也提供了model/view/controller多層實(shí)現(xiàn),但是各層的實(shí)現(xiàn)框架也確定下來(lái),省卻了程序員在多個(gè)框架之間選擇帶來(lái)的“麻煩”(這是相對(duì)的)。   而Jdon Framework則類似RoR這種提供缺省各層實(shí)現(xiàn)設(shè)計(jì),表現(xiàn)層在struts基礎(chǔ)上進(jìn)行了CRUD流程抽象;通過(guò)提供JdbcTemp實(shí)現(xiàn)持久層技術(shù),當(dāng)然,持久層具體實(shí)現(xiàn)也可以選擇hibernate等其他框架實(shí)現(xiàn),秉承提供缺省的,但是也是可替換的宗旨。   下圖是兩者各層架構(gòu)比較圖:   我們通過(guò)上圖可以看出,兩者流程基本一致,所不同的主要是兩點(diǎn):RoR的Action Pack和Active Record,下面我們就這兩點(diǎn)解釋如下: Action Pack   Action Pack是RoR的MVC組件框架:   View templates,相當(dāng)于Struts中的Jsp;   URL routing,相當(dāng)于struts-config.xml流程配置,RoR不是使用XML配置,而是作為腳本代碼,這也是一些人吹噓的RoR無(wú)繁多 XML配置真相所在,其實(shí),XML也是一種腳本,從某種意義上來(lái)說(shuō):XML比語(yǔ)言腳本更簡(jiǎn)單易寫(至少語(yǔ)法不多)。   ActionController,初看相當(dāng)于struts的DispatchAction,但是因?yàn)槠浒瑯I(yè)務(wù)邏輯,而我們?cè)趈ava中是不推薦在在控制層action中寫業(yè)務(wù)邏輯的。   ActionController功能在于:RoR可以將瀏覽器的請(qǐng)求直接映射到ActionController類的方法上,這有些類似Struts 中的DispatchAction,但是,在Java中,業(yè)務(wù)邏輯是不推薦寫在表現(xiàn)層的控制類中的,控制類只是負(fù)責(zé)前后臺(tái)流程協(xié)調(diào),是一種 Mediator模式實(shí)現(xiàn),不應(yīng)該讓其加入更多職責(zé);在JF中,業(yè)務(wù)邏輯是寫在Service類中,JF通過(guò)自己的命令服務(wù)調(diào)用模式,也可以直接將瀏覽器的請(qǐng)求直接映射到Service類的方法上,例如,調(diào)用http://localhost//MyWeb/abc.do?method=xxx,將直接激活Service類的xxx方法,程序員直接編寫xxx方法內(nèi)容即可。   RoR的Filters過(guò)濾器也是Action Pack的一個(gè)部分,主要用來(lái)實(shí)現(xiàn)一些通用功能的動(dòng)態(tài)插入,這在JF中是通過(guò)AOP攔截器和Decorator模式來(lái)實(shí)現(xiàn)的,見(jiàn)AOP vs Decorator 一文,在JiveJdon3.0中,我們通過(guò)攔截器實(shí)現(xiàn)了組件方法權(quán)限訪問(wèn)、以及緩存等通用功能。   Action Pack中還有Helpers功能相當(dāng)于Struts的標(biāo)簽庫(kù),它可以把Model/ActionForm和Action以及html連接在一起,下面是RoR的Helpers如:   Name: <%= text_field "person", "name", "size" => 20 %>   ....   當(dāng)然,RoR的Helpers有很多種類,如Form Helpers/javascriptHelpers等等,相當(dāng)于一個(gè)個(gè)API 庫(kù)。它的Ajax & JavaScript helpers倒是很時(shí)髦的。   RoR的Layouts相當(dāng)于Struts的Tiles,這就不多說(shuō)了。   Scaffolding提供一個(gè)數(shù)據(jù)表的CRUD功能實(shí)現(xiàn),Scaffolding類似代碼生成器,生成CRUD代碼,缺點(diǎn)是,如果你更改了代碼, Scaffolding會(huì)在覆蓋,必須再更改Scaffolding設(shè)置,實(shí)際用起來(lái)比較麻煩。而JF的CRUD是一個(gè)MVC流程上的精簡(jiǎn),屬于開(kāi)發(fā)框架性質(zhì),而不是代碼生成,只需要通過(guò)jdonframework.xml配置:                                                       Active Record   RoR有一個(gè)Active Record組件,其實(shí)就是ORM實(shí)現(xiàn),相當(dāng)于Hibernate,它是Martin Fowler的 Active Record pattern實(shí)現(xiàn),它是指一個(gè)既包含數(shù)據(jù)又包含行為的對(duì)象,這些數(shù)據(jù)需要持久保存到對(duì)應(yīng)的數(shù)據(jù)表中。Active Record一個(gè)很明顯的特征是:將數(shù)據(jù)訪問(wèn)邏輯也包含在這個(gè)domain對(duì)象中,通過(guò)這種辦法讓人們可以知道如何從數(shù)據(jù)庫(kù)讀寫數(shù)據(jù)。如下圖:   Active Record其實(shí)類似JF中Domain Object + Dao,也就是將Dao中對(duì)數(shù)據(jù)庫(kù)的CRUD方法和Domain Object整合在一起,我們知道,Dao模式本質(zhì)是橋模式,通過(guò)Dao可以將不同的數(shù)據(jù)庫(kù)訪問(wèn)實(shí)現(xiàn)分離,并且在運(yùn)行時(shí)組合,但是,Martin Fowler將Dao從Domain Object分離出去的對(duì)象稱為貧血對(duì)象。   他的這個(gè)觀點(diǎn)筆者認(rèn)為不是從技術(shù)觀點(diǎn),而是從領(lǐng)域建模角度出發(fā)的,其實(shí)從技術(shù)觀點(diǎn)講,將Dao從Domain Object中分離在設(shè)計(jì)上非常靈活,例如使用JF開(kāi)發(fā)的JiveJdon3.0中,我們就可以在Dao層中使用Decorator模式(過(guò)濾器)加入一層緩存,這樣,雖然我們Dao層使用的SQL實(shí)現(xiàn),我們也是可以實(shí)現(xiàn)持久層緩存,JiveJdon3.0整個(gè)Dao層設(shè)計(jì)相當(dāng)于一個(gè)Hibernate的微型(或者說(shuō)輕量化),好處是:JiveJdon3.0這樣實(shí)現(xiàn)的緩存可以被各層如表現(xiàn)層直接訪問(wèn),減少路徑,提升運(yùn)行性能。 RoR秘籍   通過(guò)以上分析,我們也許已經(jīng)明白R(shí)oR和JF定位,大家為什么突然擁戴RoR,這是因?yàn)榇蠹冶容^厭惡XML配置,太復(fù)雜的XML配置只能增加開(kāi)發(fā)的復(fù)雜性,而JF則在這方面從以下幾個(gè)方面進(jìn)行了努力: 1. 表現(xiàn)層的struts-config.xml配置是模板化的,CRUD流程固化模板化,拷貝粘貼就可以完成配置。 2. JF自身的配置很簡(jiǎn)單,只包括兩個(gè)部分Models和Services,配置語(yǔ)法主要集中再M(fèi)odels部分,語(yǔ)法數(shù)量不超過(guò)10個(gè),Models負(fù)責(zé)CRUD流程配置,如果你不需要使用CRUD可以不用配置;Services是業(yè)務(wù)類配置,對(duì)于一個(gè)POJO類,只要寫:如下:        class="com.jdon.jivejdon.service.imp.ForumServiceImp"/>        class="com.jdon.jivejdon.service.imp.ForumMessageShell"/> 至于,這些POJO之間的調(diào)用關(guān)系,無(wú)需指定,這由JF內(nèi)置IOC微容器自動(dòng)配對(duì)解決。 3. 持久層試圖通過(guò)JdbcTemp或SQL語(yǔ)句簡(jiǎn)化配置,當(dāng)然Hibernate等java工具也在進(jìn)步,不斷重構(gòu),相信會(huì)越來(lái)越簡(jiǎn)單。   總結(jié):相比RoR,作為DDD(Domain Driven Development framework )實(shí)現(xiàn)的JF在快速開(kāi)發(fā)和軟件高質(zhì)量上作了一個(gè)平衡,相當(dāng)于在RoR(快速,但非主流語(yǔ)言)和Spring(高質(zhì)量,但配置煩瑣)之間做了一個(gè)平衡。   JF一直也試圖爭(zhēng)取獲得國(guó)外軟件專家的認(rèn)可,可能會(huì)因?yàn)槠渌蛩匚茨苋缭福牵鳛楹蚏oR幾乎同時(shí)誕生的國(guó)產(chǎn)JF,作為由國(guó)人網(wǎng)民共同參與的結(jié)晶,已經(jīng)用事實(shí)證明,國(guó)人有能力靠創(chuàng)新沖刺世界軟件領(lǐng)域的前列。   無(wú)論如何,在RoR精神的召引下,Java世界將引來(lái)第四代語(yǔ)言4GL時(shí)代,同時(shí)能夠滿足求簡(jiǎn)單或求靈活等不同編程心理的需求,迎來(lái)新的發(fā)展

    posted @ 2006-09-25 08:54 Sheldon Sun 閱讀(192) | 評(píng)論 (0)編輯 收藏

    再駁Java消亡論和回應(yīng)java消亡論的支持者

    9月14日,我在CSDN上看到了透明的一篇謬文 http://blog.csdn.net/gigix/archive/2006/09/11/1210180.aspx,論調(diào)十分之荒謬。所以,我在公司里冒著被老板發(fā)現(xiàn)的危險(xiǎn),即興寫了一篇短文http://blog.csdn.net/shendl/archive/2006/09/14/1222587.aspx ,予以駁斥。 CSDN的編輯把它和透明的那篇文章放在了一起。跟貼者甚眾,令我沒(méi)想到的是,我的文章居然被不少跟貼者駁斥,而且語(yǔ)言極盡諷刺、挖苦之能事。 我并不反對(duì)就技術(shù)問(wèn)題爭(zhēng)論,也不是不允許別人就我的文章和觀點(diǎn)與我辯論。相反,我一向都非常歡迎同行指正我的錯(cuò)誤,能夠使我有所提高。 但是,多年與人打交道的經(jīng)驗(yàn)讓我深深地相信這樣一個(gè)真理:“你永遠(yuǎn)無(wú)法說(shuō)服不想被你說(shuō)服的人。” 這次眾多駁斥我的跟貼再一次驗(yàn)證了這樣一個(gè)真理。 我的文章由于成文比較倉(cāng)促,所以確實(shí)在文筆上有一些漏洞,遣詞造句也不是很妥當(dāng)。但我認(rèn)為,一個(gè)嚴(yán)肅的辯論者,是不會(huì)咬文嚼字的尋找對(duì)方文法上的弱點(diǎn)的。否則的話,除了數(shù)學(xué)公理之外,沒(méi)什么話可以說(shuō)了! 對(duì)于這樣的人,在我眼里,并不是在污辱我的智商(盡管他是這樣以為的),而是在侮辱他自己的智商。這說(shuō)明他完全不具備與人交流的能力。 如果一定要咬文嚼字,那么所有判斷句都不可以在文章里用了。Java會(huì)消亡嗎?廢話,一定會(huì)。宇宙都會(huì)消亡,什么能不消亡? 論點(diǎn): 透明的意思是,3-5年內(nèi),Ruby將占據(jù)企業(yè)級(jí)應(yīng)用市場(chǎng)的主流。也就是JavaEE和今天的Ruby換個(gè)位子。我認(rèn)為,這是不可能的。Java平臺(tái)至少能夠繼續(xù)占據(jù)、企業(yè)級(jí)應(yīng)用市場(chǎng)主流地位10年。 Java平臺(tái)優(yōu)勢(shì)和對(duì)動(dòng)態(tài)OO的支持 有人說(shuō)我不懂Ruby,也不懂Java。這我就不敢茍同了。我是不懂Ruby,但并不代表我不懂Ruby,Python,Smalltalk語(yǔ)言為代表的動(dòng)態(tài)面向?qū)ο笳Z(yǔ)言的機(jī)制。對(duì)于Java,我也許不比某些人懂得多,但也絕不會(huì)比一般的Java程序員懂得少。 我對(duì)Ruby的認(rèn)識(shí),僅僅是今年5月Martin Fowler先生在上海交大作的一次演講中Martin Fowler的Ruby編程演示。我還略為研究過(guò)Smalltalk和Python的語(yǔ)法。但是它們的類庫(kù),我沒(méi)有研究過(guò)。 因?yàn)椋疫€不打算靠它們吃飯,那厚厚的專用類庫(kù)對(duì)我而言是沒(méi)有價(jià)值的。 Spring的AOP實(shí)現(xiàn)需要使用“反射”這種動(dòng)態(tài)技術(shù)。這也是促成我當(dāng)年研究Smalltalk和Python這樣的動(dòng)態(tài)面向?qū)ο笳Z(yǔ)言的原因。我也十分折服于動(dòng)態(tài)面向?qū)ο缶幊碳夹g(shù)的強(qiáng)大能力。我一直認(rèn)為動(dòng)態(tài)OO技術(shù)在未來(lái),將在編程中發(fā)揮越來(lái)越大的作用,也一直希望JVM能夠增加更多的動(dòng)態(tài)技術(shù)。我還曾經(jīng)寫過(guò)文章為動(dòng)態(tài)OO技術(shù)搖旗吶喊過(guò),此初衷依然不改! Java作為一個(gè)平臺(tái)也確實(shí)有這樣的能力,而且也正在向這個(gè)方面發(fā)展,JVM將會(huì)支持更多的動(dòng)態(tài)OO技術(shù)。 .NET平臺(tái)當(dāng)年推出之時(shí),就以支持多種靜態(tài)面向?qū)ο缶幊陶Z(yǔ)言為賣點(diǎn)。VB.NET,C#,Delphi,托管C++這4種主流的面向?qū)ο缶幊陶Z(yǔ)言都可以在.NET平臺(tái)上運(yùn)行。 同樣都是靜態(tài)面向?qū)ο缶幊陶Z(yǔ)言,它們之間除了關(guān)鍵字不同之外,有什么本質(zhì)上的區(qū)別嗎?沒(méi)有!VB.NET和C#是我所熟悉的兩種.NET語(yǔ)言。它們之間本質(zhì)上確實(shí)沒(méi)什么區(qū)別。唯一的區(qū)別是,.NET平臺(tái)的技術(shù)更新時(shí),C#會(huì)先得到支持,VB.NET要晚一些。比如,事件機(jī)制,.NET1.1時(shí),VB.NET用的是類似于Java1.0時(shí)的機(jī)制,C#用的是Java更新版本的機(jī)制。我想,應(yīng)該是因?yàn)槲④涀钪匾旵#的緣故吧。 .NET平臺(tái)同時(shí)支持多種類似的語(yǔ)言,雖然在市場(chǎng)上有吸引VB,C++,Delphi,Java等程序員的作用,但在技術(shù)上卻導(dǎo)致了開(kāi)發(fā)資源的浪費(fèi)。一種技術(shù),要提供多個(gè)語(yǔ)言的實(shí)現(xiàn)。這比Java平臺(tái)只支持Java這一種靜態(tài)面向?qū)ο缶幊陶Z(yǔ)言要低效的多。我在發(fā)現(xiàn)了微軟優(yōu)先關(guān)照C#之后,就決定從VB.NET上轉(zhuǎn)到C#上,以免吃虧!自從Delphi投入.NET平臺(tái)之后,日漸式微,這也是一個(gè)平臺(tái)上不需要多種類似語(yǔ)言的明證!可以預(yù)見(jiàn),.NET平臺(tái)上C#獨(dú)大的趨勢(shì)還會(huì)繼續(xù)下去。 .NET支持多種類似語(yǔ)言的另一個(gè)問(wèn)題是,分裂了開(kāi)發(fā)者社區(qū)。VB.NET,C#,Delphi,還有J#,托管C++,它們的語(yǔ)言原理和能力實(shí)際上都差不多,都是靜態(tài)面向?qū)ο笳Z(yǔ)言,但是,由于語(yǔ)法不同,就分裂成了幾個(gè)開(kāi)發(fā)者社區(qū),彼此交流都不方便。 在我上一篇文章的評(píng)論者中,有人說(shuō)我說(shuō)錯(cuò)了,Java平臺(tái)上除了Java之外還有Beanshell等語(yǔ)言。拜托!兄弟,你的理解力沒(méi)什么問(wèn)題吧?我說(shuō)的是Java平臺(tái)上只有一種官方支持的靜態(tài)面向?qū)ο缶幊陶Z(yǔ)言。就是和.NET比較而言的。 Java平臺(tái)官方支持C++,C#,VB.NET,Delphi,J#嗎? Beanshell是一種動(dòng)態(tài)面向?qū)ο笳Z(yǔ)言,而且Sun官方可沒(méi)有支持它! 現(xiàn)在,Java平臺(tái)正在增強(qiáng)對(duì)動(dòng)態(tài)編程能力的支持。目前,開(kāi)源社區(qū)提供了Beanshell,JRuby,JPython,Groovy等面向?qū)ο缶幊陶Z(yǔ)言。我相信,最后,在Java平臺(tái)上也會(huì)只剩下一種主流的動(dòng)態(tài)面向?qū)ο缶幊陶Z(yǔ)言。未來(lái),Java平臺(tái)上會(huì)剩下兩種主流的編程語(yǔ)言:靜態(tài)面向?qū)ο缶幊陶Z(yǔ)言類型是Java;動(dòng)態(tài)面向?qū)ο缶幊陶Z(yǔ)言是上面中的一種,也許是Groovy,也許是JRuby。 將來(lái),我們Java程序員將有2件編程利器:Java和動(dòng)態(tài)OO語(yǔ)言。對(duì)于編程問(wèn)題,將能夠更加游刃有余!底層的API類庫(kù),既可以是Java,也可以是其它動(dòng)態(tài)OO語(yǔ)言所編寫。反正都一樣是.class文件,Java和動(dòng)態(tài)OO語(yǔ)言都可以調(diào)用。 這就是未來(lái)!Ruby和Python這兩種平臺(tái)將會(huì)繼續(xù)慘淡的過(guò)日子,也許不會(huì)消亡,但成不了主流。不是因?yàn)樗鼈兊恼Z(yǔ)法不好,機(jī)制不行,而是因?yàn)樗鼈內(nèi)鄙貸ava平臺(tái)上那樣多的API,也缺少熟悉這些API的程序員。 它們的靈魂將會(huì)飛到Java平臺(tái)上,以JRuby,JPython的形式生存下來(lái),在Java平臺(tái)上發(fā)展起來(lái)。 靜態(tài)OO語(yǔ)言和動(dòng)態(tài)OO語(yǔ)言的優(yōu)劣 接下來(lái),再談一談靜態(tài)OO語(yǔ)言和動(dòng)態(tài)OO語(yǔ)言的優(yōu)劣的問(wèn)題。 我欣賞動(dòng)態(tài)OO語(yǔ)言,smalltalk雖然出現(xiàn)的很早,開(kāi)發(fā)者甚少,但是在它的社區(qū)中卻誕生許多著名的程序員和設(shè)計(jì)模式等思想。MVC模式,XP極限編程等我所尊敬的技術(shù)都出自smalltalk。 但是,靜態(tài)OO語(yǔ)言一直占據(jù)著主流的地位,也不是沒(méi)有原因的。除了編譯型語(yǔ)言的執(zhí)行速度比解釋型語(yǔ)言快之外,靜態(tài)OO語(yǔ)言還有其它的優(yōu)勢(shì)。速度的快慢,在今天來(lái)看,并不是十分重要。Java比C++慢一些,但現(xiàn)在測(cè)試下來(lái),C++最多比Java快一倍而已(不要跟我說(shuō)某一個(gè)程序速度差很多,我這里指的是一般的程序,不作特別的優(yōu)化和劣化處理)。只要速度不是相差一個(gè)數(shù)量級(jí),就不是問(wèn)題。 靜態(tài)OO語(yǔ)言意味著更嚴(yán)格的語(yǔ)法,更多的編輯和編譯時(shí)的檢查步驟。更強(qiáng)的糾錯(cuò)能力,不正是編程語(yǔ)言發(fā)展的一個(gè)標(biāo)準(zhǔn)嗎?不是可以更好的提高效率嗎? 5月份那次看Martin Fowler先生演示編寫Ruby程序,IDE弱弱的報(bào)錯(cuò)能力讓Martin先生也傷了不少腦筋! 不錯(cuò),Ruby不需要給變量聲明類型。想指向哪個(gè)類型,就指向哪個(gè)類型。但是,指錯(cuò)了呢?只有在運(yùn)行時(shí)才能發(fā)現(xiàn)類型指錯(cuò)了。如果這是個(gè)復(fù)雜的程序,有很多執(zhí)行路徑呢?如果測(cè)試人員沒(méi)能夠窮盡所有這些可能的路徑呢?這個(gè)錯(cuò)誤豈不是會(huì)漏給用戶? 不錯(cuò),借助于測(cè)試驅(qū)動(dòng)開(kāi)發(fā),是可以降低出錯(cuò)幾率。但是,測(cè)試驅(qū)動(dòng)開(kāi)發(fā)也不是測(cè)試的銀彈,不能保證能夠找出所有的錯(cuò)誤。而且,靜態(tài)編程語(yǔ)言也可以使用測(cè)試驅(qū)動(dòng)開(kāi)發(fā)技術(shù)。 市場(chǎng)預(yù)測(cè) 我預(yù)測(cè),未來(lái)3-5年,Java平臺(tái)和.NET平臺(tái)都會(huì)增加對(duì)動(dòng)態(tài)OO語(yǔ)言的支持力度,它們上面的動(dòng)態(tài)OO語(yǔ)言將會(huì)達(dá)到實(shí)用化的程度。而Python和Ruby將會(huì)繼續(xù)維持現(xiàn)在這樣的市場(chǎng)規(guī)模。仍然處于邊緣。Python和Ruby的解釋器平臺(tái)不會(huì)得到多大范圍的應(yīng)用。就像今天,Web2.0的那些小網(wǎng)站帶來(lái)了Web2.0的概念,但最后是門戶網(wǎng)站Yahoo,Sina等占據(jù)了Web2.0的市場(chǎng)。 DSL特定領(lǐng)域語(yǔ)言 接下來(lái),說(shuō)說(shuō)DSL特定領(lǐng)域語(yǔ)言的問(wèn)題。Matin Fowler最近轉(zhuǎn)調(diào)了。我記得原來(lái)他非常支持XML格式的作用。但是,最近他說(shuō)Ruby是最合適的DSL語(yǔ)言。盡管我仍然十分敬佩Martin Fowler先生,但是對(duì)他的這個(gè)觀點(diǎn),我不敢茍同。我認(rèn)為,DSL語(yǔ)言還是應(yīng)該使用xml格式,而不是使用Ruby這種類英語(yǔ)的編程語(yǔ)言來(lái)描述。 DSL可以說(shuō)是一種“元數(shù)據(jù)”。用來(lái)描述程序。現(xiàn)在有2種元數(shù)據(jù):標(biāo)注和配置文件。 1.標(biāo)注是.net首先引入的。Java在5.0之后也引入了。標(biāo)注寫在源代碼中,和關(guān)鍵字一樣,只是標(biāo)注是可以自定義的。 標(biāo)注的優(yōu)點(diǎn)是,簡(jiǎn)單。缺點(diǎn)是表達(dá)能力不強(qiáng)。 2.配置文件,一般又分為3種:屬性文件,一般文本文件和xml文件。 屬性文件中的數(shù)據(jù)是以“名—值”對(duì)的形式表示的。缺乏數(shù)據(jù)之間的關(guān)系結(jié)構(gòu)。表達(dá)能力不強(qiáng)。 文本文件,就是直接在文本中按照規(guī)定的語(yǔ)法寫上一段文本。類似自然語(yǔ)言,只是語(yǔ)法的限制很強(qiáng)。語(yǔ)法檢查,是一個(gè)大問(wèn)題。如果沒(méi)有按照語(yǔ)法寫,就會(huì)發(fā)生運(yùn)行時(shí)錯(cuò)誤。 Xml文件,是層次結(jié)構(gòu)的。它的前身是層次數(shù)據(jù)庫(kù)。它的格式嚴(yán)謹(jǐn),語(yǔ)法容易驗(yàn)證,規(guī)則容易定義。只是稍微復(fù)雜一點(diǎn),需要寫上元素名。 但是,總的來(lái)說(shuō),XML文件格式的DSL還是功能最強(qiáng)大,語(yǔ)法驗(yàn)證能力最強(qiáng),目前也是首先的DSL語(yǔ)言的載體。 除了使用元數(shù)據(jù)之外,直接使用編程語(yǔ)言也是可以實(shí)現(xiàn)高等級(jí)的功能的。如,傳統(tǒng)的不使用xml配置文件的Java編程。Java作為一種編譯語(yǔ)言,需要編譯,不使用xml等配置,就不是很方便。 而Ruby作為解釋型語(yǔ)言,直接修改源代碼是非常方便的。我想這大概就是Martin Fowler先生關(guān)于使用Ruby作為DSL的原因吧。 但是,使用DSL語(yǔ)言的用戶,他懂Ruby嗎?懂編程嗎?愿意查看和修改源代碼嗎?我們中國(guó)的用戶懂英語(yǔ)嗎? 我認(rèn)為,DSL使用XML文件還是首選! OO就是銀彈! 最后,談?wù)勱P(guān)于OO的問(wèn)題。有網(wǎng)友說(shuō)我“言必OO?OO就是銀彈嗎?”。這里我回答他:OO就是銀彈! 我Blog上的副標(biāo)題是:“以O(shè)O為中心,堅(jiān)定不移的走Spring道路”。 面向?qū)ο缶幊蹋o我們帶來(lái)了多少API類庫(kù)。Int,String等基本的數(shù)據(jù)類型,以及順序、條件、循環(huán)3種控制流這樣簡(jiǎn)單、細(xì)粒度的元素,通過(guò)類被封裝了起來(lái),今天已經(jīng)能夠通過(guò)層層疊疊的類支持對(duì)現(xiàn)實(shí)世界的種種對(duì)象的模擬和抽象。 借助于類庫(kù),眾多的DSL特定領(lǐng)域語(yǔ)言已經(jīng)被廣泛使用。今天的java程序員使用了更多的配置文件(這就是DSL)來(lái)編程。如Ant配置文件,Hibernate配置文件,Spring配置文件等等。 最近,我正在學(xué)習(xí)jBPM。jBPM也是一個(gè)Java類庫(kù)。通過(guò)Java類,它提供了一個(gè)DSL語(yǔ)言框架。我們能夠使用xml配置文件,編寫DSL語(yǔ)言:jpdl,bpel規(guī)范的。實(shí)現(xiàn)工作流、BPM等。 當(dāng)然,除了OOP之外,還有AOP。但是,AOP只是OOP的補(bǔ)充。OOP能夠?qū)崿F(xiàn)絕大部分的抽象模擬任務(wù)。 認(rèn)為OO無(wú)用的程序員,可能工作在嵌入式開(kāi)發(fā)等與硬件有關(guān)的工作領(lǐng)域。他們的編程領(lǐng)域中,業(yè)務(wù)邏輯比較簡(jiǎn)單,不需要過(guò)多的抽象層次。 但是,這并不能成為否定OO作用的理由。你用不著OO,并不代表OO沒(méi)用,并不代表OO不是銀彈。 OO已經(jīng)給我們帶來(lái)了多大的變化啊!Java的成功就是一例。 還是毛主席的那句話:“沒(méi)有調(diào)查,就沒(méi)有發(fā)言權(quán)”。對(duì)此我也是深有體會(huì)的,曾經(jīng)也犯過(guò)很多錯(cuò)。對(duì)于自己不懂的領(lǐng)域,硬是認(rèn)為別人的說(shuō)法荒謬。后來(lái),自己真正了解了那個(gè)領(lǐng)域之后,才知道“今是而昨非”啊!

    posted @ 2006-09-25 08:53 Sheldon Sun 閱讀(556) | 評(píng)論 (2)編輯 收藏

    Nokia

    10.?諾基亞(Nokia)鎮(zhèn)的名字來(lái)自流經(jīng)當(dāng)?shù)氐囊粭l河流。這條河名為“Nokianvirta”,在芬蘭古語(yǔ)種是黑貂的意思,這種動(dòng)物現(xiàn)在已經(jīng)絕跡。
      9.?諾基亞有時(shí)候被非諾基亞用戶和移動(dòng)軟件開(kāi)發(fā)人員稱做“aikon”(就是把“Nokia”反過(guò)來(lái)寫),因?yàn)椤癮ikon”被用在許多SDK軟件包中,包括諾基亞自己的Symbian?S60?SDK。
      8.?和其他手機(jī)不同,諾基亞的通話計(jì)時(shí)器不會(huì)在通話連接的時(shí)候自動(dòng)開(kāi)啟,而是在通話開(kāi)始的時(shí)候開(kāi)啟(除了S60系列手機(jī),比如諾基亞6600)。
      7.?諾基亞名列《財(cái)富》2006年最受推崇企業(yè)第20名(網(wǎng)絡(luò)通訊行業(yè)中的第1,非美國(guó)公司中的第4)。
      6.?在亞洲,數(shù)字4從來(lái)沒(méi)有出現(xiàn)在諾基亞手機(jī)的任何型號(hào)中,因?yàn)?在南亞和東亞的許多地區(qū)被認(rèn)為是不吉利的。
      5.?諾基亞公司字體是AgfaMonotype?Nokia?Sans字體,最初由Eric?Spiekermann設(shè)計(jì)。此前在廣告和手機(jī)用戶手冊(cè)中,諾基亞最常用的是Agfa?Rotis?Sans字體。
      4.?諾基亞手機(jī)收到短信時(shí)的“特殊”鈴聲是摩斯密碼的“SMS”(短信服務(wù)),“漸強(qiáng)”短信鈴聲是摩斯密碼的“Connecting?People”(當(dāng)時(shí)是翻譯成“科技以人為本”來(lái)著嗎?),“標(biāo)準(zhǔn)”短信鈴聲是摩斯密碼的“M”(代表“Message”,“信息”)。
      3.?諾基亞現(xiàn)在是世界上最大的數(shù)碼相機(jī)制造商,因?yàn)樗呐恼帐謾C(jī)銷售量超過(guò)了任何一個(gè)相機(jī)廠商。
      2.?實(shí)際上第一個(gè)商用GSM通話是1991年在赫爾辛基通過(guò)諾基亞支持的網(wǎng)絡(luò)打出的,打電話的人是芬蘭副總理Harri?Holkeri,用的是一個(gè)諾基亞手機(jī)。
      1.?諾基亞標(biāo)志性的鈴聲"Nokia?tune"實(shí)際上是改編自19世紀(jì)的吉他作品《Gran?Vals》,作者是西班牙音樂(lè)家Francisco?Tárrega。這個(gè)鈴聲在諾基亞手機(jī)中最早名為“Grande?Valse”。在1998年,這支鈴聲已經(jīng)廣為人知并被稱做“Nokia?Tune”,諾基亞將其改名并沿用至今

    posted @ 2006-09-23 19:34 Sheldon Sun 閱讀(133) | 評(píng)論 (0)編輯 收藏

    ??

    這兩天右眼總跳, 有點(diǎn)不祥的預(yù)感。。。

    posted @ 2006-09-08 11:12 Sheldon Sun 閱讀(92) | 評(píng)論 (0)編輯 收藏

    <2006年9月>
    272829303112
    3456789
    10111213141516
    17181920212223
    24252627282930
    1234567

    導(dǎo)航

    統(tǒng)計(jì)

    常用鏈接

    留言簿(3)

    隨筆檔案

    文章檔案

    搜索

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 一级毛片免费播放男男| 国产亚洲高清不卡在线观看| 无码日韩精品一区二区三区免费 | 亚洲无砖砖区免费| 成人免费视频77777| 国产男女猛烈无遮挡免费网站| 国产高清免费在线| 毛片亚洲AV无码精品国产午夜| 国产区在线免费观看| 免费看黄视频网站| 国产成人精品日本亚洲专区| 国产亚洲精品美女久久久| a毛看片免费观看视频| 成年人免费视频观看| 亚洲综合日韩久久成人AV| 亚洲乱亚洲乱妇24p| 中文字幕免费在线看| 国产zzjjzzjj视频全免费 | 免费精品久久天干天干| 麻豆国产人免费人成免费视频| 亚洲色精品vr一区二区三区| 色噜噜噜噜亚洲第一| 亚洲国产精品无码久久久久久曰| 久久亚洲精品成人av无码网站 | 天堂亚洲免费视频| 性xxxxx免费视频播放| 中中文字幕亚洲无线码| 日本免费久久久久久久网站| 亚洲情a成黄在线观看| 亚洲av无码成人影院一区| 日韩视频在线精品视频免费观看| 精品国产成人亚洲午夜福利| 18禁美女黄网站色大片免费观看 | 亚洲AV无码乱码在线观看性色扶| 中文字幕成人免费高清在线| 亚洲视频在线免费播放| 爱丫爱丫影院在线观看免费| 亚洲va精品中文字幕| 亚洲黄色免费网址| 麻豆69堂免费视频| 国产免费人视频在线观看免费|