1、BEA dev2dev WebLogic Web Application Development精华sdj21 daijun2005-3-151Java基础21.1axman考验你的Java基础21.2如何获得客户端的MAC地址?61.3axman对equal的深入研究71.4为什么要始终使用PreparedStatement代替Statement?121.5一个利己线程调度实例?141.6GBK与GB2312字符集的问题151.7怎样制作ear,war文件?151.8乱码问题162Servlet&JSP192.1加载和启动servlet后,为一个servlet创建了一个还是多个实例?192.
2、2WebLogic里面的一个class修改了,需要重新启动WebLogic吗?192.3Tomcat关于UTF-8JSP文件的BUG202.4使用FileUpload组件上传文件?222.5session中存放数据库connection的问题242.6如果防止JSP页面刷新252.7JSP在I/O方面的一些问题252.8文件下载的时候为什么finally里面的代码没有执行?262.9请问web server怎么将配置文件参数在web application启动的时候读进内存272.10如何设置并且访问环境变量?282.11中文URL该怎么写293前台表现层313.1用JFreeReport生成
3、PDF报表313.2POI介绍383.3使用POI创建Excel格式数据414应用服务器特殊问题434.1Tomcat中的Web应用迁移到Weblogic 8.1434.2weblogic7.0中怎样实现定时执行程序?434.3养成使用在web.xml里配置引用资源的习惯444.4关于web-inf下的JSP的引用问题454.5WebLogic7关于JSP编译的一个BUG454.6如何让一个扩展名的文件在下载时提示下载而不是打开464.7在weblogic6.1下调试时如何保留系统编译jsp文件所生成的.java文件?465其他资料471 Java基础1.1 axman考验你的Java基础1.
4、简述逻辑操作(&,|,)与条件操作(&,|)的区别。(15分)2.下面程序运行会发生什么结果?如果有错误,如何改正? (15分)interface A int x = 0;class B int x =1;class C extends B implements A public void pX() System.out.println(x); public static void main(String args) new C().pX(); 3.简述 Java Server Page 和 Servlet 的联系和区别。(20分)4.XML文档定义有几种形式?它们之间有何本质区别?解析XML
5、文档有哪几种方式?(20分)5.简述synchronized和java.util.concurrent.locks.Lock的异同 ?(15分)6.EJB规范规定EJB中禁止的操作有哪些?(15分)7.最后还有一题考考你的眼力:public String toString() return this + + this.hashCode();这个toString()方法实现有无不当的地方?(toString方法其实可以按你想输出的任何内容输出一些该类的信息)答案:1.简述逻辑操作(&,|,)与条件操作(&,|)的区别。(15分)区别主要答两点:a.条件操作只能操作布尔型的,而逻辑操作不仅可以操作
6、布尔型,而且可以操作数值型b.逻辑操作不会产生短路.如:int a = 0;int b = 0;if( (a = 3) 0 | (b = 3) 0 ) /操后a =3,b=0.if( (a = 3) 0 | (b = 3) 0 ) /操后a =3,b=3. 答对第一点得5分,答对第二点得10分.本题考察最最基本的知识,但仍然有很多大牛级开发人员下马,任何语言在开始的部分都会详细介绍这些基本知识,但除了学习第一种语言时,没有人在学习新的语言时愿意花五分钟来复习一下.2.下面程序运行会发生什么结果?如果有错误,如何改正? (15分)interface A int x = 0;class B int
7、 x =1;class C extends B implements A public void pX() System.out.println(x); public static void main(String args) new C().pX(); 本题在编译时会发生错误(错误描述不同的JVM有不同的信息,意思就是未明确的x调用,两个x都匹配,就象在同时import java.util和java.sql两个包时直接声明Date一样)本题主要考察对接口和类的最最基本的结构的了解.对于父类的变量,可以用super.x来明确,而接口的属性默认隐含为 public static final.所以
8、可以通过A.x来明确.3.简述 Java Server Page 和 Servlet 的联系和区别。(20分)本题不用多说,在答相同点时应该明确知道jsp编译后是类servlet而不是Servlet,答区别时应该回答出侧重于(视图/控制逻辑).其它可根据情况加减分值.知识很简单,但从面试的角度看,被试者不仅要能知道它们的区别,而且要能比较准确地表达出来(以后写文档要能让别人看得懂,不产生歧义),回答jsp编译后就是servlet视为错误,回答jsp用于视图,servlet用于控制逻辑视为错误,应该用侧重于,主要(多数)用于等词语表达.4.XML文档定义有几种形式?它们之间有何本质区别?解析XM
9、L文档有哪几种方式?(20分)本题三个答题点:a: 两种形式 dtd,schemab: 本质区别:schema本身是xml的,可以被XML解析器解析(这也是从DTD上发展schema的根本目的)c: 两种主要方式:dom,sax.答出两种得全分,如能答出saxt,或其它(在答出dom,sax的基础上,如果应试者认为其它方式也可以视为对xml的解析应该允许.但没有答出dom,sax把其它方式说成是对XML的解析不得分)应该加分.5.简述synchronized和java.util.concurrent.locks.Lock的异同 ?(15分)主要相同点:Lock能完成synchronized所实
10、现的所有功能.(其它不重要)主要不同点:Lock有比synchronized更精确的线程语义和更好的性能(在相同点中回答此点也行)synchronized会自动释放锁.而Lock一定要求程序员手工释放.并且必须在finally从句中释放,如果没有答出在finally中释放不得分.就如Connection没有在finally中关闭一样.连最基本的资源释放都做不好,还谈什么多线程编程.6.EJB规范规定EJB中禁止的操作有哪些?(15分)共有8点,答出下列3-4点得满分.l 不能操作线程和线程API(线程API指非线程对象的方法如notify,wait等)l 不能操作awtl 不能实现服务器功能l
11、 不能对静态属生存取.l 不能使用IO操作直接存取文件系统l 不能加载本地库.l 不能将this作为变量和返回.l 不能循环调用.7 public String toString() return this + + this.hashCode();会变成public String toString() return String.valueOf(this) + + String.valueOf(this.hashCode();而valueOf方法又将去调用toString();/* public static String valueOf(Object obj) return (obj = n
12、ull) ? null : obj.toString(); */这样好像会有问题原文地址:1.2 如何获得客户端的MAC地址?Java本身没有这个能力,不过利用操作系统的命令可以做到。public static String getMACAddress() String address = ;String os = System.getProperty(os.name);if ( os != null & os.startsWith(Windows) try String command = cmd.exe /c ipconfig /all;Process p = Runtime.getRun
13、time().exec(command);BufferedReader br =new BufferedReader(new InputStreamReader(p.getInputStream();String line;while (line = br.readLine() != null) if (line.indexOf(Physical Address) 0) int index = line.indexOf(:);index += 2;address = line.substring(index);break;br.close();return address.trim();cat
14、ch (IOException e) return address;原文地址:1.3 axman对equal的深入研究equals方法的重要性毋须多言,只要你想比较的两个对象不愿是同一对象,你就应该实现equals方法,让对象用你认为相等的条件来进行比较.下面的内容只是API的规范,没有什么太高深的意义,但我之所以最先把它列在这儿,是因为这些规范在事实中并不是真正能保证得到实现.1.对于任何引用类型, o.equals(o) = true成立.2.如果 o.equals(o1) = true 成立,那么o1.equals(o)=true也一定要成立.3.如果 o.equals(o1) = tr
15、ue 成立且 o.equals(o2) = true 成立,那么o1.equals(o2) = true 也成立.4.如果第一次调用o.equals(o1) = true成立再o和o1没有改变的情况下以后的任何次调用都成立.5.o.equals(null) = true 任何时间都不成立.以上几条规则并不是最完整的表述,详细的请参见API文档.对于Object类,它提供了一个最最严密的实现,那就是只有是同一对象是,equals方法才返回true,也就是人们常说的引用比较而不是值比较.这个实现严密得已经没有什么实际的意义,所以在具体子类(相对于Object来说)中,如果我们要进行对象的值比较,就
16、必须实现自己的equals方法.先来看一下以下这段程序: public boolean equals(Object obj) if (obj = null) return false; if (!(obj instanceof FieldPosition) return false; FieldPosition other = (FieldPosition) obj; if (attribute = null) if (other.attribute != null) return false; else if (!attribute.equals(other.attribute) retur
17、n false; return (beginIndex = other.beginIndex & endIndex = other.endIndex & field = other.field); 这是JDK中java.text.FieldPosition的标准实现,似乎没有什么可说的.我信相大多数或绝大多数程序员认为,这是正确的合法的equals实现.毕竟它是JDK的API实现啊.还是让我们以事实来说话吧:package debug;import java.text.*;public class Test public static void main(String args) FieldP
18、osition fp = new FieldPosition(10); FieldPosition fp1 = new MyTest(10); System.out.println(fp.equals(fp1); System.out.println(fp1.equals(fp); class MyTest extends FieldPosition int x = 10; public MyTest(int x) super(x); this.x = x; public boolean equals(Object o) if(o=null) return false; if(!(o inst
19、anceof MyTest ) return false; return (MyTest)o).x = this.x; 运行一下看看会打印出什么:System.out.println(fp.equals(fp1);打印trueSystem.out.println(fp1.equals(fp);打印flase两个对象,出现了不对称的equals算法.问题出在哪里(脑筋急转弯:当然出在JDK实现的BUG)?我相信有太多的程序员(除了那些根本不知道实现equals方法的程序员外)在实现equals方法时都用过instanceof运行符来进行短路优化的,实事求是地说很长一段时间我也这么用过。太多的教程
20、,文档都给了我们这样的误导。而有些稍有了解的程序员可能知道这样的优化可能有些不对但找不出问题的关键。另外一种极端是知道这个技术缺陷的骨灰级专家就提议不要这样应用。我们知道,通常要对两个对象进行比较,那么它们应该是同一类型。所以首先利用instanceof运行符进行短路优化,如果被比较的对象不和当前对象是同一类型则不用比较返回false,但事实上,子类是父类的一个实例,所以如果 子类 o instanceof 父类,始终返回true,这时肯定不会发生短路优化,下面的比较有可能出现多种情况,一种是不能造型父类而抛出异常,另一种是父类的private 成员没有被子类继承而不能进行比较,还有就是形成上
21、面这种不对称比较。可能会出现太多的情况。那么,是不是就不能用 instanceof运行符来进行优化?答案是否定的,JDK中仍然有很多实现是正确的,如果一个class是final的,明知它不可能有子类,为什么不用 instanceof来优化呢?为了维护SUN的开发小组的声誉,我不说明哪个类中,但有一个小组成员在用这个方法优化时在后加加上了加上了这样的注释: if (this = obj) / quick check return true; if (!(obj instanceof XXXXClass) / (1) same object? return false;可能是有些疑问,但不知道如何
22、做(不知道为什么没有打电话给我.)那么对于非final类,如何进行类型的quick check呢?if(obj.getClass() != XXXClass.class) return false;用被比较对象的class对象和当前对象的class比较,看起来是没有问题,但是,如果这个类的子类没有重新实现equals方法,那么子类在比较的时候,obj.getClass() 肯定不等于XXXCalss.class,也就是子类的equals将无效,所以if(obj.getClass() != this.getClass() return false;才是正确的比较。是否equals方法一定比较的两
23、个对象就一定是要同一类型?上面我用了通常,这也是绝大多数程序员的愿望,但是有些特殊的情况,我们可以进行不同类型的比较,这并不违反规范。但这种特殊情况是非常罕见的,一个不恰当的例子是,Integer类的equals可以和Sort做比较,比较它们的value是不是同一数学值。(事实上JDK的API中并没有这样做,所以我才说是不恰当的例子)在完成quick check以后,我们就要真正实现你认为的“相等”。对于如果实现对象相等,没有太高的要求,比如你自己实现的“人”类,你可以认为只要name相同即认为它们是相等的,其它的sex,ago都可以不考虑。这是不完全实现,但是如果是完全实现,即要求所有的属性
24、都是相同的,那么如何实现equals方法?class Humanprivate String name;private int ago;private String sex; . public boolean equals(Object obj)quick check.Human other = (Human)ojb;return this.name.equals(other.name)& this.ago = ohter.ago& this.sex.equals(other.sex);这是一个完全实现,但是,有时equals实现是在父类中实现,而要求被子类继承后equals能正确的工作,这时
25、你并不事实知道子类到底扩展了哪些属性,所以用上面的方法无法使equals得到完全实现。一个好的方法是利用反射来对equals进行完全实现: public boolean equals(Object obj)quick check.Class c = this.getClass();Filed fds = c.getDeclaredFields();for(Filed f:fds)if(!f.get(this).equals(f.get(obj)return false;return true;为了说明的方便,上明的实现省略了异常,这样的实现放在父类中,可以保证你的子类的equals可以按你的愿
26、望正确地工作。关于equals方法的最后一点是:如果你要是自己重写(正确说应该是履盖)了equals方法,那同时就一定要重写hashCode().为是规范,否则.我们还是看一下这个例子:public final class PhoneNumber private final int areaCode; private final int exchange; private final int extension; public PhoneNumber(int areaCode, int exchange, int extension) rangeCheck(areaCode, 999, are
27、a code); rangeCheck(exchange, 99999999, exchange); rangeCheck(extension, 9999, extension); this.areaCode = areaCode; this.exchange = exchange; this.extension = extension; private static void rangeCheck(int arg, int max, String name) if(arg max) throw new IllegalArgumentException(name + : + arg); pub
28、lic boolean equals(Object o) if(o = this) return true; if(!(o instanceof PhoneNumber) return false; PhoneNumber pn = (PhoneNumber)o; return pn.extension = extension & pn.exchange = exchange & pn.areaCode = areaCode; 注意这个类是final的,所以这个equals实现没有什么问题。我们来测试一下: public static void main(String args) Map hm
29、 = new HashMap(); PhoneNumber pn = new PhoneNumber(123, 38942, 230); hm.put(pn, I love you); PhoneNumber pn1 = new PhoneNumber(123, 38942, 230); System.out.println(pn); System.out.println(pn.equals(pn1) is + pn.equals(pn1); System.out.println(hm.get(pn1); System.out.println(hm.get(pn); 既然pn.equals(p
30、n1),那么我put(pn,I love you);后,get(pn1)这什么是null呢?答案是因为它们的hashCode不一样,而hashMap就是以hashCode为主键的。所以规范要求,如果两个对象进行equals比较时如果返回true,那么它们的hashcode要求返回相等的值。原文地址:1.4 为什么要始终使用PreparedStatement代替Statement? 在JDBC应用中,如果你已经是稍有水平开发者,你就应该始终以PreparedStatement代替Statement.也就是说,在任何时候都不要使用Statement.基于以下的原因:一.代码的可读性和可维护性.虽然
31、用PreparedStatement来代替Statement会使代码多出几行,但这样的代码无论从可读性还是可维护性上来说.都比直接用Statement的代码高很多档次:stmt.executeUpdate(insert into tb_name (col1,col2,col2,col4) values (+var1+,+var2+,+var3+,+var4+);perstmt = con.prepareStatement(insert into tb_name (col1,col2,col2,col4) values (?,?,?,?);perstmt.setString(1,var1);pe
32、rstmt.setString(2,var2);perstmt.setString(3,var3);perstmt.setString(4,var4);perstmt.executeUpdate();不用我多说,对于第一种方法.别说其他人去读你的代码,就是你自己过一段时间再去读,都会觉得伤心.二.PreparedStatement尽最大可能提高性能.每一种数据库都会尽最大努力对预编译语句提供最大的性能优化.因为预编译语句有可能被重复调用.所以语句在被DB的编译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中(相当于一个涵数
33、)就会得到执行.这并不是说只有一个 Connection中多次执行的预编译语句被缓存,而是对于整个DB中,只要预编译的语句语法和缓存中匹配.那么在任何时候就可以不需要再次编译而可以直接执行.而statement的语句中,即使是相同一操作,而由于每次操作的数据不同所以使整个语句相匹配的机会极小,几乎不太可能匹配.比如:insert into tb_name (col1,col2) values (11,22);insert into tb_name (col1,col2) values (11,23);即使是相同操作但因为数据内容不一样,所以整个个语句本身不能匹配,没有缓存语句的意义.事实是没有
34、数据库会对普通语句编译后的执行代码缓存.这样每执行一次都要对传入的语句编译一次.当然并不是所以预编译语句都一定会被缓存,数据库本身会用一种策略,比如使用频度等因素来决定什么时候不再缓存已有的预编译结果.以保存有更多的空间存储新的预编译语句.三.最重要的一点是极大地提高了安全性.即使到目前为止,仍有一些人连基本的恶义SQL语法都不知道.String sql = select * from tb_name where name= +varname+ and passwd=+varpasswd+;如果我们把 or 1 = 1作为varpasswd传入进来.用户名随意,看看会成为什么?select *
35、 from tb_name = 随意 and passwd = or 1 = 1;因为1=1肯定成立,所以可以任何通过验证.更有甚者,把;drop table tb_name;作为varpasswd传入进来,则select * from tb_name = 随意 and passwd = ;drop table tb_name;有些数据库是不会让你成功的,但也有很多数据库就可以使这些语句得到执行.而如果你使用预编译语句.你传入的任何内容就不会和原来的语句发生任何匹配的关系.(前提是数据库本身支持预编译,但上前可能没有什么服务端数据库不支持编译了,只有少数的桌面数据库,就是直接文件访问的那些)只
36、要全使用预编译语句,你就用不着对传入的数据做任何过虑.而如果使用普通的statement, 有可能要对drop,等做费尽心机的判断和过虑.上面的几个原因,还不足让你在任何时候都使用PreparedStatement吗? 原文地址:1.5 一个利己线程调度实例?所谓利己线程,就是在运行时不考虑其它线程的运行权限和时间分配,一心只顾自己运行完成了事的这种线程,比如:while(true).但是,如果.的代码中要调用一些资源,就一定要sleep,让资源有空闲的时间来让本线程获取,也许这些资源不是当前线程一方要求调用,但无论如何要空闲一定的时间,即使资源空闲下来时本线程只能调用很少一部份,不然真的就死
37、锁了.在图形编程中,加载一个图形是异步的,然后组件会调用观察类ImageObserver来不断让图形加载和显示进行更新直到完成.因为图形组件的顶级对象 Component 已经实现ImageObserver,所以一般来说如果要加载一个Image,只要在drawImage方法中调用this(自己)作为观察者就行.但是,如果我们要把一个源图象缩放后输出,或把多个源图象合并成一个图象输出(图形计数器就是把很多种0-9的数字图片合并成一个图片)输出,那就是在内存中先生生成一个BufferedImage对象,然后把源图象draw到BufferedImage的一定位置,再把BufferedImage编码输
38、出到一个输出流如文件或网页.因为drawImage是BufferedImage的Graphics对象调用的,一切都在内存中而根本没有可视组件,所以根本没有观察者对象,而MediaTracker对象同样要求一个组件对象构造,在这种时候也没法调用.BufferedImage bi = new BufferedImage(目标宽,目标高,BufferedImage.TYPE_INT_RGB);Graphics2D g = (Graphics2D)image.getGraphics();Image src = Toolkit.getDefaultToolkit().getImage(d:/aaa.jp
39、g);不管你的src原来是多大,只要你draw时设定大小,就会以你设定的大小画到目标bi上,这就是缩略图或合成图的方法.但在g.drawImage(src,坐标x,坐标y,宽,高,观察者);调用时,因为没有一个观察者实例,一次调用99%不会成功.所以我是这样调用的:while (!(flag=g.drawImage(src, 0, 0, 240, 320, null) ;大家注意是如果flag为flase就只有一个;也就是什么也不做直接进入下一次循环.我试过一般画一张新图要10多秒,如果是生成计数器,这在servlet中根本不行.没有人愿意用10秒的时间等一个计数器出来.后来我想让这个serv
40、let实现观察者.就在 while (!(flag=g.drawImage(src, 0, 0, 240, 320, null) 中调试它每次getWidth(null)的log并打印出来,结果发现如果改成 while (!(flag=g.drawImage(src, 0, 0, 240, 320, null) System.out.println(src.getWidth(null); 却只要200MS,0.2秒左右就完成了.原来,System.out时要调用BIOS的资源,这时线程要闲置等待,到反而让src资源有了load的时间.于是改成: while (!(flag=g.drawImag
41、e(src, 0, 0, 240, 320, null) Thread.currentThread().sleep(1); 哈哈,成功了.sleep时1,5,10MS没有多大区别,都在200MS左右完成,一般不要再睡更多的时间.所以即使是利己线程的也要看它是否对其它资源的请求,真的应了那句话叫予人方便,于己方便!原文地址:1.6 GBK与GB2312字符集的问题有的用户比如叫扬璠,或是李珺。就不能正确显示她的名字,而显示一个扬?,李?,其他中文没问题,就是这些比较偏怪的中文无法显示。这就是GBK和GB2312的区别,你说的那几个字是GBK中的,GB2312中根本没有,只好?了,使用GBK就行了。原文地址:1.7 怎样制作ear,war文件?方法一:在JDK CLASSPATH下命令行打包:用法:jar ctxuvfm0M jar-文件 manifest-文件 -C 目录 文件名 .选项: