??xml version="1.0" encoding="utf-8" standalone="yes"?> 在此我们先来明确一下我们的前提条g。该对象臛_有一个synchronizedҎQ否则这个keyq有啥意义。当然也׃会有我们的这个主题了?/p>
一个h惌入某间上了锁的房_他来到房子门口,看见钥匙在那儿(说明暂时q没有其他h要用上锁的戉KQ。于是他CLC钥匙Qƈ且按照自q计划使用那些戉K。注意一点,他每ơ用完一ơ上锁的戉K后会马上把钥匙还回去。即使他要连l用两间上锁的戉KQ中间他也要把钥匙还回去Q再取回来?/p>
因此Q普通情况下钥匙的用原则是Q?#8220;随用随借,用完卌?#8221; q时其他人可以不受限制的使用那些不上锁的戉KQ一个h用一间可以,两个人用一间也可以Q没限制。但是如果当某个人想要进入上锁的戉KQ他p跑到大门口去看看了。有钥匙当然拿了pQ没有的话,只能等了?/p>
要是很多人在{这把钥匙,{钥匙还回来以后Q谁会优先得到钥匙?Not guaranteed。象前面例子里那个想q箋使用两个上锁戉K的家伙,他中间还钥匙的时候如果还有其他h在等钥匙Q那么没有Q何保证这家伙能再ơ拿到。(JAVA规范在很多地斚w明确说明不保证,象Thread.sleep()休息后多久会q回q行Q相同优先权的线E那个首先被执行Q当要访问对象的锁被释放后处于等待池的多个线E哪个会优先得到Q等{。我xl的军_权是在JVMQ之所以不保证Q就是因为JVM在做Zq决定的时候,l不是简单单Ҏ一个条件来做出判断Q而是Ҏ很多条。而由于判断条件太多,如果说出来可能会影响JAVA的推q,也可能是因ؓ知识产权保护的原因吧。SUNl了个不保证q去了。无可厚非。但我相信这些不定Qƈ非完全不定。因机q东西本w就是按指oq行的。即使看h很随机的现象Q其实都是有规律可寻。学q计机的都知道Q计机里随机数的学名是伪随机数Q是用一定的Ҏ写出来的Q看上去随机|了。另外,或许是因惛_的确定太费事Q也没多大意义,所以不定׃定了吧。) 再来看看同步代码块。和同步Ҏ有小的不同?/p>
1.从尺怸Ԍ同步代码块比同步Ҏ。你可以把同步代码块看成是没上锁戉K里的一块用带锁的屏风隔开的空间?/p>
2.同步代码块还可以Zؓ的指定获得某个其它对象的key。就像是指定用哪一把钥匙才能开q个屏风的锁Q你可以用本房的钥匙Q你也可以指定用另一个房子的钥匙才能开Q这L话,你要跑到另一栋房子那儿把那个钥匙拿来Qƈ用那个房子的钥匙来打开q个房子的带锁的屏风?/p>
C你获得的那另一栋房子的钥匙Qƈ不媄响其他hq入那栋房子没有锁的戉K?/p>
Z么要使用同步代码块呢Q我惛_该是q样的:首先对程序来讲同步的部分很媄响运行效率,而一个方法通常是先创徏一些局部变量,再对q些变量做一些操作,如运,昄{等Q而同步所覆盖的代码越多,Ҏ率的影响p严重。因此我们通常量~小其媄响范围。如何做Q同步代码块。我们只把一个方法中该同步的地方同步Q比如运?/p>
另外Q同步代码块可以指定钥匙q一特点有个额外的好处,是可以在一定时期内霸占某个对象的key。还记得前面说过普通情况下钥匙的用原则吗。现在不是普通情况了。你所取得的那把钥匙不是永q不q,而是在退出同步代码块时才q?/p>
q用前面那个惌l用两个上锁戉K的家伙打比方。怎样才能在用完一间以后,l箋使用另一间呢。用同步代码块吧。先创徏另外一个线E,做一个同步代码块Q把那个代码块的锁指向这个房子的钥匙。然后启动那个线E。只要你能在q入那个代码块时抓到q房子的钥匙Q你可以一直保留到退出那个代码块。也是说你甚至可以Ҏ房内所有上锁的戉K遍历Q甚臛_sleep(10*60*1000)Q而房门口却还?000个线E在{这把钥匙呢。很q瘾吧?/p>
在此对sleep()Ҏ和钥匙的兌性讲一下。一个线E在拿到key后,且没有完成同步的内容Ӟ如果被强制sleep()了,那keyq一直在它那ѝ直到它再次q行Q做完所有同步内容,才会归还key。记住,那家伙只是干zd累了Q去休息一下,他ƈ没干完他要干的事。ؓ了避免别入那个房间把里面搞的一团糟Q即使在睡觉的时候他也要把那唯一的钥匙戴在n上?/p>
最后,也许有h会问Qؓ什么要一把钥匙通开Q而不是一个钥匙一个门呢?我想q纯_Ҏ因ؓ复杂性问题。一个钥匙一个门当然更安全,但是会牵扯好多问题。钥匙的产生Q保,获得Q归q等{。其复杂性有可能随同步方法的增加呈几何数增加,严重影响效率?/p>
q也是一个权衡的问题吧。ؓ了增加一点点安全性,D效率大大降低Q是多么不可取啊?/p>
摘自Qhttp://www.54bk.com/more.asp?name=czp&id=2097 一、当两个q发U程讉K同一个对象object中的q个synchronized(this)同步代码块时Q一个时间内只能有一个线E得到执行。另一个线E必ȝ待当前线E执行完q个代码块以后才能执行该代码块?/p>
二、然而,当一个线E访问object的一个synchronized(this)同步代码块时Q另一个线E仍然可以访问该object中的非synchronized(this)同步代码块?/p>
三、尤其关键的是,当一个线E访问object的一个synchronized(this)同步代码块时Q其他线E对object中所有其它synchronized(this)同步代码块的讉K被d?/p>
四、第三个例子同样适用其它同步代码块。也是_当一个线E访问object的一个synchronized(this)同步代码块时Q它p得了q个object的对象锁。结果,其它U程对该object对象所有同步代码部分的讉K都被暂时d?/p>
五、以上规则对其它对象锁同样适用. 举例说明Q?/p>
一、当两个q发U程讉K同一个对象object中的q个synchronized(this)同步代码块时Q一个时间内只能有一个线E得到执行。另一个线E必ȝ待当前线E执行完q个代码块以后才能执行该代码块?/p>
package ths; public class Thread1 implements Runnable { l果Q?/p>
A synchronized loop 0 二、然而,当一个线E访问object的一个synchronized(this)同步代码块时Q另一个线E仍然可以访问该object中的非synchronized(this)同步代码块?/p>
package ths; public class Thread2 { l果Q?/p>
t1 : 4 三、尤其关键的是,当一个线E访问object的一个synchronized(this)同步代码块时Q其他线E对object中所有其它synchronized(this)同步代码块的讉K被d?/p>
//修改Thread2.m4t2()ҎQ?/p>
public void m4t2() { } l果Q?/p>
t1 : 4 四、第三个例子同样适用其它同步代码块。也是_当一个线E访问object的一个synchronized(this)同步代码块时Q它p得了q个object的对象锁。结果,其它U程对该object对象所有同步代码部分的讉K都被暂时d?/p>
//修改Thread2.m4t2()Ҏ如下Q?/p>
public synchronized void m4t2() { l果Q?/p>
t1 : 4 五、以上规则对其它对象锁同样适用: package ths; public class Thread3 { l果Q?/p>
管U程t1获得了对Inner的对象锁Q但׃U程t2讉K的是同一个Inner中的非同步部分。所以两个线E互不干扰?/p>
t1 : Inner.m4t1()=4 现在在Inner.m4t2()前面加上synchronizedQ?/p>
private synchronized void m4t2() { l果Q?/p>
管U程t1与t2讉K了同一个Inner对象中两个毫不相关的部分,但因为t1先获得了对Inner的对象锁Q所以t2对Inner.m4t2()的访问也被阻塞,因ؓm4t2()是Inner中的一个同步方法?/p>
t1 : Inner.m4t1()=4
public void run() {
synchronized(this) {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " synchronized loop " + i);
}
}
}
public static void main(String[] args) {
Thread1 t1 = new Thread1();
Thread ta = new Thread(t1, "A");
Thread tb = new Thread(t1, "B");
ta.start();
tb.start();
}
}
A synchronized loop 1
A synchronized loop 2
A synchronized loop 3
A synchronized loop 4
B synchronized loop 0
B synchronized loop 1
B synchronized loop 2
B synchronized loop 3
B synchronized loop 4
public void m4t1() {
synchronized(this) {
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
}
public void m4t2() {
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
public static void main(String[] args) {
final Thread2 myt2 = new Thread2();
Thread t1 = new Thread(
new Runnable() {
public void run() {
myt2.m4t1();
}
}, "t1"
);
Thread t2 = new Thread(
new Runnable() {
public void run() {
myt2.m4t2();
}
}, "t2"
);
t1.start();
t2.start();
}
}
t2 : 4
t1 : 3
t2 : 3
t1 : 2
t2 : 2
t1 : 1
t2 : 1
t1 : 0
t2 : 0
synchronized(this) {
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
t1 : 3
t1 : 2
t1 : 1
t1 : 0
t2 : 4
t2 : 3
t2 : 2
t2 : 1
t2 : 0
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
t1 : 3
t1 : 2
t1 : 1
t1 : 0
t2 : 4
t2 : 3
t2 : 2
t2 : 1
t2 : 0
class Inner {
private void m4t1() {
int i = 5;
while(i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : Inner.m4t1()=" + i);
try {
Thread.sleep(500);
} catch(InterruptedException ie) {
}
}
}
private void m4t2() {
int i = 5;
while(i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : Inner.m4t2()=" + i);
try {
Thread.sleep(500);
} catch(InterruptedException ie) {
}
}
}
}
private void m4t1(Inner inner) {
synchronized(inner) { //使用对象?
inner.m4t1();
}
}
private void m4t2(Inner inner) {
inner.m4t2();
}
public static void main(String[] args) {
final Thread3 myt3 = new Thread3();
final Inner inner = myt3.new Inner();
Thread t1 = new Thread(
new Runnable() {
public void run() {
myt3.m4t1(inner);
}
}, "t1"
);
Thread t2 = new Thread(
new Runnable() {
public void run() {
myt3.m4t2(inner);
}
}, "t2"
);
t1.start();
t2.start();
}
}
t2 : Inner.m4t2()=4
t1 : Inner.m4t1()=3
t2 : Inner.m4t2()=3
t1 : Inner.m4t1()=2
t2 : Inner.m4t2()=2
t1 : Inner.m4t1()=1
t2 : Inner.m4t2()=1
t1 : Inner.m4t1()=0
t2 : Inner.m4t2()=0
int i = 5;
while(i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : Inner.m4t2()=" + i);
try {
Thread.sleep(500);
} catch(InterruptedException ie) {
}
}
}
t1 : Inner.m4t1()=3
t1 : Inner.m4t1()=2
t1 : Inner.m4t1()=1
t1 : Inner.m4t1()=0
t2 : Inner.m4t2()=4
t2 : Inner.m4t2()=3
t2 : Inner.m4t2()=2
t2 : Inner.m4t2()=1
t2 : Inner.m4t2()=0
]]>
tar [-cxtzjvfpPN] 文g与目?br />
参数说明Q?br />
-c Q徏立一个打包文Ӟ
-x Q解开一个打包文Ӟ
-t Q查?tar包里面的文gQ?br />
Q特别注意,在选择参数Ӟc/x/t仅能存在一个,不可同时存在Q因Z可能同时压羃与解压羃。)
-z Q打包后用gzip压羃Q生?tar.gz文gQ?br />
-j Q打包后用zip2压羃Q生?tar.bz2文gQ?br />
-v Q压~的q程中显C文Ӟ
-f Q用文件名Q请留意Q在f之后要立x文g名,不要再加其它参数Q?br />
-p Q保持原文g的属性;
-P Q用绝对\径来压羃Q?br />
-N Q设定日?yyyy/mm/dd)Q比后面接的日期q要新的文g才会被打包进新徏的文件中Q?br />
--exclude FILEQ在打包的过E中Q不要将FILE打包?/p>
丑և个例子:
例一Q将整个/etc目录下的文g全部打包成ؓ/tmp/etc.tar
tar -cvf /tmp/etc.tar /etc #仅打包,不压~?br />
tar -zcvf /tmp/etc.tar.gz /etc #打包后,以gzip压羃
tar -jcvf /tmp/etc.tar.bz2 /etc #打包后,以bzip2压羃
例二Q查阅上q?tmp/etc.tar.gz文g内有哪些文g
tar -ztvf /tmp/etc.tar.gz
例三Q将/tmp/etc.tar.gz文g解压~到/usr/local/src?br />
cd /usr/local/src #先将工作目录变换?usr/local/src?br />
tar -zxvf /tmp/etc.tar.gz
例四Q只?tmp/etc.tar.gz内的etc/passwd解压?tmp?br />
cd /tmp
tar -zxvf /tmp/etc.tar.gz etc/passwd
例五Q将/etc内的所有文件备份下来,q且保存其权限!
tar -zxvpf /tmp/etc.tar.gz /etc
例六Q在/home当中Q比2005/06/01新的文g才备?br /> tar -N '2005/06/01' -zcvf home.tar.gz /home
例七Q备?home?etcQ但不要/home/dmtsai
tar --exclude /home/dmtsai -zcvf myfile.tar.gz /home/* /etc
例八Q将/etc打包后直接解开?tmp底下Q而不产生文gQ?br />
cd /tmp
tar -cvf - /etc | tar -xvf -
现在有一个需求,不知道该如何才能实现
压羃Q?tar czvf /data/backup/test.tar.gz /data/a/b/directory
解压Q?br />
cd /data/test
tar xzvf /data/backup/test.tar.gz
问题是,解压后的文gQ在/data/test/data/a/b/directory里面
能否压羃时只保留directory以下的所有目录,以directory作ؓ/Q而不?data/a/b/directoryQ?br />
问题已经解决Q找CGNU tar的官方资?br />
http://www.delorie.com/gnu/docs/tar/tar_98.html
q样写就可以解决?br />
tar czvf /data/backup/test.tar.gz /data/a/b/directory
Ҏ
tar czvf /data/backup/test.tar.gz -C /data/a/b(I格)directory
-C是时切换工作目录,-P是绝对\径,在这里只用到-C参数p?/p>
?QJava 允许多种道生成Class object?br>
Java classes l成分析
首先Ҏ以图3的java.util.LinkedListZQ将Java class的定义大卸八块,每一块分别对应图4所C的Reflection API。图5则是“获得class各区块信?#8221;的程序示例及执行l果Q它们都取自本文CZE序的对应片Dc?br>
package java.util; //(1)
import java.lang.*; //(2)
public class LinkedList<E> //(3)(4)(5)
extends AbstractSequentialList<E> //(6)
implements List<E>, Queue<E>,
Cloneable, java.io.Serializable //(7)
{
private static class Entry<E> { … }//(8)
public LinkedList() { … } //(9)
public LinkedList(Collection<? extends E> c) { … }
public E getFirst() { … } //(10)
public E getLast() { … }
private transient Entry<E> header = …; //(11)
private transient int size = 0;
}
?Q将一个Java class 大卸八块Q每块相应于一个或一lReflection APIsQ图4Q?br>
Java classes 各成份所对应的Reflection APIs
?的各个Java class成䆾Q分别对应于?的Reflection APIQ其中出现的Package、Method、Constructor、Field{等classesQ都定义于java.lang.reflect?br>Java class 内部模块Q参见图3Q?Java class 内部模块说明 相应之Reflection APIQ多半ؓClass methods?q回值类?return type)
(1) package class隶属哪个package getPackage() Package
(2) import class导入哪些classes 无直接对应之API?br>解决办法见图5-2?nbsp;
(3) modifier classQ或methods, fieldsQ的属?br> int getModifiers()
Modifier.toString(int)
Modifier.isInterface(int) int
String
bool
(4) class name or interface name class/interface 名称getName() String
(5) type parameters 参数化类型的名称 getTypeParameters() TypeVariable <Class>[]
(6) base class base classQ只可能一个) getSuperClass() Class
(7) implemented interfaces 实现有哪些interfaces getInterfaces() Class[]
(8) inner classes 内部classes getDeclaredClasses() Class[]
(8') outer class 如果我们观察的class 本n是inner classesQ那么相对它׃有个outer class?getDeclaringClass() Class
(9) constructors 构造函数getDeclaredConstructors() 不论 public 或private 或其它access levelQ皆可获得。另有功能近g取得函数?Constructor[]
(10) methods 操作函数getDeclaredMethods() 不论 public 或private 或其它access levelQ皆可获得。另有功能近g取得函数?Method[]
(11) fields 字段Q成员变量) getDeclaredFields()不论 public 或private 或其它access levelQ皆可获得。另有功能近g取得函数?Field[]
?QJava class大卸八块后(如图3Q,每一块所对应的Reflection API。本表ƈ?br>Reflection APIs 的全部?br>
Java Reflection API q用CZ
?C?提过的每一个Reflection APIQ及其执行结果。程序中出现的tName()是个辅助函数Q可其W一自变量所代表?#8220;Java class完整路径字符?#8221;剥除路径部分Q留下class名称Q储存到W二自变量所代表的一个hashtabledƈq回Q如果第二自变量为nullQ就不储存而只是返回)?br>
#001 Class c = null;
#002 c = Class.forName(args[0]);
#003
#004 Package p;
#005 p = c.getPackage();
#006
#007 if (p != null)
#008 System.out.println("package "+p.getName()+";");
执行l果Q例Q:
package java.util;
?-1Q找出class 隶属的package。其中的cl沿用于以下各程序片Dc?br>
#001 ff = c.getDeclaredFields();
#002 for (int i = 0; i < ff.length; i++)
#003 x = tName(ff[i].getType().getName(), classRef);
#004
#005 cn = c.getDeclaredConstructors();
#006 for (int i = 0; i < cn.length; i++) {
#007 Class cx[] = cn[i].getParameterTypes();
#008 for (int j = 0; j < cx.length; j++)
#009 x = tName(cx[j].getName(), classRef);
#010 }
#011
#012 mm = c.getDeclaredMethods();
#013 for (int i = 0; i < mm.length; i++) {
#014 x = tName(mm[i].getReturnType().getName(), classRef);
#015 Class cx[] = mm[i].getParameterTypes();
#016 for (int j = 0; j < cx.length; j++)
#017 x = tName(cx[j].getName(), classRef);
#018 }
#019 classRef.remove(c.getName()); //不必记录自己Q不需import 自己Q?br>
执行l果Q例Q:
import java.util.ListIterator;
import java.lang.Object;
import java.util.LinkedList$Entry;
import java.util.Collection;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
?-2Q找出导入的classesQ动作细节详见内文说明?br>
#001 int mod = c.getModifiers();
#002 System.out.print(Modifier.toString(mod)); //整个modifier
#003
#004 if (Modifier.isInterface(mod))
#005 System.out.print(" "); //关键?"interface" 已含于modifier
#006 else
#007 System.out.print(" class "); //关键?"class"
#008 System.out.print(tName(c.getName(), null)); //class 名称
执行l果Q例Q:
public class LinkedList
?-3Q找出class或interface 的名Uͼ及其属性(modifiersQ?br>
#001 TypeVariable<Class>[] tv;
#002 tv = c.getTypeParameters(); //warning: unchecked conversion
#003 for (int i = 0; i < tv.length; i++) {
#004 x = tName(tv[i].getName(), null); //例如 E,K,V...
#005 if (i == 0) //W一?br>#006 System.out.print("<" + x);
#007 else //非第一?br>#008 System.out.print("," + x);
#009 if (i == tv.length-1) //最后一?br>#010 System.out.println(">");
#011 }
执行l果Q例Q:
public abstract interface Map<K,V>
或public class LinkedList<E>
?-4Q找出parameterized types 的名U?br>
#001 Class supClass;
#002 supClass = c.getSuperclass();
#003 if (supClass != null) //如果有super class
#004 System.out.print(" extends" +
#005 tName(supClass.getName(),classRef));
执行l果Q例Q:
public class LinkedList<E>
extends AbstractSequentialList,
?-5Q找出base class。执行结果多Z个不该有的逗号于尾端。此非本处重点,为简化计Q不多做处理?br>
#001 Class cc[];
#002 Class ctmp;
#003 //扑և所有被实现的interfaces
#004 cc = c.getInterfaces();
#005 if (cc.length != 0)
#006 System.out.print(", \r\n" + " implements "); //关键?br>#007 for (Class cite : cc) //JDK1.5 新式循环写法
#008 System.out.print(tName(cite.getName(), null)+", ");
执行l果Q例Q:
public class LinkedList<E>
extends AbstractSequentialList,
implements List, Queue, Cloneable, Serializable,
?-6Q找出implemented interfaces。执行结果多Z个不该有的逗号于尾端。此非本处重点,为简化计Q不多做处理?br>
#001 cc = c.getDeclaredClasses(); //扑ևinner classes
#002 for (Class cite : cc)
#003 System.out.println(tName(cite.getName(), null));
#004
#005 ctmp = c.getDeclaringClass(); //扑ևouter classes
#006 if (ctmp != null)
#007 System.out.println(ctmp.getName());
执行l果Q例Q:
LinkedList$Entry
LinkedList$ListItr
?-7Q找出inner classes 和outer class
#001 Constructor cn[];
#002 cn = c.getDeclaredConstructors();
#003 for (int i = 0; i < cn.length; i++) {
#004 int md = cn[i].getModifiers();
#005 System.out.print(" " + Modifier.toString(md) + " " +
#006 cn[i].getName());
#007 Class cx[] = cn[i].getParameterTypes();
#008 System.out.print("(");
#009 for (int j = 0; j < cx.length; j++) {
#010 System.out.print(tName(cx[j].getName(), null));
#011 if (j < (cx.length - 1)) System.out.print(", ");
#012 }
#013 System.out.print(")");
#014 }
执行l果Q例Q:
public java.util.LinkedList(Collection)
public java.util.LinkedList()
?-8aQ找出所有constructors
#004 System.out.println(cn[i].toGenericString());
执行l果Q例Q:
public java.util.LinkedList(java.util.Collection<? extends E>)
public java.util.LinkedList()
?-8bQ找出所有constructors。本例在for 循环内用toGenericString()Q省事?br>
#001 Method mm[];
#002 mm = c.getDeclaredMethods();
#003 for (int i = 0; i < mm.length; i++) {
#004 int md = mm[i].getModifiers();
#005 System.out.print(" "+Modifier.toString(md)+" "+
#006 tName(mm[i].getReturnType().getName(), null)+" "+
#007 mm[i].getName());
#008 Class cx[] = mm[i].getParameterTypes();
#009 System.out.print("(");
#010 for (int j = 0; j < cx.length; j++) {
#011 System.out.print(tName(cx[j].getName(), null));
#012 if (j < (cx.length - 1)) System.out.print(", ");
#013 }
#014 System.out.print(")");
#015 }
执行l果Q例Q:
public Object get(int)
public int size()
?-9aQ找出所有methods
#004 System.out.println(mm[i].toGenericString());
public E java.util.LinkedList.get(int)
public int java.util.LinkedList.size()
?-9bQ找出所有methods。本例在for 循环内用toGenericString()Q省事?br>
#001 Field ff[];
#002 ff = c.getDeclaredFields();
#003 for (int i = 0; i < ff.length; i++) {
#004 int md = ff[i].getModifiers();
#005 System.out.println(" "+Modifier.toString(md)+" "+
#006 tName(ff[i].getType().getName(), null) +" "+
#007 ff[i].getName()+";");
#008 }
执行l果Q例Q:
private transient LinkedList$Entry header;
private transient int size;
?-10aQ找出所有fields
#004 System.out.println("G: " + ff[i].toGenericString());
private transient java.util.LinkedList.java.util.LinkedList$Entry<E> ??
java.util.LinkedList.header
private transient int java.util.LinkedList.size
?-10bQ找出所有fields。本例在for 循环内用toGenericString()Q省事?br>
扑ևclass参用Q导入)的所有classes
没有直接可用的Reflection API可以为我们找出某个class参用的所有其它classes。要获得q项信息Q必d苦工Q一步一脚印逐一记录。我们必观察所有fields的类型、所有methodsQ包括constructorsQ的参数cd和回q类型,剔除重复Q留下唯一。这正是Z么图5-2E序代码要ؓtName()指定一个hashtableQ而非一个nullQ做为第二自变量的缘故:hashtable可ؓ我们储存元素Q本例ؓ字符ԌQ又保证不重复?br>
本文讨论xQ几乎可以还原一个class的原貌(唯有methods 和ctors的定义无法取得)。接下来讨论Reflection 的另三个动态性质Q?1) q行时生成instancesQ?2) ?br>行期唤vmethodsQ?3) q行时改动fields?br>
q行时生成instances
Ʋ生成对象实体,在Reflection 动态机制中有两U作法,一个针?#8220;无自变量ctor”Q?br>一个针?#8220;带参数ctor”。图6是面?#8220;无自变量ctor”的例子。如果欲调用的是“带参数ctor“比较麻烦些Q图7是个例子Q其中不再调用Class的newInstance()Q而是调用Constructor 的newInstance()。图7首先准备一个Class[]做ؓctor的参数类型(本例指定Z个double和一个intQ,然后以此变量调用getConstructor()Q获得一个专属ctor。接下来再准备一个Object[] 做ؓctor实参|本例指定3.14159?25Q,调用上述专属ctor的newInstance()?br>
#001 Class c = Class.forName("DynTest");
#002 Object obj = null;
#003 obj = c.newInstance(); //不带自变?br>#004 System.out.println(obj);
?Q动态生?#8220;Class object 所对应之class”的对象实体;无自变量?br>
#001 Class c = Class.forName("DynTest");
#002 Class[] pTypes = new Class[] { double.class, int.class };
#003 Constructor ctor = c.getConstructor(pTypes);
#004 //指定parameter listQ便可获得特定之ctor
#005
#006 Object obj = null;
#007 Object[] arg = new Object[] {3.14159, 125}; //自变?br>#008 obj = ctor.newInstance(arg);
#009 System.out.println(obj);
?Q动态生?#8220;Class object 对应之class”的对象实体;自变量以Object[]表示?br>
q行时调用methods
q个动作和上q调?#8220;带参Cctor”相当cM。首先准备一个Class[]做ؓctor的参数类型(本例指定其中一个是StringQ另一个是HashtableQ,然后以此变量调用getMethod()Q获得特定的Method object。接下来准备一个Object[]攄自变量,然后调用上述所得之特定Method object的invoke()Q如?。知道ؓ什么烦取Method object时不需指定回返cd吗?因ؓmethod overloading机制要求signatureQv名式Q必d一Q而回q类型ƈ非signature的一个成份。换句话_只要指定了method名称和参数列Q就一定指Z一个独一无二的method?br>
#001 public String func(String s, Hashtable ht)
#002 {
#003 …System.out.println("func invoked"); return s;
#004 }
#005 public static void main(String args[])
#006 {
#007 Class c = Class.forName("Test");
#008 Class ptypes[] = new Class[2];
#009 ptypes[0] = Class.forName("java.lang.String");
#010 ptypes[1] = Class.forName("java.util.Hashtable");
#011 Method m = c.getMethod("func",ptypes);
#012 Test obj = new Test();
#013 Object args[] = new Object[2];
#014 arg[0] = new String("Hello,world");
#015 arg[1] = null;
#016 Object r = m.invoke(obj, arg);
#017 Integer rval = (String)r;
#018 System.out.println(rval);
#019 }
?Q动态唤起method
q行时变更fields内容
与先前两个动作相比,“变更field内容”L多了Q因为它不需要参数和自变量。首先调用Class的getField()q指定field名称。获得特定的Field object之后便可直接调用Field的get()和set()Q如??br>
#001 public class Test {
#002 public double d;
#003
#004 public static void main(String args[])
#005 {
#006 Class c = Class.forName("Test");
#007 Field f = c.getField("d"); //指定field 名称
#008 Test obj = new Test();
#009 System.out.println("d= " + (Double)f.get(obj));
#010 f.set(obj, 12.34);
#011 System.out.println("d= " + obj.d);
#012 }
#013 }
?Q动态变更field 内容
Java 源码改动办法
先前我曾提到Q原本想借由“改动Java标准库源?#8221;来测知Class object的生成,但由于其ctor原始设计为privateQ也是说不可能透过q个道生成Class objectQ而是由class loader负责生成Q,因此“在ctor中打印出某种信息”的企图也失M意义?br>
q里我要谈点题外话:如何修改Java标准库源码ƈ让它反应到我们的应用E序来。假设我想修改java.lang.ClassQ让它在某些情况下打印某U信息。首先必L出标准源码!当你下蝲JDK 套gq安装妥当,你会发现jdk150\src\java\lang 目录Q见?0Q之中有Class.javaQ这是我们此次行动的标准源码。备份后加以修改Q编译获得Class.class。接下来准备?class 搬移到jdk150\jre\lib\endorsedQ见?0Q?br>
q是一个十分特别的目录Qclass loader优先从该处d内含classes?jar文g——成功的条g?jar内的classes压羃路径必须和Java标准库的路径完全相同。ؓ此,我们可以刚才做出的Class.class先搬C个ؓ此目的而刻意做出来的\java\lang目录中,压羃为foo.zipQQ意命名,唯需夹带路径java\langQ,再将q个foo.zip搬到jdk150\jre\lib\endorsedq改名ؓfoo.jar。此后你的应用程序便会优先用上这里的java.lang.Class。整个过E可写成一个批处理文gQbatch fileQ,如图11Q在DOS Box中用?br>
?0QJDK1.5 安装后的目录l织。其中的endorsed 是我新徏?br>
del e:\java\lang\*.class //清理q净
del c:\jdk150\jre\lib\endorsed\foo.jar //清理q净
c:
cd c:\jdk150\src\java\lang
javac -Xlint:unchecked Class.java //~译源码
javac -Xlint:unchecked ClassLoader.java //~译另一个源码(如有必要Q?br>move *.class e:\java\lang //搬移臛_意制造的目录?br>e:
cd e:\java\lang //以下压羃至适当目录
pkzipc -add -path=root c:\jdk150\jre\lib\endorsed\foo.jar *.class
cd e:\test //q入试目录
javac -Xlint:unchecked Test.java //~译试E序
java Test //执行试E序
?1Q一个可在DOS Box中用的批处理文Ӟbatch fileQ,用以自动化java.lang.Class
的修改动作。Pkzipc(.exe)是个命o列压~工Padd和path都是其命令?br>
更多信息
以下是视野所及与本文主题相关的更多讨论。这些信息可以I补因文章幅限制而带来的不Q或带给您更多视野?br>
l "Take an in-depth look at the Java Reflection API -- Learn about the new Java 1.1 tools forfinding out information about classes", by Chuck McManis。此文章所附程序代码是本文CZE序的主要依据(本文CZE序C了更多Reflection APIsQƈ采用JDK1.5 新式的for-loop 写法Q?br>l
二、怎样才让在showModalDialog和showModelessDialog的超q接不弹出新H口Q?br /> 在被打开的网里加上<base target="_self">可以了。这句话一般是攑֜<html>?lt;body>之间的?/p>
三、怎样才刷新showModalDialog和showModelessDialog里的内容Q?br /> 在showModalDialog和showModelessDialog里是不能按F5h的,又不能弹单。这个只能依靠javascript了,以下是相关代码:
<body onkeydown="if (event.keyCode==116){reload.click()}">
<a id="reload" href="filename.htm" style="display:none">reload...</a>
filename.htm替换成网늚名字然后它攑ֈ你打开的网里Q按F5可以刷CQ注意,q个要配?lt;base target="_self">使用Q不然你按下F5会弹出新H口的?/p>
四、如何用javascriptxshowModalDialog(或showModelessDialog)打开的窗口?br /> <input type="button" value="关闭" onclick="window.close()">
也要配合<base target="_self">Q不然会打开一个新的IEH口Q然后再x的?/p>
五、showModalDialog和showModelessDialog数据传递技巧?br /> (作者语Q本来想用一问一{Ş式来写的Q但是我想不个怎么问,所以只好这样了?
q个东西比较ȝQ我改了好几ơ了不是没办法说明白(语文水^来差?Q只好用个例子说明了?br /> 例子Q?br /> 现在需要在一个showModalDialog(或showModelessDialog)里读取或讄一个变量var_name
一般的传递方式:
window.showModalDialog("filename.htm",var_name)
//传递var_name变量
在showModalDialog(或showModelessDialog)d和设|时Q?br /> alert(window.dialogArguments)//dvar_name变量
window.dialogArguments="oyiboy"http://讄var_name变量
q种方式是可以满的Q但是当你想在操作var_name同时再操作第二个变理var_id时呢Q就无法再进行操作了。这是q种传递方式的局限性?br />
以下是我使用的传递方式:
window.showModalDialog("filename.htm",window)
//不管要操作什么变量,只直传递主H口的window对象
在showModalDialog(或showModelessDialog)d和设|时Q?br /> alert(window.dialogArguments.var_name)//dvar_name变量
window.dialogArguments.var_name="oyiboy"http://讄var_name变量
同时我也可以操作var_id变量
alert(window.dialogArguments.var_id)//dvar_id变量
window.dialogArguments.var_id="001"http://讄var_id变量
同样q可以对ȝ口的M对象q行操作Q如form对象里的元素?br /> window.dialogArguments.form1.index1.value="q是在设|index1元素的?
六、多个showModelessDialog的相互操作?br /> 因ؓ光说很费Ԍ我就L懒,直接用代码来说了Q如果不明白的话那就直接来信(oyiboy#163.net(使用时请?Ҏ@))问我吧?/p>
以下代码的主要作用是在一个showModelessDialog里移动别一个showModelessDialog的位|?/p>
L件的部䆾js代码?br /> var s1=showModelessDialog('控制.htm',window,"dialogTop:1px;dialogLeft:1px"Q?//打开控制H口
var s2=showModelessDialog('about:blank',window,"dialogTop:200px;dialogLeft:300px"Q //打开被控制窗?/p>
控制.htm的部份代码?br /> <script>
//操作位置数据Q因为窗口的位置数据?xxxpx"方式的,所以需要这L一个特D操作函数?br /> function countNumber(A_strNumber,A_strWhatdo)
{
A_strNumber=A_strNumber.replace('px','')
A_strNumber-=0
switch(A_strWhatdo)
{
case "-":A_strNumber-=10;break;
case "+":A_strNumber+=10;break;
}
return A_strNumber + "px"
}
</script>
<input type="button" onclick="window.dialogArguments.s2.dialogTop=countNumber(window.dialogArguments.s2.dialogTop,'-')" value="上移">
<input type="button" onclick="window.dialogArguments.s2.dialogLeft=countNumber(window.dialogArguments.s2.dialogLeft,'-')" value="左移">
<input type="button" onclick="window.dialogArguments.s2.dialogLeft=countNumber(window.dialogArguments.s2.dialogLeft,'+')" value="右移">
<input type="button" onclick="window.dialogArguments.s2.dialogTop=countNumber(window.dialogArguments.s2.dialogTop,'+')" value="下移">
以上关键部䆾是:
H口命名方式Qvar s1=showModelessDialog('控制.htm',window,"dialogTop:1px;dialogLeft:1px"Q?br /> 变量讉K方式Qwindow.dialogArguments.s2.dialogTop
q个例子只是现实showModelessDialog与showModelessDialog之间的位|操作功能,通过q个原理Q在showModelessDialog之间怺控制各自的显C页面,传递变量和数据{。这要看各位的发挥了?/p>
showModalDialog()、showModelessDialog()Ҏ使用详解
javascript有许多内建的Ҏ来生对话框Q如Qwindow.alert(), window.confirm(),window.prompt().{?然而IE提供更多的方法支持对话框。如Q?/p>
showModalDialog() (IE 4+ 支持)
showModelessDialog() (IE 5+ 支持)
window.showModalDialog()Ҏ用来创徏一个显CHTML内容的模态对话框Q由于是对话框,因此它ƈ没有一般用window.open()打开的窗口的所有属性?br />window.showModelessDialog()Ҏ用来创徏一个显CHTML内容的非模态对话框?/p>
当我们用showModelessDialog()打开H口Ӟ不必用window.close()d闭它Q当以非模态方式EIE5Q打开Ӟ 打开对话框的H口仍可以进行其他的操作Q即对话框不L最上面的焦点,当打开它的H口QRQ改变时Q它自动关闭。而模态EQIQ]方式的对话框始终有焦点(焦点不可U走Q直到它关闭Q。模态对话框和打开它的H口相联p,因此我们打开另外的窗口时Q他们的链接关系依然保存Qƈ且隐藏在zdH口的下面?/p>
使用Ҏ如下Q?br />vReturnValue = window.showModalDialog(sURL [, vArguments] [, sFeatures])
vReturnValue = window.showModelessDialog(sURL [, vArguments] [, sFeatures])
参数说明Q?br />sURL
必选参敎ͼcdQ字W串。用来指定对话框要显C的文档的URL?br />vArguments
可选参敎ͼcdQ变体。用来向对话框传递参数。传递的参数cd不限Q包括数l等。对话框通过window.dialogArguments来取得传递进来的参数?br />sFeatures
可选参敎ͼcdQ字W串。用来描q对话框的外观等信息Q可以用以下的一个或几个Q用分号?”隔开?br />dialogHeight 对话框高度,不小于1Q0pxQテQ4中dialogHeight ?dialogWidth 默认的单位是emQ而テQ5中是pxQؓ方便其见Q在定义modal方式的对话框Ӟ用px做单位?br /> dialogWidth: 对话框宽度?br /> dialogLeft: 距离桌面左的距离?br /> dialogTop: L面上的距R?br /> center: {yes | no | 1 | 0 }Q窗口是否居中,默认yesQ但仍可以指定高度和宽度?br /> help: {yes | no | 1 | 0 }Q是否显C帮助按钮,默认yes?br /> resizable: {yes | no | 1 | 0 } QテQ5Q]Q是否可被改变大。默认no?br /> status: {yes | no | 1 | 0 } QIE5+Q:是否昄状态栏。默认ؓyes[ Modeless]或no[Modal]?br />scroll:{ yes | no | 1 | 0 | on | off }Q指明对话框是否昄滚动条。默认ؓyes?/p>
q有几个属性是用在HTA中的Q在一般的|页中一般不使用?br />dialogHide:{ yes | no | 1 | 0 | on | off }Q在打印或者打印预览时对话框是否隐藏。默认ؓno?br />edge:{ sunken | raised }Q指明对话框的边框样式。默认ؓraised?br />unadorned:{ yes | no | 1 | 0 | on | off }Q默认ؓno?/p>
传入参数Q?br />要想对话框传递参敎ͼ是通过vArguments来进行传递的。类型不限制Q对于字W串cdQ最大ؓ4096个字W。也可以传递对象,例如Q?/p>
test1.htm
====================
<script>
var mxh1 = new Array("mxh","net_lover","孟子E?)
var mxh2 = window.open("about:blank","window_mxh")
// 向对话框传递数l?br />window.showModalDialog("test2.htm",mxh1)
// 向对话框传递window对象
window.showModalDialog("test3.htm",mxh2)
</script>
test2.htm
====================
<script>
var a = window.dialogArguments
alert("您传递的参数为:" + a)
</script>
test3.htm
====================
<script>
var a = window.dialogArguments
alert("您传递的参数为window对象Q名Uͼ" + a.name)
</script>
可以通过window.returnValue向打开对话框的H口q回信息Q当然也可以是对象。例如:
test4.htm
===================
<script>
var a = window.showModalDialog("test5.htm")
for(i=0;i<a.length;i++) alert(a[i])
</script>
test5.htm
===================
<script>
function sendTo()
{
var a=new Array("a","b")
window.returnValue = a
window.close()
}
</script>
<body>
<form>
<input value="q回" type=button onclick="sendTo()">
</form>
常见问题Q?br />1Q如何在模态对话框中进行提交而不新开H口Q?br />如果??览器是IE5.5+,可以在对话框中用带name属性的iframeQ提交时可以制定targetiframe的name。对于IE4+Q你可以用高度ؓ0的frame来作Q例子,
test6.htm
===================
<script>
window.showModalDialog("test7.htm")
</script>
test7.htm
===================
if(window.location.search) alert(window.location.search)
<frameset rows="0,*">
<frame src="about:blank">
<frame src="test8.htm">
</frameset>
test8.htm
===================
<form target="_self" method="get">
<input name=txt value="test">
<input type=submit>
</form>
<script>
if(window.location.search) alert(window.location.search)
</script>
2,可以通过http://servername/virtualdirname/test.htm?name=mxh方式直接向对话框传递参数吗Q?br />{案是不能。但在frame里是可以的?/p>
extends Object
implements Enumeration<Object>
string tokenizer cd许应用程序将字符串分解ؓ标记。tokenization Ҏ?StreamTokenizer cL使用的方法更单。StringTokenizer Ҏ不区分标识符、数和带引号的字W串Q它们也不识别ƈ跌注释?/p>
可以在创建时指定Q也可以Ҏ每个标记来指定分隔符Q分隔标记的字符Q集合?/p>
StringTokenizer 的实例有两种行ؓ方式Q这取决于它在创建时使用?returnDelims 标志的值是 true q是 falseQ?/p>
如果标志?falseQ则分隔W字W用来分隔标记。标记是q箋字符Q不是分隔符Q的最大序列?
如果标志?trueQ则认ؓ那些分隔W字W本w即为标记。因此标记要么是一个分隔符字符Q要么是那些q箋字符Q不是分隔符Q的最大序列?
StringTokenizer 对象在内部维护字W串中要被标记的当前位置。某些操作将此当前位|移臛_处理的字W后?/p>
通过截取字符串的一个子串来q回标记Q该字符串用于创?StringTokenizer 对象?/p>
下面是一个?tokenizer 的实例。代码如下:
StringTokenizer st = new StringTokenizer("this is a test");
while (st.hasMoreTokens()) {
System.out.println(st.nextToken());
}
输出以下字符Ԍ
this
is
a
test
StringTokenizer 是出于兼Ҏ的原因而被保留的遗留类Q虽然在C码中q不鼓励使用它)。徏议所有寻求此功能的h使用 String ?split Ҏ?java.util.regex 包?/p>
下面的示例阐明了如何使用 String.split Ҏ字W串分解为基本标讎ͼ
String[] result = "this is a test".split("\\s");
for (int x=0; x<result.length; x++)
System.out.println(result[x]);
输出以下字符Ԍ
this
is
a
test
q几步是如果使用htmlarea3.0的说?是在|上看到? ?htmlarea/examples/web-menuq个文g里有更ؓ详细的说?下边的这个链接的版本是多国语a版本,默认的语a?
一
下蝲HTMLarea3.0 http://www.jhdown.com/soft/8/141/html/2006220010681.html,解压里面的文件到web站点?htmlarea目录?可以是自己徏的目?q里直接用htmlarea做ؓ目录)Q?/p>
二、定义javascript的全局变量及引入js文g:
<script type="text/javascript">
_editor_url = "${pageContext.request.contextPath}/htmlarea/";
_editor_lang = "en";
</script>
<script type="text/javascript" src="${pageContext.request.contextPath}/htmlarea/htmlarea.js"></script>
<script type="text/javascript">
var editor = null;
function initEditor() {
editor = new HTMLArea("content");
editor.generate();
}
</script>
有句editor = new HTMLArea("content");"content"是表单中textarea属性的idQ如Q?/p>
<html:form action="/actionBbsreply.do?method=update" onsubmit="this['content'].value=editor.getHTML();">
<textarea cols="110" rows="15" id="content" name="content">
<bean:write name="bbsreply" property="content"/>
</textarea>
<html:submit value=" ??">
</html:submit>
</html:form>
三、在body的onload事g中加载initEditor():
如:<body bgcolor="#ffffff" onload="initEditor()">
四、注意点:
1、editor = new HTMLArea("content");参数值是表单中textarea属性id;
2、在body的onload事g中加载initEditor()Q?/p>
3、表单onsubmit事g调用this['content'].value=editor.getHTML()
在用的q程中发?因ؓ默认是英文语?提示信息也是英文? q对于飞惯用中文的朋友来说很是不方便 ,如果要改变语a的话
_editor_lang = "en";
把上边代码里?_editor_lang="gb"理论上就可以? q样,当代码去q行的时候会?lang文g夹下的gb.js文g,但是作者发布这套源代码的时候jb.js里的中文是用iso8859-1~码?我用MyEclipse的javascriptEdit查看?MyEclipse?.js的默?打开的时候看到的全是q,q就D了在jsp面出现错误.解决的办法就是在改变gb.js的文件的属? 编码格式改为utf-8的格? 然后再加上en.js下边?br /> buttons: {
"ok": "定",
"cancel": "取消"
},
msg: {
"Path": "路径",
"TEXT_MODE": "现在模式是文本模? 按[<>]键切换到可视化编辑模?",
"IE-sucks-full-screen" :
// translate here
"The full screen mode is known to cause problems with Internet Explorer, " +
"due to browser bugs that we weren't able to workaround. You might experience garbage " +
"display, lack of editor functions and/or random browser crashes. If your system is Windows 9x " +
"it's very likely that you'll get a 'General Protection Fault' and need to reboot.\n\n" +
"You have been warned. Please press OK if you still want to try the full screen editor."
},
dialogs: {
"Cancel" : "Cancel",
"Insert/Modify Link" : "Insert/Modify Link",
"New window (_blank)" : "New window (_blank)",
"None (use implicit)" : "None (use implicit)",
"OK" : "OK",
"Other" : "Other",
"Same frame (_self)" : "Same frame (_self)",
"Target:" : "Target:",
"Title (tooltip):" : "Title (tooltip):",
"Top frame (_top)" : "Top frame (_top)",
"URL:" : "URL:",
"You must enter the URL where this link points to" : "You must enter the URL where this link points to"
}
q些代码.如果有需要的? 可以把右边属性的值翻译成汉语,q里q有一个要注意的地方就是要对照格式,我把我改正过的脓到这? 方便查看
// I18N constants -- Chinese GB
// by Dave Lo -- dlo@interactivetools.com
HTMLArea.I18N = {
// the following should be the filename without .js extension
// it will be used for automatically load plugin language.
lang: "gb",
tooltips: {
bold: "_体",
italic: "斜体",
underline: "底线",
strikethrough: "删除U?,
subscript: "下标",
superscript: "上标",
justifyleft: "位置靠左",
justifycenter: "位置居中",
justifyright: "位置靠右",
justifyfull: "位置左右q等",
orderedlist: "位置左右q等",
unorderedlist: "无序清单",
outdent: "减小行前I白",
indent: "加宽行前I白",
forecolor: "文字颜色",
backcolor: "背景颜色",
horizontalrule: "水^U?,
horizontalrule: "水^标尺",
createlink: "插入q结",
insertimage: "插入囑Ş",
inserttable: "插入表格",
htmlmode: "切换HTML原始?,
popupeditor: "攑֤",
about: "x HTMLArea",
help: "说明",
textindicator: "字体例子"
},
buttons: {
"ok": "定",
"cancel": "取消"
},
msg: {
"Path": "路径",
"TEXT_MODE": "现在模式是文本模? 按[<>]键切换到可视化编辑模?",
"IE-sucks-full-screen" :
// translate here
"The full screen mode is known to cause problems with Internet Explorer, " +
"due to browser bugs that we weren't able to workaround. You might experience garbage " +
"display, lack of editor functions and/or random browser crashes. If your system is Windows 9x " +
"it's very likely that you'll get a 'General Protection Fault' and need to reboot.\n\n" +
"You have been warned. Please press OK if you still want to try the full screen editor."
},
dialogs: {
"Cancel" : "Cancel",
"Insert/Modify Link" : "Insert/Modify Link",
"New window (_blank)" : "New window (_blank)",
"None (use implicit)" : "None (use implicit)",
"OK" : "OK",
"Other" : "Other",
"Same frame (_self)" : "Same frame (_self)",
"Target:" : "Target:",
"Title (tooltip):" : "Title (tooltip):",
"Top frame (_top)" : "Top frame (_top)",
"URL:" : "URL:",
"You must enter the URL where this link points to" : "You must enter the URL where this link points to"
}
};
呵呵.文g改好了以?把q个文g复制?plugins/?(在plugins下有5个子文g?每个又文件夹下有一个lang文g?把gb.js文g放进dOK?)
然后启动,成功?..^_^
赉|原?转蝲h?/p>
org.apache.struts.util.RequestUtils中的源代?br />
public static Actionform createActionform(
HttpServletRequest request,
ActionMapping mapping,
ModuleConfig moduleConfig,
ActionServlet servlet) {
............
............
String attribute = mapping.getAttribute();
......
Actionform instance = null;
HttpSession session = null;
if ("request".equals(mapping.getScope())) {
instance = (Actionform) request.getAttribute(attribute);
} else {
session = request.getSession();
instance = (Actionform) session.getAttribute(attribute);
}
................
................
}
如果没有配置attribute属性的? struts才会从name属性里d要创建的formbean 的名?q创Z下实?看下边的源代码就知道? 呵呵.
org.apache.struts.config.ActionConfig
protected String attribute = null;
public String getAttribute() {
//是q里?
if (this.attribute == null) {
return (this.name);
} else {
return (this.attribute);
}
}
public void setAttribute(String attribute) {
if (configured) {
throw new IllegalStateException("Configuration is frozen");
}
this.attribute = attribute;
}
errors.byte={0} must be an byte.
errors.short={0} must be an short.
errors.integer={0} must be an integer.
errors.long={0} must be an long.
errors.float={0} must be an float.
errors.double={0} must be an double.
errors.date={0} is not a date.
errors.range={0} is not in the range {1} through {2}.
errors.creditcard={0} is not a valid credit card number.
errors.email={0} is an invalid e-mail address.<p>
LogonForm.ipcode=<font color=blue>User name</font>
LogonForm.password=<font color=blue>User password</font>
{等你所惌d的信?br />
<script>window.location.href='url';</script>
<SCRIPT LANGUAGE="javascript">
<!--
window.open ('page.html', 'newwindow', 'height=100, width=400, top=0, left=0, toolbar=no, menubar=no, scrollbars=no, resizable=no,location=no, status=no')
//写成一?
-->
</SCRIPT>
参数解释Q?
<SCRIPT LANGUAGE="javascript"> js脚本开始;
window.open 弹出新窗口的命oQ?
'page.html' 弹出H口的文件名Q?
'newwindow' 弹出H口的名字(不是文g名)Q非必须Q可用空''代替Q?
height=100 H口高度Q?
width=400 H口宽度Q?
top=0 H口距离屏幕上方的象素|
left=0 H口距离屏幕左侧的象素|
toolbar=no 是否昄工具栏,yes为显C;
menubarQscrollbars 表示菜单栏和滚动栏?
resizable=no 是否允许改变H口大小Qyes为允许;
location=no 是否昄地址栏,yes为允许;
status=no 是否昄状态栏内的信息Q通常是文件已l打开Q,yes为允许;
</SCRIPT> js脚本l束
?、用函数控制弹出H口?
下面是一个完整的代码?
<html>
<head>
<script LANGUAGE="JavaScript">
<!--
function openwin() {
window.open ("page.html", "newwindow", "height=100, width=400, toolbar=no, menubar=no, scrollbars=no, resizable=no, location=no, status=no")
//写成一?
}
//-->
</script>
</head>
<body onload="openwin()">
...L的页面内?..
</body>
</html>
q里定义了一个函数openwin(),函数内容是打开一个窗口。在调用它之前没有Q何用途?
怎么调用呢?
Ҏ一Q?lt;body onload="openwin()"> 览器读面时弹出窗口;
Ҏ二:<body onunload="openwin()"> 览器离开面时弹出窗口;
Ҏ三:用一个连接调用:
<a href="#" onclick="openwin()">打开一个窗?lt;/a>
注意Q用的?”是虚连接?
Ҏ四:用一个按钮调用:
<input type="button" onclick="openwin()" value="打开H口">
?、同时弹?个窗口?
Ҏ代码E微改动一下:
<script LANGUAGE="JavaScript">
<!--
function openwin() {
window.open ("page.html", "newwindow", "height=100, width=100, top=0, left=0,toolbar=no, menubar=no, scrollbars=no, resizable=no, location=no, status=no")
//写成一?
window.open ("page2.html", "newwindow2", "height=100, width=100, top=100, left=100,toolbar=no, menubar=no, scrollbars=no, resizable=no, location=no, status=no")
//写成一?
}
//-->
</script>
为避免弹出的2个窗口覆盖,用top和left控制一下弹出的位置不要怺覆盖卛_。最后用上面说过的四U方法调用即可?
注意Q?个窗口的name(newwindows和newwindow2)不要相同Q或者干脆全部ؓI。OKQ?
?、主H口打开文g1.htmQ同时弹出小H口page.html?
如下代码加入ȝ?lt;head>区:
<script language="javascript">
<!--
function openwin() {
window.open("page.html","","width=200,height=200")
}
//-->
</script>
加入<body>区:
<a href="/blog/1.htm" onclick="openwin()">open</a>卛_?
?、弹出的H口之定时关闭控制?
下面我们再对弹出的窗口进行一些控Ӟ效果更好了。如果我们再一段代码加入弹出的页?注意是加入到page.html的HTML中,可不是主面中,否则...)Q让?0U后自动关闭是不是更酷了Q?
首先Q将如下代码加入page.html文g?lt;head>区:
<script language="JavaScript">
function closeit() {
setTimeout("self.close()",10000) //毫秒
}
</script>
然后Q再?lt;body onload="closeit()"> q一句话代替page.html中原有的<BODY>q一句就可以了?q一句话千万不要忘记写啊Q这一句的作用是调用关闭窗口的代码Q?0U钟后就自行关闭该窗口?
?、在弹出H口中加上一个关闭按钮?
<FORM>
<INPUT TYPE='BUTTON' VALUE='关闭' onClick='window.close()'>
</FORM>
呵呵Q现在更加完了Q?
?、内包含的弹出窗?一个页面两个窗口?
上面的例子都包含两个H口Q一个是ȝ口,另一个是弹出的小H口?
通过下面的例子,你可以在一个页面内完成上面的效果?
<html>
<head>
<SCRIPT LANGUAGE="JavaScript">
function openwin()
{
OpenWindow=window.open("", "newwin", "height=250, width=250,toolbar=no,scrollbars="+scroll+",menubar=no");
//写成一?
OpenWindow.document.write("<TITLE>例子</TITLE>")
OpenWindow.document.write("<BODY BGCOLOR=#ffffff>")
OpenWindow.document.write("<h1>Hello!</h1>")
OpenWindow.document.write("New window opened!")
OpenWindow.document.write("</BODY>")
OpenWindow.document.write("</HTML>")
OpenWindow.document.close()
}
</SCRIPT>
</head>
<body>
<a href="#" onclick="openwin()">打开一个窗?lt;/a>
<input type="button" onclick="openwin()" value="打开H口">
</body>
</html>
看看 OpenWindow.document.write()里面的代码不是标准的HTML吗?只要按照格式写更多的行即可。千万注意多一个标{或一个标{ְ会出现错误。记得用OpenWindow.document.close()l束啊?
?、终极应?-弹出的窗口之Cookie控制?
回想一下,上面的弹出窗口虽焉Q但是有一点小毛病(沉浸在喜悦之中,一定没有发现吧Q?比如你将上面的脚本放在一个需要频J经q的面?例如首页)Q那么每ơ刷新这个页面,H口都会弹出一ơ,是不是非常烦人?:-(
有解决的办法吗?Yes! ;-) Follow me.
我们使用cookie来控制一下就可以了?
首先Q将如下代码加入主页面HTML?lt;HEAD>区:
<script>
function openwin(){
window.open("page.html","","width=200,height=200")
}
function get_cookie(Name) {
var search = Name + "="
var returnvalue = "";
if (document.cookie.length > 0) {
offset = document.cookie.indexOf(search)
if (offset != -1) {
offset += search.length
end = document.cookie.indexOf(";", offset);
if (end == -1)
end = document.cookie.length;
returnvalue="/blog/unescape(document.cookie.substring(offset," end))
}
}
return returnvalue;
}
function loadpopup(){
if (get_cookie('popped')==''){
openwin()
document.cookie="popped=yes"
}
}
</script>
然后Q用<body onload="loadpopup()">Q注意不是openwin而是loadpop啊!Q替换主面中原有的<BODY>q一句即可。你可以试着h一下这个页面或重新q入该页面,H口再也不会弹出了。真正的Pop-Only-OnceQ?br />