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

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

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

    coolfiry

    認認真真做人,兢兢業業做事!
    posts - 39, comments - 17, trackbacks - 0, articles - 0

    ?和?'f'標志指定的相同順序。

    示例1:將兩個class文件存檔到一個名為?'classes.jar'?的存檔文件中:
    ?& nbsp;?????jar?cvf& nbsp;classes.jar?Foo.class?Bar.class
    示例2:用一個存在的清單(manifest)文件?'mymanifest'?將?foo/& nbsp;目錄下的所有
    ????? ??????文件存檔到一個名為 ?'classes.jar'?的存檔文件中:
    ?? ?????jar?cvfm? classes.jar?mymanifest?-C?foo/?.

    來個小例子試試看:
    我們只有一個HelloWorld,如下:
    public& nbsp;?class??HelloWorld{
    ?public& nbsp;static?void?main(String[]?args){
    ?System.out.println(“Hi,?Hello?World!”);
    }
    }
    我將這個java文件存到C盤跟目錄下,ok,接下來,
    在先前打開的命令提示符下(跳轉到C盤提示符下),我們輸入javac?HelloWorld.java,然后繼續輸入:jar?& nbsp;cvf??hello.jar??HelloWorld.class,回車后去你的C盤看看,多了什么,沒錯?hello.jar?。
    基本的步驟我們現在都知道了,你可以自己去嘗試一下隨著jar后面的參數的不同,結果有什么變化。
    緊接著我們看看如何運行我們的jar包。
    在進入正題之前,你要先打開我們剛剛做好的jar包看看,多了什么呢,META-INF目錄?再看看里面是什么,還有一個MANIFEST.MF文件是不是?用文本編輯器(我這里是UltraEdit)打開它看看:
    Manifest-Version:? 1.0
    Created-By:?1.4.2?(Sun?Microsystems& nbsp;Inc.)
    就是這樣。這里我們對它進行修改,加一句:Main-Class:? HelloWorld?(在第三行)。這個就是我們之前寫的那個類,也就是我們的入口類。也即,
    Manifest -Version:?1.0
    Created-By:?1.4.2?(Sun& nbsp;Microsystems?Inc.)
    Main-Class:?HelloWorld< BR>接下來,我們在命令提示符里執行:
    jar?umf? MANIFEST.MF?app.jar
    這樣我們使用了我們自己的MANIFEST.MF文件對原來默認的進行了更新。你不妨可以再進去看看是不是添上了Main-Class:?HelloWorld這一句。
    Ok,這個最后的一步了,來驗證我們做的一切,在命令提示符中輸入:
    java?-jar?hello.jar (執行)
    出現了什么,――Hi,?Hello?World!
    我們再來看看 jar文件在tomcat中發布,注意:在tomcat中我們就不能再用jar這種格式,而改war格式,它是專門用于web應用的,其實整個過程下來基本上和jar是類似的:
    先準備我們要打包的資源。
    找到存放tomcat的webapps目錄,進到其中,新建一個文件夾,這里命名為hello,再進去新建WEB-INF文件夾,再進去新建classes文件夾,此時我們也將我們唯一的servlet, HelloWorld.java放到這里,在與classes目錄同級下建立一文件web.xml。Ok,目前我們初步建立了一個簡單的web應用。
    這是HelloWorld.java:
    import?java.io.*;< BR>import?javax.servlet.*;
    import?javax.servlet.http.*;
    public?class?HelloWorld?extends& nbsp;HttpServlet?{
    ?public?void? doGet(HttpServletRequest?req,?HttpServletResponse? res)
    ?????? ???????& nbsp;??????? ???????& nbsp;?throws?ServletException,?IOException& nbsp;{
    ??res.setContentType("text/html");
    ??PrintWriter?out?=?res.getWriter ();
    ??out.println("<HTML>");< BR>??out.println("<HEAD><TITLE& gt;Hello,?World!</TITLE></HEAD>");< BR>??out.println("<BODY>");
    & nbsp;?out.println("Hello,?World!");
    ? ?out.println("</BODY></HTML>");
    ?}
    }//end?here!
    對它編譯。下面是web.xml:< BR><?xml?version="1.0"?encoding="ISO-8859-1"?>
    <!DOCTYPE?web-app?PUBLIC
    ??'-//Sun?Microsystems,?Inc.//DTD?Web?Application?2.3//EN'
    ??'http://java.sun.com/j2ee/dtds/web-app_2_3.dtd&< /FONT>#39;>
    <web-app>
    ??<servlet>
    ?? ??<servlet-name>hello</servlet-name& gt;
    ????<servlet-class& gt;HelloWorld</servlet-class>
    ?? </servlet>
    ??<servlet-mapping& gt;
    ?<servlet-name>hello</servlet- name>
    ?<url-pattern>/HelloWorld& lt;/url-pattern>
    ??</servlet-mapping& gt;
    </web-app>
    開始壓縮,形成war檔:
    在命令提示符下進到先前創制的hello目錄下,執行?jar??cvf? ?hello.war??*?,我們便得到hello.war。將它拷貝至 webapps目錄下,ok,來看最后一步,打開tomcat的目錄conf中的server.xml,加入:
    ? ?<Context?path="/hello"?docBase="hello.war"& nbsp;debug="0"
    ????reloadable ="true"/>
    大功告成!運行它,啟動tomcat,后在瀏覽器中輸入http://localhost:8080/hello/HelloWorld,有了嗎?
    最后,如果你想用ant來完成以上的打包活動,下面就告訴你:
    對于jar來說。在build.xml 中,
    ?<target?name="jar">< BR>??<jar?destfile="${app_home}/hello.jar"& gt;
    ???<fileset?dir=" ${dest}"?includes="**"/>
    ??& nbsp;???<!--fileset?dir="${dest} "?includes="**/action.properties"/-->
    ? ???</jar>
    ?& lt;/target>

    對于war,
    <war& nbsp;warfile="hello.war"?webxml="./WEB-INF/web.xml">
    ????<fileset?dir="html"/& gt;
    ????<lib? dir="lib/">
    ????& nbsp;???<exclude?name="oracle*.jar"/& gt;
    ????</lib>
    ????<classes? dir="build/servlets">
    ???& nbsp;?????<include& nbsp;name="**/*.class"/>
    ??</classes& gt;
    </war>?
    好了,就這么多,希望對你有點幫助。:)
    我上傳了上面打過的兩個包,hello.jar和hello.war。『 點擊下載』
    『 點擊下載』
    第一rar文件對應的是hello.jar,下載后將其名改為 hello.jar
    第二rar文件對應hello.war,下載后改為hello.war。
    這是由于上傳不了 jar格式和war格式的文件,你只好照我上面說的去做了?:)

    補充:
    ############
    jar基本操作:
    ############
    1.& nbsp;創建jar文件
    ??jar?cf?jar- file?input-file(s)
    c---want?to?Create& nbsp;a?JAR?file.
    f---want?the? output?to?go?to?a?file? rather?than?to?stdout.
    eg:?1) jar?cf?myjar.jar?query_maintain_insert.htm< BR>????2)jar?cvf? myjar.jar?query_maintain_insert.htm
    ?? ????v---Produces?verbose(詳細的)?output.
    ????3)jar& nbsp;cvf?myjar.jar?query_maintain_insert.htm?mydirectory< BR>????4)jar?cv0f? myjar.jar?query_maintain_insert.htm?mydirectory
    ??????0---don't& nbsp;want?the?JAR?file?to?be& nbsp;compressed.
    ????5)jar& nbsp;cmf?MANIFEST.MF?myjar.jar?yahh.txt
    ??????m---Used& nbsp;to?include?manifest?information? from?an?existing?manifest?file.
    ????6)jar?cMf?MANIFEST.MF& nbsp;myjar.jar?yahh.txt
    ???& nbsp;??M---the?default?manifest? file?should?not?be?produced.
    ????7)jar?cvf?myjar.jar& nbsp;*
    ?????? *---create?all?contents?in?current& nbsp;directory.
    2.?察看jar文件
    ?& nbsp;jar?tf?jar-file
    t---want?to& nbsp;view?the?Table?of?contents? of?the?JAR?file.
    eg:?1)jar& nbsp;vft?yahh.jar
    ???? ??v---Produces?verbose(詳細的)? output.
    3.?提取jar文件
    ?? jar?xf?jar-file?[archived-file(s)]
    x- --want?to?extract?files?from? the?JAR?archive.
    eg:?1)jar?xf& nbsp;yahh.jar?yahh.txt(僅提取文件yahh.txt)
    ?& nbsp;??2)jar?xf?yahh.jar?alex/yahhalex.txt (僅提取目錄alex下的文件yahhalex.txt)
    ???& nbsp;3)jar?xf?yahh.jar(提取該jar包中的所有文件或目錄)
    4.?修改Manifest文件
    ??jar? cmf?manifest-addition?jar-file?input-file(s)< BR>m---Used?to?include?manifest?information& nbsp;from?an?existing?manifest?file.< BR>5.?更新jar文件
    ??jar? uf?jar-file?input-file(s)
    u---want?to?update?a

    posted @ 2006-10-12 18:40 Coolfiry 閱讀(348) | 評論 (0)編輯 收藏

    發布Java應用程序時你會感到困難?好在Java提供了一系列打包和發布工具,可以顯著的簡化發布過程
      
      該文章提供了打包Java code的幾種方法,我們將會探討Java manifest 文件,給出用于管理JAR文件所依賴文件、估計跨平臺發布所需的CLasspath的合適方法.我也會解釋如何使用manifest包版本特性來確認包的兼容性...
      
      什么是JAR文件?
      
      在開發過程中,我們可以直接使用Java class文件來運行程序,但這并不是一個好方式,好在Java 提供了 JAR(Java Archive)文件來提供發布和運行。
      
      jar 文件實際上是class 文件的ZIP壓縮存檔,這種格式被廣泛使用,因此易與使用,有很多中工具可以操作這種格式的文件。也正是因為這個原因,jar文件本身并不能表達所包含應用程序的標簽信息。
      
      Manifest 因此得以出現
      
       為了要提供存檔的標簽信息,jar 文件指定了一個特定目錄來存放標簽信息:META-INF 目錄,其中我們來關注該目錄中的MANIFEST.MF文件,他就是JAR的manifest文件,他包含了JAR文件的內容描述,并在運行時向JVM提 供應用程序的信息,大多數JAR文件含有一個默認生成的manifest 文件,執行JAR命令或使用zip工具,都可以產生它
      
      如果是由jar命令產生的 manifest 文件,形如:
      Manifest-Version: 1.0
      Created-By:1.4.0-beta
      (Sun Microsystems Inc.)
      
       這些信息沒甚么用,僅僅告訴我們使用的是1.0的manifest文件,第一行定義manifest的格式,第二行說明使用 SUN 的JDK1.4的jar工具生成該文件,如果manifest文件是由其他 (如ant) 創建的,那將會出現 “Created-By: Ant 1.2” 之類的內容,如果你是自己創建manifest文件,你可以加入自己的一些相關信息.
      
      基礎格式
      
      manifest 文件的格式 是很簡單的,每一行都是 名-值 對應的:屬性名開頭,接著是 ":" ,然后是屬性值,每行最多72個字符,如果需要增加,你可以在下一行續行,續行以空格開頭,以空格開頭的行都會被視為前一行的續行。
      
      所有在開頭的屬性都是全局的,你也可以定義特定class 或package的屬性,稍后將介紹這種
      
      把manifest文件插入JAR文件
      
      使用 m 選項,把指定文件名的manifest文件 傳入,例如
      jar cvfm myapplication.jar myapplication.mf -C classdir
      
      如果你使用ant來創建時,在ant 的build.xml 加入如下條目
      <target name="jar">
      <jar jarfile ="myapplication.jar"
      manifest="myapplication.mf">
      <fileset dir="classdir"
      includes="**/*.class"/>
      </jar>
      </target>
      
      運行Java程序
      
      現在我們來體驗一下manifest文件的作用,如果現在我們有一個Java 應用程序打包在myapplication.jar中, main class為 com.example.myapp.MyAppMain ,那么我們可以用以下的命令來運行
      java -classpath myapplication.jar com.example.myapp.MyAppMain
      
      這顯然太麻煩了,現在我們來創建自己的manifest文件,如下:
      Manifest-Version: 1.0
      Created-By: JDJ example
      Main-Class: com.example.myapp.MyAppMain
      
      這樣我們就可以使用如下的命令來運行程序了:(明顯簡單多了,也不會造成無謂的拼寫錯誤)
      java -jar myapplication.jar
      
      管理JAR的依賴資源
      
       很少Java應用會僅僅只有一個jar文件,一般還需要 其他類庫。比如我的應用程序用到了Sun 的 Javamail classes ,在classpath中我需要包含activation.jar 和 mail.jar,這樣在運行程序時,相比上面的例子,我們要增加一些:
      java -classpath mail.jar:activation.jar -jar myapplication.jar
      
      在不同的操作系統中,jar包間的分隔符也不一樣,在UNIX用“:”,在window中使用 “;”,這樣也不方便
      
      同樣,我們改寫我們的manifest文件,如下
      Manifest-Version: 1.0
      Created-By: JDJ example
      Main-Class: com.example.myapp.MyAppMain
      Class-Path: mail.jar activation.jar
      
     ?。尤肓薈lass-Path: mail.jar activation.jar,用空格分隔兩個jar包)
      
      這樣我們仍然可以使用和上例中相同的命令來執行該程序:
      java -jar myapplication.jar
      
       Class-Path屬性中包含了用空格分隔的jar文件,在這些jar文件名中要對特定的字符使用逃逸符,比如空格,要表示成"%20",在路徑的表 示中,都采用“/”來分隔目錄,無論是在什么操作系統中,(即使在window中),而且這里用的是相對路徑(相對于本身的JAR文件):
      Manifest-Version: 1.0
      Created-By: JDJ example
      Main-Class: com.example.myapp.MyAppMain
      Class-Path: ext/mail.jar ext/activation.jar
      Multiple Main Classes(多主類)
      
       還有一種Multiple Main Classes情況,如果你的應用程序可能有命令行版本 和GUI版本,或者一些不同的應用卻共享很多相同的代碼,這時你可能有多個Main Class,我們建議你采取這樣的策略:把共享的類打成lib包,然后把不同的應用打成不同的包,分別標志主類:如下
      Manifest for myapplicationlib.jar:
      Manifest-Version: 1.0
      Created-By: JDJ example
      Class-Path: mail.jar activation.jar
      Manifest for myappconsole.jar:
      Manifest-Version: 1.0
      Created-By: JDJ example
      Class-Path: myapplicationlib.jar
      Main-Class: com.example.myapp.MyAppMain
      Manifest for myappadmin.jar:
      Manifest-Version: 1.0
      Created-By: JDJ example
      Class-Path: myapplicationlib.jar
      Main-Class: com.example.myapp.MyAdminTool
      在myappconsole.jar 和 myappadmin.jar的manifest文件中分別注明各自的 Main Class
      Package Versioning
      
      完成發布后,如果使用者想了解 ,哪些代碼是誰的?目前是什么版本?使用什么版本的類庫?解決的方法很多 ,manifest提供了一個較好的方法,你可以在manifest文件中描述每一個包的信息。
      
       Java 秉承了實現說明與描述分離的原則,package 的描述 定義了package 是什么,實現說明 定義了誰提供了描述的實現,描述和實現包含 名、版本號和提供者。要得到這些信息,可以查看JVM的系統屬性(使用 java.lang.System.getProperty() )
      
      在manifest文件中,我可以為每個package定義描述和實現版本,聲明名字,并加入描述屬性和實現屬性,這些屬性是
      
      Specification-Title
      Specification-Version
      Specification-Vendor
      Implementation-Title
      Implementation-Version
      Implementation-Vendor
      
      當要提供一個類庫或編程接口時,描述信息顯得是很重要,見以下范例:
      
      Manifest-Version: 1.0
      Created-By: JDJ example
      Class-Path: mail.jar activation.jar
      Name: com/example/myapp/
      Specification-Title: MyApp
      Specification-Version: 2.4
      Specification-Vendor: example.com
      Implementation-Title: com.example.myapp
      Implementation-Version: 2002-03-05-A
      Implementation-Vendor: example.com
      
      Package Version 查詢
      
      在manifest文件中加入package描述后,就可以使用Java提供的java.lang.Package class進行Package 的信息查詢,這里列舉3個最基本的獲取package object的方法
      
      1.Package.getPackages():返回系統中所有定義的package列表
      
      2.Package.getPackage(String packagename):按名返回package
      
      3.Class.getPackage():返回給定class所在的package
      
      使用者這方法就可以動態的獲取package信息.
      
      需要注意的是如果給定的package中沒有class被加載,則也無法獲得package 對象
      
      Manifest 技巧
      
      總是以Manifest-Version屬性開頭
      
      每行最長72個字符,如果超過的化,采用續行
      
      確認每行都以回車結束,否則改行將會被忽略
      
      如果Class-Path 中的存在路徑,使用"/"分隔目錄,與平臺無關
      
      使用空行分隔主屬性和package屬性
      
      使用"/"而不是"."來分隔package 和class ,比如 com/example/myapp/
      
      class 要以.class結尾,package 要以 / 結尾

    posted @ 2006-10-12 18:38 Coolfiry 閱讀(295) | 評論 (0)編輯 收藏

    下面就來看看什么是 JAR 文件包吧:

    1. JAR 文件包

    JAR 文件就是 Java Archive File,顧名思意,它的應用是與 Java 息息相關的,是 Java 的一種文檔格式。JAR 文件非常類似 ZIP 文件——準確的說,它就是 ZIP 文件,所以叫它文件包。JAR 文件與 ZIP 文件唯一的區別就是在 JAR 文件的內容中,包含了一個 META-INF/MANIFEST.MF 文件,這個文件是在生成 JAR 文件的時候自動創建的。舉個例子,如果我們具有如下目錄結構的一些文件:

      ==

      `-- test

        `-- Test.class

    把它壓縮成 ZIP 文件 test.zip,則這個 ZIP 文件的內部目錄結構為:

      test.zip

      `-- test

        `-- Test.class

    如果我們使用 JDK 的 jar 命令把它打成 JAR 文件包 test.jar,則這個 JAR 文件的內部目錄結構為:

      test.jar

      |-- META-INF

      |  `-- MANIFEST.MF

      `-- test

        `--Test.class

    2. 創建可執行的 JAR 文件包

    制作一個可執行的 JAR 文件包來發布你的程序是 JAR 文件包最典型的用法。

    Java 程序是由若干個 .class 文件組成的。這些 .class 文件必須根據它們所屬的包不同而分級分目錄存放;運行前需要把所有用到的包的根目錄指定給 CLASSPATH 環境變量或者 java 命令的 -cp 參數;運行時還要到控制臺下去使用 java 命令來運行,如果需要直接雙擊運行必須寫 Windows 的批處理文件 (.bat) 或者 Linux 的 Shell 程序。因此,許多人說,Java 是一種方便開發者苦了用戶的程序設計語言。

    其實不然,如果開發者能夠制作一個可執行的 JAR 文件包交給用戶,那么用戶使用起來就方便了。在 Windows 下安裝 JRE (Java Runtime Environment) 的時候,安裝文件會將 .jar 文件映射給 javaw.exe 打開。那么,對于一個可執行的 JAR 文件包,用戶只需要雙擊它就可以運行程序了,和閱讀 .chm 文檔一樣方便 (.chm 文檔默認是由 hh.exe 打開的)。那么,現在的關鍵,就是如何來創建這個可執行的 JAR 文件包。

    創建可執行的 JAR 文件包,需要使用帶 cvfm 參數的 jar 命令,同樣以上述 test 目錄為例,命令如下:

    jar cvfm test.jar manifest.mf test

    這里 test.jar 和 manifest.mf 兩個文件,分別是對應的參數 f 和 m,其重頭戲在 manifest.mf。因為要創建可執行的 JAR 文件包,光靠指定一個 manifest.mf 文件是不夠的,因為 MANIFEST 是 JAR 文件包的特征,可執行的 JAR 文件包和不可執行的 JAR 文件包都包含 MANIFEST。關鍵在于可執行 JAR 文件包的 MANIFEST,其內容包含了 Main-Class 一項。這在 MANIFEST 中書寫格式如下:

    Main-Class: 可執行主類全名(包含包名)

    例如,假設上例中的 Test.class 是屬于 test 包的,而且是可執行的類 (定義了 public static void main(String[]) 方法),那么這個 manifest.mf 可以編輯如下:

    Main-Class: test.Test <回車>

    這個 manifest.mf 可以放在任何位置,也可以是其它的文件名,只需要有 Main-Class: test.Test 一行,且該行以一個回車符結束即可。創建了 manifest.mf 文件之后,我們的目錄結構變為:

      ==

      |-- test

      |  `-- Test.class

      `-- manifest.mf

    這時候,需要到 test 目錄的上級目錄中去使用 jar 命令來創建 JAR 文件包。也就是在目錄樹中使用“==”表示的那個目錄中,使用如下命令:

    jar cvfm test.jar manifest.mf test

    之后在“==”目錄中創建了 test.jar,這個 test.jar 就是執行的 JAR 文件包。運行時只需要使用 java -jar test.jar 命令即可。

    需要注意的是,創建的 JAR 文件包中需要包含完整的、與 Java 程序的包結構對應的目錄結構,就像上例一樣。而 Main-Class 指定的類,也必須是完整的、包含包路徑的類名,如上例的 test.Test;而且在沒有打成 JAR 文件包之前可以使用 java <類名> 來運行這個類,即在上例中 java test.Test 是可以正確運行的 (當然要在 CLASSPATH 正確的情況下)。

    3. jar 命令詳解

    jar 是隨 JDK 安裝的,在 JDK 安裝目錄下的 bin 目錄中,Windows 下文件名為 jar.exe,Linux 下文件名為 jar。它的運行需要用到 JDK 安裝目錄下 lib 目錄中的 tools.jar 文件。不過我們除了安裝 JDK 什么也不需要做,因為 SUN 已經幫我們做好了。我們甚至不需要將 tools.jar 放到 CLASSPATH 中。

    使用不帶任何的 jar 命令我們可以看到 jar 命令的用法如下:

    jar {ctxu}[vfm0M] [jar-文件] [manifest-文件] [-C 目錄] 文件名 ...

    其中 {ctxu} 是 jar 命令的子命令,每次 jar 命令只能包含 ctxu 中的一個,它們分別表示:

    -c 創建新的 JAR 文件包

    -t 列出 JAR 文件包的內容列表

    -x 展開 JAR 文件包的指定文件或者所有文件

    -u 更新已存在的 JAR 文件包 (添加文件到 JAR 文件包中)

    [vfm0M] 中的選項可以任選,也可以不選,它們是 jar 命令的選項參數

    -v 生成詳細報告并打印到標準輸出

    -f 指定 JAR 文件名,通常這個參數是必須的

    -m 指定需要包含的 MANIFEST 清單文件

    -0 只存儲,不壓縮,這樣產生的 JAR 文件包會比不用該參數產生的體積大,但速度更快

    -M 不產生所有項的清單(MANIFEST〕文件,此參數會忽略 -m 參數

    [jar-文件] 即需要生成、查看、更新或者解開的 JAR 文件包,它是 -f 參數的附屬參數

    [manifest-文件] 即 MANIFEST 清單文件,它是 -m 參數的附屬參數

    [-C 目錄] 表示轉到指定目錄下去執行這個 jar 命令的操作。它相當于先使用 cd 命令轉該目錄下再執行不帶 -C 參數的 jar 命令,它只能在創建和更新 JAR 文件包的時候可用?! ?

    文件名 ... 指定一個文件/目錄列表,這些文件/目錄就是要添加到 JAR 文件包中的文件/目錄。如果指定了目錄,那么 jar 命令打包的時候會自動把該目錄中的所有文件和子目錄打入包中。

    下面舉一些例子來說明 jar 命令的用法:

    1) jar cf test.jar test

    該命令沒有執行過程的顯示,執行結果是在當前目錄生成了 test.jar 文件。如果當前目錄已經存在 test.jar,那么該文件將被覆蓋。

    2) jar cvf test.jar test

    該命令與上例中的結果相同,但是由于 v 參數的作用,顯示出了打包過程,如下:

    標明清單(manifest)

    增加:test/(讀入= 0) (寫出= 0)(存儲了 0%)

    增加:test/Test.class(讀入= 7) (寫出= 6)(壓縮了 14%)

    3) jar cvfM test.jar test

    該命令與 2) 結果類似,但在生成的 test.jar 中沒有包含 META-INF/MANIFEST 文件,打包過程的信息也略有差別:

    增加:test/(讀入= 0) (寫出= 0)(存儲了 0%)

    增加:test/Test.class(讀入= 7) (寫出= 6)(壓縮了 14%)

    4) jar cvfm test.jar manifest.mf test

    運行結果與 2) 相似,顯示信息也相同,只是生成 JAR 包中的 META-INF/MANIFEST 內容不同,是包含了 manifest.mf 的內容

    5) jar tf test.jar

    在 test.jar 已經存在的情況下,可以查看 test.jar 中的內容,如對于 2) 和 3) 生成的 test.jar 分別應該此命令,結果如下;

    對于 2)

    META-INF/

    META-INF/MANIFEST.MF

    test/

    test/Test.class

    對于 3)

    test/

    test/Test.class

    6) jar tvf test.jar

    除顯示 5) 中顯示的內容外,還包括包內文件的詳細信息,如:

    0 Wed Jun 19 15:39:06 GMT 2002 META-INF/

    86 Wed Jun 19 15:39:06 GMT 2002 META-INF/MANIFEST.MF

    0 Wed Jun 19 15:33:04 GMT 2002 test/

    7 Wed Jun 19 15:33:04 GMT 2002 test/Test.class

    7) jar xf test.jar

    解開 test.jar 到當前目錄,不顯示任何信息,對于 2) 生成的 test.jar,解開后的目錄結構如下:

      ==

      |-- META-INF

      |  `-- MANIFEST

      `-- test

        `--Test.class

    .net/forum/images/smiles/icon_cool.gif border=0> jar xvf test.jar

    運行結果與 7) 相同,對于解壓過程有詳細信息顯示,如:

    創建:META-INF/

    展開:META-INF/MANIFEST.MF

    創建:test/

    展開:test/Test.class

    9) jar uf test.jar manifest.mf

    在 test.jar 中添加了文件 manifest.mf,此使用 jar tf 來查看 test.jar 可以發現 test.jar 中比原來多了一個 manifest。這里順便提一下,如果使用 -m 參數并指定 manifest.mf 文件,那么 manifest.mf 是作為清單文件 MANIFEST 來使用的,它的內容會被添加到 MANIFEST 中;但是,如果作為一般文件添加到 JAR 文件包中,它跟一般文件無異。

    10) jar uvf test.jar manifest.mf

    與 9) 結果相同,同時有詳細信息顯示,如:

    增加:manifest.mf(讀入= 17) (寫出= 19)(壓縮了 -11%)

    4. 關于 JAR 文件包的一些技巧

    1) 使用 unzip 來解壓 JAR 文件

    在介紹 JAR 文件的時候就已經說過了,JAR 文件實際上就是 ZIP 文件,所以可以使用常見的一些解壓 ZIP 文件的工具來解壓 JAR 文件,如 Windows 下的 WinZip、WinRAR 等和 Linux 下的 unzip 等。使用 WinZip 和 WinRAR 等來解壓是因為它們解壓比較直觀,方便。而使用 unzip,則是因為它解壓時可以使用 -d 參數指定目標目錄。

    在解壓一個 JAR 文件的時候是不能使用 jar 的 -C 參數來指定解壓的目標的,因為 -C 參數只在創建或者更新包的時候可用。那么需要將文件解壓到某個指定目錄下的時候就需要先將這具 JAR 文件拷貝到目標目錄下,再進行解壓,比較麻煩。如果使用 unzip,就不需要這么麻煩了,只需要指定一個 -d 參數即可。如:

    unzip test.jar -d dest/

    2) 使用 WinZip 或者 WinRAR 等工具創建 JAR 文件

    上面提到 JAR 文件就是包含了 META-INF/MANIFEST 的 ZIP 文件,所以,只需要使用 WinZip、WinRAR 等工具創建所需要 ZIP 壓縮包,再往這個 ZIP 壓縮包中添加一個包含 MANIFEST 文件的 META-INF 目錄即可。對于使用 jar 命令的 -m 參數指定清單文件的情況,只需要將這個 MANIFEST 按需要修改即可。

    3) 使用 jar 命令創建 ZIP 文件

    有些 Linux 下提供了 unzip 命令,但沒有 zip 命令,所以需要可以對 ZIP 文件進行解壓,即不能創建 ZIP 文件。如要創建一個 ZIP 文件,使用帶 -M 參數的 jar 命令即可,因為 -M 參數表示制作 JAR 包的時候不添加 MANIFEST 清單,那么只需要在指定目標 JAR 文件的地方將 .jar 擴展名改為 .zip 擴展名,創建的就是一個不折不扣的 ZIP 文件了,如將上一節的第 3) 個例子略作改動:

    jar cvfM test.zip test

    posted @ 2006-10-12 15:54 Coolfiry 閱讀(356) | 評論 (0)編輯 收藏

         摘要: 周 登朋 (zhoudengpeng@yahoo.com.cn), 軟件工程師, 上海交通大學 2006 年 9 月 06 日? 在本篇文章中,你會學習到如何利用 Lucene 實現高級搜索功能以及如何利用 Lucene 來創建 Web 搜索應用程序。通過這些學習,你就可以利用 Lucene 來創建自己的搜索應用程序。 ...  閱讀全文

    posted @ 2006-10-03 20:11 Coolfiry 閱讀(366) | 評論 (1)編輯 收藏

    一、閑聊

      今天要談的話題是COM,稍微深入一點,不知道大家用過C++Test或者Visual Assistant之類的軟件沒有,它們都有個非常引人注目的功能,那就是把它們自身嵌入到VC開發環境中去。這個功能讓我癡迷不已,原因只有一個:我想做一個可以嵌入VC開發環境的VC工程解析器,這樣用戶在VC開發環境中就可以直接對當前或所有工程進行各種分析,統計。那么實現它簡單嗎?簡單,Next和Copy即可輕松完成;僅僅這些嗎?不是,它的背后還有博大精深的COM做支撐。不管困難與否,還是讓我們先試為快。

      二、效果圖

    ?

      三、實現步驟:

      <3.1>新建一個<DevStudio Add-in Wizard>類型工程,輸入工程名稱"CodeAnalyser".

      <3.2>進入第二個畫面,系統要求用戶輸入插件的名稱和描述信息。并且要求用戶選擇是否需要生成工具欄以及是否自動添加VC事件響應代碼。


      <3.3>點擊"Finish"結束向導,進入代碼編輯窗口。

      在這里我們要說的一點是:該工程引用了ICommands接口,并從該接口上派生出 CCommands類。該類完成了所有用戶自定義函數接口,VC應用程序消息響應和VC調試動作的消息響應工作。當我們真正為CCommands類添加成員函數之前我們必須先為ICommands接口添加相應的函數接口聲明。在本工程中我總共為ICommands接口添加了兩個函數接口,它們名字分別為:GetCurDirCommandMethod和QuitCommandMethod聲明如下:(在CodeAnalyer.odl文件中)

    interface ICommands : IDispatch
    {
     // methods
     [id(1)] //在Vtable中的函數索引號
     HRESULT GetCurDirCommandMethod(); //得到VC當前工作目錄

     [id(2)] //在Vtable中的函數索引號
     HRESULT QuitCommandMethod (); //退出VC編輯器
    };

      在接口ICommands添加接口函數,那么相應的我們也要在類CCommands中聲明和實現ICommands接口函數,函數的內部代碼和普通工程代碼沒什么區別。

    //Implement(CCommands類內部接口函數的聲明)
    public:
    STDMETHOD(GetCurDirCommandMethod)(THIS);
    STDMETHOD(QuitCommandMethod)(THIS);

    //Function Code(Ccommands類內部接口函數的實現)
    //得到當前VC開發環境的工作目錄[您也可以讓它成為你想要實現的功能代碼]
    STDMETHODIMP CCommands::GetCurDirCommandMethod()
    {
     AFX_MANAGE_STATE(AfxGetStaticModuleState());
     VERIFY_OK(m_pApplication->EnableModeless(VARIANT_FALSE));
     BSTR bstrCurDir;
     m_pApplication->get_CurrentDirectory(&bstrCurDir);
     CString str(bstrCurDir);
     ::MessageBox(NULL, str, "VC工作目錄", MB_OK | MB_ICONINFORMATION);
     VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));
     return S_OK;
    }

    //退出VC開發環境

    STDMETHODIMP CCommands::QuitCommandMethod()
    {
     AFX_MANAGE_STATE(AfxGetStaticModuleState());
     VERIFY_OK(m_pApplication->EnableModeless(VARIANT_FALSE));
     if(::MessageBox(NULL,"您想退出VC++編輯器嗎(Y/N)?","詢問信息...", MB_YESNO | MB_ICONQUESTION) == IDYES)
      m_pApplication->Quit();
      VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));
     return S_OK;
    }

      <3.4> 創建工具欄,連接工具欄按鈕事件

      所有的幕后工作已經準備就緒,只差個工具欄界面就一切OK了。打開類CDSAddIn,它里面有三個成員函數,其中OnConnection和OnDisconnection成員函數的意義非常重要。它們的意義如下:

      <1>OnConnection:插件的初始化任務都在這里完成。如COM服務的啟動,工具欄/菜單欄的創建,工具欄按鈕/菜單項的添加與修改等等。

      <2>OnDisconnection:插件的卸載工作都在這里完成。如COM服務的卸載,工具欄/菜單欄的銷毀,釋放等等。

      了解了它們各自的用途之后我們就可以在相應的消息事件中添加代碼了。很顯然工具欄的初始化應該在OnConnection事件中完成。

      在OnConnection事件中系統首先獲得了VC應用程序接口,然后調用一個接口函數:AddCommand來為插件添加命令和命令影射函數。然后再使用另外一個接口函數AddCommandBarButton向工具欄中添加工具欄按鈕,其中每個工具欄按鈕會和一個命令標志符號相連接,這樣就能實現按鈕和命令(消息)之間的一一對應。下面是添加一個命令和一個工具欄按鈕的代碼(如果你要添加多個工具欄按鈕只要重復此步驟即可):

    LPCTSTR szCommand = _T("GetCurDirCommand");
    VARIANT_BOOL bRet;
    CString strCmdString;
    strCmdString.LoadString(IDS_CMD_STRING);
    strCmdString = szCommand + strCmdString;
    CComBSTR bszCmdString(strCmdString);
    CComBSTR bszMethod(_T("GetCurDirCommandMethod"));

    CComBSTR bszCmdName(szCommand); //和下面添加工具欄按鈕對應

    VERIFY_OK(pApplication->AddCommand(bszCmdString,bszMethod,0,dwCookie,&bRet));
    //AddCommand 參數含義:
    //bszCmdString:命令字符串。
    //bszMethod:Icommands接口函數名。
    //第三個參數代表位圖偏移量。
    //第四和第五個參數分貝為系統參數和返回值(參照MSDN的IApplication介紹)

    if (bRet == VARIANT_FALSE)
    {
     *OnConnection = VARIANT_FALSE;
     return S_OK;
    }

    //添加工具欄按鈕
    if (bFirstTime == VARIANT_TRUE)
    {
     VERIFY_OK(pApplication->AddCommandBarButton(dsGlyph, bszCmdName, m_dwCookie));
    }

      <3.5> 編譯,連接及在VC中引入插件

      以上就是我們所有的代碼工作,接下來趕快Build以下吧。編譯通過的話,在你的工程Debug目錄下會有個dll文件。然后打開VC編輯器,在VC任何一個工具欄上點擊鼠標右鍵,彈出如下圖所示菜單。然后選擇”Customize”子菜單,打開如下圖所示的工具欄定制窗口:


      接著選擇該窗口的最后一頁"Add-Ins and Macro Files"出現下圖所示窗口。


      然后點擊”Browse...”按鈕,這時打開你工程下的Debug目錄中的DLL文件,這樣你就可以看到你制作的工具欄了。同樣你再次打開上面的菜單,這次可以看到多了一個工具欄,并且名字亂七八糟的,怎么改變工具欄的名字呢?方法很簡單:打開上面窗口中的”Toolbars”選項頁,在工具欄列表框中找到你的工具欄,然后在”Toolbar name”編輯框中輸入你想要的名字即可。再打開上面的菜單看看名字是不是變了,哈哈!


      OK,今天的話題就聊到這里。

    posted @ 2006-09-30 22:58 Coolfiry 閱讀(278) | 評論 (0)編輯 收藏

      插件式設計近年來非常流行,其中eclipse起了推波助瀾的作用,提到插件式就會不由自主的想到eclipse。其實插件式設計并不是什么新事物,早在幾十年前就有了。像X Server就是基于插件式設計的,除了核心功能外,它所有的擴展功能和設備驅動都是以插件方式加入進來的。

      基于插件的設計好處很多:把擴展功能從框架中剝離出來,降低了框架的復雜度,讓框架更容易實現。擴展功能與框架以一種很松的方式耦合,兩者在保持接口不變的情況下,可以獨立變化和發布。公開插件接口,讓第三方有機會擴展應用程序的功能,有財大家一起發。另外,還可以讓開源與閉源共存于一套軟件,你的插件是開源還是閉源,完全由你自己決定。

      基于插件設計并不神秘,相反它比起一團泥的設計更簡單,更容易理解。各種基于插件設計的架構都有自己的特色,但從總體架構上看,其模型都大同小異。這里我們介紹一個簡單的模型,并給出幾個實例,希望對新手有所啟發。

      1. 基本架構

    plugin.jpg

      插件式設計的應用程序,基本上可以用上圖來表示。當然,此圖是一種較高層次的表示,實際的設計會更復雜一些。我們在這里為了闡述方便,不用故意搞得那么復雜。

      應用程序由應用程序框架、插件接口、插件和公共函數庫四部分組成。

      應用程序框架負責應用程序的整體運作,它清楚程序整個流程,但并不知道每個過程具體要做什么。它在適當的時候調用一些插件,來完成真正的功能。

      插件接口是一個協議,可能用IDL描述,可能是頭文件,也可能一段文字說明。插件按照這個協議實現出來,就可以加入到應用程序中來。當然,對于復雜的系統,插件接口可能有多個,各自具有獨立的功能。

      插件是完成實際功能的實體,實現了要求的插件接口。盡管實現什么以及怎么實現,完全是插件自己的自由。在實際情況來,一般還是有些限制,因為插件接口本身可能就是一個限制。如,實現編譯功能的插件,自然不能實現成一個聊天功能的插件。

      公共函數庫是一組函數或者類,應用程序框架和插件都可以調用。它通常是一個獨立的動態庫(DLL)。應用程序框架本身是公用的,是代碼復用的一種方式。但并不是所有可復用代碼都可以放在框架中,特別是插件會用到的公共代碼,那會造成插件對框架的依賴。把這些公共代碼提取到一個獨立的庫中,是一種好的方法。

      另外,值得補充說明一下的是插件接口。插件接口通常有兩種:

      通用插件接口:這一類插件接口是通用的,你無法從接口函數看出這個插件的功能。它的接口函數通常有這些函數:

      init : 用于初始化插件,通常在插件被加載時調用。

      deinit:用于反初始化插件,通常在插件被卸載時調用。

      run:讓插件起動。

      stop:讓插件停止。

      至于插件要完成什么功能,要插到哪里,在init函數里決定,它調用公共函數庫里的函數把自己注冊到框架中某個位置。

      專用插件接口:這一類插件接口是專用的,看到它的接口函數說明,你就可以大致了解它的功能了。

      加入插件的方式通常采用配置信息來實現,配置信息可以是注冊表,也可以配置文件。也可以動態注冊進來,或者把插件放到指定的位置。

      下面我們來看幾個實例:

      2. 桌面設計

      最近一段時間完成了桌面模塊的設計和實現。按照以往的經驗,桌面模塊通常是變化最多的一個模塊,SPEC總是在不斷的調整的效果,不同客戶要求實現具有個性化的桌面,直到產品快發布了,桌面的SPEC還在不停的修改。另外,在智能手機中,桌面占有特殊的地位,很多東西都可能往桌面里塞,桌面不但是各種功能的大雜燴,還是一些系統消息的中轉站。

      這個任務比較棘手,所以在設計時就分外小心。首先想到的就是采用插件式設計,把外圍功能獨立出來,盡量簡化框架的實現。

      插件:每一個最小功能單元都是一個插件,它可以是可見的,也可以是不可的,也可以是動態變化的。比如時間、電池電量、網絡連接、信號強弱、新事件(如SMS、MMS、EMAL、ALARM和未接電話等)、應用程序快捷方式、左右操作按鈕和其它處理系統事件的功能單元。每個插件都用一個.desktop來描述,這是遵循freedesktop.org的標準的。

      桌面框架包括:狀態欄、開始菜單、操作欄、桌面區、事件管理器和主題管理器。而狀態欄、開始菜單、操作欄、桌面區和事件管理器都是容器,容納各種插件。對于可見的插件,可以有自己的表現方式,也可以采用通用的表現方式。

      公共函數庫:一些抽象的類、實現插件的輔助類以及其它一些可能被公用的類。

      插件接口:對于不可見的插件要求實現事件處理功能,可見的插件還要求實現繪制功能。

      3. 模擬器設計

      一個同事負責設計另外一個平臺的PC模擬環境設計。在我的建議下,他對架構作了調整。調整后的架構非常簡單,也可以認為是插件式的設計,它由下面幾部分組成:

      應用程序框架:負責模擬器基本功能,如模擬鍵盤和顯示設備、換膚功能等。

      插件:就是被模擬的平臺,如microwindow及相應的手機應用程序。盡管運行時通常只有一個插件運行,這樣做仍然有意義,如果要換成minigui或者其它平臺時,模擬器不需要作任何修改。

      公共函數庫:它由應用程序框架初始化一些信息和回調函數,然后供插件(即microwindow)調用,插件利用它來實現顯示和輸入等驅動程序。

      插件接口:如起動和停止模擬平臺等。

      4. GIMP

      GIMP是一個功能強大的圖形圖像編輯器,典型的基于插件式的設計,在《unix編程藝術》中,作為插件式設計示例介紹過。

      應用程序框架:GUI

      插件:完成圖像的各種轉換和處理功能,如模糊、去斑和色彩調整等。

      公共函數庫:放在libgimp.so里。

      插件接口:對GIMP感興趣的朋友,可以到官方網站上去閱讀更多的文檔。

    posted @ 2006-09-30 22:57 Coolfiry 閱讀(705) | 評論 (0)編輯 收藏

      Google推薦的開發環境是VS 2003,GoogleDesktop的插件是基于COM的,而COM是語言無關的,所以你可以用任何能開發COM的工具(語言)開發。

      如果你使用的VS 2003或者VS 2005,建立開發環境非常容易。不過,如果你像我一樣戀舊,還是喜愛VC6的簡潔快速,排斥龐大緩慢的VS 2003或者VS 2005,可能就要費一點周折了。

      這里只討論VC6的環境設置。

      Google沒有為VC6 提供開發向導,也就是說,所有代碼你都得手工就編寫。如果是出于學習的目的,手工去寫這些代碼,付出的勞動會有所回報的。另外,VC6所帶的ATL版本也有點老,一些類只有在新版本中才有,在VC6中無法使用,所以有時你不得不面對一些COM的細節問題。同樣,同樣如果出于學習的目的,所花費的時間也是值得的。

      建立開發環境的第一步就是下載GoogleDesktop的SDK,下載地址為http://desktop.google.com/。

      解開之后,GD_SDK\api目錄下有下面幾個目錄:

    documentation
    samples
    tools
    wizards

      建議先大概看一下documentation中的文檔,然后閱讀samples中的部分代碼,找一下感覺。

      GoogleDesktop提供全部接口都在三個IDL文件中聲明:

    GoogleDesktopActionAPI.idl
    GoogleDesktopAPI.idl
    GoogleDesktopDisplayAPI.idl

      開發GoogleDesktop的插件,有以上文件已經足夠(當然你要安裝GoogleDesktop本身)了。但是C++中不能直接使用idl文件,要通過midl.exe編譯成頭文件,才能使用。其實不用這么麻煩,GD_SDK\api\samples\common目錄中已經有相關頭文件了:

    GoogleDesktopDisplayAPI.h

    GoogleDesktopComponentRegistration.h

    GoogleDesktopAPI.h

    GoogleDesktopActionAPI.h

      直接使用這幾個頭文件,可以省去用midl編譯步驟。只要修改VC6的設置,讓它可以找到上述頭文件就行了。有兩種方式可以做到這一點。一種方式是針對當前項目的:

      1. 打開菜單Project->Settings

      2. 打開屬性頁的C/C++標簽

      3. 選擇Categary的Preprocessor項

      4. 在Additional Include directories一欄加入上述文件所在的目錄

      另一種方式是針對VC6所有的項目的:

      1. 打開菜單Tool->Options…

      2. 打開屬性頁的Directories標簽

      3. 選擇Show directories for中的include files項

      4. 在Directories中加上述文件所在的目錄

      至于選擇哪一種方式,完全看你個人愛好,后者會方便一點,對懶人比較適用,但它會影響所有的VC6項目,或許會有某些副作用。

    posted @ 2006-09-30 22:55 Coolfiry 閱讀(252) | 評論 (0)編輯 收藏

    ?

    原文地址:http://m.tkk7.com/BlueDavy/archive/2006/05/28/48593.html

    摘要:插件開發框架其實和目前開源界流行的MVC框架之類的相同,都決定了基于這個框架的開發方式,如基于MVC框架,就會按照MVC思想來進行開發,而插件開發框架呢,也是同樣如此,就要求基于插件的方式來進行開發,不過插件開發框架和MVC框架又有不同,插件開發框架是一個可以成為系統基礎架構的框架,而MVC框架通常來講不足以成為,如在目前的MVC框架Webwork、Struts上我們通常都需要加上Spring、Hibernate來構成系統完整的基礎架構,這個時候由于MVC框架的實現是沒有標準可參照的,就造成了在各種系統中形成了不同的但很類似的基礎架構,但卻造成了無法復用的現象;插件開發框架則是作為統一系統基礎架構的一種開發方式,它使得系統的復用成為了可能,而同時由于插件開發框架對于動態性的支持,使得系統更加的靈活和可擴展。來看看一個插件開發框架,應該提供些什么東西,作為改變系統架構思想的框架,插件框架需要考慮很多方面,如開發、測試、部署等,總結下來一個插件框架應提供插件的開發規范;插件開發、調試的IDE;

    posted @ 2006-09-30 22:53 Coolfiry 閱讀(272) | 評論 (0)編輯 收藏

         摘要: N皇后問題是一個典型的需要用回溯算法來解決的問題。回溯算法可以用遞歸方法來實現,也可以用非遞歸方法來實現。用遞歸的方法來解決回溯的問題思路很清晰,但是耗費的內存資源較多,速度也較慢;非遞歸方法具有速度快和耗費較少內存資源的優點,但是程序的邏輯結構卻很復雜——不過搞懂之后覺得也很簡單。???在寫非遞歸算法之前,參考了網上的一些文章,但是覺得那些程序都很晦澀難懂,而且存在一些問題,我索性自己寫了一個,...  閱讀全文

    posted @ 2006-09-27 22:20 Coolfiry 閱讀(470) | 評論 (0)編輯 收藏

    煩的很啊,但要認認真真做人,兢兢業業做事哦

    posted @ 2006-09-27 22:15 Coolfiry 閱讀(265) | 評論 (0)編輯 收藏

    僅列出標題
    共4頁: 上一頁 1 2 3 4 下一頁 
    主站蜘蛛池模板: 99在线免费视频| 美女无遮挡免费视频网站| 国产免费牲交视频免费播放| 亚洲AV无码乱码精品国产| 国产综合激情在线亚洲第一页| 啦啦啦手机完整免费高清观看| 亚洲精品无码永久在线观看男男| 女人让男人免费桶爽30分钟| 亚洲av成人一区二区三区观看在线 | 美女露100%胸无遮挡免费观看| 国产成人无码区免费A∨视频网站 国产成人涩涩涩视频在线观看免费 | 久久亚洲AV成人无码| 亚洲免费人成视频观看| 久久亚洲AV成人无码国产| 3d成人免费动漫在线观看| 99热亚洲色精品国产88| 日本免费的一级v一片| 美女尿口扒开图片免费| 国产亚洲精久久久久久无码AV| 国产在线观看免费视频软件| 中文字幕亚洲免费无线观看日本| 亚洲无砖砖区免费| 亚洲人成自拍网站在线观看| 少妇亚洲免费精品| 国产猛男猛女超爽免费视频| 亚洲精品在线不卡| 国产精品深夜福利免费观看| 大地资源中文在线观看免费版 | 亚洲国产精品乱码在线观看97| 免费无码又爽又刺激高潮 | 91嫩草私人成人亚洲影院| 久久WWW色情成人免费观看| 黄色a三级免费看| 国产AV无码专区亚洲精品| 美女视频黄的全免费视频网站| 亚洲AV无码一区二区乱子仑| 亚洲人成伊人成综合网久久久| 免费无码肉片在线观看| 一区二区三区免费电影| 亚洲国产一区在线观看| 亚洲日韩中文在线精品第一|