GONE WITH THE WIND

          --tomorrow is another day

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            30 隨筆 :: 19 文章 :: 0 評論 :: 0 Trackbacks

          #

          1.作用的范圍不同:

          1)inverse :<set/>,<map/>,<list/>,<array/>,<bag/>

          2)cascade :<many-to-one>,<one-to-one/>,<set/>,<map/>,<list/>,<array/>,<bag/>.

          2.執(zhí)行策略不同

          1)inverse :首先判斷集合的變化情況,然后針對變化執(zhí)行相應(yīng)的處理。

          2)cascade :直接對集合中的每個元素執(zhí)行相應(yīng)的處理。

          3.執(zhí)行的時機不同

          1)inverse :在執(zhí)行SQL語句之前判斷是否要執(zhí)行該SQL語句。

          2)cascade :在主控方發(fā)生操作時用來判斷是否進(jìn)行級聯(lián)操作。

          4.執(zhí)行的目標(biāo)不同

          1)inverse :對于<one-to-many>處理被管理表,<many-to-many/>處理中間表。

          2)cascade :都只只對被關(guān)聯(lián)表。

          總結(jié):書上說了inverse 一對多的時候最好把多的一方設(shè)置成false由一的一方來控制;cascade盡量別使,進(jìn)行顯示的添加刪除。

          posted @ 2009-03-30 16:46 張永耀 閱讀(181) | 評論 (0)編輯 收藏

          構(gòu)造這樣一個例子,在測試過程中來說明一些Hibernate的高級配置及其相關(guān)機制:
          有三個類:Category.java,Prodcuct.java,ConfigurationTest.java,其中第三個類是用來測試的。
          Category.java代碼:
                 

          package unsaved_value;    
          import ......    
          public class Category {    
              private Integer id;    
              private String name;    
              private String description;    
              private Set products;    
              public Category(){    
                   id=null;    
                   name=null;    
                  description=null;    
                  products=new HashSet ();    
               }    
               public void addProduct(Product p){    
                   products.add(p);    
              }    
               //**********setter and getter    
              ........    
          }   


          Product.java代碼:


          package unsaved_value;      
          public class Product {      
              private Integer id;      
              private String name;      
              private Category category;      
              private String description;      
              public Product(){     
                   
              }      
               //*******getter and setter      
               .........      
          }      

          ConfigurationTest.java

          public void testSave()throws Exception{    
                  Category category=new Category();    
                  category.setName("java編程書籍2");    
                  category.setDescription("編程經(jīng)典書籍2");    
                  Product pro=new Product();    
                  pro.setName("java編程思想2");    
                  pro.setDescription("第四版中文版2");     
                  pro.setCategory(category);    
                  category.addProduct(pro);    
                  Transaction tx=session.beginTransaction();    
                  assert (session!=null):("session is null");    
                  session.save(category);    
                  tx.commit();    
              }    

               
          Category代表產(chǎn)品目錄,而Product代表產(chǎn)品,顯然Category與Product是一對多的關(guān)系。Hibernate在映射一對多關(guān)系時,有兩種方式,一種是單向一對多,一種是雙向關(guān)系。兩者相比,雙向一對多的好處體現(xiàn)在兩方面:首先,也是很明顯的一點,由于是雙向關(guān)聯(lián),我們在實際業(yè)務(wù)邏輯時將更方便,例如我們可以檢索一個Category下的所有Product,同時還可以檢索出Product屬于哪個。其次,雙向關(guān)系相對單向關(guān)系而言,在數(shù)據(jù)庫的訪問方面更有優(yōu)勢。這一點留在后面講inverse時講
          。雙向關(guān)聯(lián)比單向關(guān)聯(lián)唯一的”劣勢“,就在于雙向關(guān)聯(lián)需要比單向關(guān)聯(lián)多寫一個映射文件,這不問題。使用雙向關(guān)聯(lián)實現(xiàn)這兩個類同數(shù)據(jù)庫的映射:

          Category.hbm.xml:  
          version="1.0" encoding="UTF-8"?>  

          " <hibernate-mapping package="unsaved_value">  
             <class name="Category" table="category">  
               <id name="id" column="id">  
                 <generator class="native">generator>  
               id>  
               
               <property name="name" column="name"/>  
               <property name="description" column="description"/>


               <set name="products" table="product" lazy="true" inverse="true" cascade="all">  
                   <key column="category"/>  
                      <one-to-many class="Product"/>  
               set>  
               
             class>  
          hibernate-mapping>  
            
          Product.hbm.xml:


          version="1.0" encoding="UTF-8"?>    
          "
          <hibernate-mapping package="unsaved_value">    
          <class name="Product" table="product">    
               <id name="id" column="id" unsaved-value="null">    
                   <generator class="native">generator>    
               id>    
                   
               <property name="name" column="name"/>    
               <property name="description" column="description"/>    
                 
               <many-to-one name="category"    
                            column="category"     
                            class="Category"    
               />    
             class>    
          hibernate-mapping>    
                  
          現(xiàn)在把這個例子所牽涉到的知識一一展開:
          一.inverse
              該詞的譯意是“反轉(zhuǎn)”,反轉(zhuǎn)什么——反轉(zhuǎn)控制端,這項配置決定了由關(guān)聯(lián)雙方中的哪一方來維持關(guān)聯(lián)關(guān)系(在數(shù)據(jù)庫中表現(xiàn)為外鍵約束)。上述配置中,在Category.hbm.xml中將inverse設(shè)置為true,意思是說“我需要反轉(zhuǎn)(控制端)”,反轉(zhuǎn)的結(jié)果是由對方即Product來維持關(guān)聯(lián)關(guān)系。用單向關(guān)聯(lián)更容易說明”維持關(guān)聯(lián)關(guān)系“是什么意思:考慮用單向關(guān)系來實現(xiàn)這個映射關(guān)系的情況,即由Category關(guān)聯(lián)到Product,考慮下面的代碼:

          Product p=new Product();  
          ..setXXX  
          Category c=new Category();  
          ..設(shè)置Category的屬性  
          c.addProduct(p);//建立起了c和p的關(guān)聯(lián)關(guān)系  
          session.save(c);  

          會執(zhí)行三條SQL語句:兩條插入語句,分別插入c和p,然后還有一條update語句建立起c和p的關(guān)聯(lián)(更新p的外鍵)。上面,我們說由Category端控制關(guān)聯(lián),因此p.setCategory(c)這樣一句話是沒用的,它并不會導(dǎo)致在插入p的時候就設(shè)置p的外鍵以建立起兩者的關(guān)聯(lián)關(guān)系,從而節(jié)省一條update語句。同時我們還會看到,如果在數(shù)據(jù)庫模式中將p的外鍵設(shè)置成非空,這些代碼將不能執(zhí)行,因為在插入p時,由于c和p的關(guān)聯(lián)關(guān)系還未建立起來,因此p的外鍵為空。回到雙向關(guān)聯(lián)上來,為了更清楚地明白inverse在雙向關(guān)聯(lián)中到底起什么作用,我們分別將其值設(shè)為true和false,看看打印出的的SQL有何區(qū)別:

          inverse=true時的打印結(jié)果:

          Hibernate: insert into category (name, description) values (?, ?)  
          Hibernate: insert into product (name, description, category) values (?, ?, ?)   
          inverse=false時的打印結(jié)果:

          Hibernate: insert into category (name, description) values (?, ?)    
          Hibernate: insert into product (name, description, category) values (?, ?, ?)    
          Hibernate: update product set category=? where id=?   
                 為什么inverse=true時會比inverse=false時少執(zhí)行一條SQL語句?這是由控制端的不同造成的。前者說"我要反轉(zhuǎn)控制,由Product來控制關(guān)聯(lián)",因此在將p對象insert時,p已經(jīng)設(shè)置了其category字段,從而建立了關(guān)聯(lián)關(guān)系,而后者說"我不反轉(zhuǎn)控制,由我自己來控制關(guān)聯(lián)",因此在將p對象insert后,c為了維持兩者的關(guān)聯(lián),還要去執(zhí)行一次update,以更新p的外鍵,從而建立起兩者的關(guān)聯(lián)關(guān)系。
          結(jié)論:對于一對多雙向關(guān)系,始終在“一”那一方將其inverse設(shè)置成true,這樣會提高性能。

          二.cascade
             級聯(lián)。當(dāng)關(guān)聯(lián)的"一"方進(jìn)行某種動作(更新,刪除)時,"多"方即使沒有顯式地進(jìn)行編碼,它也會自動進(jìn)行同樣的動作。cascade的可選值有:
          all : 所有情況下均進(jìn)行關(guān)聯(lián)操作。即是save-update + delete
          none:所有情況下均不進(jìn)行關(guān)聯(lián)操作。這是默認(rèn)值。
          save-update:在執(zhí)行save/update/saveOrUpdate時進(jìn)行關(guān)聯(lián)操作。
          delete:在執(zhí)行delete時進(jìn)行關(guān)聯(lián)操作。
          all-delete-orphan:A:級聯(lián)save-update B級聯(lián)delete C:刪除所有孤兒項(orphan孤兒)。先看看父子關(guān)系,例如在Customer和Order的模型中,這兩者便是父子關(guān)系,當(dāng)一個Customer的生命周期決定Order的生命周期,如果一個Customer不在了,其相關(guān)的Order繼續(xù)存在是毫無業(yè)務(wù)意義的。刪除所有孤兒項的意思即是,刪除所有與父對象失去關(guān)聯(lián)關(guān)系的子對象。

          三.lazy
              是否延遲加載。一般來說,應(yīng)該延遲加載,即將lazy設(shè)為true。延遲加載的相關(guān)點很多,這在另外的學(xué)習(xí)筆記中總結(jié)。

          四.unsaved-value
              以上是"一"方的重要配置,再看看"多"方的一個重要配置:unsaved-value,就像上面Product.hbm.xml中的設(shè)置那樣,這一項在id的配置中設(shè)置。這一設(shè)置是與級聯(lián)一起工作的。關(guān)于這一點,robbin講的很清楚:
          當(dāng)你顯式的使用session.save()或者session.update()操作一個對象的時候,實際上是用不到unsaved-value 的。某些情況下(父子表關(guān)聯(lián)保存),當(dāng)你在程序中并沒有顯式的使用save或者update一個持久對象,那么Hibernate需要判斷被操作的對象究竟是一個已經(jīng)持久化過的持久對象,是一個尚未被持久化過的內(nèi)存臨時對象。例如:
                 Session session = ...;
          Transaction tx = ...;  
          Parent parent = (Parent) session.load(Parent.class, id);  
          Child child = new Child();  
          child.setParent(parent);  
          child.setName("sun");  
          parent.addChild(child);  
          s.update(parent);  
          s.flush();  
          tx.commit();  
          s.close();  
               在上例中,程序并沒有顯式的session.save(child); 那么Hibernate需要知道child究竟是一個臨時對象,還是已經(jīng)在數(shù)據(jù)庫中有的持久對象。如果child是一個新創(chuàng)建的臨時對象(本例中就是這種情況),那么Hibernate應(yīng)該自動產(chǎn)生session.save(child)這樣的操作,如果child是已經(jīng)在數(shù)據(jù)庫中有的持久對象,那么 Hibernate應(yīng)該自動產(chǎn)生session.update(child)這樣的操作。因此我們需要暗示一下Hibernate,究竟 child對象應(yīng)該對它自動save還是update。在上例中,顯然我們應(yīng)該暗示Hibernate對child自動save,而不是自動 update。那么Hibernate如何判斷究竟對child是save還是update呢?它會取一下child的主鍵屬性 child.getId() ,這里假設(shè)id是 java.lang.Integer類型的。如果取到的Id值和hbm映射文件中指定的unsave-value相等,那么Hibernate認(rèn)為 child是新的內(nèi)存臨時對象,發(fā)送save,如果不相等,那么Hibernate認(rèn)為child是已經(jīng)持久過的對象,發(fā)送update。unsaved-value="null" (默認(rèn)情況,適用于大多數(shù)對象類型主鍵 Integer/Long/String/...)
          當(dāng)Hibernate取一下child的Id,取出來的是null(在上例中肯定取出來的是null),和unsaved-value設(shè)定值相等,發(fā)送save(child)
          當(dāng)Hibernate取一下child的id,取出來的不是null,那么和unsaved-value設(shè)定值不相等,發(fā)送update(child)
             unsaved-value的可選配置有:
          none,any,null
          unsaved-value="none"和unsaved-value="any"主要用在主鍵屬性不是通過Hibernate生成,而是程序自己setId()的時候。unsaved-value="none"和unsaved-value="any"究竟有什么含義了。如果你非要用assigned不可,那么繼續(xù)解釋一下:
          unsaved-value="none" 的時候,由于不論主鍵屬性為任何值,都不可能為none,因此Hibernate總是對child對象發(fā)送update(child)
          unsaved-value="any" 的時候,由于不論主鍵屬性為任何值,都肯定為any,因此Hibernate總是對child對象發(fā)送save(child)
                大多數(shù)情況下,可以避免使用assigned,只有當(dāng)你使用復(fù)合主鍵的時候不得不手工setId(),這時候需要你自己考慮究竟怎么設(shè)置unsaved-value了,根據(jù)你自己的需要來定。
                關(guān)于為什么不要使主鍵帶有義務(wù)意義,robbin的解釋很清楚:還是以上面的例子打比方,如果我們將Category的某一個性質(zhì)(比如產(chǎn)品序號或者名稱)作為主鍵,如果后來由于業(yè)務(wù)需要,我們把這個性質(zhì)改了,那將不可僻免地要去修改與這個對象相關(guān)聯(lián)的所有數(shù)據(jù)的外鍵,而如果我們只要代理主鍵,這個問題就可完全僻免。

          posted @ 2009-03-30 16:06 張永耀 閱讀(329) | 評論 (0)編輯 收藏

          今天在寫程序的時候發(fā)現(xiàn)了一個很奇怪的問題“ResultSet can not re-read row data for column”,用google一搜,原來是微軟公司的驅(qū)動的兼容性不太好。有熱心人總結(jié)了微軟驅(qū)動的缺點:(1)如果采用jdbc-odbc驅(qū)動,那么就必須按照查詢順序來一次讀取(不論有沒有image或text,ntext類型)(2)如果采用微軟提供的ms sql server jdbc driver,如果查詢語句中,不存在image或text,ntext類型字段,那么可以按照無序獲取(3)如果采用微軟提供的ms sql server jdbc driver,如果查詢語句中,存在image或text,ntext類型字段,那么就必須按照順序讀取,否則就會報告Driver]ResultSet can not re-read row data for column之類的錯誤(4)如果想不查詢語句中有沒有image或text,,ntext類型字段,都可以不按照順序獲取,或重復(fù)獲取。那么就必須更換驅(qū)動,改用第三方的。 最后,我改用了第三方的驅(qū)動。測試成功。
          posted @ 2009-03-27 14:25 張永耀 閱讀(311) | 評論 (0)編輯 收藏

          用delphi和VB實現(xiàn)瀏覽器中超長文件的上傳
           

          摘 要 本文通過delphi的Tihttp控件,將超大文件分割成幾個小文件,通過構(gòu)造的表單數(shù)據(jù)流,

                      直接發(fā)送到接收數(shù)據(jù)網(wǎng)頁,由vb編寫的服務(wù)器端進(jìn)行文件接收和還原

          一、問題的提出:

          本單位在開發(fā)課件生成系統(tǒng)時,需要通過瀏覽器向服務(wù)器指定目錄傳送大的音、視頻文件。在微軟asp中未提供相應(yīng)的控件,asp.net雖然提供了form表單中的file控件進(jìn)行文件上傳,但對上傳的文件有長度限制,文件長度大于50M上傳會失敗,而微軟基于安全考量,file控件中的文件名在運行期間只讀,這樣利用微軟提供的控件向服務(wù)器端上傳長度超過50M的文件變?yōu)椴豢尚校仨毩砼鑿健?/span>

          二、解決方案

          delphi以其強大的控件集,快速的RAD開發(fā),深得程序開發(fā)人員的青睞,其最新控件集Indy,集成了大部分流行的Internet協(xié)議,包括TCPUDPDNSICMPFINGERFTPGOPHERHTTPPOP3SMTPTELNETWHOIS,而瀏覽器的傳輸協(xié)議為http。這樣我們可以利用delphi7中的TIHTTP控件,將數(shù)據(jù)打包后上傳到服務(wù)器端。基本思路為:開發(fā)兩部分功能程序,一個為ActiveX控件,嵌入到網(wǎng)頁中,負(fù)責(zé)將客戶端本地上傳文件分解成n個數(shù)據(jù)包,每個數(shù)據(jù)包直接編碼成“multipart/form-data”格式的表單信息,依次調(diào)用TIhttp控件的post方法向服務(wù)器端發(fā)送信息。另一個為服務(wù)器端的com組件,接受發(fā)送過來的原始信息,將數(shù)據(jù)包拼接還原成文件保存到服務(wù)器的指定目錄中。

          三、技術(shù)要點:

              1Delyhi 7開發(fā)Active X控件要點:選擇新建項目→Active x標(biāo)簽→Active Form→填入控件名可快速搭建一個Acfire X控件架構(gòu),產(chǎn)生一個表單和一個框架代碼文件。

          2.上傳Active x控件設(shè)計要點:①表單控件中放置一個編輯控件、三個命令按鈕、一個進(jìn)度條控件、一個文本標(biāo)簽控件、一個文件對話框控件。編輯控件用來放置上傳文件名。一個瀏覽按鈕打開文件選擇對話框,選擇上傳文件;進(jìn)度條控件顯示上傳文件進(jìn)度;文本標(biāo)簽顯示上傳文件百分比,取消按鈕可中斷文件上傳。

          ②項目包含兩個代碼文件,其中一個文件用來將上傳文件拆分成小數(shù)據(jù)包。其關(guān)鍵代碼如下:

              for y:=0 to filenum  do

                 begin

                   if y=0  then   //第一個包

                       begin

                      if y <> filenum then

                            begin

                                for i:=1 to basenum do

                                  begin

                                     read(f,ch);

                                     tempf:=chr(ch);

                                     temp:=temp+tempf;

                                    application.ProcessMessages;

                                  end;

                              vflag:=postdata(vurl,vfilename,temp,'0');

                              end

                            else

                                   begin

                                   j:=0;

                                      while not eof(f) do

                                      begin

                                        read(f,ch);

                                      tempf:=chr(ch);

                                      temp:=temp+tempf;

                                      j:=j+1;

                                      application.ProcessMessages;

                            vflag:=postdata(vurl,vfilename,temp,'-2');

                          end;

                         end

                         else if y<> filenum then //中間包

                             begin

                                for i:=1 to basenum do

                                  begin

                                     read(f,ch);

                                    tempf:=chr(ch);

                                     temp:=temp+tempf;

                                      application.ProcessMessages;

                                  end;

                                    vflag:=postdata(vurl,vfilename,temp,'1');

                            end

                         else  //最后一個包

                           begin

                                  j:=0;

                                  while not eof(f) do

                                 begin

                                   read(f,ch);

                                   tempf:=chr(ch);

                                   temp:=temp+tempf;

                                   j:=j+1;

                                    application.ProcessMessages;

                               end;

                             vflag:=postdata(vurl,vfilename,temp,'-1');

                           end;

                 end;

          end;

          ③另一個文件用來將小數(shù)據(jù)包按照http格式封裝成二進(jìn)制文件上傳數(shù)據(jù)流發(fā)送到指定的接收頁面(URL),數(shù)據(jù)流除必要的頭信息,包含兩個表單城,一個數(shù)據(jù)塊,其中一個表單域用來傳遞文件標(biāo)記,用來區(qū)分本數(shù)據(jù)包是第一個包,中間包還是最后一個包,另一個表單域傳遞上傳文件名,其關(guān)鍵代碼如下:

             try

               filedata.Seek(0,sofrombeginning);

               tempstring:='';

               tempstring:=tempstring+'------------------------------7cf87224d2020a'+

                   newline;

               tempstring:=tempstring+'Content-Disposition: form-data;name="vflag"'+newline;

               tempstring:=tempstring+''+newline;

               tempstring:=tempstring+vflag+newline;

               tempstring:=tempstring+''+newline;

               tempstring:=tempstring+''+newline;

               tempstring:=tempstring+'Content-Disposition: form-data; name="editfilename"; filename="'+infile+'"'+newline;

               tempstring:=tempstring+'Content-Type: application/octet-stream'+newline;

               tempstring:=tempstring+''+newline;

               fillchar(temparray,sizeof(temparray),#0);

               strpcopy(temparray,tempstring);

               request.Write(temparray,length(tempstring));

               request.seek(0,sofromend);

               request.CopyFrom(filedata,filedata.size);

               tempstring:='';

               tempstring:=tempstring+''+newline;

               tempstring:=tempstring+'------------------------------7cf87224d2020a--'

                    +newline;

               fillchar(temparray,sizeof(temparray),#0);

               strpcopy(temparray,tempstring);

               request.write(temparray,length(tempstring));

               try

                 http.Post(url,request,response);

                 if pos('成功',response.datastring)<>0 then

                    flag:=1

               end.

          End.

          ④本ActiveX控件特色:可以實時顯示上傳進(jìn)度,并能隨時中斷文件的上傳,上傳頁面畫面如圖所示,可不能隨時中斷文件上傳,即應(yīng)用程序能隨時從循環(huán)語句中跳出,在循環(huán)語句中使用了ayydicdition Process Messages語句,該語句用來監(jiān)聽和處理系統(tǒng)消息這樣就有效避免了文件上傳時,不能進(jìn)行系統(tǒng)的其它操作。

          3.用VB6.0開發(fā)服務(wù)器端接收文件的Activeex dll,主要利用VB6.0強大的網(wǎng)頁操作功能,引用庫文件microsoft Active sever Page object library。其中包含有asp對象Asp library request。創(chuàng)建一個接收函數(shù)load,使用request對象讀取上傳給接收頁面的二進(jìn)制數(shù)據(jù)流,分離出上傳標(biāo)志、上傳文件名以及文件內(nèi)容,根據(jù)上傳標(biāo)志將分段傳送來的文件內(nèi)容拼接成一個完整的文件,保存到指定目錄。

          四、幾點說明

              1.本程序在操作系統(tǒng)為Win98 Win2000的客戶端機器,IIS服務(wù)器端為Win 2000的環(huán)境下調(diào)試通過;

          2.將upfile.htmupload.aspmyget.dllupfileproj1.ocx文件放置到IIS服務(wù)之虛擬目錄upfile下(缺省目錄為C:"Inetpub"unnroot"upfile);

          3.修改upfile.htmcodebase屬性(缺省為http://11.68.17.80/upfile/upfileproj1.ocx)中的IP地址為服務(wù)器端地址;

          4.修改delphi工程文件upfileprojl中的upfilelmpl1文件中的Button2 click事件中的vulstring=’http://11.68.17.80/upfile/upload.asp’一行數(shù)據(jù),將其中的IP地址轉(zhuǎn)接為服務(wù)器端地址,重新編譯后將upfrleprojl.ocx放置到虛擬目錄下;

          5.上傳文件在服務(wù)器端的默認(rèn)保存目錄為c:"temp;

          6.須手工注冊myget.dll,命令語句為regsvr32  C:"inetpub"wwwroot"upfile"myget.dll

          7.覽器中敲擊網(wǎng)站地址執(zhí)行,缺省地址為http://11.68.17.80/upfile/upfile.htm
          posted @ 2009-03-27 08:48 張永耀 閱讀(492) | 評論 (0)編輯 收藏

          我們的產(chǎn)品中間件的啟動是由批處理文件開始,這就導(dǎo)致,始終有個DOS窗口,來顯示服務(wù)器的運行情況。可客戶不樂意啊:他們就想萬一誰不小心把那窗口給關(guān)了,損害了數(shù)據(jù),那問題可就大了!這個問題確實是挺有價值的。
          首先,我們考慮WINDOWS環(huán)境吧,我不認(rèn)為WINDOWS環(huán)境下和*NIX環(huán)境下的實現(xiàn)有很大差別。想到以前看到的,聽到的,再加上自己的經(jīng)驗,大概有這么集中方式:
        1. 包裝bat文件為exe文件,然后以后臺服務(wù)的形式注冊
        2. 利用windows自帶的Wscript.Shell
        3. 寫個Swing界面小程序,利用多線程,啟動應(yīng)用服務(wù),把DOS窗口替換成應(yīng)用窗口。
        4. 但我們需要考慮另外一點:我們的應(yīng)用在運行的時候,會向dos窗口輸出一些出來的一些信息,這些信息在很多情況下都是很有用的。現(xiàn)在如果把DOS窗口隱藏了,那么那些信息我把他們存放到哪兒呢?我想最好還是以文件的形式保存起來,將來如有問題還可以追查!
          現(xiàn)在考慮各種實現(xiàn)方式。包裝為exe的形式,也只能在windows環(huán)境下運行,并且需要額外的工具;Swing界面小程序這個其實是最可行的,但我這個人比較懶,比較討厭寫界面;利用windows自帶的Wscript.Shell,自然也只能依賴于windows環(huán)境,后來我想了下,其實這個方案可以和swing界面那個方案有不少東西是可以公用的。最后決定,為了簡單期間,偶就先用Wscript.Shell,來做測試了。
          實際的情況大致是:
        5. 應(yīng)用服務(wù)的啟動腳本是/startup.bat 實際中我們可以使用vbs腳本:
        6. dim ws
          Set ws = CreateObject("Wscript.Shell")
          ws.run "cmd /c /startup.bat >> myServer.log" ,vbhide
          通過這樣簡單的設(shè)置,我們可以做到隱藏DOS窗口,但是,如果我們的應(yīng)用一下子運行好幾個月,那我們的日志文件myServer.log的日積月累地,就太大了。我們在查找問題的時候,也很不容易!所以我們應(yīng)該想法子把日志文件myServer.log,按時間或者按大小分開存儲。這也是我們應(yīng)用服務(wù)器日志的做法。所以,我們需要再做一步中間處理,想想看"appRoot/startup.bat"這一步,我們在程序當(dāng)中還是可以獲得它的輸出結(jié)果的。看下面java程序:
          package nc.client.StartupUtil;

          import java.lang.ProcessBuilder;
          import java.util.Vector ;
          import java.io.BufferedReader;
          import java.io.File;
          import java.io.IOException;
          import java.io.InputStreamReader;
          import java.io.FileWriter;
          import java.io.BufferedWriter;
          import java.util.Collections ;

          public class NC50StartUtil
          {

          public static final String logFileNamePrefix = "ncconsolelogs";

          public static void main(String[] args)
          {
          ProcessBuilder processBuilder = new ProcessBuilder("cmd", "/C", args[0]+"/startup.bat");
          processBuilder.directory(new File(args[0]));
          Process process = null;
          try
          {
          process = processBuilder.start();
          BufferedReader datais =
          new BufferedReader(
          new InputStreamReader( process.getInputStream()));


          // 服務(wù)器日志目錄
          String serverLogDirName = args[0] + "/nclogs/server";
          File serverLogDir = new File (serverLogDirName);
          if (!serverLogDir.exists())
          {
          serverLogDir.mkdirs();
          }

          int maxFileIndex = getMaxFileIndex(serverLogDirName).intValue();
          File logFile = new File(serverLogDirName+"/ncconsolelogs.log");
          if (!logFile.exists())
          {
          logFile.createNewFile();
          }
          else
          {
          // 如果已經(jīng)存在日志文件,則先把原來的文件歸檔,然后新創(chuàng)建一個日志文件
          StringBuffer oldFileName = new StringBuffer();
          oldFileName.append(serverLogDirName);
          oldFileName.append("/");
          oldFileName.append(logFileNamePrefix).append("[").append(maxFileIndex).append("].log");
          logFile.renameTo(new File(oldFileName.toString()));
          maxFileIndex++;
          //創(chuàng)建新的日志文件
          if (!logFile.exists())
          {
          logFile.createNewFile();
          }

          }

          BufferedWriter writer = new BufferedWriter(new FileWriter(logFile));

          // 文件的最大大小是2M
          int maxlength = 1024*1024*2;

          String c;
          while ((c = datais.readLine()) != null)
          {

          writer.write(c);
          writer.newLine();
          writer.flush();

          // 超過日志文件規(guī)定的大小了,則把日志文件歸檔,然后新創(chuàng)建一個日志文件
          if (logFile.length() > maxlength)
          {
          writer.close();
          StringBuffer oldFileName = new StringBuffer();
          oldFileName.append(serverLogDirName);
          oldFileName.append("/");
          oldFileName.append(logFileNamePrefix).append("[").append(maxFileIndex).append("].log");
          logFile.renameTo(new File(oldFileName.toString()));
          maxFileIndex++;

          // 創(chuàng)建新的日志文件
          if (!logFile.exists())
          {
          logFile.createNewFile();
          }
          writer =   new BufferedWriter(new FileWriter(logFile));
          }

          }
          }
          catch(IOException e)
          {
          e.printStackTrace ();
          }
          }

          public static Integer getMaxFileIndex(String ncconsolelogdirname)
          {
          File ncconsolelogdir = new File(ncconsolelogdirname);
          File[] ncconsolelogs = ncconsolelogdir.listFiles(new NcLogFileNameFilter(logFileNamePrefix));

          if (ncconsolelogs != null && ncconsolelogs.length > 0)
          {
          Vector v = new Vector();
          for (int i=0, len=ncconsolelogs.length; i startIndex)
          {
          String index = logFileName.substring (startIndex+1, endIndex);
          int ind = -1;
          try
          {
          ind = Integer.parseInt(index);
          }
          catch(Exception e)
          {

          }

          if (ind > 0)
          {
          v.add(ind);
          }
          }
          }
          if (v.size() > 0)
          {
          return Collections.max(v) + 1;
          }
          else
          {
          return 1;
          }
          }

          return 1;
          }
          }
          package nc.client.StartupUtil;

          import java.io.File;
          import java.io.FilenameFilter;

          // 一個簡單的文件名過濾類
          public class NcLogFileNameFilter implements FilenameFilter {

          private String fileNamePrefix = null;

          public NcLogFileNameFilter(String fileNamePrefix)
          {
          this.fileNamePrefix = fileNamePrefix;
          }

          public boolean accept(File dir, String name)
          {
          if (name.toLowerCase().startsWith(fileNamePrefix))
          {
          return true;
          }
          return false;
          }
          }
          之后,為了運行方便,我們把這兩個類編譯后打成可執(zhí)行的jar包,例如ncstartuputil.jar。并修改vbs腳本為:
          dim ws
          Set ws = CreateObject("Wscript.Shell")
          ws.run "cmd /c java -jar ncstartuputil.jar E:/nchome_zhengshi" ,vbhide
          如果換做swing界面,其實僅僅需要寫另外一個Thread,thread的主體也正式上面static main方法主體,然后通過多線程,可以獲得原始start.bat批處理文件的輸出,并且把輸出的信息放到一個textarea里面顯示出來。:-)....
          posted @ 2009-03-26 17:16 張永耀 閱讀(741) | 評論 (0)編輯 收藏

          最近做在做一個項目,涉及到文件上傳的問題。 以前也做過文件上傳。但都是些小文件,不超過2M。 這次要求上傳1G以上的東西。 沒辦法找來資料研究了一下。 基于WEB的文件上傳可以使用FTP和HTTP兩種協(xié)議,用FTP的話雖然傳輸穩(wěn)定,但安全性是個嚴(yán)重的問題,所以沒有考慮。 剩下只有HTTP。 在HTTP中有3種方式,PUT、WEBDAV、RFC1867,前2種方法不適合大文件上傳,在這里也不說了。
          確定使用RFC1867格式處理之后開始分析流行的上傳組件。看了N多代碼之后發(fā)現(xiàn),目前無組件程序和一些COM組件都是使用Request.BinaryRead方法。一次性得到上傳的數(shù)據(jù),然后分析處理。這就是為什么上傳大文件很慢的原因了,IIS超時不說,就算1G文件上去了,分析處理也得一陣子。 之后我把注意力放在國外商業(yè)組件上,比較流行的有Power-Web,AspUpload,ActiveFile,ABCUpload,aspSmartUpload,SA-FileUp。其中比較優(yōu)秀的是ASPUPLOAD和SA-FILE,他們號稱可以處理2G的文件(SA-FILE EE版甚至沒有文件大小的限制),而且效率也是非常棒,難道編程語言的效率差這么多?(我的編程環(huán)境是VB6) 查了一些資料,覺得他們都是直接操作文件流。這樣就不受文件大小的制約。 真是個好方法。
          但老外的東西也不是絕對完美,ASPUPLOAD處理大文件后,內(nèi)存占用情況驚人。1G左右都是稀松平常。我用的是3.0.0.3版。至于SA-FILE雖然是好東西但是破解難尋(郁悶死..) 失望之際,發(fā)現(xiàn)2款上傳組件,Lion.Web.UpLoadModule和AspnetUpload,都是.NET的,估計也是操作文件流。但是上傳速度和CPU占用率都不如老外的商業(yè)組件。
          做了個測試,LAN內(nèi)傳1G的文件。ASPUPLOAD上傳速度平均是4.4M/s,CPU占用10-15,內(nèi)存占用700M。SA-FILE也差不多這樣。而AspnetUpload最快也只有1.5M/s,平均是700K/s,CPU占用15-39,測試環(huán)境:PIII800,256M內(nèi)存,100M LAN。我想AspnetUpload速度慢是可能因為一邊接收文件,一邊寫硬盤。資源占用低的代價就是降低傳輸速度。 但也不得不佩服老外的程序,CPU占用如此之低.....這樣2個.net的組件也被PASS.

          稍帶2個問題就是上傳進(jìn)度和斷點續(xù)傳。
          顯示上傳進(jìn)度比較簡單,主要是查詢用戶上傳的狀態(tài),用Script顯示到瀏覽器中,至于無刷新顯示就要看腳本語言運用的熟練程度了。
          斷點續(xù)傳,HTTP方式是實現(xiàn)不了的,因為瀏覽器每次上傳文件都是從頭開始,沒有Range標(biāo)簽。實現(xiàn)的方法只能用ActiveX。

          研究之后決定寫個CGI來處理文件上傳。 這樣可以不走IIS以免程序出錯影響網(wǎng)站訪問。小弟比較菜只能用VB6做,完成之后發(fā)現(xiàn)WIN CGI的效率簡直就是差的不能再差。索性寫個FILE SERVER,專門處理文件的上傳。但是現(xiàn)在遇到一個2個問題。
          一、用WINSOCK控件接收到的文本有亂碼 不知道是程序轉(zhuǎn)換時的錯誤還是WINSOCK本身垃圾,SO 換了PowerTCP的WINSOCK TOOL,情況有所好轉(zhuǎn) 亂碼沒那么多了.........準(zhǔn)備換vb.net,直接操作socket,程序還沒做,不知道用.net接收會不會亂碼。再有就哭了。
          二、這個問題就比較初級了....接收到的文件流不能還原成文件..寒一個,

          最后就是如何高效處理文件流, 我想來想去也就只有2種方法,一是都放在內(nèi)存里,然后一起處理, 二是一邊接收一邊寫文件。 但這2種方法都不盡如人意思
          posted @ 2009-03-26 17:00 張永耀 閱讀(127) | 評論 (0)編輯 收藏


          http://cydn.8k.com      http://cydn.8m.com     http://cydn.s5.com

          登陸修改地址:http://cydn.8k.com/cgi-bin/login

          http://cydn.8k.com/cgi-bin/login

          http://cydn.s5.com/cgi-bin/login


          1。  個人空間和Blog   http://zhoubing518.x.27h.org/

          也就是: http://www.27h.com/blog/html/03/143103.html

          支持Ftp上傳,地址:ftp.27h.com  最好用CutFtp工具上傳。用戶名密碼為登陸的用戶名和密碼

          支持Html解析,不能解析jsp,屬于WEB服務(wù)器。

          網(wǎng)站的信件內(nèi)容如下:

               尊敬的 cydn 用戶你好!
              我是醬子家園的管理員!
          感謝您申請我們的免費主頁服務(wù),您已經(jīng)成為我們的用戶。
          ======================================================================
          您的FTP地址為 ftp://ftp.27h.com
          用戶名為 cydn
          目前空間大小為 50M 您的主頁地址為 http://cydn.27h.com

          您必須安裝FTP軟件,例如LEAPFTP CUTEFTP等

          2.    速度最快,最穩(wěn)定的一個:  http://hi.baidu.com/zbzb  

          不能上傳自己的Html頁面.但有100M的照片庫  

          3.   個人空間   http://zb.s5.com    國外免費空間,支持Html .用戶登陸頁:http://www.s5.comhttp://www.s5.comhttp://www.s5.comhttp://www.s5.com    國外免費空間,支持Html .用戶登陸頁:http://www.s5.com

          登陸修改地址:http://zb.s5.com/cgi-bin/login

          4.   個人Blog  博客地址:http://zb66.139.com   您的用戶名:zb66  您的密碼:***
          手機登陸的WAP地址:http://zb66.m.139.com     頁面不是很好看,模版少。速度快,.net網(wǎng)站。

          5.  http://host.tomore.com   

          主機名:http://host.tomore.com/cydn/

          FTP:

          主機:host.tomore.com
          用戶名:cydn
          密碼:你的會員密碼.
          空間大小:50 M .

          Mysql:未開通,請升級為正式會員!

          5.  我申請的幾個免費域名

          我申請的域名:
          http://cydn.wyou.cn
          http://smys.9126.com
          http://smys.9126.com
          http://cydn.1www.cn/http://xacydn.9126.com
          圣博個人免費空間:
          http://cydn.home.sunbo.net

          6.  免費域名申請網(wǎng)址簡介:

          http://www.wyou.cn/reg/reg.asp   
          免費域名服務(wù)由萬游網(wǎng)提供

          http://www.xinfree.com/default.htm

          申請地址:http://www.008.net/free/

          申請網(wǎng)址:http://ew88.com/reg.asp

          申請地址:http://www.eee.cc/

          申請網(wǎng)址: http://www.chinese.cn.com/freedomain/
          CHINESE.cn.com 免費域名開始測試,域名長度要求在3至20個字符之間。 您可以注冊以下域名:
          yourname.chinese.cn.com
          yourname.163.cn.com
          yourname.263.cn.com
          yourname.sina.cn.com
          yourname.sohu.cn.com
          yourname.tom.cn.com
          快來搶注呀!

          申請網(wǎng)址: http://reg.900du.com/

          免費 ***.k6.cn域名!
          申請網(wǎng)址: http://jsyzt.k6.cn/reg/reg.asp

          申請網(wǎng)址:http://mycool.net/

          申請網(wǎng)址:http://my.k6.cn/reg/reg2.asp

          很不錯的免費域名,共27種后綴,例如:cc.ly/tv.ly/cn.ly/on.ly,快去申請吧!

          申請網(wǎng)址:
          http://tv.ly/

          可選擇的后綴有:   hk.ly   dj.md   ok.mu   n.md   w.md   hk.md   tea.ms   email.ly   cn.ly   jp.ly   kr.pn   cc.ly   tv.ly   co.kr.mw   co.kr.pn   name.md   kr.mw   to.tc   email.dj   blog.vg   on.ly   cc.la   cn.la   tw.la   jp4.jp   na.la   wa.la

          Lycos中國免費聊天室申請! 
          時間: 2004-07-12 21:08:37 | [<<] [>>]
          --------------------------------------------------------------------------------
              免費提供個人聊天室,申請簡單,只需在主頁添加一段html代碼即可,沒有廣告,速度尚可,但功能較少。

          申請網(wǎng)址: http://chat.lycos.com.cn/hkcn/code.html
          碧聊免費聊天室申請!
          --------------------------------------------------------------------------------
          免費提供支持10人的語音聊天室,速度快、功能強,如果需要更大在線人數(shù)可以購買收費服務(wù)。

          申請網(wǎng)址: http://www.bliao.com/help/help23.htm

          posted @ 2009-03-26 14:12 張永耀 閱讀(118) | 評論 (0)編輯 收藏

          閱讀全文
          類別:數(shù)據(jù)庫 查看評論
          文章來源:http://hi.baidu.com/zbzb/blog/item/286f8b5438a4bf183b293556.html
          posted @ 2009-03-26 13:21 張永耀 閱讀(52) | 評論 (0)編輯 收藏

          閱讀全文
          類別:免費資源 查看評論
          文章來源:http://hi.baidu.com/zbzb/blog/item/ef6dae7724dae11cb151b9d4.html
          posted @ 2009-03-26 13:21 張永耀 閱讀(65) | 評論 (0)編輯 收藏

          閱讀全文
          類別:底層軟件 查看評論
          文章來源:http://hi.baidu.com/zbzb/blog/item/9013d0ca2ad45241f31fe763.html
          posted @ 2009-03-26 13:21 張永耀 閱讀(90) | 評論 (0)編輯 收藏

          僅列出標(biāo)題
          共3頁: 上一頁 1 2 3 下一頁 
          主站蜘蛛池模板: 夏津县| 姚安县| 阜阳市| 花莲市| 阿城市| 延寿县| 宝应县| 岑溪市| 宁明县| 延川县| 仪陇县| 津市市| 郯城县| 西丰县| 巴林右旗| 枣强县| 温泉县| 海南省| 靖西县| 太仆寺旗| 拉萨市| 长丰县| 买车| 新宁县| 宁化县| 长顺县| 介休市| 安仁县| 昭觉县| 柏乡县| 虞城县| 色达县| 印江| 多伦县| 淮南市| 临邑县| 苍山县| 泗阳县| 五大连池市| 镇安县| 绵竹市|