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不允许打印?
PDF有自己的加密措施,其中就有限制打印.找到trailer,如果这个pdf是加密的话会有一个/Encrypt的name,它的值一般形式是n 0 R,表示这个pdf文件的加密信息在n 0这个obj里面记录.找到这个obj,其下有一个/P的name,它的值是一个数字(32位),其中第三位代表是否有打印权限:)