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