How Web Servers Work & How Servlet Containers Work
1.可以生成一個類(Constants.java),用來保存那些公共的常量,路徑等等。
2.類的安全性考慮:
try {
servlet = (Servlet) myClass.newInstance();
servlet.service((ServletRequest) request, (ServletResponse) response);
}
這里,由于將request,response直接cast成ServletRequest,ServletResponse傳入應用程序的servlet.service中,就會導致在servlet里可以調用request,response里的公共方法,這是一種不好的設計方法。
改進的方法是:
Servlet servlet = null;
RequestFacade requestFacade = new RequestFacade(request);
ResponseFacade responseFacade = new ResponseFacade(response);
try {
servlet = (Servlet) myClass.newInstance();
servlet.service((ServletRequest) requestFacade, (ServletResponse) responseFacade);
}
這樣做,通過使用requestFacade,responseFacade,將request,response和ServletRequest,ServletResponse隔離開,就可以避免出現安全隱患了。
3.Java里,類路徑是個比較麻煩的設計,常常由于類的路徑沒有設置正確,導致調試無法通過。這時候,可以多考慮一下改變類的位置試試看。
Java深度歷險
1.JDK,JRE,JVM三者間的關系。
安裝JDK時會在JDK安裝目錄和C:\Program Files\java底下生成兩個JRE目錄。
而安裝JRE的話,只在C:\Program Files\java下生成一個JRE目錄。
JRE的作用:類似于一臺虛擬的Java PC,用來執行用java編寫的程序。
JVM只是JRE中的一個動態連接函數庫(dll)。
JDK里面的工具幾乎是用JAVA編寫的,所以JDK本身就是Java應用程序,因此要使用JDK附的工具來開發java程序,也必須要自行附一套JRE才行,這就是<JDK安裝目錄>\jre底下需要一套JRE的原因。而位于Program Files\底下的那套JRE就是拿來執行我們自己寫的java應用程序的。
Java.exe的執行順序:
1.自己的目錄下有沒有JRE目錄。
2.父目錄底下JRE子目錄。
3.查詢Windows Registry(HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment)。
結論:要搞清楚1.哪一個java.exe被執行;2.java.exe找到哪一套JRE。
本人在RSA里編寫了一個Java程序,但是在DOS命令行下卻始終無法運行,老是報:NoClassDefFoundError。最后發現錯誤的原因是由于該java程序是在jxb.ibm.com.cn的package下,所以在DOS里運行時,應該在項目所在的目錄下輸入:
java jxb/ibm/com/cn/CheckLineLen......
這樣,才可以正常地執行。
2.類裝載器。
兩種載入方式:預先載入(pre-loading),比如載入基礎類(核心類)函數庫時;隨需載入(load-on-demand),比如在載入自己編寫的java程序時。
對于隨需載入,僅僅聲明一個對象,不會使其被載入到內存中,只有用new xxx()才能將其載入。
這種設計的好處是不需要占用很大的內存,因為早期java就是被用于嵌入式系統的設計上。
讓java具有動態性的兩種方法:
1.隱性法:使用new()關鍵字;
2.顯性法:a.使用Class的forName()方法;b.使用ClassLoader的loadClass()方法。
forName()實際上有兩個同名的方法,一個帶一個參數,另外一個帶三個參數。
對于后一個forName()來說,其第二個參數用來控制是否調用static initialization block,如果為false的話,那么僅僅命令類裝載器載入類,但不調用static block,只有當第一次實例化該類時才調用。
Java啟動流程:
1.輸入命令:java xxx.class
2.找到JRE
3.找到JVM.DLL
4.啟動JVM并進行初始化
5.產生Bootstrap Loader
6.載入ExtClassLoader,將parent設為Bootstrap Loader
7.載入AppClassLoader,將parent設為ExtClassLoader
8.載入xxx.class
執行時期動態更改搜尋路徑的設定是不可能的事情。如果因為特殊需求,有些類的所在路徑并非在一開始時就能決定,那么除了產生新的類裝載器來輔助我們載入所需的類之外,沒有其他的方法了。
類裝載器的委派模型:
就是類裝載器有載入類的需求時,會先請示其parent使用其搜尋路徑幫忙載入,如果parent找不到,那么才由自己依照自己的搜尋路徑搜尋類。--遞歸性。
3.Java與Microsoft Office。
使用JNI(Java Native Interface)可以從Java中操作Windows Registry,Microsoft WORD等應用程序。
基本的流程是:
Java程序->Java轉接器->(JNI)->動態連接函數庫(dll)->(OLE Automation)->VBA組件->文件對象等。
4.Package和import。
一,如果你的類屬于某個package,那么你就應該將它置于該package所對應的相對路徑之下。例如,如果你有個類叫做C,屬于xyz.pqr.abc package,那么你就必須建立一個三層目錄:xyz\pqr\abc,然后將C.java或者C.class放置到這個目錄下,才能讓javac.exe或是java.exe順利執行。
二,當你使用javac.exe編譯的時候,類原始碼的位置一定要根據結論一所說來放置,如果該原始碼出現在不該出現的地方,除了很容易造成混淆不清,而且有時候抓不出編譯為何發生錯誤,因為javac.exe輸出的錯誤信息根本無法改善問題。
三,編譯時,如果程序里用到其他的類,不需要該類的原始碼也一樣能夠通過編譯。
四,當你使用javac.exe編譯程序卻又沒有該類的原始碼時,類放置的位置應該根據結論一所說的方式放置。如果類出現在不該出現的地方,有很大的可能性會造成難以理解的編譯錯誤。盡管這時仍然能夠正常執行程序。
五,在結論一中新建的目錄可以從任何地方開始建起。但是你必須告訴java.exe與javac.exe到哪里去找才行,方式就是利用它們的-classpath選項。也可以在CLASSPATH環境參數里進行設定。
六,使用ZIP檔的效果和單純的目錄相同,如果你在-classpath選項指定了目錄,就是告訴java.exe和javac.exe到該目錄下尋找類;如果你在-classpath選項指定了ZIP檔的檔名,那么就是請java.exe和javac.exe到該壓縮檔中尋找類。請注意,即使是在壓縮檔中,但是該有的相對路徑還是要有,否則java.exe和javac.exe仍然無法找到它們所需要的類。
七,在指定環境變量CLASSPATH或-classpath選項時,所給與的目錄名或者JAR檔名稱之順序一定要謹慎。
八,將JAVA檔和類確實安置在其所屬之package所對應的相對路徑下。
九,不管使用java.exe或javac.exe,最好明確指定-classpath選項,如果怕麻煩,使用環境變量CLASSPATH可以省去額外輸入指令的時間。
十,注意指令中“\”和“.”的區別。一般,-classpath選項中一定要用“\”,而source files的地方在使用javac.exe時用的是“\”,而在使用java.exe時用的是“.”。
十一,無論是否使用import指令,存在目前目錄下的類都會被編譯器優先采用,只要它不屬于任何package。這是因為編譯器總是先假設你所輸入的類名稱就是該類的全名(不屬于任何package),然后從-classpath所指定的路徑中搜尋屬于該類的.java或.class。
兩個常見的誤解:
1.import和C/C++里的include同意義。
2.在import里使用如import x.y.*;會讓編譯器效率降低。
十二,Java具有很強的動態連接特性,每個類都可以看作一個動態連接函數庫。這樣就可以在不重新編譯其他類的情況下照樣也能更新對象類。
PDF知識講座
PDF(Portable Document Format,便攜式文檔結構)是一種很有用的文件格式,其最大的特點是平臺無關而且功能強大(支持文字\圖象\音樂\視頻).今天先講一下pdf的文件(物理)結構
PDF文件結構可分為以下幾塊:
1.header:
pdf文件的第一行,格式如下:
%PDF-1.3
表示當前文件的版本是1.3(目前最高版本為1.6)
2.body:
pdf文件中用到的所有對象,包括文本\圖象\音樂\視頻\字體\超連接\加密信息等等,格式如下:
2 0 obj
...
end obj
其中省略號部分是pdf規定的任意合法對象(一共8種)
3.cross reference table:
所有pdf對象的引用表,其格式如下:
xref
0 5
0000000000 65535 f
0000000009 00000 n
0000000074 00000 n
0000000120 00000 n
0000000179 00000 n
其中,xref是開始標志,表示以下為引用表內容;0 5表示從對象號為0的開始,
連續有5個對象(0,1,2,3,4),分別用5行來表示.每行的前10個數字代表這個
這個對象相對文件頭的偏移地址,后面5個數字只有當這個對象被刪除的時
候才有用,表示這個對象被刪除后又被重新生成后的對象號最后一位f或n表
示對象是否被使用(n表示使用,f表示被刪除或沒有用)
4.trailer:
整個pdf文件的入口點,形式如下:
trailer
<<
/Size 8
/Root 1 0 R
>>
startxref
553
%%EOF
/size :這個pdf中總共使用了多少個對象
/root :這個pdf文件的catalog對象的對象號,這是pdf中最頂層的對象
/startxref: 后面的數字表示cross reference table的開始位置
/%%EOF :文件結束符.
實際一個pdf文件是很復雜的,但是上面幾個部分是確定的,只能多不能少.
以下是一個完整的pdf源文件,內容是顯示一個"hello world",對照上面的說明應該能看個差不多
%PDF-1.0
1 0 obj
<<
/Type /Catalog
/Pages 3 0 R
/Outlines 2 0 R
>>
endobj
2 0 obj
<<
/Type /Outlines
/Count 0
>>
endobj
3 0 obj
<<
/Type /Pages
/Count 1
/Kids [4 0 R]
>>
endobj
4 0 obj
<<
/Type /Page
/Parent 3 0 R
/Resources << /Font << /F1 7 0 R >>/ProcSet 6 0 R
>>
/MediaBox [0 0 612 792]
/Contents 5 0 R
>>
endobj
5 0 obj
<< /Length 44 >>
stream
BT
/F1 24 Tf
100 100 Td (Hello World) Tj
ET
endstream
endobj
6 0 obj
[/PDF /Text]
endobj
7 0 obj
<<
/Type /Font
/Subtype /Type1
/Name /F1
/BaseFont /Helvetica
/Encoding /MacRomanEncoding
>>
endobj
xref
0 8
0000000000 65535 f
0000000009 00000 n
0000000074 00000 n
0000000120 00000 n
0000000179 00000 n
0000000322 00000 n
0000000415 00000 n
0000000445 00000 n
trailer
<<
/Size 8
/Root 1 0 R
>>
startxref
553
%%EOF
pdf8種對象類型
1.booleam
用關鍵字true或false表示,可以是array對象的一個元素,或dictionary對象的一個條目.
2.numeric
包括整形和實型,不支持非十進制數字,不支持指數形式的數字.
例:
1)整數 123 4567 +111 -2
范圍:正2的31次方-1到負的2的31次方
2)實數 12.3 0.8 +6.3 -4.01 -3. +.03
范圍:±3.403 × 10的38次方 ±1.175 × 10的-38次方
注意:如果整數超過表示范圍將轉化成實數,如果實數超過范圍就出錯了
3.string
由一系列0-255之間的字節組成,一個string總長度不能超過65535.string有以下兩種方式:
1)由()包含起來的一個字串,中間可以使用轉義符"\".
例:
(abc) 表示abc
(a\\) 表示a\
2)由<>包含起來的一個16進制串,兩位表示一個字符,不足兩位用0補齊
例:
表示AA和BB兩個字符
表示AA和B0兩個字符
4.name
由一個前導/和后面一系列字符組成,最大長度為127.和string不同的是,name是不可分割的和唯一的,不可分割就是說一個name對象就是一個原子,比如/name,不能說n就是這個name的一個元素;唯一就是指兩個相同的name一定代表同一個對象.從pdf1.2開始,除了ascii的0,別的都可以用一個#加兩個十六進制的數字表示.
例:
/name 表示name
/name#20is 表示name is
/name#200 表示name 0
5.array
用[]包含的一組對象,可以是任何pdf對象(包括array).雖然pdf只支持一維array,但可以通過array的嵌套實現任意維數的array(但是一個array的元素不能超過8191)
例:
[549 3.14 false (Ralph) /SomeName]
6.Dictionary
用"<<"和">>"包含的若干組條目,每組條目都由key和value組成,其中key必須是name對象,并且一個dictionary內的key是唯一的;value可以是任何pdf的合法對象(包括dictionary對象).
例:
<< /IntegerItem 12
/StringItem (a string)
/Subdictionary << /Item1 0.4
/Item2 true
/LastItem (not!)
/VeryLastItem (OK)
>>
>>
7.stream
由關鍵字stream和endstream包含一系列字節.內容和string很相似,但有區別:stream可以分幾次讀取,分開使用不同的部分,string必須作為一個整體一次全部讀取使用;string有長度限制,但stream卻沒有這個限制.一般較大的數據都用stream表示.
例:(略)
8.NULL
用null表示,代表空.如果一個key的值為null,則這個key可以被忽略;如果引用一個不存在的object則等價于引用一個空對象.
例:(略)
給大家說點有用的東西:為什么有的pdf不允許打?。?nbsp;
PDF有自己的加密措施,其中就有限制打印.找到trailer,如果這個pdf是加密的話會有一個/Encrypt的name,它的值一般形式是n 0 R,表示這個pdf文件的加密信息在n 0這個obj里面記錄.找到這個obj,其下有一個/P的name,它的值是一個數字(32位),其中第三位代表是否有打印權限:)