??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲精品成人片在线播放,亚洲乱码国产一区网址,亚洲av中文无码乱人伦在线观看 http://www.tkk7.com/licheng700/zh-cnSat, 10 May 2025 16:12:14 GMTSat, 10 May 2025 16:12:14 GMT60存取E序状态的几种Ҏ——Java I/O应用杂谈 (Jungleford's Home Blog?http://www.tkk7.com/licheng700/archive/2005/09/28/14272.htmlv?/dc:creator>v?/author>Wed, 28 Sep 2005 02:09:00 GMThttp://www.tkk7.com/licheng700/archive/2005/09/28/14272.htmlhttp://www.tkk7.com/licheng700/comments/14272.htmlhttp://www.tkk7.com/licheng700/archive/2005/09/28/14272.html#Feedback0http://www.tkk7.com/licheng700/comments/commentRss/14272.htmlhttp://www.tkk7.com/licheng700/services/trackbacks/14272.html 

jungleford如是?/STRONG>

    已经有一个多月没有搭理blog了,原因很多Q譬如实验室的项目正在收工,巨忙Q譬如找工作及其相关的事情;而且二月份大部分旉是陪老爹老妈Q家里拨L速度可想而知……但主要q是没有扑ֈ一个合适的topicQ或者说q段旉懒了Q毕业前期l合症)Q净在看《汉武大帝》和历史斚w的书Q还有其它ؕ七八p的闲书Q就是没有认真地玩JavaQ哈哈!现在工作差不多落实了Q好在不太烂,资青年jungleford的生zd开始步入正轨了Q以上是新年里的一些废话?BR>    今天E微聊一点关于“程序状态保存”方面的问题Q我们很Ҏ׃惛_?STRONG>序列?/STRONG>”(SerializationQ有的书上又译为“顺序化”或者“串行化”,但“串行”一词L让我联想到通信和硬件接口,所以我更习惯于“序列化”的叫法Q何况这U叫法是有来头的Q后面我会谈?A href="http://www.tkk7.com/licheng700/jungleford/archive/2005/04/02/2763.html#1">q个名称的由?/FONT>Q,当然Q序列化是一U方便有效的数据存取方式Q但它还有更加广泛的应用。广义上Ԍ是讨论一下I/O的一些应用?

文gI/OQ文件流→序列化

?STRONG>文g?/STRONG>
    文g操作是最单最直接也是最Ҏ惛_的一U方式,我们说的文g操作不仅仅是通过FileInputStream/FileOutputStreamq么“裸”的方式直接把数据写入到本地文gQ像我以前写的一个扫L游戏JavaMine是q样保存一局的状态的Q,q样比较“底层”了?

主要cMҎ 描述
FileInputStream.read() 从本地文件读?STRONG>二进制格?/STRONG>的数?/FONT>
FileReader.read() 从本地文件读?STRONG>字符Q文本)数据
FileOutputStream.write() 保存二进制数据到本地文g
FileWriter.write() 保存字符数据到本地文?/FONT>

?STRONG>XML
    和上面的单纯的I/O方式相比QXML显得“高档”得多,以至于成ZU数据交换的标准。以DOM方式ZQ它兛_的是首先在内存中构造文档树Q数据保存在某个l点上(可以是叶子结点,也可以是标签l点的属性)Q构造好了以后一ơ性的写入到外部文Ӟ但我们只需要知道文件的位置Qƈ不知道I/O是怎么操作的,XML操作方式可能多数Z实践q,所以这里也只列出相关的ҎQ供初学者预先了解一下。主要的包是javax.xml.parsersQ?A target=_blank>org.w3c.domQ?A target=_blank>javax.xml.transform?

主要cMҎ 描述
DocumentBuilderFactory.newDocumentBuilder().parse() 解析一个外部的XML文gQ得C个Document对象的DOM?/FONT>
DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument() 初始化一DOM?/FONT>
Document.getDocumentElement(). appendChild() Z个标{Ҏ加一个子l点
Document.createTextNode() 生成一个字W串l点
Node.getChildNodes() 取得某个l点的所有下一层子l点
Node.removeChild() 删除某个l点的子l点
Document. getElementsByTagName() 查找所有指定名U的标签l点
Document.getElementById() 查找指定名称的一个标{点,如果有多个符合,则返回某一个,通常是第一?/FONT>
Element.getAttribute() 取得一个标{某个属性的的?/FONT>
Element.setAttribute() 讄一个标{某个属性的的?/FONT>
Element.removeAttribute() 删除一个标{某个属?/FONT>
TransformerFactory.newInstance().newTransformer().transform() 一DOM树写入到外部XML文g

?STRONG>序列?/STRONG>
    使用基本的文件读写方式存取数据,如果我们仅仅保存相同cd的数据,则可以用同一U格式保存,譬如在我的JavaMine中保存一个盘局Ӟ需要保存每一个方格的坐标、是否有地雷Q是否被d{,q些信息l合成一个“复合类型”;相反Q如果有多种不同cd的数据,那我们要么把它分解成若干部分Q以相同cdQ譬如StringQ保存,要么我们需要在E序中添加解析不同类型数据格式的逻辑Q这很不方ѝ于是我们期望用一U比较“高”的层次上处理数据,E序员应?STRONG>花尽可能的旉和代码对数据q行解析Q事实上Q序列化操作为我们提供了q样一条途径?BR>    序列化(SerializationQ大家可能都有所接触Q它可以把对象以某种特定的编码格式写入或从外部字节流Q即ObjectInputStream/ObjectOutputStreamQ中d。序列化一个对象非怹单,仅仅实现一?A target=_blank>Serializable接口卛_Q甚至都不用为它专门dMҎQ?

public class MySerial implements java.io.Serializable
{
  ...
}

但有一个条Ӟ?STRONG>你要序列化的cd中,它的每个属性都必须是是“可序列化”的。这句话说v来有Ҏ口,其实所?STRONG>基本cdQ就是intQcharQboolean之类的)都是“可序列化”的Q而你可以看看JDK文档Q会发现很多cd实已l实CSerializableQ即已经是“可序列化”的了)Q于是这些类的对象以及基本数据类型都可以直接作ؓ你需要序列化的那个类的内部属性。如果碰C不是“可序列化”的属性怎么办?对不P那这个属性的c还需要事先实现Serializable接口Q如此递归Q?STRONG>直到所有属性都是“可序列化”的?

主要cMҎ 描述
ObjectOutputStream.writeObject() 一个对象序列化到外部字节流
ObjectInputStream.readObject() 从外部字节流dq新构造对?/FONT>

    从实际应用上看来Q“Serializable”这个接口ƈ没有定义MҎQ仿佛它只是一?STRONG>标记Q或者说像是Java的关键字Q而已Q一旦虚拟机看到q个“标记”,׃试调用自n预定义的序列化机?/STRONG>Q除非你在实现Serializable接口的同时还定义了私有的readObject()或writeObject()Ҏ。这一点很奇怪。不q你要是不愿意让pȝ使用~省的方式进行序列化Q那必d义上面提到的两个ҎQ?

public class MySerial implements java.io.Serializable
{
  private void writeObject(java.io.ObjectOutputStream out) throws IOException
  {
    ...
  }
  private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException
  {
    ...
  }
  ...
}

    譬如你可以在上面的writeObject()里调用默认的序列化方法ObjectOutputStream.defaultWriteObject();譬如你不愿意某些敏感的属性和信息序列化,你也可以调用ObjectOutputStream.writeObject()Ҏ明确指定需要序列化那些属性。关于用?A href="http://www.tkk7.com/licheng700/jungleford/archive/2005/04/02/2763.html#4">可定制的序列化方?/FONT>Q我们将在后面提到?

?STRONG>Bean
    上面的序列化只是一U基本应用,你把一个对象序列化到外部文件以后,用notepad打开那个文gQ只能从为数不多的一些可dW中猜到q是有关q个cȝ信息文gQ这需要你熟悉序列化文件的字节~码方式Q那是比较痛苦的(?A target=_blank>《Core Java 2》第一?/FONT>里提C相关~码方式Q有兴趣的话可以查看参考资?/FONT>Q,某些情况下我们可能需要被序列化的文gh更好的可L。另一斚wQ作为Javalg的核心概念?A target=_blank>JavaBeans”,从JDK 1.4开始,其规范里也要求支持文本方式的?STRONG>长期的持久化”(long-term persistenceQ?BR>    打开JDK文档Q?A target=_blank>java.beans?/FONT>里的有一个名为?A target=_blank>Encoder”的c,q就是一个可以序列化bean的实用类。和它相关的两个主要cLXMLEcoder?A target=_blank>XMLDecoderQ显Ӟq是以XML文g的格式保存和dbean的工兗他们的用法也很单,和上面ObjectOutputStream/ObjectInputStream比较cM?

主要cMҎ 描述
XMLEncoder.writeObject() 一个对象序列化到外部字节流
XMLDecoder.readObject() 从外部字节流dq新构造对?/FONT>

    如果一个bean是如下格式:

public class MyBean
{
  int i;
  char[] c;
  String s;
  ...(get和set操作省略)...
}

那么通过XMLEcoder序列化出来的XML文ghq样的Ş式:

<?xml version="1.0" encoding="UTF-8"?>
<java version="1.4.0" class="java.beans.XMLDecoder">
  <object class="MyBean">
    <void property="i">
      <int>1</int>
    </void>
    <void property="c">
      <array class="char" length="3">
        <void index="0">
          <int>a</int>
        </void>
        <void index="1">
          <int>b</int>
        </void>
        <void index="2">
          <int>c</int>
        </void>
      </array>
    </void>
    <void property="s">
      <string>fox jump!</string>
    </void>
  </object>
</java>

    ?A target=_blank>AWT?A target=_blank>Swing中很多可视化lg都是beanQ当然也是可以用q种方式序列化的Q下面就是从JDK文档中摘录的一?A target=_blank>JFrame序列化以后的XML文gQ?

<?xml version="1.0" encoding="UTF-8"?>
<java version="1.0" class="java.beans.XMLDecoder">
  <object class="javax.swing.JFrame">
    <void property="name">
      <string>frame1</string>
    </void>
    <void property="bounds">
      <object class="java.awt.Rectangle">
        <int>0</int>
        <int>0</int>
        <int>200</int>
        <int>200</int>
      </object>
    </void>
    <void property="contentPane">
      <void method="add">
        <object class="javax.swing.JButton">
          <void property="label">
            <string>Hello</string>
          </void>
        </object>
      </void>
    </void>
    <void property="visible">
      <boolean>true</boolean>
    </void>
  </object>
</java>

    因此但你惌保存的数据是一些不是太复杂的类型的话,把它做成bean再序列化也不׃ؓ一U方便的选择?

?STRONG>Properties
    在以前我ȝ的一关于集合框架的文章里提到q,Properties是历史集合类的一个典型的例子Q这里主要不是介l它的集合特性。大家可能都l常接触一?STRONG>配置文gQ如Windows的ini文gQApache的conf文gQ还有Java里的properties文g{,q些文g当中的数据以“关键字-值”对的方式保存。?STRONG>环境变量”这个概念都知道吧,它也是一U“key-value”对Q以前也常常看到版上问“如何取得系l某某信息”之cȝ问题Q其实很多都保存在环境变量里Q只要用一?

System.getProperties().list(System.out);

p获得全部环境变量的列表:

-- listing properties --
java.runtime.name=Java(TM) 2 Runtime Environment, Stand...
sun.boot.library.path=C:\Program Files\Java\j2re1.4.2_05\bin
java.vm.version=1.4.2_05-b04
java.vm.vendor=Sun Microsystems Inc.
java.vendor.url=http://java.sun.com/
path.separator=;
java.vm.name=Java HotSpot(TM) Client VM
file.encoding.pkg=sun.io
user.country=CN
sun.os.patch.level=Service Pack 1
java.vm.specification.name=Java Virtual Machine Specification
user.dir=d:\my documents\目\eclipse\SWTDemo
java.runtime.version=1.4.2_05-b04
java.awt.graphicsenv=sun.awt.Win32GraphicsEnvironment
java.endorsed.dirs=C:\Program Files\Java\j2re1.4.2_05\li...
os.arch=x86
java.io.tmpdir=C:\DOCUME~1\cn2lx0q0\LOCALS~1\Temp\
line.separator=

java.vm.specification.vendor=Sun Microsystems Inc.
user.variant=
os.name=Windows XP
sun.java2d.fontpath=
java.library.path=C:\Program Files\Java\j2re1.4.2_05\bi...
java.specification.name=Java Platform API Specification
java.class.version=48.0
java.util.prefs.PreferencesFactory=java.util.prefs.WindowsPreferencesFac...
os.version=5.1
user.home=D:\Users\cn2lx0q0
user.timezone=
java.awt.printerjob=sun.awt.windows.WPrinterJob
file.encoding=GBK
java.specification.version=1.4
user.name=cn2lx0q0
java.class.path=d:\my documents\目\eclipse\SWTDemo\bi...
java.vm.specification.version=1.0
sun.arch.data.model=32
java.home=C:\Program Files\Java\j2re1.4.2_05
java.specification.vendor=Sun Microsystems Inc.
user.language=zh
awt.toolkit=sun.awt.windows.WToolkit
java.vm.info=mixed mode
java.version=1.4.2_05
java.ext.dirs=C:\Program Files\Java\j2re1.4.2_05\li...
sun.boot.class.path=C:\Program Files\Java\j2re1.4.2_05\li...
java.vendor=Sun Microsystems Inc.
file.separator=\
java.vendor.url.bug=http://java.sun.com/cgi-bin/bugreport...
sun.cpu.endian=little
sun.io.unicode.encoding=UnicodeLittle
sun.cpu.isalist=pentium i486 i386


主要cMҎ 描述
load() 从一个外部流d属?/FONT>
store() 属性保存到外部(特别是文Ӟ
getProperty() 取得一个指定的属?/FONT>
setProperty() 讄一个指定的属?/FONT>
list() 列出q个Properties对象包含的全部“key-value”对
System.getProperties() 取得pȝ当前的环境变?/FONT>

    你可以这样保存一个properties文gQ?

Properties prop = new Properties();
prop.setProperty("key1", "value1");
...
FileOutputStream out = new FileOutputStream("config.properties");
prop.store(out, "--q里是文件头Q可以加入注?-");

?STRONG>Preferences
    如果我说Java里面可以不用JNI的手D|作Windows的注册表你信不信Q很多Y件的菜单里都有“Setting”或“Preferences”这L选项用来讑֮或修改Y件的配置Q这些配|信息可以保存到一个像上面所q的配置文g当中Q如果是Windowsq_下,也可能会保存到系l注册表中。从JDK 1.4开始,Java?A target=_blank>java.util下加入了一个专门处理用户和pȝ配置信息?A target=_blank>java.util.prefs包,其中一个类Preferences是一U比较“高U”的玩意。从本质上讲QPreferences本n是一个与q_无关的东西,但不同的OS对它的SPIQService Provider InterfaceQ的实现却是与^台相关的Q因此,在不同的pȝ中你可能看到首选项保存为本地文件、LDAP目录V数据库条目{,像在Windowsq_下,它就保存Cpȝ注册表中。不仅如此,你还可以把首选项导出为XML文g或从XML文g导入?

主要cMҎ 描述
systemNodeForPackage() Ҏ指定的Class对象得到一个Preferences对象Q这个对象的注册表\径是从“HKEY_LOCAL_MACHINE\”开始的
systemRoot() 得到以注册表路径HKEY_LOCAL_MACHINE\SOFTWARE\Javasoft\Prefs 为根l点的Preferences对象
userNodeForPackage() Ҏ指定的Class对象得到一个Preferences对象Q这个对象的注册表\径是从“HKEY_CURRENT_USER\”开始的
userRoot() 得到以注册表路径HKEY_CURRENT_USER\SOFTWARE\Javasoft\Prefs 为根l点的Preferences对象
putXXX() 讄一个属性的|q里XXX可以为基本数值型cdQ如int、long{,但首字母大写Q表C参Cؓ相应的类型,也可以不写而直接用putQ参数则为字W串
getXXX() 得到一个属性的?/FONT>
exportNode() 全部首选项导出Z个XML文g
exportSubtree() 部分首选项导出Z个XML文g
importPreferences() 从XML文g导入首选项

    你可以按如下步骤保存数据Q?

Preferences myPrefs1 = Preferences.userNodeForPackage(this);// q种Ҏ是在“HKEY_CURRENT_USER\”下按当前类的\径徏立一个注册表?/SPAN>
Preferences myPrefs2 = Preferences.systemNodeForPackage(this);// q种Ҏ是在“HKEY_LOCAL_MACHINE\”下按当前类的\径徏立一个注册表?/SPAN>
Preferences myPrefs3 = Preferences.userRoot().node("com.jungleford.demo");// q种Ҏ是在“HKEY_CURRENT_USER\SOFTWARE\Javasoft\Prefs\”下按“com\jungleford\demo”的路径建立一个注册表?/SPAN>
Preferences myPrefs4 = Preferences.systemRoot().node("com.jungleford.demo");// q种Ҏ是在“HKEY_LOCAL_MACHINE\SOFTWARE\Javasoft\Prefs\”下按“com\jungleford\demo”的路径建立一个注册表?/SPAN>
myPrefs1.putInt("key1", 10);
myPrefs1.putDouble("key2", -7.15);
myPrefs1.put("key3", "value3");
FileOutputStream out = new FileOutputStream("prefs.xml");
myPrefs1.exportNode(out);

|络I/OQSocket→RMI

?STRONG>Socket
    Socket~程可能大家都很熟,所以就不多讨论了,只是说通过socket把数据保存到q端服务器或从网lsocketd数据也不׃ؓ一U值得考虑的方式?/P>

?STRONG>RMI
    RMI机制其实是RPCQ远E过E调用)的Java版本Q它使用socket作ؓ基本传输手段Q同时也是序列化最重要的一个应用。现在网l传输从~程的角度来看基本上都是以流的方式操?/STRONG>Qsocket是一个例子,对象{换成字节的一个重要目标就是ؓ了方便网l传输?BR>    惌一下传l的单机环境下的E序设计Q对于Java语言的函敎ͼҎQ调用(注意与C语言函数调用的区别)的参C递,会有两种情况Q如果是基本数据cdQ这U情况下和C语言是一LQ采?STRONG>g?/STRONG>方式Q如果是对象Q则传递的是对象的引用Q包括返回g是引用,而不是一个完整的对象拯Q试想一下在不同的虚拟机之间q行Ҏ调用Q即使是两个完全同名同类型的对象他们也很可能是不同的引用Q此外对于方法调用过E,׃被调用过E的压栈Q内存“现场”完全被被调用者占有,当被调用Ҏq回Ӟ才将调用者的地址写回到程序计数器QPCQ,恢复调用者的状态,如果是两个虚拟机Q根本不可能用简单压栈的方式来保存调用者的状态。因为种U原因,我们才需要徏立RMI通信实体之间的“代理”对象,譬如“存根”就相当于远E服务器对象在客h上的代理Qstub是q么来的Q当然这是后话了?BR>    本地对象与远E对象(未必是物理位|上的不同机器,只要不是在同一个虚拟机内皆为“远E”)之间传递参数和q回|可能有这么几U情形:

  • g递:q又包括两种子情形:如果是基本数据类型,那么都是“可序列化”的Q统l序列化成可传输的字节流Q如果是对象Q而且不是“远E对象”(所谓“远E对象”是实现了java.rmi.Remote接口的对象)Q本来对象传递的应该是引用,但由于上q原因,引用是不以证明对象w䆾的,所以传递的仍然?STRONG>一个序列化的拷?/STRONG>Q当然这个对象也必须满上述“可序列化”的条gQ?
  • 引用传递:可以引用传递的只能是“远E对象”。这里所谓的“引用”不要理解成了真的只是一个符P它其实是一个留在(客户机)本地stub中的Q和q端服务器上那个真实的对象张得一模一L镜像而已Q只是因为它有点“特权”(不需要经q序列化Q,在本地内存里已经有了一个实例,真正引用的其实是q个“孪生子”?
    由此可见Q序列化在RMI当中占有多么重要的地位?

数据库I/OQCMP、Hibernate

?STRONG>什么是“Persistence?/STRONG>
    用过VMWare的朋友大概都知道当一个guest OS正在q行的时候点几ZSuspend”将虚拟OS挂vQ它会把整个虚拟内存的内容保存到盘上,譬如你ؓ虚拟OS分配?28M的运行内存,那挂起以后你会在虚拟OS所在的目录下找C个同h128M的文Ӟq就是虚拟OS内存的完整镜像!q种内存的镜像手D其实就是“Persistence”(持久化)概念的由来?/P>

?STRONG>CMP和Hibernate
    因ؓ我对J2EE的东西不是太熟悉Q随便找了点材料看看Q所以担心说的不CQ这ơ就不作具体ȝ了,学习……真是一件痛苦的事情 

序列化再探讨

    从以上技术的讨论中我们不难体会到Q序列化是Java之所以能够出色地实现光吹的两大卖点——分布式QdistributedQ和跨^収ͼOS independentQ的一个重要基。TIJQ即?A target=_blank>Thinking in Java”)谈到I/OpȝӞ把序列化UCؓ“lightweight persistence”——“轻量的持久化”,q确实很有意思?/P>

?STRONG>Z么叫做“序列”化Q?/STRONG>
    开场白里我说更习惯于把“Serialization”称为“序列化”而不是“串行化”,q是有原因的。介l这个原因之前先回顾一些计机基本的知识,我们知道C计算机的内存I间都是U性编址的(什么是“线性”知道吧Q就是一个元素只有一个唯一的“前驱”和唯一的“后l”,当然头尾元素是个例外Q对于地址来说Q它的下一个地址当然不可能有两个Q否则就乱套了)Q“地址”这个概忉|q到数据l构Q就相当于“指针”,q个在本U低q大概q道了。注意了Q既然是U性的Q那“地址”就可以看作是内存空间的?STRONG>序号”,说明它的l织是有序的,“序号”或者说“序列号”正是“Serialization”机制的一U体现。ؓ什么这么说呢?譬如我们有两个对象a和b,分别是类A和B的实例,它们都是可序列化的,而A和B都有一个类型ؓC的属性,Ҏ前面我们说过?A href="http://www.tkk7.com/licheng700/jungleford/archive/2005/04/02/2763.html#2">原则QC当然也必L可序列化的?

import java.io.*;
...
class A implements Serializable
{
  C c;
  ...
}

class B implements Serializable
{
  C c;
  ...
}

class C implements Serializable
{
  ...
}

A a;
B b;
C c1;
...

    注意Q这里我们在实例化a和b的时候,有意让他们的c属性用同一个Ccd对象的引用,譬如c1Q那么请试想一下,但我们序列化a和b的时候,它们的c属性在外部字节(当然可以不仅仅是文gQ里保存的是一份拷贝还是两份拷贝呢Q序列化在这里用的是一U?STRONG>cM于“指针”的ҎQ它为每个被序列化的对象标上一个?STRONG>序列?/STRONG>”(serial numberQ,但序列化一个对象的时候,如果其某个属性对象是已经被序列化的,那么q里只向输出写入该属性的序列P从字节流恢复被序列化的对象时Q也Ҏ序列h到对应的来恢复。这是“序列化”名U的由来Q这里我们看到“序列化”和“指针”是极相似的Q只不过“指针”是内存I间的地址链,而序列化用的?STRONG>外部中的“序列号䏀?/STRONG>?BR>    使用“序列号”而不是内存地址来标识一个被序列化的对象Q是因ؓ从流中恢复对象到内存Q其地址可能未必是原来的地址了——我们需要的只是q些对象之间的引用关p,而不是死板的原始位置Q这在RMI中就更是必要Q在两台不同的机器之间传递对象()Q根本就不可能指望它们在两台机器上都h相同的内存地址?

?STRONG>更灵zȝ“序列化”:transient属性和Externalizable
    Serializable实很方便,方便C几乎不需要做M额外的工作就可以L内存中的对象保存到外部。但有两个问题得Serializable的威力收到束~:
    一个是效率问题Q《Core Java 2》中指出QSerializable使用pȝ默认的序列化机制会媄响Y件的q行速度Q因为需要ؓ每个属性的引用~号和查P再加上I/O操作的时_I/O和内存读写差的可是一个数量的大)Q其代h当然是可观的?BR>    另一个困扰是“裸”的Serializable不可定制Q傻乎乎C么都l你序列化了Q不你是不是想q么做。其实你可以有至三U定制序列化的选择。其中一U前面已l提CQ就是在implements Serializable的类里面dU有的writeObject()和readObject()ҎQ这USerializable׃怺Q?IMG height=19 src="http://www.tkk7.com/Emoticons/teeth_smile.gif" width=19 border=0>Q,在这两个Ҏ里,该序列化什么,不该序列化什么,那就׃说了了Q你当然可以在这两个Ҏ体里面分别调用ObjectOutputStream.defaultWriteObject()和ObjectInputStream.defaultReadObject()仍然执行默认的序列化动作Q那你在代码上不做无用功了Q呵呵)Q也可以用ObjectOutputStream.writeObject()和ObjectInputStream.readObject()Ҏ对你中意的属性进行序列化。但虚拟Z看到你定义了q两个方法,它就不再用默认的机制了?BR>    如果仅仅Z跌某些属性不让它序列化,上面的动作似乎显得麻烦,更简单的Ҏ是对不想序列化的属性加?SPAN class=style3>transient关键字,说明它是个“暂态变量”,默认序列化的时候就不会把这些属性也塞到外部里了。当Ӟ你如果定义writeObject()和readObject()Ҏ的化Q仍然可以把暂态变量进行序列化。题外话Q像transient?SPAN class=style3>violate?SPAN class=style3>finally?/FONT>assertq样的关键字初学者可能会不太重视Q而现在有的公司招聘就偏偏喜欢问这L问题
    再一个方案就是不实现Serializable而改成实?A target=_blank>Externalizable接口。我们研I一下这两个接口的源代码Q发现它们很cMQ甚臛_易؜淆。我们要C的是QExternalizable默认q?STRONG>不保存Q何对象相关信?/STRONG>QQ何保存和恢复对象的动作都是你自己定义的。Externalizable包含两个public的方法:

public void writeExternal(ObjectOutput out) throws IOException;
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;

    乍一看这和上面的writeObject()和readObject()几乎差不多,但Serializable和Externalizable走的是两个不同的程QSerializable在对象不存在的情况下Q就可以仅凭外部的字节序列把整个对象重徏出来Q但Externalizable在重建对象时Q先是调用该cȝ默认构造函敎ͼ即不含参数的那个构造函敎ͼ使得内存中先有这么一个实例,然后再调用readExternalҎ对实例中的属性进行恢复,因此Q如果默认构造函C和readExternalҎ中都没有赋值的那些属性,特别他们是非基本cd的话Q将会是I(nullQ。在q里需要注意的是,transient只能用在对Serializable而不是Externalizable的实现里?/STRONG>?

?STRONG>序列化与克隆
    从“可序列化”的递归定义来看Q一个序列化的对象貌似对象内存映象的外部克隆Q如果没有共享引用的属性的化,那么应该是一?STRONG>深度克隆。关于克隆的话题有可以谈很多Q这里就不细说了Q有兴趣的话可以参?A target=_blank>IBM developerWorks上的一文章:JAVA中的指针,引用及对象的clone

一点启C?/FONT>

    作ؓ一个实际的应用Q我在写那个易的邮g客户端JExp的时候曾l对比过好几U保存Message对象Q主要是几个关键属性和邮g的内容)到本地的ҎQ譬如XML、Properties{,最后还是选择了用序列化的方式Q因U方法最单, 大约可算是“学以致用”Ş。这里“存取程序状态”其实只是一个引子话题Ş了,我想说的是——就如同前面我们讨论的关于logging的话题一样——在Java面前对同一个问题你可以有很多种solutionQ熟悉文件操作的Q你可能会觉得Properties、XML或Bean比较方便Q然后又发现了还有Preferencesq么一个东东,大概又会感慨“天外有天”了Q等C接触了很多种新方法以后,l果又会“殊途同归”,重新反省Serialization机制本n。这不仅是JavaQ科学也是同L道理?



]]>
关于Java中文件流操作的一点知?/title><link>http://www.tkk7.com/licheng700/archive/2005/09/27/14191.html</link><dc:creator>v?/dc:creator><author>v?/author><pubDate>Tue, 27 Sep 2005 06:00:00 GMT</pubDate><guid>http://www.tkk7.com/licheng700/archive/2005/09/27/14191.html</guid><wfw:comment>http://www.tkk7.com/licheng700/comments/14191.html</wfw:comment><comments>http://www.tkk7.com/licheng700/archive/2005/09/27/14191.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.tkk7.com/licheng700/comments/commentRss/14191.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/licheng700/services/trackbacks/14191.html</trackback:ping><description><![CDATA[<STRONG>1。追加文件方?BR></STRONG>          1.java.io.FileWriter 的构造函CQ?A href="file:///F:/jdk_doc/jse1-4.2/docs/api/java/io/FileWriter.html#FileWriter(java.io.File, boolean)"><FONT face="Courier New">FileWriter</FONT></A><FONT face="Courier New">(</FONT><A title="class in java.io" href="file:///F:/jdk_doc/jse1-4.2/docs/api/java/io/File.html"><FONT face="Courier New">File</FONT></A><FONT face="Courier New"> file, boolean append)</FONT> <BR>          Constructs a FileWriter object given a File object.<BR> <DD><CODE>append</CODE> - if <CODE>true</CODE>, then bytes will be written to the end of the file rather than the beginning <BR><BR>         2.cjava.io.<B>RandomAccessFile</B> extends <A title="class in java.lang" href="file:///F:/jdk_doc/jse1-4.2/docs/api/java/lang/Object.html">Object</A> implements <A title="interface in java.io" href="file:///F:/jdk_doc/jse1-4.2/docs/api/java/io/DataOutput.html">DataOutput</A>, <A title="interface in java.io" href="file:///F:/jdk_doc/jse1-4.2/docs/api/java/io/DataInput.html">DataInput</A> 中方?BR>              <A href="file:///F:/jdk_doc/jse1-4.2/docs/api/java/io/RandomAccessFile.html#seek(long)"><STRONG><FONT face="Courier New">seek</FONT></STRONG></A><FONT face="Courier New">(long pos)当前操作指针移到文件末?<BR>2.关于隔行写入文g<STRONG>java.io.BufferedWritercM的方?/STRONG><A href="file:///F:/jdk_doc/jse1-4.2/docs/api/java/io/BufferedWriter.html#newLine()"><STRONG>newLine</STRONG></A>() <BR><BR></FONT></DD><BR><BR><img src ="http://www.tkk7.com/licheng700/aggbug/14191.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/licheng700/" target="_blank">v?/a> 2005-09-27 14:00 <a href="http://www.tkk7.com/licheng700/archive/2005/09/27/14191.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>log4jhttp://www.tkk7.com/licheng700/archive/2005/09/26/14129.htmlv?/dc:creator>v?/author>Mon, 26 Sep 2005 09:27:00 GMThttp://www.tkk7.com/licheng700/archive/2005/09/26/14129.htmlhttp://www.tkk7.com/licheng700/comments/14129.htmlhttp://www.tkk7.com/licheng700/archive/2005/09/26/14129.html#Feedback0http://www.tkk7.com/licheng700/comments/commentRss/14129.htmlhttp://www.tkk7.com/licheng700/services/trackbacks/14129.htmlLog4j 学习W记

ccjsmile (http://ijsp.net)

 

q是我在学习Log4j时做的一点笔讎ͼ希望对各位朋友有一点帮助。我?/SPAN>mail:ccjsmile@sohu.comQ希望能与您q行讨论^_*

 

Log4j 是一个开放源码项目,它是一个日志管理程序?/SPAN>

Log4j的优点:

1.       方便的调试信?/SPAN>;

2.       日志以各U丰富的Q主要是文gQŞ式保留,用于以后分析;

~点Q减慢程序运行速度.


(A) 其中Q?/SPAN>level 是日志记录的优先U,分ؓOFF?/SPAN>FATAL?/SPAN>ERROR?/SPAN>WARN?/SPAN>INFO?/SPAN>DEBUG?/SPAN>ALL或者您定义的别?/SPAN>Log4j只用四个别,优先U从高到低分别是ERROR?/SPAN>WARN?/SPAN>INFO?/SPAN>DEBUG。通过在这里定义的U别Q您可以控制到应用程序中相应U别的日志信息的开兟뀂比如在q里定义?/SPAN>INFOU别Q则应用E序中所?/SPAN>DEBUGU别的日志信息将不被打印出来?/SPAN>

appenderName是指定日志信息输出到哪个地斏V您可以同时指定多个输出目的地?/SPAN>

 

(B) 其中Q?/SPAN>Log4j提供?/SPAN>appender有以下几U:

org.apache.log4j.ConsoleAppenderQ控制台Q,

org.apache.log4j.FileAppenderQ文ӞQ?/SPAN>

org.apache.log4j.DailyRollingFileAppenderQ每天生一个日志文ӞQ?/SPAN>org.apache.log4j.RollingFileAppenderQ文件大到达指定尺寸的时候生一个新的文ӞQ?/SPAN>

org.apache.log4j.WriterAppenderQ将日志信息以流格式发送到L指定的地方)

 

(C) 其中Q?/SPAN>Log4j提供?/SPAN>layout有以下几U:

org.apache.log4j.HTMLLayoutQ以HTML表格形式布局Q,

org.apache.log4j.PatternLayoutQ可以灵zd指定布局模式Q,

org.apache.log4j.SimpleLayoutQ包含日志信息的U别和信息字W串Q,

org.apache.log4j.TTCCLayoutQ包含日志生的旉、线E、类别等{信息)

 

 

下面介绍一?/SPAN>log4j?/SPAN>web中应用的例子Q?/SPAN>

q是一个用?/SPAN>log4j初始化的servlet

 

package net.ijsp.log4j;

 

import org.apache.log4j.PropertyConfigurator;

import javax.servlet.http.HttpServlet;

import javax.servlet.ServletException;

 

public class InitLog4j extends HttpServlet {

 

  public  void init() throws ServletException  {

   PropertyConfigurator.configure("D:/resin/webapps/log4j/web-inf/classes/log4j.properties");

    System.out.println("ok");

  }

}

 

在上q文件中我们发现需要一?/SPAN>log4j.properties的文Ӟ他的存放路径为:D:/resin/webapps/log4j/web-inf/classes/log4j.properties

q个properties的文件内容如下:

#log4j.properties

#Set root logger level to DEBUG and its only appender to A1.

log4j.rootLogger=INFO,A1

#A1 is set to be a ConsoleAppender.

#log4j.appender.A1=org.apache.log4j.ConsoleAppender

       log4j.appender.A1=org.apache.log4j.RollingFileAppender

       log4j.appender.A1.File=example11.log

#A1 uses PatternLayout

       log4j.appender.A1.layout=org.apache.log4j.PatternLayout

       log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c \n- %m%n\n"

 

log4j.logger.ltestlog4j=INFO,A2

log4j.appender.A2=org.apache.log4j.ConsoleAppender

       log4j.appender.A2.layout=org.apache.log4j.PatternLayout

       log4j.appender.A2.layout.ConversionPattern=%d [%t] %-5p %c \n- %m%n\n"

 

#log4j.appender.A1.MaxFileSize=1000KB

# Keep one backup file

#log4j.appender.A1.MaxBackupIndex=1

 

因ؓq是一?/SPAN>servlet文gQ同时我们还要修?/SPAN>web.xml文g

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>

       <servlet>

              <servlet-name>log4jinit</servlet-name>

              <servlet-class>net.ijsp.log4j.InitLog4j</servlet-class>

              <load-on-startup>1</load-on-startup>

  </servlet>

</web-app>

 

下面q两个ؓ试文gQ?/SPAN>

package net.ijsp.log4j;

 

import org.apache.log4j.PropertyConfigurator;

import org.apache.log4j.Logger;

import javax.servlet.http.HttpServlet;

import javax.servlet.ServletException;

 

public class Test {

 

  public Test() {}

 

  static Logger logger =Logger.getRootLogger();

  static Logger logger1 = Logger.getLogger("ltestlog4j");

 

  public void t() {

    logger.error("sssssssssss");

    System.out.println(logger);

    logger1.error("kjdlfkj");

    System.out.println("ddddddddddddddd");

  }

}

 

 

<%@page import ="net.ijsp.log4j.*"%>

 

<%

Test t = new Test();

t.t();

%>



]]>
一D导数据的操?/title><link>http://www.tkk7.com/licheng700/archive/2005/09/26/14060.html</link><dc:creator>v?/dc:creator><author>v?/author><pubDate>Mon, 26 Sep 2005 01:38:00 GMT</pubDate><guid>http://www.tkk7.com/licheng700/archive/2005/09/26/14060.html</guid><wfw:comment>http://www.tkk7.com/licheng700/comments/14060.html</wfw:comment><comments>http://www.tkk7.com/licheng700/archive/2005/09/26/14060.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/licheng700/comments/commentRss/14060.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/licheng700/services/trackbacks/14060.html</trackback:ping><description><![CDATA[<P><BR>Last login: Fri Sep 23 14:37:23 2005 from 211.155.247.222<BR>Sun Microsystems Inc.   SunOS 5.9       Generic May 2002<BR>[iplanet@ec2 sunone]$ telnet 10.211.12.22<BR>Trying 10.211.12.22...<BR>Connected to 10.211.12.22.<BR>Escape character is '^]'.</P> <P><BR>SunOS 5.9</P> <P>login: oracle<BR>Password: <BR>Last login: Mon Sep 26 06:39:46 from 10.211.12.233<BR>Sun Microsystems Inc.   SunOS 5.9       Generic May 2002<BR>You have mail.<BR>[oracle@db oracle]$ sqlplus cpf/cpf</P> <P>SQL*Plus: Release 9.2.0.5.0 - Production on Mon Sep 26 09:24:44 2005</P> <P>Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved.</P> <P><BR>Connected to:<BR>Oracle9i Enterprise Edition Release 9.2.0.5.0 - 64bit Production<BR>With the Partitioning, OLAP and Oracle Data Mining options<BR>JServer Release 9.2.0.5.0 - Production</P> <P>SQL> drop table bs_banksetting<BR>  2  ;</P> <P>Table dropped.</P> <P>SQL> drop table bs_bankaccountinfo;</P> <P>Table dropped.</P> <P>SQL> drop table bs_clientsetting;</P> <P>Table dropped.</P> <P>SQL> drop table bs_countrysetting;</P> <P>Table dropped.</P> <P>SQL> drop table bs_currencysetting;</P> <P>Table dropped.</P> <P>SQL> exit<BR>Disconnected from Oracle9i Enterprise Edition Release 9.2.0.5.0 - 64bit Production<BR>With the Partitioning, OLAP and Oracle Data Mining options<BR>JServer Release 9.2.0.5.0 - Production<BR>[oracle@db oracle]$ ftp 211.155.247.197<BR>Connected to 211.155.247.197.<BR>220 fsdev FTP server ready.<BR>Name (211.155.247.197:oracle): root<BR>331 Password required for root.<BR>Password:<BR>230 User root logged in.<BR>Remote system type is UNIX.<BR>Using binary mode to transfer files.<BR>ftp> cd bankportal<BR>250 CWD command successful.<BR>ftp> ls<BR>200 PORT command successful.<BR>150 Opening ASCII mode data connection for file list.<BR>AcctDataSourceType.class<BR>AcctDataSourceType.java<BR>CurrencyMappingDAO_oracle.class<BR>SettingData.dmp<BR>account<BR>addp.jsp<BR>bankportal.properties<BR>create_table.sql<BR>datamaintain<BR>example.xls<BR>expbp0926.dmp<BR>expbp1420.dmp<BR>iTreasury-bankportal.ear<BR>itreasury.properties<BR>menubp.dmp<BR>model.xls<BR>query<BR>v003.jsp<BR>v005.jsp<BR>226 Transfer complete.<BR>316 bytes received in 0.016 seconds (19.33 Kbytes/s)<BR>ftp> get expbp0926.dmp<BR>200 PORT command successful.<BR>150 Opening BINARY mode data connection for expbp0926.dmp (47104 bytes).<BR>226 Transfer complete.<BR>local: expbp0926.dmp remote: expbp0926.dmp<BR>47104 bytes received in 0.16 seconds (292.70 Kbytes/s)<BR>ftp> bye<BR>221-You have transferred 47104 bytes in 1 files.<BR>221-Total traffic for this session was 48051 bytes in 2 transfers.<BR>221-Thank you for using the FTP service on fsdev.<BR>221 Goodbye.<BR>[oracle@db oracle]$ imp system/manager1 file=expbp0926.dmp fromuser=bp_cpf touser=cpf</P> <P>Import: Release 9.2.0.5.0 - Production on Mon Sep 26 09:30:09 2005</P> <P>Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved.</P> <P><BR>Connected to: Oracle9i Enterprise Edition Release 9.2.0.5.0 - 64bit Production<BR>With the Partitioning, OLAP and Oracle Data Mining options<BR>JServer Release 9.2.0.5.0 - Production</P> <P>Export file created by EXPORT:V09.02.00 via conventional path</P> <P>Warning: the objects were exported by BP_CPF, not by you</P> <P>import done in ZHS16GBK character set and AL16UTF16 NCHAR character set<BR>. importing BP_CPF's objects into CPF<BR>. . importing table           "BS_BANKACCOUNTINFO"        150 rows imported<BR>. . importing table               "BS_BANKSETTING"        107 rows imported<BR>. . importing table             "BS_CLIENTSETTING"         27 rows imported<BR>. . importing table            "BS_COUNTRYSETTING"         21 rows imported<BR>. . importing table           "BS_CURRENCYSETTING"         53 rows imported<BR>Import terminated successfully without warnings.<BR>[oracle@db oracle]$ </P><img src ="http://www.tkk7.com/licheng700/aggbug/14060.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/licheng700/" target="_blank">v?/a> 2005-09-26 09:38 <a href="http://www.tkk7.com/licheng700/archive/2005/09/26/14060.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>dproperts文ghttp://www.tkk7.com/licheng700/archive/2005/09/21/13662.htmlv?/dc:creator>v?/author>Wed, 21 Sep 2005 09:51:00 GMThttp://www.tkk7.com/licheng700/archive/2005/09/21/13662.htmlhttp://www.tkk7.com/licheng700/comments/13662.htmlhttp://www.tkk7.com/licheng700/archive/2005/09/21/13662.html#Feedback0http://www.tkk7.com/licheng700/comments/commentRss/13662.htmlhttp://www.tkk7.com/licheng700/services/trackbacks/13662.htmlpackage property;

import java.io.*;
import java.util.*;

public class TemplateId {

 private static Properties p;

 private static final TemplateId pi = new TemplateId();

 public TemplateId() {
  // 从templateId.properties属性文件获得数?BR>  InputStream is = getClass()
    .getResourceAsStream("templateId.properties");
  p = new Properties();
  try {
   p.load(is);
  } catch (IOException ex) {
   ex.printStackTrace();
  }
 }

 // 此处的templateId是templateId.properties属性文件中的templateId?BR> public static String getTemplateId() {
  return pi.p.getProperty("templateId");
 }

 public static void main(String args[]) {
  System.out.println("templateId=" + getTemplateId()); // 试调用
 }
}
templateId.properties文g内容:templateId=FFD4156506-3-2F8CAC7



]]>
热部|?名称I间,c装入器http://www.tkk7.com/licheng700/archive/2005/09/21/13640.htmlv?/dc:creator>v?/author>Wed, 21 Sep 2005 07:50:00 GMThttp://www.tkk7.com/licheng700/archive/2005/09/21/13640.htmlhttp://www.tkk7.com/licheng700/comments/13640.htmlhttp://www.tkk7.com/licheng700/archive/2005/09/21/13640.html#Feedback0http://www.tkk7.com/licheng700/comments/commentRss/13640.htmlhttp://www.tkk7.com/licheng700/services/trackbacks/13640.html热部|?/FONT>Q就是在应用正在q行的时候升UYӞ却不需要重新启动应用。对于Java应用E序来说Q热部v是在运行时更新JavacL件。在ZJava的应用服务器实现热部|的q程中,c装入器扮演着重要的角艌Ӏ大多数ZJava的应用服务器Q包括EJB服务器和Servlet容器Q都支持热部|Ӏ类装入器不能重新装入一个已l装入的c,但只要用一个新的类装入器实例,可以将cdơ装入一个正在运行的应用E序?BR>
       ׃c装入器担负着把代码装入JVM的重任,所以它的体pȝ构应当保证整个^台的安全性不会受到威胁。每一个类装入器要为它装入的类定义一个独立的名称I间Q因此运行时Q一个类由它的包名称和装入它的类装入器两者结合唯一地标识?BR>
  在名U空间之外,cM可见Q运行时不同名称I间的类之间有一U保护性的“隔d”,在Java 2向父cd托的c装入模式中Q类装入器可以请求其父类装入器装入的c,因此c装入器需要的cM一定全部由它自p入?BR>
  在Javaq行环境中,不同的类装入器从不同的代码库装入c,之所以要各个类装入器代码库的位|分开Q是Z便于l不同的代码库设定不同的信QU别。在JVM中,由bootstrapc装入器装入的类h最高的信QU别Q用戯定义c装入器代码库的信QU别最低。此外,c装入器可以把每一个装入的cL入一个保护域Q保护域定义了代码执行时所拥有的权限?

  如果要以pȝ安全{略Q一个java.security.Policy的实例)为基定义代码的权限,定制c装入器必须扩展java.security.SecureClassLoadc,调用其defineClassҎQSecureClassLoadcȝdefineClassҎ有一个java.security.CodeSource参数。defindClassҎ从系l策略获得与CodeSource兌的权限,以此为基定义一个java.security.ProtectionDomain。详l介l该安全模型已经出了本文的范围Q请读者自行参阅有关JVM内部机制的资料?BR>
 c装入器装入的最执行单元是Java .class文g。Java .class文g包含Javacȝ二进制描qͼ其中有可执行的字节码以及该类用到的对其他cȝ引用Q包括对Java标准API里面的类的引用。简单地_c装入器首先扑ֈ要装入的Javacȝ字节码,d字节码,创徏一个java.lang.Classcȝ实例。做好这些准备之后,cd可以被JVM执行了?
 当JVM最初开始运行时Q它里面不装入Q何类。如果要求JVM执行一个程序,被执行的c首先装入,字节码执行期间会引用到其他类和接口,q些被引用到的类和接口随之也被装入。因此,有h把JVM的类装入方式UCؓ“懒惰的”装入方式,卛_有必ȝ到某个类时才会装入它Q而不是预先装入各U可能用到的c)Q正因ؓ如此Q开始时JVM不必知道q行时要装入哪些cR在Javaq_上,懒惰的装入方式是实现动态可扩展性机制的关键因素之一。在本文的后面,你将会看到通过实现一个定制的Javac装入器Q我们可以ؓJavaq行时环境加入许多有的功能
   一、委托模?BR>     Java 2q行时环境中有多个类装入器的实例Q每一个类装入器的实例从不同的代码库装入JavacR例如,Java核心APIcȝbootstrapQ或primordialQ类装入器装入,应用E序的类由systemQ或applicationQ类装入器装入。另外,应用E序可以自定义类装入器从指定的代码库装入cRJava 2定义了类装入器之间的?子关p,每一个类装入器(bootstrap除外Q都有一个父c装入器QŞ成一个由c装入器构成的树形结构,bootstrapc装入器是这个树形结构的根,因此bootstrap没有父类装入器?BR> 当客L序请求类装入器装入某个类Ӟc装入器按照下面的算法装入一个类Q?/FONT>
  ?/STRONG> 首先执行一ơ检查,查看客户E序h的类是否已经由当前的c装入器装入。如果是Q则q回已装入的c,h处理完毕。JVM~冲了类装入器装入的所有类Q已l装入的cM会被再次装入?BR>
 ?如果未装入c,则装入类的请求被委托l父c装入器Q这个操作发生在当前的类装入器尝试装入指定的cM前。委托装入类的操作一直向上传递,直至bootstrapc装入器Q如前所qͼbootstrapc装入器是处于树形结构的层Q它不再有可委托的父c装入器?

 ?如果父类装入器未能装入指定的c,则当前的c装入器尝试搜索该cR每一个类装入器有预定义的搜烦和装入类的位|。例如,bootstrapc装入器搜烦sun.boot.class.pathpȝ属性中指定的位|(包括目录和zip、jar文gQ,systemc装入器搜烦的位|由JVM开始运行时传入的CLASSPATH命o行变量指定(相当于设|java.class.pathpȝ属性)。如果找Cc,则类装入器将c返回给pȝQ请求处理完毕?BR>   
 ?/STRONG> 如果找不到类Q则抛出java.lang.ClassNotFoundException异常?

]]>
关于23U设计模式的有趣见解 http://www.tkk7.com/licheng700/archive/2005/09/20/13559.htmlv?/dc:creator>v?/author>Tue, 20 Sep 2005 12:06:00 GMThttp://www.tkk7.com/licheng700/archive/2005/09/20/13559.htmlhttp://www.tkk7.com/licheng700/comments/13559.htmlhttp://www.tkk7.com/licheng700/archive/2005/09/20/13559.html#Feedback0http://www.tkk7.com/licheng700/comments/commentRss/13559.htmlhttp://www.tkk7.com/licheng700/services/trackbacks/13559.html在网上看见了q篇文章Q作者以L的语a比喻了java?2U模式,有很好的启发作用?
        创徏型模?
       
        1、FACTORY—追MM不了请吃饭了,麦当劳的鸡翅和肯德基的鸡都是MM爱吃的东西,虽然口味有所不同Q但不管你带MM去麦当劳或肯德基Q只向服务员说“来四个鸡翅”就行了。麦当劳和肯德基是生鸡翅的Factory
       
        工厂模式Q客L和工厂类分开。消费者Q何时候需要某U品,只需向工厂请求即可。消费者无M改就可以接纳C品。缺Ҏ当品修ҎQ工厂类也要做相应的修改。如Q如何创建及如何向客L提供?
       
        2、BUILDER—MM最爱听的就是“我׃”这句话了,见到不同地方的MM,要能够用她们的方a跟她说这句话哦,我有一个多U语a译机,上面每种语言都有一个按键,见到MM我只要按对应的键Q它p够用相应的语a说出“我׃”这句话了,国外的MM也可以轻松搞掂,q就是我的“我׃”builder。(q一定比军在伊拉克用的译机好卖)
       
        建造模式:品的内部表象和品的生成q程分割开来,从而一个徏造过E生成具有不同的内部表象的品对象。徏造模式得品内部表象可以独立的变化Q客户不必知道品内部组成的l节。徏造模式可以强制实行一U分步骤q行的徏造过E?
       
        3、FACTORY METHOD—请MM去麦当劳吃汉堡,不同的MM有不同的口味Q要每个都记住是一件烦人的事情Q我一般采用Factory Method模式Q带着MM到服务员那儿Q说“要一个汉堡”,具体要什么样的汉堡呢Q让MM直接跟服务员说就行了?
       
        工厂Ҏ模式Q核心工厂类不再负责所有品的创徏Q而是具体创建的工作交给子类dQ成Z个抽象工厂角Ԍ仅负责给出具体工厂类必须实现的接口,而不接触哪一个品类应当被实例化q种l节?
       
        4、PROTOTYPE—跟MM用QQ聊天Q一定要说些深情的话语了Q我搜集了好多肉ȝ情话Q需要时只要copy出来攑ֈQQ里面p了,q就是我的情话prototype了。(100块钱一份,你要不要Q?
       
        原始模型模式Q通过l出一个原型对象来指明所要创建的对象的类型,然后用复制这个原型对象的Ҏ创徏出更多同cd的对象。原始模型模式允许动态的增加或减品类Q品类不需要非得有M事先定的等U结构,原始模型模式适用于Q何的{l构。缺Ҏ每一个类都必配备一个克隆方法?
       
        5、SINGLETON—俺?个漂亮的老婆Q她们的老公都是我,我就是我们家里的老公SigletonQ她们只要说道“老公”,都是指的同一个hQ那是?刚才做了个梦啦,哪有q么好的?
       
        单例模式Q单例模式确保某一个类只有一个实例,而且自行实例化ƈ向整个系l提供这个实例单例模式。单例模式只应在有真正的“单一实例”的需求时才可使用?
       
        l构型模?
       
        6、ADAPTER—在朋友聚会上碰C一个美女SarahQ从香港来的Q可我不会说_语Q她不会说普通话Q只好求助于我的朋友kent了,他作为我和Sarah之间的AdapterQ让我和Sarah可以怺交谈?也不知道他会不会耍我)
       
        适配器(变压器)模式Q把一个类的接口变换成客户端所期待的另一U接口,从而原本因接口原因不匚w而无法一起工作的两个c能够一起工作。适配cd以根据参数返q一个合适的实例l客L?
       
        7、BRIDGE—早上碰到MMQ要说早上好Q晚上碰到MMQ要说晚上好Q碰到MMI了件新衣服Q要说你的衣服好漂亮哦,到MM新做的发型,要说你的头发好漂亮哦。不要问我“早上碰到MM新做了个发型怎么说”这U问题,自己用BRIDGEl合一下不p?
       
        桥梁模式Q将抽象化与实现化脱耦,使得二者可以独立的变化Q也是说将他们之间的强兌变成弱关联,也就是指在一个Y件系l的抽象化和实现化之间用组?聚合关系而不是承关p,从而两者可以独立的变化?
       
        8、COMPOSITE—Mary今天q生日。“我q生日,你要送我一件礼物。”“嗯Q好吧,d店,你自己挑。”“这件T恤挺漂亮Q买Q这条裙子好看,乎ͼq个包也不错Q买。”“喂Q买了三件了呀Q我只答应送一件礼物的哦。”“什么呀QT恤加裙子加包包,正好配成一套呀Q小姐,ȝ你包h。”“……”,MM都会用Composite模式了,你会了没有?
       
        合成模式Q合成模式将对象l织到树l构中,可以用来描述整体与部分的关系。合成模式就是一个处理对象的树结构的模式。合成模式把部分与整体的关系用树l构表示出来。合成模式得客L把一个个单独的成分对象和׃们复合而成的合成对象同{看待?
       
        9、DECORATOR—Maryq完轮到Sarlyq生日,q是不要叫她自己挑了Q不然这个月伙食费肯定玩完,拿出我去q在华山上照的照片Q在背面写上“最好的的礼物,是׃的Fita”,再到街上C品店买了个像框Q卖C品的MM也很漂亮哦)Q再N壁搞术设计的Mike设计了一个漂亮的盒子装v来……,我们都是DecoratorQ最l都在修饰我q个人呀Q怎么P看懂了吗Q?
       
        装饰模式Q装饰模式以对客L透明的方式扩展对象的功能Q是l承关系的一个替代方案,提供比承更多的灉|性。动态给一个对象增加功能,q些功能可以再动态的撤消。增加由一些基本功能的排列l合而生的非常大量的功能?
       
        10、FACADE—我有一个专业的Nikon相机Q我喜Ƣ自己手动调光圈、快门,q样照出来的照片才专业,但MM可不懂这些,教了半天也不会。幸好相机有Facade设计模式Q把相机调整到自动档Q只要对准目标按快门p了,一切由相机自动调整Q这样MM也可以用q个相机l我拍张照片了?
       
        门面模式Q外部与一个子pȝ的通信必须通过一个统一的门面对象进行。门面模式提供一个高层次的接口,使得子系l更易于使用。每一个子pȝ只有一个门面类Q而且此门面类只有一个实例,也就是说它是一个单例模式。但整个pȝ可以有多个门面类?
       
        11、FLYWEIGHT—每天跟MM发短信,手指都篏MQ最q买了个新手机,可以把一些常用的句子存在手机里,要用的时候,直接拿出来,在前面加上MM的名字就可以发送了Q再不用一个字一个字敲了。共享的句子是FlyweightQMM的名字就是提取出来的外部特征Q根据上下文情况使用?
       
        享元模式QFLYWEIGHT在拳L赛中指最轻量U。n元模式以׃n的方式高效的支持大量的细_度对象。n元模式能做到׃n的关键是区分内蕴状态和外蕴状态。内蕴状态存储在享元内部Q不会随环境的改变而有所不同。外蕴状态是随环境的改变而改变的。外蕴状态不能媄响内蕴状态,它们是相互独立的。将可以׃n的状态和不可以共享的状态从常规cM区分开来,不可以׃n的状态从c里剔除出去。客L不可以直接创׃n的对象,而应当用一个工厂对象负责创׃n的对象。n元模式大q度的降低内存中对象的数量?
       
        12、PROXY—跟MM在网上聊天,一开头L“hi,你好?“你从哪儿来呀Q”“你多大了?”“n高多呀Q”这些话Q真烦hQ写个程序做为我的Proxy吧,凡是接收到这些话都设|好了自动的回答Q接收到其他的话时再通知我回{,怎么P酷吧?
       
        代理模式Q代理模式给某一个对象提供一个代理对象,q由代理对象控制Ҏ对象的引用。代理就是一个h或一个机构代表另一个h或者一个机构采取行动。某些情况下Q客户不x者不能够直接引用一个对象,代理对象可以在客户和目标对象直接起到中介的作用。客L分L不出代理主题对象与真实主题对象。代理模式可以ƈ不知道真正的被代理对象,而仅仅持有一个被代理对象的接口,q时候代理对象不能够创徏被代理对象,被代理对象必Lpȝ的其他角色代为创建ƈ传入?
       
        行ؓ模式
       
        13、CHAIN OF RESPONSIBLEITY—晚上去上英语课Qؓ了好开溜坐C最后一排,哇,前面坐了好几个漂亮的MM哎,扑ּU条Q写上“Hi,可以做我的女朋友吗?如果不愿意请向前传”,U条׃个接一个的传上MQ糟p,传到W一排的MM把纸条传l老师了,听说是个老处奛_Q快?
       
        责Q链模式:在责任链模式中,很多对象由每一个对象对其下家的引用而接
       
        h形成一条链。请求在q个链上传递,直到链上的某一个对象决定处理此h。客户ƈ不知道链上的哪一个对象最l处理这个请求,pȝ可以在不影响客户端的情况下动态的重新l织铑֒分配责Q。处理者有两个选择Q承担责L者把责Q推给下家。一个请求可以最l不被Q何接收端对象所接受?
       
        14、COMMAND—俺有一个MM安得特别严,没法见面Q只好借助于她弟弟在我们俩之间传送信息,她对我有什么指C,写一张纸条让她弟弟带l我。这不,她弟弟又传送过来一个COMMANDQؓ了感谢他Q我请他吃了杂酱面Q哪知道他说Q“我同时l我姐姐三个h友送COMMANDQ就C最气Q才h吃面。”,:-(
       
        命o模式Q命令模式把一个请求或者操作封装到一个对象中。命令模式把发出命o的责d执行命o的责d割开Q委z不同的对象。命令模式允许请求的一方和发送的一方独立开来,使得h的一方不必知道接收请求的一方的接口Q更不必知道h是怎么被接Ӟ以及操作是否执行Q何时被执行以及是怎么被执行的。系l支持命令的撤消?
       
        15、INTERPRETER—俺有一个《MM真经》,上面有各UMM的攻略,比如说去吃西的步骤、去看电qҎ{等Q跟MMU会Ӟ只要做一个InterpreterQ照着上面的脚本执行就可以了?
       
        解释器模式:l定一个语a后,解释器模式可以定义出其文法的一U表C,q同时提供一个解释器。客L可以使用q个解释器来解释q个语言中的句子。解释器模式描q怎样在有了一个简单的文法后,使用模式设计解释q些语句。在解释器模式里面提到的语言是指M解释器对象能够解释的Ml合。在解释器模式中需要定义一个代表文法的命ocȝ{l构Q也是一pd的组合规则。每一个命令对象都有一个解释方法,代表对命令对象的解释。命令对象的{l构中的对象的Q何排列组合都是一个语a?
       
       
       
        16、ITERATOR—我׃了MaryQ不一切的向她求婚?
       
        MaryQ“想要我跟你l婚Q得{应我的条g?
       
        我:“什么条件我都答应,你说吧?
       
        MaryQ“我看上了那个一克拉的钻石?
       
        我:“我乎ͼ我买Q还有吗Q?
       
        MaryQ“我看上了湖边的那栋别墅?
       
        我:“我乎ͼ我买Q还有吗Q?
       
        MaryQ“你的小弟弟必须要有50cm镎?
       
        我脑袋嗡的一壎ͼ坐在椅子上,一咬牙Q“我剪,我剪Q还有吗Q?
       
        …?
       
        q代子模式:q代子模式可以顺序访问一个聚集中的元素而不必暴露聚集的内部表象。多个对象聚在一起Ş成的MUC集,聚集对象是能够包容一l对象的容器对象。P代子模式P代逻辑装C个独立的子对象中Q从而与聚集本n隔开。P代子模式化了聚集的界面。每一个聚集对象都可以有一个或一个以上的q代子对象,每一个P代子的P代状态可以是彼此独立的。P代算法可以独立于聚集角色变化?
       
        17、MEDIATOR—四个MM打麻,怺之间谁应该给谁多钱不清楚了,q怺当时我在旁边Q按照各自的{码数算钱,赚了q从我q里拿,赔了q也付l我Q一切就OK啦,俺得C四个MM的电话?
       
        调停者模式:调停者模式包装了一pd对象怺作用的方式,使得q些对象不必怺明显作用。从而他们可以松散偶合。当某些对象之间的作用发生改变时Q不会立卛_响其他的一些对象之间的作用。保证这些作用可以彼此独立的变化。调停者模式将多对多的怺作用转化Z对多的相互作用。调停者模式将对象的行为和协作抽象化,把对象在尺度的行ؓ上与其他对象的相互作用分开处理?
       
        18、MEMENTO—同时跟几个MM聊天Ӟ一定要记清楚刚才跟MM说了些什么话Q不然MM发现了会不高兴的哦,q怺我有个备忘录Q刚才与哪个MM说了什么话我都拯一份放到备忘录里面保存Q这样可以随时察看以前的记录啦?
       
        备忘录模式:备忘录对象是一个用来存储另外一个对象内部状态的快照的对象。备忘录模式的用意是在不破坏装的条件下Q将一个对象的状态捉住,q外部化Q存储v来,从而可以在来合适的时候把q个对象q原到存储v来的状态?
       
        19、OBSERVER—想知道׃公司最新MM情报吗?加入公司的MM情报邮gl就行了Qtom负责搜集情报Q他发现的新情报不用一个一个通知我们Q直接发布给邮gl,我们作ؓ订阅者(观察者)可以及时收到情报啦
       
        观察者模式:观察者模式定义了一U一队多的依赖关p,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化Ӟ会通知所有观察者对象,使他们能够自动更新自己?
       
        20、STATE—跟MM交往Ӟ一定要注意她的状态哦Q在不同的状态时她的行ؓ会有不同Q比如你U她今天晚上ȝ电媄Q对你没兴趣的MM׃说“有事情啦”,对你不讨厌但q没喜欢上的MM׃说“好啊,不过可以带上我同事么Q”,已经喜欢上你的MM׃说“几炚wQ看完电影再L吧怎么P”,当然你看电媄q程中表现良好的话,也可以把MM的状态从不讨厌不喜欢变成喜欢哦?
       
        状态模式:状态模式允怸个对象在其内部状态改变的时候改变行为。这个对象看上去象是改变了它的类一栗状态模式把所研究的对象的行ؓ包装在不同的状态对象里Q每一个状态对象都属于一个抽象状态类的一个子cR状态模式的意图是让一个对象在其内部状态改变的时候,其行Z随之改变。状态模式需要对每一个系l可能取得的状态创立一个状态类的子cR当pȝ的状态变化时Q系l便改变所选的子类?
       
        21、STRATEGY—跟不同cd的MMU会Q要用不同的{略Q有的请电媄比较好,有的则去吃小吃效果不错,有的LvҎ漫最合适,单目的都是ؓ了得到MM的芳心,我的qMM锦囊中有好多Strategy哦?
       
        {略模式Q策略模式针对一l算法,每一个算法封装到h共同接口的独立的cMQ从而得它们可以相互替换。策略模式得算法可以在不媄响到客户端的情况下发生变化。策略模式把行ؓ和环境分开。环境类负责l持和查询行为类Q各U算法在具体的策略类中提供。由于算法和环境独立开来,法的增减,修改都不会媄响到环境和客L?
       
        22、TEMPLATE METHOD——看q《如何说服女生上床》这部经典文章吗Q女生从认识C床的不变的步骤分为y遇、打破僵局、展开q求、接吅R前戏、动手、爱抚、进d大步?Template method)Q但每个步骤针对不同的情况,都有不一L做法Q这p看你随机应变?具体实现)Q?
       
        模板Ҏ模式Q模板方法模式准备一个抽象类Q将部分逻辑以具体方法以及具体构造子的Ş式实玎ͼ然后声明一些抽象方法来q子类实现剩余的逻辑。不同的子类可以以不同的方式实现q些抽象ҎQ从而对剩余的逻辑有不同的实现。先制定一个顶U逻辑框架Q而将逻辑的细节留l具体的子类d现?
       
        23、VISITOR—情CQ要l每个MM送一束鲜花和一张卡片,可是每个MM送的花都要针对她个h的特点,每张卡片也要Ҏ个h的特Ҏ挑,我一个h哪搞得清楚,q是找花店老板和礼品店老板做一下VisitorQ让花店老板ҎMM的特炚w一束花Q让C品店老板也根据每个h特点选一张卡Q这样就L多了Q?
       
        讉K者模式:讉K者模式的目的是封装一些施加于某种数据l构元素之上的操作。一旦这些操作需要修改的话,接受q个操作的数据结构可以保持不变。访问者模式适用于数据结构相Ҏ定的pȝQ它把数据结构和作用于结构上的操作之间的耦合解脱开Q得操作集合可以相对自q演化。访问者模式得增加新的操作变的很ҎQ就是增加一个新的访问者类。访问者模式将有关的行为集中到一个访问者对象中Q而不是分散到一个个的节点类中。当使用讉K者模式时Q要尽可能多的对象览逻辑攑֜讉K者类中,而不是放到它的子cM。访问者模式可以跨q几个类的等U结构访问属于不同的{l构的成员类?BR>

]]>
Session详解 http://www.tkk7.com/licheng700/archive/2005/09/20/13494.htmlv?/dc:creator>v?/author>Tue, 20 Sep 2005 02:04:00 GMThttp://www.tkk7.com/licheng700/archive/2005/09/20/13494.htmlhttp://www.tkk7.com/licheng700/comments/13494.htmlhttp://www.tkk7.com/licheng700/archive/2005/09/20/13494.html#Feedback4http://www.tkk7.com/licheng700/comments/commentRss/13494.htmlhttp://www.tkk7.com/licheng700/services/trackbacks/13494.html
摘要Q虽然session机制在web应用E序中被采用已经很长旉了,但是仍然有很多h不清楚session机制的本质,以至不能正确的应用这一技术。本文将详细讨论session的工作机制ƈ且对在Java web application中应用session机制时常见的问题作出解答?BR>
目录Q?BR>一、术语session
二、HTTP协议与状态保?BR>三、理解cookie机制
四、理解session机制
五、理解javax.servlet.http.HttpSession
六、HttpSession常见问题
七、跨应用E序的session׃n
八、ȝ
参考文?BR>
一、术语session
在我的经验里Qsessionq个词被滥用的程度大概仅ơ于transactionQ更加有的是transaction与session在某些语境下的含义是相同的?BR>
sessionQ中文经常翻译ؓ会话Q其本来的含义是指有始有l的一pd动作/消息Q比如打电话时从拿v电话拨号到挂断电话这中间的一pdq程可以UCZ?session。有时候我们可以看到这L话“在一个浏览器会话期间Q?..”,q里的会话一词用的就是其本义Q是指从一个浏览器H口打开到关闭这个期?①。最混ؕ的是“用P客户端)在一ơ会话期间”这样一句话Q它可能指用L一pd动作Q一般情况下是同某个具体目的相关的一pd动作Q比如从d到选购商品到结账登样一个网上购物的q程Q有时候也被称Z个transactionQ,然而有时候也可能仅仅是指一ơ连接,也有可能是指含义①,其中的差别只能靠上下文来推断②?BR>
然而当session一词与|络协议相关联时Q它又往往隐含了“面向连接”和/或“保持状态”这样两个含义, “面向连接”指的是在通信双方在通信之前要先建立一个通信的渠道,比如打电话,直到Ҏ接了电话通信才能开始,与此相对的是写信Q在你把信发出去的时候你q不能确认对方的地址是否正确Q通信渠道不一定能建立Q但对发信h来说Q通信已经开始了。“保持状态”则是指通信的一方能够把一pd的消息关联v来,使得消息之间可以互相依赖Q比如一个服务员能够认出再次光的老顾客ƈ且记得上ơ这个顾客还Ơ店里一块钱。这一cȝ例子有“一个TCP session”或?“一个POP3 session”③?BR>
而到了web服务器蓬勃发展的时代Qsession在web开发语境下的语义又有了新的扩展Q它的含义是指一cȝ来在客户端与服务器之间保持状态的解决Ҏ④。有时候session也用来指q种解决Ҏ的存储结构,如“把xxx保存在session 里”⑤。由于各U用于web开发的语言在一定程度上都提供了对这U解x案的支持Q所以在某种特定语言的语境下Qsession也被用来指代该语a的解x案,比如l常把Java里提供的javax.servlet.http.HttpSessionUCؓsession⑥?BR>
鉴于q种混ؕ已不可改变,本文中session一词的q用也会Ҏ上下文有不同的含义,请大家注意分辨?BR>在本文中Q用中文“浏览器会话期间”来表达含义①,使用“session机制”来表达含义④,使用“session”表辑֐义⑤Q用具体的“HttpSession”来表达含义?BR>
二、HTTP协议与状态保?BR>HTTP 协议本n是无状态的Q这与HTTP协议本来的目的是相符的,客户端只需要简单的向服务器h下蝲某些文gQ无论是客户端还是服务器都没有必要纪录彼此过ȝ行ؓQ每一ơ请求之间都是独立的Q好比一个顾客和一个自动售货机或者一个普通的Q非会员Ӟ大卖Z间的关系一栗?BR>
然而聪明(或者贪心?Q的Z很快发现如果能够提供一些按需生成的动态信息会使web变得更加有用Q就像给有线电视加上Ҏ功能一栗这U需求一斚wqHTML逐步d了表单、脚本、DOM{客L行ؓQ另一斚w在服务器端则出现了CGI规范以响应客L的动态请求,作ؓ传输载体的HTTP协议也添加了文g上蝲?cookieq些Ҏ。其中cookie的作用就是ؓ了解决HTTP协议无状态的~陷所作出的努力。至于后来出现的session机制则是又一U在客户端与服务器之间保持状态的解决Ҏ?BR>
让我们用几个例子来描qC下cookie和session机制之间的区别与联系。笔者曾l常ȝ一家咖啡店有喝5杯咖啡免费赠一杯咖啡的优惠Q然而一ơ性消?杯咖啡的Z微乎其微Q这时就需要某U方式来U录某位֮的消Ҏ量。想象一下其实也无外乎下面的几种ҎQ?BR>1、该店的店员很厉宻I能记住每位顾客的消费数量Q只要顾客一走进咖啡店,店员q道该怎么对待了。这U做法就是协议本w支持状态?BR>2、发l顾客一张卡片,上面记录着消费的数量,一般还有个有效期限。每ơ消ҎQ如果顾客出C张卡片,则此ơ消费就会与以前或以后的消费相联pv来。这U做法就是在客户端保持状态?BR>3、发l顾客一张会员卡Q除了卡号之外什么信息也不纪录,每次消费Ӟ如果֮出示该卡片,则店员在店里的纪录本上找到这个卡号对应的U录d一些消费信息。这U做法就是在服务器端保持状态?BR>
׃HTTP协议是无状态的Q而出于种U考虑也不希望使之成ؓ有状态的Q因此,后面两种Ҏ成为现实的选择。具体来说cookie机制采用的是在客L保持状态的ҎQ而session机制采用的是在服务器端保持状态的Ҏ。同时我们也看到Q由于采用服务器端保持状态的Ҏ在客L也需要保存一个标识,所以session机制可能需要借助于cookie机制来达C存标识的目的Q但实际上它q有其他选择?BR>
三、理解cookie机制 
cookie机制的基本原理就如上面的例子一L单,但是q有几个问题需要解冻I“会员卡”如何分发;“会员卡”的内容Q以及客户如何用“会员卡”?BR>
正统的cookie分发是通过扩展HTTP协议来实现的Q服务器通过在HTTP的响应头中加上一行特D的指示以提C浏览器按照指示生成相应的cookie。然而纯_的客户端脚本如JavaScript或者VBScript也可以生成cookie?BR>
而cookie 的用是由浏览器按照一定的原则在后台自动发送给服务器的。浏览器查所有存储的cookieQ如果某个cookie所声明的作用范围大于等于将要请求的资源所在的位置Q则把该cookie附在h资源的HTTPh头上发送给服务器。意思是麦当劳的会员卡只能在麦当劳的店里出示Q如果某家分店还发行了自q会员卡,那么q这家店的时候除了要出示麦当劳的会员卡,q要出示q家店的会员卡?BR>
cookie的内容主要包括:名字Q|q期旉Q\径和域?BR>其中域可以指定某一个域比如.google.comQ相当于d招牌Q比如宝z公司,也可以指定一个域下的具体某台机器比如www.google.com或者froogle.google.comQ可以用飘柔来做比?BR>路径是跟在域名后面的URL路径Q比?或?foo{等Q可以用某飘柔专柜做比?BR>路径与域合在一起就构成了cookie的作用范围?BR>如果不设|过期时_则表C个cookie的生命期为浏览器会话期间Q只要关闭浏览器H口Qcookie消׃。这U生命期为浏览器会话期的 cookie被称Z话cookie。会话cookie一般不存储在硬盘上而是保存在内存里Q当然这U行为ƈ不是规范规定的。如果设|了q期旉Q浏览器׃把cookie保存到硬盘上Q关闭后再次打开览器,q些cookie仍然有效直到过讑֮的过期时间?BR>
存储在硬盘上的cookie 可以在不同的览器进E间׃nQ比如两个IEH口。而对于保存在内存里的cookieQ不同的览器有不同的处理方式。对于IEQ在一个打开的窗口上?Ctrl-NQ或者从文g菜单Q打开的窗口可以与原窗口共享,而用其他方式新开的IEq程则不能共享已l打开的窗口的内存cookieQ对?Mozilla Firefox0.8Q所有的q程和标{N都可以共享同Lcookie。一般来说是用javascript的window.open打开的窗口会与原H口׃n内存cookie。浏览器对于会话cookie的这U只认cookie不认人的处理方式l常l采用session机制的web应用E序开发者造成很大的困扰?BR>
下面是一个goolge讄cookie的响应头的例?BR>HTTP/1.1 302 Found
Location: http://www.google.com/intl/zh-CN/
Set-Cookie: PREF=ID=0565f77e132de138:NW=1:TM=1098082649:LM=1098082649:S=KaeaCFPo49RiA_d8; expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/; domain=.google.com
Content-Type: text/html




q是使用HTTPLookq个HTTP Sniffer软g来俘LHTTP通讯U录的一部分




览器在再次讉Kgoolge的资源时自动向外发送cookie

 


使用Firefox可以很容易的观察现有的cookie的?BR>使用HTTPLook配合Firefox可以很容易的理解cookie的工作原理?BR>



IE也可以设|在接受cookie前询?BR>
 


q是一个询问接受cookie的对话框?BR>
四、理解session机制
session机制是一U服务器端的机制Q服务器使用一U类g散列表的l构Q也可能是使用散列表)来保存信息?BR>
当程序需要ؓ某个客户端的h创徏一个session的时候,服务器首先检查这个客L的请求里是否已包含了一个session标识 - UCؓ session idQ如果已包含一个session id则说明以前已lؓ此客L创徏qsessionQ服务器按照session id把这?session索出来用(如果索不刎ͼ可能会新Z个)Q如果客Lh不包含session idQ则为此客户端创Z个sessionq且生成一个与此session相关联的session idQsession id的值应该是一个既不会重复Q又不容易被扑ֈ规律以仿造的字符Ԍq个 session id被在本ơ响应中q回l客L保存?BR>
保存q个session id的方式可以采用cookieQ这样在交互q程中浏览器可以自动的按照规则把q个标识发挥l服务器。一般这个cookie的名字都是类gSEEESIONIDQ而。比如weblogic对于web应用E序生成的cookieQJSESSIONID= ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764Q它的名字就?JSESSIONID?BR>
׃cookie可以被h为的止Q必L其他机制以便在cookie被禁止时仍然能够把session id传递回服务器。经常被使用的一U技术叫做URL重写Q就是把session id直接附加在URL路径的后面,附加方式也有两种Q一U是作ؓURL路径的附加信息,表现形式为http://...../xxx;jsessionid= ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
另一U是作ؓ查询字符串附加在URL后面Q表现Ş式ؓhttp://...../xxx?jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
q两U方式对于用h说是没有区别的,只是服务器在解析的时候处理的方式不同Q采用第一U方式也有利于把session id的信息和正常E序参数区分开来?BR>Z在整个交互过E中始终保持状态,必d每个客户端可能请求的路径后面都包含这个session id?BR>
另一U技术叫做表单隐藏字Dc就是服务器会自动修改表单,d一个隐藏字D,以便在表单提交时能够把session id传递回服务器。比如下面的表单
<form name="testform" action="/xxx">
<input type="text">
</form>
在被传递给客户端之前将被改写成
<form name="testform" action="/xxx">
<input type="hidden" name="jsessionid" value="ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764">
<input type="text">
</form>
q种技术现在已较少应用Q笔者接触过的很古老的iPlanet6(SunONE应用服务器的前n)׃用了q种技术?BR>实际上这U技术可以简单的用对action应用URL重写来代ѝ?BR>
在谈论session机制的时候,常常听到q样一U误解“只要关闭浏览器Qsession消׃”。其实可以想象一下会员卡的例子,除非֮d对店家提出销卡,否则店家l对不会L删除֮的资料。对session来说也是一LQ除非程序通知服务器删除一个sessionQ否则服务器会一直保留,E序一般都是在用户做log off的时候发个指令去删除session。然而浏览器从来不会d在关闭之前通知服务器它要关闭Q因此服务器Ҏ不会有机会知道浏览器已经关闭Q之所以会有这U错觉,是大部分session机制都用会话cookie来保存session idQ而关闭浏览器后这?session id消׃Q再ơ连接服务器时也无法找到原来的session。如果服务器讄的cookie被保存到盘上,或者用某U手D|写浏览器发出的HTTPh_把原来的session id发送给服务器,则再ơ打开览器仍然能够找到原来的session?BR>
恰恰是由于关闭浏览器不会Dsession被删除,q服务器ؓseesion讄了一个失效时_当距dL上一ơ用session的时间超q这个失效时间时Q服务器可以认为客L已经停止了活动,才会把session删除以节省存储空间?BR>
五、理解javax.servlet.http.HttpSession
HttpSession是Javaq_对session机制的实现规范,因ؓ它仅仅是个接口,具体到每个web应用服务器的提供商,除了对规范支持之外,仍然会有一些规范里没有规定的细微差异。这里我们以BEA的Weblogic Server8.1作ؓ例子来演C?BR>
首先QWeblogic Server提供了一pd的参数来控制它的HttpSession的实玎ͼ包括使用cookie的开关选项Q用URL重写的开关选项Qsession持久化的讄Qsession失效旉的设|,以及针对cookie的各U设|,比如讄cookie的名字、\径、域Q?cookie的生存时间等?BR>
一般情况下Qsession都是存储在内存里Q当服务器进E被停止或者重启的时候,内存里的session也会被清I,如果讄了session的持久化Ҏ,服务器就会把session保存到硬盘上Q当服务器进E重新启动或q些信息能够被再次使用Q?Weblogic Server支持的持久性方式包括文件、数据库、客Lcookie保存和复制?BR>
复制严格说来不算持久化保存,因ؓsession实际上还是保存在内存里,不过同样的信息被复制到各个cluster内的服务器进E中Q这样即使某个服务器q程停止工作也仍然可以从其他q程中取得session?BR>
cookie生存旉的设|则会媄响浏览器生成的cookie是否是一个会话cookie。默认是使用会话cookie。有兴趣的可以用它来试验我们在第四节里提到的那个误解?BR>
cookie的\径对于web应用E序来说是一个非帔R要的选项QWeblogic Server对这个选项的默认处理方式得它与其他服务器有明昄区别。后面我们会专题讨论?BR>
关于session的设|参考[5] http://e-docs.bea.com/wls/docs70/webapp/weblogic_xml.html#1036869

六、HttpSession常见问题
Q在本小节中session的含义ؓ⑤和⑥的混合Q?BR>

1、session在何时被创徏
一个常见的误解是以为session在有客户端访问时p创徏Q然而事实是直到某server端程序调?HttpServletRequest.getSession(true)q样的语句时才被创徏Q注意如果JSP没有昄的?nbsp;<% @page session="false"%> 关闭sessionQ则JSP文g在编译成Servlet时将会自动加上这样一条语?HttpSession session = HttpServletRequest.getSession(true);q也是JSP中隐含的 session对象的来历?BR>
׃session会消耗内存资源,因此Q如果不打算使用sessionQ应该在所有的JSP中关闭它?BR>
2、session何时被删?BR>l合前面的讨论,session在下列情况下被删除a.E序调用HttpSession.invalidate();或b.距离上一ơ收到客L发送的session id旉间隔过了session的超时设|?或c.服务器进E被停止Q非持久sessionQ?BR>
3、如何做到在览器关闭时删除session
严格的讲Q做不到q一炏V可以做一点努力的办法是在所有的客户端页面里使用javascript代码window.oncolose来监视浏览器的关闭动作,然后向服务器发送一个请求来删除session。但是对于浏览器崩溃或者强行杀死进E这些非常规手段仍然无能为力?BR>
4、有个HttpSessionListener是怎么回事
你可以创Llistenerȝ控session的创建和销毁事Ӟ使得在发生这L事g时你可以做一些相应的工作。注意是session的创建和销毁动作触发listenerQ而不是相反。类似的与HttpSession有关的listenerq有 HttpSessionBindingListenerQHttpSessionActivationListener?HttpSessionAttributeListener?BR>
5、存攑֜session中的对象必须是可序列化的?BR>不是必需的。要求对象可序列化只是ؓ了session能够在集中被复制或者能够持久保存或者在必要时server能够暂时把session交换出内存。在 Weblogic Server的session中放|一个不可序列化的对象在控制C会收C个警告。我所用过的某个iPlanet版本如果 session中有不可序列化的对象Q在session销毁时会有一个ExceptionQ很奇怪?BR>
6、如何才能正的应付客户端禁止cookie的可能?BR>Ҏ有的URL使用URL重写Q包括超链接Qform的actionQ和重定向的URLQ具体做法参见[6]
http://e-docs.bea.com/wls/docs70/webapp/sessions.html#100770

7、开两个览器窗口访问应用程序会使用同一个sessionq是不同的session
参见W三节对cookie的讨论,对session来说是只认id不认人,因此不同的浏览器Q不同的H口打开方式以及不同的cookie存储方式都会对这个问题的{案有媄响?BR>
8、如何防止用h开两个览器窗口操作导致的session混ؕ
q个问题与防止表单多ơ提交是cM的,可以通过讄客户端的令牌来解冟뀂就是在服务器每ơ生成一个不同的idq回l客LQ同时保存在session里,客户端提交表单时必须把这个id也返回服务器Q程序首先比较返回的id与保存在session里的值是否一_如果不一致则说明本次操作已经被提交过了。可以参看《J2EE核心模式》关于表C层模式的部分。需要注意的是对于用javascript window.open打开的窗口,一般不讄q个idQ或者用单独的idQ以防主H口无法操作Q徏议不要再window.open打开的窗口里做修Ҏ作,q样可以不用设|?BR>
9、ؓ什么在Weblogic Server中改变session的值后要重新调用一ơsession.setValue
做这个动作主要是Z在集环境中提示Weblogic Server session中的值发生了改变Q需要向其他服务器进E复制新的session倹{?BR>
10、ؓ什么session不见?BR>排除session正常失效的因素之外,服务器本w的可能性应该是微乎其微的,虽然W者在iPlanet6SP1加若q补丁的Solaris版本上倒也遇到q;览器插件的可能性次之,W者也遇到q?721插g造成的问题;理论上防火墙或者代理服务器在cookie处理上也有可能会出现问题?BR>出现q一问题的大部分原因都是E序的错误,最常见的就是在一个应用程序中去访问另外一个应用程序。我们在下一节讨个问题?BR>
七、跨应用E序的session׃n

常常有这L情况Q一个大目被分割成若干项目开发,Z能够互不q扰Q要求每个小目作ؓ一个单独的web应用E序开发,可是C最后突然发现某几个项目之间需要共享一些信息,或者想使用session来实现SSO(single sign on)Q在session中保存login的用户信息,最自然的要求是应用E序间能够访问彼此的session?BR>
然而按照Servlet规范Qsession的作用范围应该仅仅限于当前应用程序下Q不同的应用E序之间是不能够互相讉KҎ的session的。各个应用服务器从实际效果上都遵守了q一规范Q但是实现的l节却可能各有不同,因此解决跨应用程序session׃n的方法也各不相同?BR>
首先来看一下Tomcat是如何实现web应用E序之间session的隔ȝQ从 Tomcat讄的cookie路径来看Q它对不同的应用E序讄的cookie路径是不同的Q这样不同的应用E序所用的session id是不同的Q因此即使在同一个浏览器H口里访问不同的应用E序Q发送给服务器的session id也可以是不同的?BR>

  

Ҏq个Ҏ,我们可以推测Tomcat中session的内存结构大致如下?BR>

 

W者以前用q的iPlanet也采用的是同L方式Q估计SunONE与iPlanet之间不会有太大的差别。对于这U方式的服务器,解决的思\很简单,实际实行h也不难。要么让所有的应用E序׃n一个session idQ要么让应用E序能够获得其他应用E序的session id?BR>
iPlanet中有一U很单的Ҏ来实现共享一个session idQ那是把各个应用程序的cookie路径都设?Q实际上应该?NASAppQ对于应用程序来讲它的作用相当于根)?BR><session-info>
<path>/NASApp</path>
</session-info>

需要注意的是,操作׃n的session应该遵@一些编E约定,比如在session attribute名字的前面加上应用程序的前缀Q?setAttribute("name", "neo")变成setAttribute("app1.name", "neo")Q以防止命名I间冲突Q导致互相覆盖?BR>

在Tomcat中则没有q么方便的选择。在Tomcat版本3上,我们q可以有一些手D|׃nsession。对于版?以上的TomcatQ目前笔者尚未发现简单的办法。只能借助于第三方的力量,比如使用文g、数据库、JMS或者客LcookieQURL参数或者隐藏字D늭手段?BR>
我们再看一下Weblogic Server是如何处理session的?BR>

  

从截屏画面上可以看到Weblogic ServerҎ有的应用E序讄的cookie的\径都?Q这是不是意味着在Weblogic Server中默认的可以共享session了呢Q然而一个小实验卛_证明即不同的应用程序用的是同一个sessionQ各个应用程序仍然只能访问自己所讄的那些属性。这说明Weblogic Server中的session的内存结构可能如?BR>

 

对于q样一U结构,?session机制本n上来解决session׃n的问题应该是不可能的了。除了借助于第三方的力量,比如使用文g、数据库、JMS或者客L cookieQURL参数或者隐藏字D늭手段Q还有一U较为方便的做法Q就是把一个应用程序的session攑ֈServletContext中,q样另外一个应用程序就可以从ServletContext中取得前一个应用程序的引用。示例代码如下,

应用E序A
context.setAttribute("appA", session); 

应用E序B
contextA = context.getContext("/appA");
HttpSession sessionA = (HttpSession)contextA.getAttribute("appA"); 

值得注意的是q种用法不可ULQ因为根据ServletContext的JavaDocQ应用服务器可以处于安全的原因对于context.getContext("/appA");q回I|以上做法在Weblogic Server 8.1中通过?BR>
那么Weblogic ServerZ么要把所有的应用E序的cookie路径都设?呢?原来是ؓ了SSOQ凡是共享这个session的应用程序都可以׃n认证的信息。一个简单的实验可以证明这一点,修改首先d的那个应用程序的描述Wweblogic.xmlQ把cookie路径修改?appA 讉K另外一个应用程序会重新要求dQ即使是反过来,先访问cookie路径?的应用程序,再访问修改过路径的这个,虽然不再提示dQ但是登录的用户信息也会丢失。注意做q个实验时认证方式应该用FORMQ因为浏览器和web服务器对basic认证方式有其他的处理方式Q第二次h的认证不是通过 session来实现的。具体请参看[7] secion 14.8 AuthorizationQ你可以修改所附的CZE序来做q些试验?BR>
八、ȝ
session机制本nq不复杂Q然而其实现和配|上的灵zL却使得具体情况复杂多变。这也要求我们不能把仅仅某一ơ的l验或者某一个浏览器Q服务器的经验当作普遍适用的经验,而是始终需要具体情况具体分析?BR>
关于作者:
郎云鹏(dev2dev ID: hippiewolfQ,软g工程师,从事J2EE开?BR>电子邮gQlangyunpeng@yahoo.com.cn
地址Q大qY件园?1L技大厦A座大q博涵咨询服务有限公?BR>
参考文档:
[1] Preliminary Specification http://wp.netscape.com/newsref/std/cookie_spec.html
[2] RFC2109 http://www.rfc-editor.org/rfc/rfc2109.txt
[3] RFC2965 http://www.rfc-editor.org/rfc/rfc2965.txt
[4] The Unofficial Cookie FAQ http://www.cookiecentral.com/faq/
[5] http://e-docs.bea.com/wls/docs70/webapp/weblogic_xml.html#1036869
[6] http://e-docs.bea.com/wls/docs70/webapp/sessions.html#100770
[7] RFC2616 http://www.rfc-editor.org/rfc/rfc2616.txt


]]>
初识JAAShttp://www.tkk7.com/licheng700/archive/2005/09/19/13405.htmlv?/dc:creator>v?/author>Mon, 19 Sep 2005 07:40:00 GMThttp://www.tkk7.com/licheng700/archive/2005/09/19/13405.htmlhttp://www.tkk7.com/licheng700/comments/13405.htmlhttp://www.tkk7.com/licheng700/archive/2005/09/19/13405.html#Feedback0http://www.tkk7.com/licheng700/comments/commentRss/13405.htmlhttp://www.tkk7.com/licheng700/services/trackbacks/13405.htmlJava Authentication and Authorization Service ?JDK 1.4 正式加入 Java 标准?Security 模块, 单来? JAAS 是让我们把w䆾验证与权限管控用标准的Ҏ来开发。根据google到的信息得知?BR>JAAS主要的类如下Q?BR>普通对?
  • Subject
  • Principals
  • Credentials
w䆾验证相关的对?
  • LoginContext
  • LoginModule
  • CallbackHandler
  • Callback
权限控相关的对?
  • Policy
  • AuthPermission
  • PrivateCredentialPermission

接下来便是利用空余时间通过JDKQtutorialq行研究了。希望不是半途而废Q也谨以此文CQ以表决心?/P>(注明:q是一个网友的文章,记此是希望和他一起学?共勉 )

]]>
Java的基本数据类型与?/title><link>http://www.tkk7.com/licheng700/archive/2005/09/19/13367.html</link><dc:creator>v?/dc:creator><author>v?/author><pubDate>Mon, 19 Sep 2005 01:26:00 GMT</pubDate><guid>http://www.tkk7.com/licheng700/archive/2005/09/19/13367.html</guid><wfw:comment>http://www.tkk7.com/licheng700/comments/13367.html</wfw:comment><comments>http://www.tkk7.com/licheng700/archive/2005/09/19/13367.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/licheng700/comments/commentRss/13367.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/licheng700/services/trackbacks/13367.html</trackback:ping><description><![CDATA[<span id="nidupzv" class=unnamed3><A title="文章标题Q用Java操作二进制文?#13; ? 者:mingjava 更新旉Q?004-9-11 16:00:49 点击ơ数Q?7" target=_blank><FONT color=#333333>使用Java操作二进制文?/FONT></A>?A title="文章标题Q用Java操作文本文g ? 者:mingjava 更新旉Q?004-9-11 23:24:43 点击ơ数Q?" target=_blank><FONT color=#666666>使用Java操作文本文g</FONT></A>两篇文章分别介绍了如何操作二q制文g和文本文Ӟ事实上Java中还有基于Data的数据操作,q里的Data指的是Java的基本数据类型和String。基本数据类型包括byte、int、char、long、float、double、boolean和short? <P>    说到Java的基本数据类型必谈到的两个cLDataInputStream和DataOutputStream。它们提供了对Java基本数据cd的操作,但是q些Ҏ事实上是在两个重要的接口中定义的DataInput和DataOutputQ它们的功能是把二q制的字节流转换成Java的基本数据类型,同时q提供了从数据中使用UTF-8~码构徏String的功能。有一个重要的cRandomAccessFile实现了DataInput和DataOutput两个接口使得他能够对文g同时q行写和ȝ操作?/P> <P>    在DataInputStream和DataOutputStream两个cM的方法都很简单,基本l构为readXXXX()和writeXXXX()其中XXXX代表基本数据cd或者String。在q里不多讲述Q不q值得一提的是我们有必要读读java中unicode的编码规则,在API doc中有比较详细的介l。通常我们的对象有很多都是由java的基本数据类型构成的Q比如一个h的信息包括姓名,电子信箱Q电话号码和性别{。其实我们可以用DataInputStream中的Ҏ和DataOutputStream中的Ҏ按照一定的序列把数据写入流中再按照相同的序列把他们d出来Q这是我们自己实现的序列化Q这可以用在数据传输中,比如在J2ME联网E序中用序列化机制传输数据。下面我们看看如何自己实现序列化Q首先我们要有两个构造函数其中一个参CؓI?BR>public Account()<BR>    {</P> <P>    }</P> <P>    public Account(String userName, String email, int age, boolean gender)<BR>    {<BR>        this.userName = userName;<BR>        this.email = email;<BR>        this.age = age;<BR>        this.gender = gender;<BR>    }<BR>当我们进行序列化的时候也很简单,我们只是往DataOutputStream中按照顺序写入对象的成员变量。例?BR>public void serialize(DataOutputStream dos) throws IOException<BR>    {<BR>        dos.writeUTF(userName);<BR>        dos.writeUTF(email);<BR>        dos.writeInt(age);<BR>        dos.writeBoolean(gender);<BR>        <BR>    }<BR>当我们进行反序列化的时候则按照相同的顺序从DataInputStream里面d数据q赋值给成员变量。例?BR>    public static Account deserialize(DataInputStream dis) throws IOException<BR>    {<BR>        Account account = new Account();<BR>        account.userName = dis.readUTF();<BR>        account.email = dis.readUTF();<BR>        account.age = dis.readInt();<BR>        account.gender = dis.readBoolean();<BR>       <BR>        return account;<BR>    }<BR>Z便于调试我们q提供一个toString()的方法打印出对象的实际信息。这是个好的习惯?BR>    public String toString()<BR>    {<BR>        return "UserName = " + userName + " Email = " + email + " age = " + age<BR>                + " gender = " + (gender ? "male" : "female");<BR>    }</P> <P>     Z试序列化我们编写下面的E序q行试Q代码比较简单?BR><BR>package com.j2medev.mingjava;</P> <P>import java.io.*;</P> <P><BR>public class TestDataIO<BR>{</P> <P>    public static void main(String[] args) throws IOException<BR>    {<BR>        Account account = new Account("mingjava","<A href='mailto:eric.zhan@263.net",25,true'><FONT color=#666666>eric.zhan@263.net",25,true</FONT></A>);<BR>        System.out.println("before serialization.........");<BR>        System.out.println(account.toString());<BR>        ByteArrayOutputStream baos = new ByteArrayOutputStream();<BR>        DataOutputStream dos = new DataOutputStream(baos);<BR>        account.serialize(dos);<BR>        DataInputStream dis = new DataInputStream(new ByteArrayInputStream(baos.toByteArray()));<BR>        Account sAccount = Account.deserialize(dis);<BR>        System.out.println("after serialization..........");<BR>        System.out.println(sAccount.toString());<BR>        dos.close();<BR>        dis.close();<BR>    }<BR>}<BR><BR>package com.j2medev.mingjava;</P> <P>import java.io.*;</P> <P>public class Account<BR>{<BR>    private String userName = "";<BR>    private String email = "";<BR>    private int age = 0;<BR>    private boolean gender = false;</P> <P>    public Account()<BR>    {</P> <P>    }</P> <P>    public Account(String userName, String email, int age, boolean gender)<BR>    {<BR>        this.userName = userName;<BR>        this.email = email;<BR>        this.age = age;<BR>        this.gender = gender;<BR>    }</P> <P>    public void serialize(DataOutputStream dos) throws IOException<BR>    {<BR>        dos.writeUTF(userName);<BR>        dos.writeUTF(email);<BR>        dos.writeInt(age);<BR>        dos.writeBoolean(gender);<BR>        <BR>    }</P> <P>    public static Account deserialize(DataInputStream dis) throws IOException<BR>    {<BR>        Account account = new Account();<BR>        account.userName = dis.readUTF();<BR>        account.email = dis.readUTF();<BR>        account.age = dis.readInt();<BR>        account.gender = dis.readBoolean();<BR>       <BR>        return account;<BR>    }</P> <P>    public String toString()<BR>    {<BR>        return "UserName = " + userName + " Email = " + email + " age = " + age<BR>                + " gender = " + (gender ? "male" : "female");<BR>    }<BR>}<BR>~译q行E序在控制台输出Q?BR>before serialization.........<BR>UserName = mingjava Email = <A href="mailto:eric.zhan@263.net"><FONT color=#666666>eric.zhan@263.net</FONT></A> age = 25 gender = male<BR>after serialization..........<BR>UserName = mingjava Email = <A href="mailto:eric.zhan@263.net"><FONT color=#666666>eric.zhan@263.net</FONT></A> age = 25 gender = male<BR>序列化成功,后面我将讲述如何在J2ME联网中用序列化机制?/P></SPAN></SPAN><img src ="http://www.tkk7.com/licheng700/aggbug/13367.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/licheng700/" target="_blank">v?/a> 2005-09-19 09:26 <a href="http://www.tkk7.com/licheng700/archive/2005/09/19/13367.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.tkk7.com/" title="亚洲av成人片在线观看">亚洲av成人片在线观看</a> <div class="friend-links"> </div> </div> </footer> վ֩ģ壺 <a href="http://szzrjk.com" target="_blank">avƬ߹ۿ</a>| <a href="http://guakao88.com" target="_blank">ҹƵѹۿ</a>| <a href="http://dbyssw.com" target="_blank">ɫһëƬ</a>| <a href="http://517fanfan.com" target="_blank">Ļ</a>| <a href="http://331927.com" target="_blank">AV뾫ƷһٶӰԺ</a>| <a href="http://djqq520.com" target="_blank">ĻȫƵ </a>| <a href="http://yy7699.com" target="_blank">ޱavӲʵ</a>| <a href="http://246210.com" target="_blank">޹Ʒһ </a>| <a href="http://941sese.com" target="_blank">ۺ޾Ʒ</a>| <a href="http://yuejiju.com" target="_blank">ѹۿձwwվһ</a>| <a href="http://xww678.com" target="_blank">ӰԺѹۿ</a>| <a href="http://9981tv.com" target="_blank">Ʒ99Ʒþ</a>| <a href="http://hssw1688.com" target="_blank">Ʒ97˳Ƶ</a>| <a href="http://gzltchem.com" target="_blank">ҳڻӭ</a>| <a href="http://www003924.com" target="_blank">޾Ʒ456˳</a>| <a href="http://2828228.com" target="_blank">þ޴ɫĻþþ</a>| <a href="http://paweax.com" target="_blank">޾ƷþþþþðĦ</a>| <a href="http://011107.com" target="_blank">ѹҹ</a>| <a href="http://siqingsizu.com" target="_blank">ëƬѹۿ</a>| <a href="http://778002.com" target="_blank">AVһ</a>| <a href="http://qulu999.com" target="_blank">þ޾Ʒ</a>| <a href="http://500308k.com" target="_blank">˿wwwƵ</a>| <a href="http://ynkaishan.com" target="_blank">jizzѹۿƵ</a>| <a href="http://dasheng178.com" target="_blank">VA߹ۿ</a>| <a href="http://klno1.com" target="_blank">bbbѹۿƵ</a>| <a href="http://yeyaweiban.com" target="_blank">avƬvrһ</a>| <a href="http://www-282555.com" target="_blank">˳޵һվ߲</a>| <a href="http://664403.com" target="_blank">þþþAVרJN</a>| <a href="http://szgreater.com" target="_blank">޹˾þþƷӰ</a>| <a href="http://sqmdjz.com" target="_blank">޵һAAAAAƬ</a>| <a href="http://dt677.com" target="_blank">þ޾Ʒ</a>| <a href="http://bb927bb.com" target="_blank">޹ƷߵӰ</a>| <a href="http://19933k.com" target="_blank">AVƷ鶹</a>| <a href="http://8b22.com" target="_blank">AVþþƷ</a>| <a href="http://zhaosifuwang.com" target="_blank">þ91˳ɵӰվ</a>| <a href="http://jipiao020.com" target="_blank">˳ͼƬС˵վ</a>| <a href="http://shmtweld.com" target="_blank">޾ƷMV߹ۿ</a>| <a href="http://aierphoto.com" target="_blank">þҹɫƷ</a>| <a href="http://diswooo.com" target="_blank">AV</a>| <a href="http://ytshdiping.com" target="_blank">AVպAV߳ר</a>| <a href="http://am3736.com" target="_blank">һ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>