一周学员问题解答 【2008-5-14至2008-5-20】(下)
1. 学生问: 讲讲关于java中字符编码的一点心得,可能对初学者有点帮助?
2. 学生问: 使用Java操作文本文件的方法详解 ?
3. 学生问: JAVA开放源码项目与工具在企业应用开发中的运用?
4. 学生问: ASP记录集对象的方法有哪些?
1. 学生问: 讲讲关于java中字符编码的一点心得,可能对初学者有点帮助?
老师解答: 编写下面的程序代码,分析和观察程序的运行结果:
import java.io.*;
public class TestCodeIO {
public static void main(String[] args) throws Exception{
InputStreamReader isr = new InputStreamReader(System.in,"iso8859-1");
BufferedReader br = new BufferedReader (isr);
String strLine = br.readLine();
br.close();
isr.close();
System.out.println(strLine);
}
}
运行程序后,输入“中国”两个字,输出结果为 ???ú
请按照下面两种方法修改上述程序,是输入的中文能够正常输出
1。修改程序中的语句
InputStreamReader isr = new InputStreamReader(System.in,"iso8859-1");
2。不修改上面的语句,修改下面的语句
System.out.println(strLine);
第一种该法很简单,只要改成下面这样就可以了,这里不详细讨论
InputStreamReader isr = new InputStreamReader(System.in,"gb2312");
这里我要详细讨论的是第二种该法怎么改
起初我是这样改的
System.out.println(new String (strLine.getBytes(),"iso8859-1"));
输入“中国”后输出的结果虽然不是上面所述的乱码,但是还是乱码,显然这种该法是不正确的!
这里我要感谢 软件民工 告诉我的正确改法,使我恍然大悟
System.out.println(new String (strLine.getBytes("iso8859-1")));
这两种改法究竟有什么区别呢?为了方便大家阅读,我先把正确和错误的改法帖出来:
import java.io.*;
public class TestCodeIO {
public static void main(String[] args) throws Exception{
InputStreamReader isr = new InputStreamReader(System.in,"iso8859-1");
//Create an InputStreamReader that uses the given charset decoder
BufferedReader br = new BufferedReader (isr);
String strLine = br.readLine();
br.close();
isr.close();
System.out.println(strLine);
System.out.println(new String (strLine.getBytes(),"iso8859-1")); //错误改法
//Encodes this String (strLine) into a sequence of bytes using the platform's
//default charset(gb2312) then constructs a new String by decoding the
//specified array of bytes using the specified charset (iso8859-1)
//because this String (strLine) uses the charset decoder "iso8859-1",so it can
//only be encoded by "iso8859-1",cann't be encoded by the platform's default
//charset "gb2312",so this line is wrong.
System.out.println(new String (strLine.getBytes("iso8859-1"))); //正确改法
//Encodes this String (strLine) into a sequence of bytes using the named
//charset (iso8859-1),then constructs a new String by decoding the
//specified array of bytes using the platform's default charset (gb2312).
//This line is right.
}
}
上面的英文注释已经说得很清楚了,这里我还是解释一下吧:
首先是错误的改法 System.out.println(new String (strLine.getBytes(),"iso8859-1"));
这句代码是将strLine中的字符串用系统默认的编码方式(这里是gb2312)
转换为字节序列,然后用指定的编码方式(这里是iso8859-1)构造一个新的
String对象,并打印到屏幕上。
错误在哪里呢?
请注意这一段代码:
InputStreamReader isr = new InputStreamReader(System.in,"iso8859-1");
BufferedReader br = new BufferedReader (isr);
String strLine = br.readLine();
这里strLine存储的内容是用指定的编码方式( iso8859-1 )存储的,而转换成字节码的时候(这句代码 strLine.getBytes() )却使用了系统默认的gb2312编码,所以当然就输出乱码了!然后用gb2312编码的字节序列构建新的String对象的时候又使用了 iso8859-1编码,所以输出的乱码和 System.out.println(strLine) 有所不同。 至于正确的改法就不用详细说明了吧,首先将strLine用iso8859-1编码方式转换成字节序列,然后用系统默认的编码方式(gb2312)构建新的String对象,然后打印输出。
2. 学生问: 使用Java操作文本文件的方法详解?
老师解答: 最初java是不支持对文本文件的处理的,为了弥补这个缺憾而引入了Reader和Writer两个类,这两个类都是抽象类,Writer中write(char[] ch,int off,int length),flush()和close()方法为抽象方法,Reader中read(char[] ch,int off,int length)和close()方法是抽象方法。子类应该分别实现他们。
当我们读写文本文件的时候,采用Reader是非常方便的,比如FileReader,InputStreamReader和BufferedReader。其中最重要的类是InputStreamReader,它是字节转换为字符的桥梁。你可以在构造器重指定编码的方式,如果不指定的话将采用底层操作系统的默认编码方式,例如GBK等。当使用FileReader读取文件的时候。
FileReader fr = new FileReader("ming.txt");
int ch = 0;
while((ch = fr.read())!=-1 )
{
System.out.print((char)ch);
}
其中read()方法返回的是读取得下个字符。当然你也可以使用read(char[] ch,int off,int length)这和处理二进制文件的时候类似,不多说了。如果使用InputStreamReader来读取文件的时候
while((ch = isr.read())!=-1)
{
System.out.print((char)ch);
}
这和FileReader并没有什么区别,事实上在FileReader中的方法都是从InputStreamReader中继承过来的。read()方法是比较好费时间的,如果为了提高效率我们可以使用BufferedReader对Reader进行包装,这样可以提高读取得速度,我们可以一行一行的读取文本,使用readLine()方法。
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("ming.txt")));
String data = null;
while((data = br.readLine())!=null)
{
System.out.println(data);
}
当你明白了如何用Reader来读取文本文件的时候那么用Writer写文件同样非常简单。有一点需要注意,当你写文件的时候,为了提高效率,写入的数据会先放入缓冲区,然后写入文件。因此有时候你需要主动调用flush()方法。与上面对应的写文件的方法为:
FileWriter fw = new FileWriter("hello.txt");
String s = "hello world";
fw.write(s,0,s.length());
fw.flush();
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("hello2.txt"));
osw.write(s,0,s.length());
osw.flush();
PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream("hello3.txt")),true);
pw.println(s);
不要忘记用完后关闭流!下面是个小例子,帮助新手理解。其实有的时候java的IO系统是需要我们多记记的,不然哪天就生疏了。
hello world i like java language
import java.io.*;
public class TestFile2
{
public static void main(String[] args) throws IOException
{
FileReader fr = new FileReader("ming.txt");
char[] buffer = new char[1024];
int ch = 0;
while((ch = fr.read())!=-1 )
{
System.out.print((char)ch);
}
InputStreamReader isr = new InputStreamReader(new FileInputStream("ming.txt"));
while((ch = isr.read())!=-1)
{
System.out.print((char)ch);
}
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("ming.txt")));
String data = null;
while((data = br.readLine())!=null)
{
System.out.println(data);
}
FileWriter fw = new FileWriter("hello.txt");
String s = "hello world";
fw.write(s,0,s.length());
fw.flush();
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("hello2.txt"));
osw.write(s,0,s.length());
osw.flush();
PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream("hello3.txt")),true);
pw.println(s);
fr.close();
isr.close();
br.close();
fw.close();
osw.close();
pw.close();
}
}
3. 学生问: JAVA开放源码项目与工具在企业应用开发中的运用?
老师解答:业应用开发目前面临的主要问题
企业应用是指服务于商业目的,处理企业业务信息、数据的软件系统。虽然随着dot COM热潮逐渐冷却,企业开始谨慎考虑自己在应用系统开发方面的投入,但是毕竟企业的业务流程需要专门的信息系统处理,从而提高自动化程度、减少中间环节、加快信息处理速度。因此,目前国内的企业应用项目开发还是日益火爆,尤其在电子政务、CRM、SCM等领域更是如此。
但是,不论企业应用开发是采用自行开发或者委托系统集成商进行开发,都存在着下面一些情况:
大部分项目超时或者超出预算;
项目在部署以后BUG很多,而且修改的周期比较长; 对于系统集成商来说,下面的情况更是比较普遍:
没有统一的FRAMEWORK,每个项目都会重新设计ARCHITECTURE;
项目开发过程的自动化程度和重复步骤不是很多,人为引入的BUG很多;
开放源码项目现状
开放源码运动在90年代开始日益发展,目前已经成为软件业内不可低估的一股势力,比较著名的有Linux,、Apache、Tomcat、MySQL等。目前,开放源码的潮流已经超出了操作系统、数据库管理系统和WEB服务器等系统开发领域,开发在企业应用开发中寻找新的领地。尤其是对于企业应用开发的框架和CASE工具,开放源码项目都有很优秀的解决方案。
国外开放源码项目的集中地有 www.apache.org 以及 www.sourceforge.net ,其中,前者为大家奉献了著名的Apache、Tomcat、Struts、Axis;而后者是最著名的开源项目中心。同时,国内自90年代末开始也有很多人投入到开源项目的开发,比较集中的网址是 "共创软件联盟"( www.cosoft.org.cn ) 等等,他们除了提供各种CASE工具以外,还有一些项目是专注于特定领域的解决方案开发,如CRM等。
JAVA开发源码项目与工具的应用
对于目前企业应用开发竞争日益激烈,需求变更频繁,各个系统集成商都面临巨大的生存压力。其中有两个方面表现尤其突出:
没有统一的软件开发过程或者照搬重量级的软件开发过程,例如RUP等,但是往往由于时间等压力的影响,并不能切实执行;
大部分企业仍然没有摆脱手工作坊期间的做法,每个项目或者产品由于管理人员或者团队的不同,重新设计系统框架,浪费大量的时间在结构验证与调整上;
企业应用系统的开发中,需求的变更是项目中唯一不变的东西,而且,为了保持开发的一致性和利益最大化,系统集成商需要与客户保持长期的合作。因此,采取演进式敏捷软件开发,可以更好的保证项目质量。在所有的敏捷软件开发方法中,XP是目前应用最为广泛的一种。它是一种高度动态的过程,它通过非常短的迭代周期来应对需求的变化;沟通、简单、反馈和勇气是它的四大核心价值。同时,它集中了业界的很多最佳实践,目前已经有18条之多,XP强调通过严格执行全部的最佳实践来获得"极限"效果。
同时,出于复用和效率的考虑,尤其是对于系统集成商,企业应用系统应该具有自己的框架和结构。拥有具有良好性能、经过项目验证的系统框架,结合有效的软件开发过程,系统集成商可以快速、成功地开发企业应用系统。
为了更好的开发成功的系统,系统集成商们可以试着从以下两个方面着手解决问题:
结合开源工具的支持,在组织内部实施"敏捷软件开发方法";
为核心业务领域建立灵活、有效的Framework;
由于目前很多企业应用是采用基于J2EE技术的网络应用程序开发,因此,下面主要介绍基于JAVA的开源项目、工具的应用。
1. 开源工具与XP
XP的12条最佳实践,对于所有的企业应用开发商而言,由于组织和文化的不同,不可能全部应用,但是,下面几个实践是有条件逐步实施的:
代码规范:CODE STANDARD
测试驱动开发:TEST-DRIVEN DEVELOPMENT
日构建:DAILY BUILDING
持续集成:CONTINUOUS INTEGRATION
小步发布:SMALL RELEASE
每日晨会:DAILY MEETING
每周40小时工作:40-HOURS A WEEK
其中,CODE STANDARD和TDD是CONTINUOUS INTEGRATION、DAILY BUILDING和SMALL RELEASE的基础;而DAILY MEETING和40-HOURS A WORK是单独的实践过程,可以与其他的实践想结合,增强项目小组的沟通,激发士气。
需要说明的是以上最佳实践并非XP所独有,而是被最多的软件开发方法所应用,其中"日构建"就在微软的软件开发方法中正式出现过。
代码规范
虽然大部分的企业在一定程度上推行代码标准与规范,而且对于使用JAVA的应用程序开发,也有SUN的推荐编码规范,但是,实际的情况并不理想。
主要的原因在于:一方面,开发人员的习惯势力很大;另一方面,代码审查的力度不够。如果能够借助工具,从一定程度上帮助进行代码标准的执行情况检查,那么代码审查就可以着重检查程序的逻辑和性能等方面。
开源产品CheckStyle ( http://sourceforge.net/projects/checkstyle ) 可以帮助开发组织解决代码标准审查的问题。
目前的最新版本为3.0,它提供了两种运行方式:一种是命令行;一种是与Ant结合(Ant自1.5以后提供的OPTIONAL TASKS中有对于CheckStyle的支持)。同时,SourceForge中有对于JBuilder等流行IDE的插件支持,可以定义Global、Project级别上的属性文件, 但是,目前只是支持2.42版本。
在3.x版本之前,CheckStyle的配置信息写在Property File中;而在3.x之后,配置信息为XML文件,配置更加灵活。3.0的发布版本中提供了针对Sun Code Conventions的特定Check File,可以参考使用。
建议执行情况:
手动执行:开发人员在IDE中手动触发CheckStyle检查或者代码审查时由审查者手动执行;
自动执行:将CheckStyle与源码控制系统(CVS)结合,在源码Checkin的时候进行规则判断,如果不符合,则不允许代码进入系统。
测试驱动开发
测试先行或者测试驱动是XP的基本实践之一,同时测试在软件开发中的重要作用正越来越得到人们的重视。审查和测试作为系统确认和验证的有效方式,是项目质量保证的重要措施。
下面按照一般的测试分类,介绍各个领域内的开源测试工具:
单元测试:JUnit ( http://www.junit.org )
JUnit是由 Erich Gamma 和 Kent Beck 编写的一个回归测试框架(regression testing framework),用于Java开发人员编写单元测试之用。下面介绍的开源测试工具,很多都是对于JUnit的扩展。
它目前的版本为3.7,为编写单元测试提供了主要的接口。目前主流的IDE都提供了对于JUnit的支持。
XP强调测试先行,尤其重视单元测试。系统集成商需要通过软件开发过程的执行,来强化JUnit的使用。
目前很多商业测试软件都提供了与JUnit的联合使用,例如获得1999和2000年Jolt测试类工具亚军和生产率大奖的Jtest (ParaSoft公司产品,内置200余条编码规范,提供Java代码静态和动态检查,同时还可以自动生成简单的测试用例等等)就可以导入和导出JUnit的测试用例。
集成与功能测试:HttpUnit ( http://unit.sourceforge.net ) & Cactus ( http://jakarta.apache.org/cactus/ )
HttpUnit是一套通过HTTP连接测试Web应用程序的Java类。在结合JUnit的情况下,HttpUnit可以作为一种创建测试程序的强大工具用来保证Web应用程序正常的端对端功能。
虽然JUnit自身就可以通过编写单一类的测试程序对服务器端Java代码进行测试,不过,有了HttpUnit的帮助,JUnit就可以扩展为模拟Web浏览器-Web服务器的工作方式对整个Web程序结构进行测试。
Cactus为我们提供了一种测试SERVLET等WEB组件的有效手段。它是JUnit的一个扩展,但是它又和JUnit有一些不同。Cactus的测试分为三种不同的测试类别,JspTestCase, ServletTestCase, FilterTestCase, 而不是像JUnit就一种TestCase。Cactus的测试代码有服务器端和客户端两个部分,他们协同工作。
一般意义上,可以采用Cactus作集成测试;而使用HttpUnit做功能测试。
虽然在集成与功能测试方面,有很多优秀的开源工具,但是在实际应用过程中,还是采用商业测试软件的比较多,对于复杂应用更是如此。这是因为集成与功能测试大部分还是由专门的测试人员进行,而他们对于已有的商业软件,例如Rational Robot、E-Test Suite、WinRunner等都比较熟悉,同时商业软件也提供了更为强大的功能。
压力与性能测试: JMeter ( http://jakarta.apache.org/jmeter/ )
由于企业应用越来越复杂,用户数量也是越来越多,系统的性能参数以及众多的非功能性需求在开发中获得了越来越多的重视。因此,很多压力与性能测试工具也开始出现,这其中有一定影响的是Apache Software Foundation的JMeter。
JMeter是100%的JAVA桌面应用,用来测试系统的负载与性能。它最开始设计是用来测试WEB应用,后来加以扩展,可以测试Http,FTP,支持JDBC的关系型数据库的性能与压力。同时,JMeter提供一定的定制功能,系统集成商可以自行开发针对EJB、CORBA或者SOAP的插件。
压力与性能测试方面,由于测试比较复杂,实际企业应用测试中,也是采用商业测试软件比较多,例如LoadRunner、JProbe Suite以及与JBuilder8 同步发布的OptimizerIT;
日构建
在软件开发的领域里有各种各样的"最佳实践",它们经常被人们谈起,但是似乎很少有真正得到实现的。这些实践最基本、最有价值的就是:都有一个完全自动化的创建、测试过程,让开发团队可以每天多次创建他们的软件。
"日创建"也是人们经常讨论的一个观点,McConnell在他的《快速软件开发》中将日创建作为一个最佳实践来推荐,同时日创建也是微软很出名的一项开发方法。但是,我们更支持XP社群的观点:日创建只是最低要求。一个完全自动化的过程让你可以每天完成多次创建,这是可以做到的,也是完全值得的。
Ant是Apache Jakarta的一个项目,是"不带 make 缺点的 make"。Ant 正在成为开放源代码世界中实际上的标准。原因很简单:Ant 是使用 Java 语言编写的,这种语言可以让创建过程在多种平台上使用。
Ant目前的版本为1.5,它的执行是基于一个XML文件,配置文件由目标树构成。每个目标都包含了要执行的任务,其中任务就是可以执行的代码。在下面给出的例子中,mkdir 是目标 compile 的任务。mkdir 是建立在 Ant 中的一个任务,用于创建目录。 Ant 带有一套健全的内置任务,也可以通过扩展 Ant 任务类来添加自己的功能。
4. 学生问: Java学习从入门到精通?
老师解答: 每个人的学习方法是不同的,一个人的方法不见得适合另一个人,我只能是谈自己的学习方法。因为我学习 Java 是完全自学的,从来没有问过别人,所以学习的过程基本上完全是自己摸索出来的。我也不知道这种方法是否是比较好的方法,只能给大家提供一点参考了。
学习 Java 的第一步是安装好 JDK ,写一个 Hello J World , 其实 JDK 的学习没有那么简单,关于 JDK 有两个问题是很容易一直困扰 Java 程序员的地方:一个是 CLASSPATH 的问题,其实从原理上来说,是要搞清楚 JRE 的 ClassLoader 是如何加载 Class 的;另一个问题是 package 和 import 问题,如何来寻找类的路径问题。把这两个问题摸索清楚了,就扫除了学习 Java 和使用 JDK 的最大障碍。推荐看一下王森的《 Java 深度历险》,对这两个问题进行了深入的探讨。
第二步是学习 Java 的语法。 Java 的语法是类 C++ 的,基本上主流的编程语言不是类 C ,就是类 C++ 的,没有什么新东西,所以语法的学习,大概就是半天的时间足够了。唯一需要注意的是有几个不容易搞清楚的关键字的用法, public , protected , private , static ,什么时候用,为什么要用,怎么用,这可能需要有人来指点一下,我当初是完全自己琢磨出来的,花了很久的时间。不过后来我看到《 Thinking in Java 》这本书上面是讲了这些概念的。
第三步是学习 Java 的面向对象的编程语言的特性的地方。比如继承,构造器,抽象类,接口,方法的多态,重载,覆盖, Java 的异常处理机制。对于一个没有面向对象语言背景的人来说,我觉得这个过程需要花很长很长时间,因为学习 Java 之前没有 C++ 的经验,只有 C 的经验,我是大概花了一个月左右吧,才彻底把这些概念都搞清楚,把书上面的例子反复的揣摩,修改,尝试,把那几章内容反复的看过来,看过去,看了不下 5 遍,才彻底领悟了。不过我想如果有 C++ 经验的话,应该一两天时间足够了。那么在这个过程中,可以多看看《 Thinking in Java 》这本书,对面向对象的讲解非常透彻。可惜的是我学习的时候,并没有看到这本书,所以自己花了大量的时间,通过自己的尝试和揣摩来学会的。
第四步就是开始熟悉 Java 的类库。 Java 的基础类库其实就是 JDK 安装目录下面 jre\lib\rt.jar 这个包。学习基础类库就是学习 rt.jar 。基础类库里面的类非常非常多。据说有 3000 多个,我没有统计过。但是真正对于我们来说最核心的只有 4 个,分别是
java.lang.*;
java.io.*;
java.util.*;
java.sql.*;
这四个包的学习,每个包的学习都可以写成一本厚厚的教材,而 O'reilly 也确实是这样做的。我觉得如果时间比较紧,是不可能通过读四本书来学习。我觉得比较好的学习方法是这样的:
首先要通读整个 package 的框架,了解整个 package 的 class , interface , exception 的构成,最好是能够找到介绍整个包框架的文章。这些专门介绍包的书籍的前几章应该就是这些总体的框架内容介绍。
对包整体框架的把握并不是要熟悉每个类的用法,记住它有哪些属性,方法。想记也记不住的。而是要知道包有哪些方面的类构成的,这些类的用途是什么,最核心的几个类分别是完成什么功能的。我在给人培训的时候一般是一次课讲一个包,所以不可能详细的介绍每个类的用法,但是我反复强调,我给你们讲这些包的不是要告诉你们类的方法是怎么调用的,也不要求你们记住类的方法调用,而是要你们了解, Java 给我们提供了哪些类,每个类是用在什么场合,当我遇到问题的时候,我知道哪个类,或者哪几个类的组合可以解决我的问题, That'all !,当我们具体写程序的时候,只要你知道该用哪个类来完成你的工作就足够了。编码的时候,具体的方法调用,是边写代码,边查 Documentation ,所有的东西都在 Documentation 里面,不要求你一定记住,实际你也记不住 3000 多个类的总共将近 10 万个方法调用。所以对每个包的总体框架的把握就变得极为重要。
第五步,通过上面的学习,如果学的比较扎实的话,就打好了 Java 的基础了,剩下要做的工作是扫清 Documentation 里面除了上面 4 个包之外的其他一些比较有用处的类。相信进展到这一步, Java 的自学能力已经被培养出来了,可以到了直接学习 Documentation 的水平了。除了要做 GUI 编程之外, JDK 里面其他会有用处的包是这些:
java.text.*;
java.net.*;
javax.naming.*;
这些包里面真正用的比较多的类其实很少,只有几个,所以不需要花很多时间。
第六步, Java Web 编程
Web 编程的核心是 HTTP 协议, HTTP 协议和 Java 无关,如果不熟悉 HTTP 协议的话,虽然也可以学好 Servlet/JSP 编程,但是达不到举一反三,一通百通的境界。所以 HTTP 协议的学习是必备的。如果熟悉了 HTTP 协议的话,又有了 Java 编程的良好的基础,学习 Servlet/JSP 简直易如反掌,我学习 Servlet/JSP 就用了不到一周的时间,然后就开始用 JSP 来做项目了。
在 Servlet/JSP 的学习中,重头仍然是 Servlet Documentation 。 Servlet API 最常用的类很少,花比较少的时间就可以掌握了。把这些类都看一遍,多写几个例子试试。 Servlet/JSP 编程本质就是在反复调用这些类来通过 HTTP 协议在 Web Server 和 Brower 之间交谈。另外对 JSP ,还需要熟悉几个常用 JSP 的标记,具体的写法记不住的话,临时查就是了。
此外 Java Web 编程学习的重点要放在 Web Application 的设计模式上,如何进行业务逻辑的分析,并且进行合理的设计,按照 MVC 设计模式的要求,运用 Servlet 和 JSP 分别完成不同的逻辑层,掌握如何在 Servlet 和 JSP 之间进行流程的控制和数据的共享,以及 Web Application 应该如何配置和部署。
第七步, J2EE 编程
以上的学习过程如果是比较顺利的话,进行到这一步,难度又陡然提高。因为上面的知识内容都是只涉及一个方面,而像 EJB , JMS , JTA 等核心的 J2EE 规范往往是几种 Java 技术的综合运用的结晶,所以掌握起来难度比较大。
首先一定要学习好 JNDI , JNDI 是 App Server 定位服务器资源( EJB 组件, Datasouce , JMS )查找方法,如果对 JNDI 不熟悉的话, EJB , JMS 这些东西几乎学不下去。 JNDI 其实就是 javax.naming.* 这个包,运用起来很简单。难点在于服务器资源文件的配置。对于服务器资源文件的配置,就需要看看专门的文档规范了,比如 web.xml 的写法, ejb-jar.xml 的写法等等。针对每种不同的 App Server ,还有自己的服务资源配置文件,也是需要熟悉的。
然后可以学习 JTA ,主要是要理解 JTA 对于事务的控制的方法,以及该在什么场合使用 JTA 。这里可以简单的举个例子,我们知道一般情况可以对于一个数据库连接进行事务控制 (conn.setAutoCommit(false),....,conn.commit()) ,做为一个原子操作,但是假设我的业务需求是要把对两个不同数据库的操作做为一个原子操作,你能做的到吗?这时候只能用 JTA 了。假设操作过程是先往 A 数据库插一条记录,然后删除 B 数据库另一个记录,我们自己写代码是控制不了把整个操作做为一个原子操作的。用 JTA 的话,由 App Server 来完成控制。
在学习 EJB 之前要学习对象序列化和 RMI , RMI 是 EJB 的基础。接着学习 JMS 和 EJB ,对于 EJB 来说,最关键是要理解 EJB 是如何通过 RMI 来实现对远端对象的调用的,以及在什么情况下要用到 EJB 。
在学习完 EJB , JMS 这些东西之后,你可能会意识到要急不可待学习两个领域的知识,一个是 UML ,另一个是 Design Pattern 。 Java 企业软件的设计非常重视框架 (Framework) 的设计,一个好的软件框架是软件开发成功的必要条件。在这个时候,应该开始把学习的重点放在设计模式和框架的学习上,通过学习和实际的编程经验来掌握 EJB 的设计模式和 J2EE 的核心模式。
J2EE 规范里面,除了 EJB , JMS , JTA , Servlet/JSP , JDBC 之外还有很多很多的企业技术,这里不一一进行介绍了。
另外还有一个最新领域 Web Services 。 Web Services 也完全没有任何新东西,它像是一种黏合剂,可以把不同的服务统一起来提供一个统一的调用接口,作为使用者来说,我只要获得服务提供者给我的 WSDL (对服务的描述),就够了,我完全不知道服务器提供者提供的服务究竟是 EJB 组件,还是 .Net 组件,还是什么 CORBA 组件,还是其他的什么实现,我也不需要知道。 Web Services 最伟大的地方就在于通过统一的服务提供方式和调用方式,实现了整个 Internet 服务的共享,是一个非常令人激动的技术领域。 Web Services 好像目前还没有什么很好的书籍,但是可以通过在网络上面查资料的方式来学习。
方法篇
Java 作为一门编程语言,最好的学习方法就是写代码。当你学习一个类以后,你就可以自己写个简单的例子程序来运行一下,看看有什么结果,然后再多调用几个类的方法,看看运行结果,这样非常直观的把类给学会了,而且记忆非常深刻。然后不应该满足把代码调通,你应该想想看如果我不这样写,换个方式,再试试行不行。记得哪个高人说过学习编程就是个破坏的过程,把书上的例子,自己学习 Documentation 编写的例子在运行通过以后,不断的尝试着用不同的方法实现,不断的尝试破坏代码的结构,看看它会有什么结果。通过这样的方式,你会很彻底的很精通的掌握 Java 。
举个例子,我们都编过 Hello World
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World");
}
}
很多初学者不是很理解为什么 main 方法一定要这样来定义 public static void main(String[] args) ,能不能不这样写?包括我刚学习 Java 的时候也有这样的疑问。想知道答案吗?很简单,你把 main 改个名字运行一下,看看报什么错误,然后根据出错信息进行分析;把 main 的 public 取掉,在试试看,报什么错误; static 去掉还能不能运行;不知道 main 方法是否一定要传一个 String[] 数组的,把 String[] 改掉,改成 int[] ,或者 String 试试看;不知道是否必须写 args 参数名称的,也可以把 args 改成别的名字,看看运行结果如何。
我当初学习 Java 的时候就是这样做的,把 Hello World 程序反复改了七八次,不断运行,分析运行结果,最后就彻底明白为什么了 main 方法是这样定义的了。
此外,我对于 staic , public , private , Exception , try{ }catch {}finally{} 等等等等一开始都不是很懂,都是把参考书上面的例子运行成功,然后就开始破坏它,不断的根据自己心里面的疑问来重新改写程序,看看能不能运行,运行出来是个什么样子,是否可以得到预期的结果。这样虽然比较费时间,不过一个例子程序这样反复破坏几次之后。我就对这个相关的知识彻底学通了。有时候甚至故意写一些错误的代码来运行,看看能否得到预期的运行错误。这样对于编程的掌握是及其深刻的。
其中特别值得一提的是 JDK 有一个非常棒的调试功能, -verbose
java –verbose
javac –verbose 以及其它很多 JDK 工具都有这个选项
-verbose 可以显示在命令执行的过程中, JVM 都依次加载哪里 Class ,通过这些宝贵的调试信息,可以帮助我们分析出 JVM 在执行的过程中都干了些什么。
另外,自己在学习过程中,写的很多的这种破坏例程,应该有意识的分门别类的保存下来,在工作中积累的典型例程也应该定期整理,日积月累,自己就有了一个代码库了。遇到类似的问题,到代码库里面 Copy & Paste , Search & Replace ,就好了,极大提高了开发速度。最理想的情况是把一些通用的例程自己再抽象一层,形成一个通用的类库,封装好。那么可复用性就更强了。
所以我觉得其实不是特别需要例程的,自己写的破坏例程就是最好的例子,如果你实在对自己写的代码不放心的话,我强烈推荐你看看 JDK 基础类库的 Java 源代码。在 JDK 安装目录下面会有一个 src.zip ,解开来就可以完整的看到整个 JDK 基础类库,也就是 rt.jar 的 Java 源代码,你可以参考一下 Sun 是怎么写 Java 程序的,规范是什么样子的。我自己在学习 Java 的类库的时候,当有些地方理解的不是很清楚的时候,或者想更加清晰的理解运作的细节的时候,往往会打开相应的类的源代码,通过看源代码,所有的问题都会一扫而空。 |