#
在Oracle9i中执行下面的SQL重建exu81rls视图即可。
CREATE OR REPLACE view exu81rls
(objown,objnam,policy,polown,polsch,polfun,stmts,chkopt,enabled,spolicy)
AS select u.name, o.name, r.pname, r.pfschma, r.ppname, r.pfname,
decode(bitand(r.stmt_type,1), 0,'', 'SELECT,')
|| decode(bitand(r.stmt_type,2), 0,'', 'INSERT,')
|| decode(bitand(r.stmt_type,4), 0,'', 'UPDATE,')
|| decode(bitand(r.stmt_type,8), 0,'', 'DELETE,'),
r.check_opt, r.enable_flag,
DECODE(BITAND(r.stmt_type, 16), 0, 0, 1)
from user$ u, obj$ o, rls$ r
where u.user# = o.owner#
and r.obj# = o.obj#
and (uid = 0 or
uid = o.owner# or
exists ( select * from session_roles where role='SELECT_CATALOG_ROLE')
)
/
grant select on sys.exu81rls to public;
/
-- Change the HTTP/WEBDAV port from 8080 to 8081
SQL> call dbms_xdb.cfg_update(updateXML( dbms_xdb.cfg_get() ,
'/xdbconfig/sysconfig/protocolconfig/httpconfig/http-port/text()'
8081))
/
-- Change the FTP port from 2100 to 2111
SQL> call dbms_xdb.cfg_update(updateXML( dbms_xdb.cfg_get() ,
'/xdbconfig/sysconfig/protocolconfig/ftpconfig/ftp-port/text()' , 2111))
SQL> COMMIT;
SQL> EXEC dbms_xdb.cfg_refresh
@echo off
if '%1=='## goto ENVSET
rem 要启动的类名
SET CLSNAME=com.main
rem 设定CLSPATH
SET CLSPATH=.
FOR %%c IN (.\lib\*.jar) DO CALL %0 ## %%c
rem 运行
GOTO RUN
:RUN
java -cp %CLSPATH% %CLSNAME%
goto END
:ENVSET
set CLSPATH=%CLSPATH%;%2
goto END
:END
在query的时候加上binary,select * from usertest where username like binary '%夏%'
一、同步问题提出
线程的同步是为了防止多个线程访问一个数据对象时,对数据造成的破坏。
例如:两个线程ThreadA、ThreadB都操作同一个对象Foo对象,并修改Foo对象上的数据。
public class Foo {
private int x = 100;
public int getX() {
return x;
}
public int fix(int y) {
x = x - y;
return x;
}
}
public class MyRunnable implements Runnable {
private Foo foo = new Foo();
public static void main(String[] args) {
MyRunnable r = new MyRunnable();
Thread ta = new Thread(r, "Thread-A");
Thread tb = new Thread(r, "Thread-B");
ta.start();
tb.start();
}
public void run() {
for (int i = 0; i < 3; i++) {
this.fix(30);
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " : 当前foo对象的x值= " + foo.getX());
}
}
public int fix(int y) {
return foo.fix(y);
}
}
运行结果:
Thread-A : 当前foo对象的x值= 40
Thread-B : 当前foo对象的x值= 40
Thread-B : 当前foo对象的x值= -20
Thread-A : 当前foo对象的x值= -50
Thread-A : 当前foo对象的x值= -80
Thread-B : 当前foo对象的x值= -80
Process finished with exit code 0
从结果发现,这样的输出值明显是不合理的。原因是两个线程不加控制的访问Foo对象并修改其数据所致。
如果要保持结果的合理性,只需要达到一个目的,就是将对Foo的访问加以限制,每次只能有一个线程在访问。这样就能保证Foo对象中数据的合理性了。
在具体的Java代码中需要完成一下两个操作:
把竞争访问的资源类Foo变量x标识为private;
同步哪些修改变量的代码,使用synchronized关键字同步方法或代码。
二、同步和锁定
1、锁的原理
Java中每个对象都有一个内置锁
当程序运行到非静态的synchronized同步方法上时,自动获得与正在执行代码类的当前实例(this实例)有关的锁。获得一个对象的锁也称为获取锁、锁定对象、在对象上锁定或在对象上同步。
当程序运行到synchronized同步方法或代码块时才该对象锁才起作用。
一个对象只有一个锁。所以,如果一个线程获得该锁,就没有其他线程可以获得锁,直到第一个线程释放(或返回)锁。这也意味着任何其他线程都不能进入该对象上的synchronized方法或代码块,直到该锁被释放。
释放锁是指持锁线程退出了synchronized同步方法或代码块。
关于锁和同步,有一下几个要点:
1)、只能同步方法,而不能同步变量和类;
2)、每个对象只有一个锁;当提到同步时,应该清楚在什么上同步?也就是说,在哪个对象上同步?
3)、不必同步类中所有的方法,类可以同时拥有同步和非同步方法。
4)、如果两个线程要执行一个类中的synchronized方法,并且两个线程使用相同的实例来调用方法,那么一次只能有一个线程能够执行方法,另一个需要等待,直到锁被释放。也就是说:如果一个线程在对象上获得一个锁,就没有任何其他线程可以进入(该对象的)类中的任何一个同步方法。
5)、如果线程拥有同步和非同步方法,则非同步方法可以被多个线程自由访问而不受锁的限制。
6)、线程睡眠时,它所持的任何锁都不会释放。
7)、线程可以获得多个锁。比如,在一个对象的同步方法里面调用另外一个对象的同步方法,则获取了两个对象的同步锁。
8)、同步损害并发性,应该尽可能缩小同步范围。同步不但可以同步整个方法,还可以同步方法中一部分代码块。
9)、在使用同步代码块时候,应该指定在哪个对象上同步,也就是说要获取哪个对象的锁。例如:
public int fix(int y) {
synchronized (this) {
x = x - y;
}
return x;
}
当然,同步方法也可以改写为非同步方法,但功能完全一样的,例如:
public synchronized int getX() {
return x++;
}
与
public int getX() {
synchronized (this) {
return x;
}
}
效果是完全一样的。
三、静态方法同步
要同步静态方法,需要一个用于整个类对象的锁,这个对象是就是这个类(XXX.class)。
例如:
public static synchronized int setName(String name){
Xxx.name = name;
}
等价于
public static int setName(String name){
synchronized(Xxx.class){
Xxx.name = name;
}
}
四、如果线程不能不能获得锁会怎么样
如果线程试图进入同步方法,而其锁已经被占用,则线程在该对象上被阻塞。实质上,线程进入该对象的的一种池中,必须在哪里等待,直到其锁被释放,该线程再次变为可运行或运行为止。
当考虑阻塞时,一定要注意哪个对象正被用于锁定:
1、调用同一个对象中非静态同步方法的线程将彼此阻塞。如果是不同对象,则每个线程有自己的对象的锁,线程间彼此互不干预。
2、调用同一个类中的静态同步方法的线程将彼此阻塞,它们都是锁定在相同的Class对象上。
3、静态同步方法和非静态同步方法将永远不会彼此阻塞,因为静态方法锁定在Class对象上,非静态方法锁定在该类的对象上。
4、对于同步代码块,要看清楚什么对象已经用于锁定(synchronized后面括号的内容)。在同一个对象上进行同步的线程将彼此阻塞,在不同对象上锁定的线程将永远不会彼此阻塞。
五、何时需要同步
在多个线程同时访问互斥(可交换)数据时,应该同步以保护数据,确保两个线程不会同时修改更改它。
对于非静态字段中可更改的数据,通常使用非静态方法访问。
对于静态字段中可更改的数据,通常使用静态方法访问。
如果需要在非静态方法中使用静态字段,或者在静态字段中调用非静态方法,问题将变得非常复杂。已经超出SJCP考试范围了。
六、线程安全类
当一个类已经很好的同步以保护它的数据时,这个类就称为“线程安全的”。
即使是线程安全类,也应该特别小心,因为操作的线程是间仍然不一定安全。
举个形象的例子,比如一个集合是线程安全的,有两个线程在操作同一个集合对象,当第一个线程查询集合非空后,删除集合中所有元素的时候。第二个线程也来执行与第一个线程相同的操作,也许在第一个线程查询后,第二个线程也查询出集合非空,但是当第一个执行清除后,第二个再执行删除显然是不对的,因为此时集合已经为空了。
看个代码:
public class NameList {
private List nameList = Collections.synchronizedList(new LinkedList());
public void add(String name) {
nameList.add(name);
}
public String removeFirst() {
if (nameList.size() > 0) {
return (String) nameList.remove(0);
} else {
return null;
}
}
}
public class Test {
public static void main(String[] args) {
final NameList nl = new NameList();
nl.add("aaa");
class NameDropper extends Thread{
public void run(){
String name = nl.removeFirst();
System.out.println(name);
}
}
Thread t1 = new NameDropper();
Thread t2 = new NameDropper();
t1.start();
t2.start();
}
}
虽然集合对象
private List nameList = Collections.synchronizedList(new LinkedList());
是同步的,但是程序还不是线程安全的。
出现这种事件的原因是,上例中一个线程操作列表过程中无法阻止另外一个线程对列表的其他操作。
解决上面问题的办法是,在操作集合对象的NameList上面做一个同步。改写后的代码如下:
public class NameList {
private List nameList = Collections.synchronizedList(new LinkedList());
public synchronized void add(String name) {
nameList.add(name);
}
public synchronized String removeFirst() {
if (nameList.size() > 0) {
return (String) nameList.remove(0);
} else {
return null;
}
}
}
这样,当一个线程访问其中一个同步方法时,其他线程只有等待。
七、线程死锁
死锁对Java程序来说,是很复杂的,也很难发现问题。当两个线程被阻塞,每个线程在等待另一个线程时就发生死锁。
还是看一个比较直观的死锁例子:
public class DeadlockRisk {
private static class Resource {
public int value;
}
private Resource resourceA = new Resource();
private Resource resourceB = new Resource();
public int read() {
synchronized (resourceA) {
synchronized (resourceB) {
return resourceB.value + resourceA.value;
}
}
}
public void write(int a, int b) {
synchronized (resourceB) {
synchronized (resourceA) {
resourceA.value = a;
resourceB.value = b;
}
}
}
}
假设read()方法由一个线程启动,write()方法由另外一个线程启动。读线程将拥有resourceA锁,写线程将拥有resourceB锁,两者都坚持等待的话就出现死锁。
实际上,上面这个例子发生死锁的概率很小。因为在代码内的某个点,CPU必须从读线程切换到写线程,所以,死锁基本上不能发生。
但是,无论代码中发生死锁的概率有多小,一旦发生死锁,程序就死掉。有一些设计方法能帮助避免死锁,包括始终按照预定义的顺序获取锁这一策略。已经超出SCJP的考试范围。
八、线程同步小结
1、线程同步的目的是为了保护多个线程反问一个资源时对资源的破坏。
2、线程同步方法是通过锁来实现,每个对象都有切仅有一个锁,这个锁与一个特定的对象关联,线程一旦获取了对象锁,其他访问该对象的线程就无法再访问该对象的其他非同步方法。
3、对于静态同步方法,锁是针对这个类的,锁对象是该类的Class对象。静态和非静态方法的锁互不干预。一个线程获得锁,当在一个同步方法中访问另外对象上的同步方法时,会获取这两个对象锁。
4、对于同步,要时刻清醒在哪个对象上同步,这是关键。
5、编写线程安全的类,需要时刻注意对多个线程竞争访问资源的逻辑和安全做出正确的判断,对“原子”操作做出分析,并保证原子操作期间别的线程无法访问竞争资源。
6、当多个线程等待一个对象锁时,没有获取到锁的线程将发生阻塞。
7、死锁是线程间相互等待锁锁造成的,在实际中发生的概率非常的小。真让你写个死锁程序,不一定好使,呵呵。但是,一旦程序发生死锁,程序将死掉。
测试通过的版本如下:
Eclipse:3.3.2
jdk:1.6
junit:3.8
ant:1.7(1.7之前的版本好像还不提供mail功能。。。)
<!-- JUnit build script using ant 1.7 -->
<project name="JunitTestProject" default="mail" basedir=".">
<property name="app.name" value="JunitTestProject" />
<property name="build.dir" value="bin" />
<!-- ====================" path define " ================================ -->
<path id="cobertura.classpath">
<fileset dir="lib/coberture">
<include name="cobertura.jar" />
<include name="*.jar" />
</fileset>
</path>
<!-- ====================" cobertura task define " Target ================================ -->
<taskdef classpathref="cobertura.classpath" resource="tasks.properties" />
<!-- ==================== "clean " Target ================================ -->
<target name="clean">
<available property="junit.present" classname="junit.framework.TestCase" />
<delete dir="${build.dir}" quiet="true" />
<delete file="report" quiet="true" />
</target>
<!-- ==================== "copy xml resource " Target ================================ -->
<target name="copyxml" depends="clean">
<copy todir="${build.dir}/testcases">
<fileset dir="WEB-INF" />
</copy>
</target>
<!-- ==================== "compile src" Target ================================ -->
<target name="compile" depends="copyxml">
<mkdir dir="${build.dir}" />
<javac srcdir="src" destdir="${build.dir}" debug="yes">
<classpath>
<fileset dir="lib" casesensitive="yes">
<include name="**/*.jar" />
</fileset>
</classpath>
<include name="**/*.java" />
</javac>
<javac srcdir="WEB-INF" destdir="${build.dir}">
<classpath>
<fileset dir="lib" casesensitive="yes">
<include name="**/*.jar" />
</fileset>
</classpath>
<include name="*.jsp" />
</javac>
</target>
<!-- ==================== jar" Target ================================ -->
<target name="jar" depends="compile">
<mkdir dir="dist/lib" />
<jar jarfile="dist/lib/${app.name}.jar" basedir="${build.dir}" includes="com/**" />
</target>
<!-- ==================== compile test src" Target ================================ -->
<target name="compiletests" depends="jar">
<mkdir dir="${build.dir}/testcases" />
<javac srcdir="test" destdir="${build.dir}/testcases" >
<classpath>
<fileset dir="lib" casesensitive="yes">
<include name="**/*.jar" />
</fileset>
<fileset dir="dist/lib" casesensitive="yes">
<include name="**/*.jar" />
</fileset>
</classpath>
<include name="**/*.java" />
</javac>
</target>
<!-- ==================== instrumented" Target ================================ -->
<target name="instrumented" depends="compiletests">
<cobertura-instrument todir="bin/instrumented-classes">
<ignore regex="org.apache.log4j.*" />
<fileset dir="bin">
<include name="com/**/*.class" />
</fileset>
</cobertura-instrument>
</target>
<!-- ==================== junit-test" Target ================================ -->
<target name="runtests" depends="instrumented">
<mkdir dir="report" />
<property name="tests" value="*Test" />
<junit printsummary="yes" haltonerror="yes" haltonfailure="yes" fork="yes">
<formatter type="plain" usefile="false" />
<formatter type="xml" />
<batchtest todir="report">
<fileset dir="test">
<include name="**/${tests}.java" />
<exclude name="**/ConfigTest.java" />
</fileset>
</batchtest>
<!--
Note the classpath order: instrumented classes are before the
original (uninstrumented) classes. This is important.
-->
<classpath location="bin/instrumented-classes" />
<!--
src classpath
-->
<classpath location="bin" />
<!--
The instrumented classes reference classes used by the
Cobertura runtime, so Cobertura and its dependencies
must be on your classpath.
-->
<classpath refid="cobertura.classpath" />
<!--
test case class path define
-->
<classpath>
<fileset dir="lib" casesensitive="yes">
<include name="**/*.jar" />
</fileset>
<pathelement location="bin/testcases" />
</classpath>
</junit>
</target>
<!-- ==================== junit-report" Target ================================ -->
<target name="report" depends="runtests">
<mkdir dir="report/html" />
<junitreport todir="report">
<fileset dir="report">
<include name="TEST-*.xml" />
</fileset>
<report todir="report/html" />
</junitreport>
</target>
<!-- ==================== "coverage-report" Target ================================ -->
<target name="coverage-report" depends="report">
<cobertura-report format="html" destdir="cobertura" >
<fileset dir="src">
<include name="**/*.java" />
</fileset>
</cobertura-report>
<echo>The execution of coverage-report is complete. Coverage Reports are available in /${coverage-report}</echo>
</target>
<!-- ==================== "make file to zip" Target ================================ -->
<target name="make_data_zip" depends="coverage-report">
<tstamp>
<format property="date" pattern="yyyy-MM-dd HH-mm" />
</tstamp>
<jar jarfile="dist/lib/cobertura${date}.zip" basedir="cobertura" />
<jar jarfile="dist/lib/report${date}.zip" basedir="report" excludes="*.xml"/>
</target>
<!-- ==================== "mail" Target ================================ -->
<target name="mail" depends="make_data_zip">
<!-- <taskdef name="mail" classname="org.apache.tools.ant.taskdefs.optional.mail.MimeMail"/> -->
<tstamp/>
<mail messageMimeType="text/html"
messageFile="message.txt"
tolist="bpcjy@hotmail.com"
mailhost="mailsvr or mail IPAddress"
subject="JUnit Test Results: ${TODAY}"
from="bpcjy@hotmail.com">
<fileset dir=".">
<include name="dist/lib/*.zip"/>
</fileset>
</mail>
</target>
</project>
struts2.0:(6)
lib/antlr-2.7.6.jar
lib/struts2-core-2.0.14.jar
lib/struts2-spring-plugin-2.0.14.jar
lib/freemarker-2.3.8.jar
lib/ognl-2.6.11.jar
lib/xwork-2.0.7.jar
(注意单用时必须还要用lib/commons-logging-1.0.4.jar)
spring2.5:(10)
dist/modules/spring-aop.jar
dist/modules/spring-beans.jar
dist/modules/spring-context.jar
dist/modules/spring-context-support.jar
dist/modules/spring-core.jar
dist/modules/spring-jdbc.jar
dist/modules/spring-orm.jar
dist/modules/spring-tx.jar
dist/modules/spring-web.jar
dist/modules/spring-webmvc-struts.jar
hibernate3.2:(10)
hibernate3.jar
lib/asm.jar
lib/asm-attrs.jar
lib/cglib-2.1.3.jar
lib/commons-collections-2.1.1.jar
lib/commons-logging-1.0.4.jar
lib/dom4j-1.6.1.jar
lib/ehcache-1.2.3.jar
lib/jta.jar
lib/xml-apis.jar
其它jar:(6)
servlet.jar
sqljdbc.jar
jsonplugin-0.30.jar(jsonplugin-0.30于6月6号发布,修复了一直很头疼的cglib序列化问题)
serializer.jar
xalan.jar
(Xalan是将可扩展标记语言(XML)转换为超文本链接标识语言(HTML)或其它类型XML文档的规范,添加操作XML的jar,一般要添加xalan.jar、serializer.jar这两个包,如有特殊需求可将下载的所有jar全部添加
(下载地址:http://apache.seekmeup.com/xml/xalan-j里面的一个xalan-j_2_7_0-bin.zip))
xercesImpl.jar
( 实现解析XML文件的功能很方便,我们可以通过下载第三方的一些工具包如xml-apis.jar和xercesImpl.jar 等.Xerces是一个与可扩展标记语言(XML)兼容的语法分析器。Xerces分析器可处理Java和C++,它采用互联网联盟XML、文件对象...Xerces-C是用可移植的C++子集编写的XML分析器。Xerces-C允许对XML数据进行读写操作)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title> ĵ</title>
<style>
body {
margin: 7px;
font:12px Verdana, Arial, Helvetica, sans-serif;
}
* {
list-style-type: none;
margin: 0px;
padding: 0px;
border: thin none;
}
#nav {
position: absolute;
font-size: 9px;
opacity: 0.8;
}
#nav a {
display: block;
width: 100px;
height: 15px;
padding: 3px 5px 12px;
background: #666;
color: #fff;
text-decoration: none;
}
#nav a:hover {
background: #333;
}
#nav li {
width: 120px;
height:30px;
overflow:hidden;
background: #ccc;
padding-bottom: 3px;
}
#nav ul {
position: absolute;
margin-left: 110px;
margin-top: -30px;
}
html>body #nav ul {
margin-left: 119px;
margin-top: -39px;
}
#nav ul {
display: none;
}
#nav li.show ul {
display: block;
}
#nav li.show li ul {
display: none;
}
#nav li li.show ul {
display: block;
}
</style>
<script language="javascript" type="text/javascript">
function menuFix() {
var sfEls = document.getElementById("nav").getElementsByTagName("li");
for (var i=0; i<sfEls.length; i++) {
sfEls[i].onmouseover=function() {
this.className+=(this.className.length>0? " ": "") + "show";
}
sfEls[i].onmouseout=function() {
this.className=this.className.replace(new RegExp("( ?|^)show\\b"), "");
}
}
}
window.onload=menuFix;
</script>
</head>
<body>
<ul id="nav">
<li><a href="#">nav item</a>.
<ul>
<li><a href="#">nav item</a>.
<ul>
<li><a href="#">nav item</a>.</li>
<li><a href="#">nav item</a>.</li>
</ul>
</li>
<li><a href="#">nav item</a>.
<ul>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
</ul>
</li>
<li><a href="#">nav item</a>.
<ul>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
</ul>
</li>
<li><a href="#">nav item</a>.
<ul>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#">nav item</a>.
<ul>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
</ul>
</li>
<li><a href="#">nav item</a>.
<ul>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
<li><a href="#">nav item</a></li>
</ul>
</li>
</ul>
</body>
</html>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0049)http://vip.5d.cn/flood/myjs/htm/menu/coolmenu.htm -->
<HTML><HEAD><TITLE>下滑菜单</TITLE>
<META http-equiv=Content-Type content="text/html; charset=gb2312">
<META content="MSHTML 6.00.2900.2802" name=GENERATOR>
<META content=FrontPage.Editor.Document name=ProgId>
<STYLE type=text/css>.menubar {
BORDER-RIGHT: 1px outset; BORDER-TOP: 1px outset; BACKGROUND: #0099cc; BORDER-LEFT: 1px outset; WIDTH: 100px; CURSOR: default; COLOR: yellow; BORDER-BOTTOM: 1px outset; POSITION: absolute; TOP: 10px; HEIGHT: 20px
}
.menu {
BORDER-RIGHT: 2px outset; PADDING-RIGHT: 15px; BORDER-TOP: white 2px outset; DISPLAY: none; PADDING-LEFT: 15px; BACKGROUND: yellow; PADDING-BOTTOM: 15px; BORDER-LEFT: 2px outset; WIDTH: 140px; PADDING-TOP: 15px; BORDER-BOTTOM: 2px outset; POSITION: absolute; TOP: 30px
}
.menu A {
COLOR: blue; TEXT-DECORATION: none
}
.menu A:hover {
COLOR: #00ffff
}
</STYLE>
<SCRIPT language=javascript>
function menuControl(show)
{
window.event.cancelBubble=true;
var objID=event.srcElement.id;
var index=objID.indexOf("_");
var mainID=objID.substring(0,index);
var numID=objID.substring(index+1,objID.length);
if(mainID=="menubar")
{
if(show==1)
{
eval("showMenu("+"menu_"+numID+")");
}
else
{
eval("hideMenu("+"menu_"+numID+")");
}
}
}
var nbottom=0,speed=1;
function displayMenu(obj)
{
obj.style.clip="rect(0 100% "+nbottom+"% 0)";
nbottom+=speed;
if(nbottom<=100)
{
timerID=setTimeout("displayMenu("+obj.id+"),70");
}
else clearTimeout(timerID);
}
function showMenu(obj)
{
obj.style.display="block";
obj.style.clip="rect(0 0 0 0)";
nbottom=5;
displayMenu(obj);
}
function hideMenu(obj)
{
nbottom=0;
obj.style.display="none";
}
function keepMenu(obj)
{
obj.style.display="block";
}
</SCRIPT>
</HEAD>
<BODY>
<TABLE style="FONT-SIZE: 15px" cellSpacing=0 cellPadding=0 width=400 border=0>
<TBODY>
<TR>
<TD width="20%">
<DIV class=menubar id=menubar_1 onmouseover=menuControl(1)
onmouseout=menuControl(0) align=center>教育网站 </DIV></TD>
<TD width="20%">
<DIV class=menubar id=menubar_2 onmouseover=menuControl(1)
onmouseout=menuControl(0) align=center>电脑网站 </DIV></TD>
<TD width="20%">
<DIV class=menubar id=menubar_3 onmouseover=menuControl(1)
onmouseout=menuControl(0) align=center>免费邮件 </DIV></TD>
<TD width="20%">
<DIV class=menubar id=menubar_4 onmouseover=menuControl(1)
onmouseout=menuControl(0) align=center>其它网站 </DIV></TD></TR>
<TR>
<TD width="20%">
<DIV class=menu id=menu_1 onmouseover=keepMenu(this)
onmouseout=hideMenu(this) align=left><A
href="http://www.cqcas.edu.cn/">重庆民政学校</A><BR><A
href="http://www.cqu.edu.cn/">重庆大学</A><BR><A
href="http://www.cquc.edu.cn/">重庆交通学院</A> </DIV></TD>
<TD width="20%">
<DIV class=menu id=menu_2 onmouseover=keepMenu(this)
onmouseout=hideMenu(this) align=left><A
href="http://www.yesky.com/">天极网</A><BR><A
href="http://www.cfan.cn.net/">电脑爱好者</A><BR><A
href="http://www.intoweb.com.cn/">上网杂志</A> </DIV></TD>
<TD width="20%">
<DIV class=menu id=menu_3 onmouseover=keepMenu(this)
onmouseout=hideMenu(this) align=left><A
href="http://www.163.com/">163电子邮件</A><BR><A
href="http://freemail.263.net/">首都在线</A><BR><A
href="http://www.21cn.com/">21CN电子邮件</A><BR><A
href="http://www.chinese.com/">炎皇在线</A> </DIV></TD>
<TD width="20%">
<DIV class=menu id=menu_4 onmouseover=keepMenu(this)
onmouseout=hideMenu(this) align=left><A
href="http://www.sohu.com.cn/">搜狐</A><BR><A
href="http://www.yahoo.com/">雅虎</A><BR><A
href="http://www.cseek.com/">搜索客</A><BR><A
href="http://www.sina.com/">新浪网</A><BR><A
href="http://vip.5d.cn/flood/myjs/htm/menu/httP;//www.cqcas.edu.cn/user/sailing">远航网站</A>
</DIV></TD></TR></TBODY></TABLE></SCRIPT></BODY></HTML>