关于Serializable的serialVersionUID

Posted by 猪头小队长 | 程序设计 | Friday 15 May 2009 11:17

众所周知,当某class实现了Serializable接口后,由此class构建出的对象将具备序列化的能力,而Serializable这个接口中没有任何需要实现的方法,所以这个接口的作用仅仅是作为一个标记,告诉虚拟机,具有这个标记的对象,是可以被序列化的,而没有这个标记的则不要序列化。所以,虚拟机应该是可以将任何对象序列化的,只不过是它遵守了一个“道德“规范,仅序列化那些被允许可以序列化的。那为什么不是所有的对象都是可序列化的呢?我想也许是基于安全性的考量吧。

序列化的一般过程是:

  1. 在虚拟机A中,构造了class AClass的对象AObject
  2. 将AObject序列化写入到文件ObjectFile中
  3. 在虚拟机B中,读取文件ObjectFile
  4. 根据AClass和读取进来的byte[],构造虚拟机B中的AClass的对象BObject

这里面,不好理解的事情是在第四步中,如果虚拟机B仅有AObject的数据,并不足以构造出BObject,它必须还需要有AClass的信息。也就是说, 序列化,仅仅是把对象以二进制的形式写入到了文件之中,但是这些二进制该组织成什么样的一个东西,却并不能说明,所以还需要AClass的类型信息,这就 如同交给了你一大堆的机器零件,还需要你拥有一本组装说明书,你才能把这些零件组装成一架波音747。:)。也就是说,序列化的仅仅是Object,而没有同时把这个Object所依赖的所有class一并序列化过去。那为什么不这么做呢?也许和ClassLoader有关?又和安全性有关?

在实现了Serializable接口的class中,需要声明一个long serialVersionUID,用来标明当前class的版本号:

  • 如果在序列化时的版本号和序列化时的版本号,不一致,将会有异常:
    java.io.InvalidClassException:
    local class incompatible: stream classdesc serialVersionUID = …, local class serialVersionUID = …
  • 那如果在class中不声明这个属性呢?那结果可以就会变得比较诡异了:
    • 在序列化的时候,虚拟机A会为它计算出一个serialVersionUID,计算的方法是依据class的信息,再具体我也不清楚了。
    • 在序列化的时候,虚拟机B也会为class计算出一个serialVersionUID,然后做比较。
    • 那么如果两个虚拟机是不同类型的虚拟机,那么计算方法可能就不一样了,于是即使相同的class,serialVersionUID也可能会不同,不同的class的,理论上来说,也存在serialVersionUID相同的可能性,所以,serialVersionUID尽量由我们自己来指定,而不要由虚拟机来计算。
  • 那如果serialVersionUID一致,而class发生了变化呢?
    • 如果虚拟机A中的AClass有一个属性,而虚拟机B中的AClass,没有这个属性,那么这个属性将被忽略,而不会有异常。
    • 如果虚拟机A中的AClass没有的属性,而在虚拟机B中多出来的属性,那么这个属性将被赋予一个缺省值,而不会有异常。
    • 如果虚拟机A中的AClass有一个属性,在虚拟机B中的AClass也有这个属性,但这个属性的类型变了,比如说int变成了long,抑或其他的变化,将会有异常:
      java.io.InvalidClassException:
      incompatible types for field …

经过序列化而产生的异常都是 java.io.InvalidClassException,不会产生java.lang.ClassCastException,两者还是有比较大的区别的,从名字上就可以看得出来。

关于mysql的表名的大小写

Posted by 猪头小队长 | 程序设计 | Wednesday 6 May 2009 12:03

比较规矩的做法都是将所有的表名全部小写或者是全部大写,我比较喜欢全部小写,无论是在创建表的语句中还是在后面的CRUD语句中。然而,有时由于各种众所不知的原因,很难做到统一。于是该如何让mysql大小写不敏感呢?

在表名大小写敏感的情况下,表A和表a是不一样的,这样,如果在语句中还不分大小写的乱写,就会出现找不到表的错误,那此时的解决方案就是让它大小写不敏感:在my.conf中的mysqld栏目下加入一行:lower_case_table_names=1,然后重启mysql。

但是,如果以前,在大小写敏感的设置下,创建表时使用的是大写的表名,在执行完上面设置后会怎么样捏?这个表将不再会被访问到了。这下麻烦了:还得把上面设置改回去,然后将表名rename到小写,然后再加上上面的设置。

更多参考:http://dev.mysql.com/doc/refman/5.0/en/identifier-case-sensitivity.html

意译:mysql的using filesort是什么意思?

Posted by 猪头小队长 | 程序设计 | Tuesday 5 May 2009 18:47

通常的解释是:选择出来的记录太多了,内存中放不下了,所以会存储在磁盘中,并通过操作磁盘的文件的方式来排序。但是呢,这是不对的。

正解是,filesort这个名字有问题,容易给人误解,在mysql中,任何不能通过index进行的sort都称之为filesort,这里的filesort和文件没有任何关系,应该称之为“sort”而不是“filesort”,它的内部实现就是快速排序。

意译自:
What does Using filesort mean in MySQL?
http://www.mysqlperformanceblog.com/2009/03/05/what-does-using-filesort-mean-in-mysql/

How MySQL executes ORDER BY
http://s.petrunia.net/blog/?p=24

The DDMS of android 1.0 plugin for eclipse can’t works

Posted by 猪头小队长 | 程序设计 | Wednesday 22 October 2008 19:21

在安装了Android的SDK(1.0版)和为Eclipse安装完毕ADT插件之后,DDMS控制台没有打印出什么信息,在0.9版本的时候,没有遇到这个问题,不知道该怎么办。

临时的办法是:继续使用Eclipse来启动模拟器,直接使用sdk中提供的ddms来连接这个模拟器。也没有麻烦太多。但是发现ddms也启动不了:

12:43 E/ddms: shutting down due to uncaught exception
12:43 E/ddms: java.lang.UnsatisfiedLinkError:
/data/programs/android/android-sdk-linux_x86-1.0_r1/tools/lib/libswt-pi-gtk-3232.so:
/data/programs/android/android-sdk-linux_x86-1.0_r1/tools/lib/libswt-pi-gtk-3232.so:
wrong ELF class: ELFCLASS32 (Possible cause: architecture word width
mismatch)
    at java.lang.ClassLoader$NativeLibrary.load(Native Method)
    at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1751)
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1660)
    at java.lang.Runtime.loadLibrary0(Runtime.java:822)
    at java.lang.System.loadLibrary(System.java:993)
    at org.eclipse.swt.internal.Library.loadLibrary(Library.java:123)
    at org.eclipse.swt.internal.gtk.OS.<clinit>(OS.java:22)
    at org.eclipse.swt.internal.Converter.wcsToMbcs(Converter.java:63)
    at org.eclipse.swt.internal.Converter.wcsToMbcs(Converter.java:54)
    at org.eclipse.swt.widgets.Display.<clinit>(Display.java:126)
    at com.android.ddms.UIThread.runUI(UIThread.java:329)
    at com.android.ddms.Main.main(Main.java:97)

原因大概是android sdk不是for x86_64版本的,所以从Eclipse那里下载swt-3.2-gtk-linux-x86_64.zip,解压缩后覆盖tools/lib下的那几个文件,就可以启动了。

 

Spring与DWR集成的两种配置方式

Posted by 猪头小队长 | 程序设计 | Tuesday 14 October 2008 18:02

关于Ajax的框架,以前用的是Buffalo,但是DWR比较热,于是配置一下DWR玩一玩。现在的形势是:无论弄个什么框架,如果不和Spring集成一下,都不好意思跟别人打招呼。

在这里使用的Spring和DWR都是最新的版本:
Spring版本: 2.5.5
DWR版本:2.0.5

首先来一个测试页面,这是一个静态页面,在这个页面中调用java.util.Date的toString()方法。使用java.util.Date比较简单,这样除了用到了Spring和DWR的类库外,不用写任何Java代码既可以达到演示的目的。

<html>
<head>
<title>www.simplelife.cn</title>
<script type=’text/javascript’ src=’dwr/interface/javaDate.js’></script>
<script type=’text/javascript’ src=’dwr/engine.js’></script>
<script type=’text/javascript’ src=’dwr/util.js’></script>
</head>

<body>
<input type=’button’ on-click=’javaDate.toString(reply);’ value=’show time’/>

<script type=’text/javascript’>
var reply = function(data)
{
if (data != null && typeof data == ’object’)
alert(dwr.util.toDescriptiveString(data, 2));
else
dwr.util.setValue(’d0′, dwr.util.toDescriptiveString(data, 1));
}
</script>
<br>
<span id=’d0′></span>
</body>
</html>

接下来有两种配置Spring与DWR集成的方式:

第一种配置方式
在这种方式中,不需要dwr.xml文件,将这部分配置与Spring的配置写在同一个文件中。DWR使用的servlet为:org.directwebremoting.spring.DwrSpringServlet,这样,只需要两个配置文件就可以了,分别是:

web.xml:

<?xml version=”1.0″ encoding=”ISO-8859-1″?>
<!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 id=”simplelife.cn”>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-
class>
org.springframework.web.context.ContextLoaderListener
</listener-
class>
</listener>

<servlet>
<servlet-name>dwr-invoker</servlet-name>
<display-name>DWR Servlet</display-name>
<description>Direct Web Remoter Servlet</description>
<servlet-class>org.directwebremoting.spring.DwrSpringServlet</servlet-class>

<!– This should NEVER be present in live –>
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>

<!– Remove this unless you want to use active function reverse() {
[native code]
} ajax –>
<init-param>
<param-name>activeReverseAjaxEnabled</param-name>
<param-value>true</param-value>
</init-param>

<!– By default DWR creates application scope objects when they are first
used. This creates them when the app-server is started –>
<init-param>
<param-name>initApplicationScopeCreatorsAtStartup</param-name>
<param-value>true</param-value>
</init-param>

<!– This enables full streaming mode. It’s probably better to leave this
out if you are running across the internet –>
<init-param>
<param-name>maxWaitAfterWrite</param-name>
<param-value>-1</param-value>
</init-param>

<!–
For more information on these parameters, see:
- http://getahead.org/dwr/server/servlet
- http://getahead.org/dwr/function reverse() {
[native code]
}-ajax/configuration
–>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>dwr-invoker</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
</web-app>

另外一个文件是applicationContext.xml文件:

<?xml version=”1.0″ encoding=”UTF-8″?>
<beans xmlns=”http://www.springframework.org/schema/beans”
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xmlns:p=”http://www.springframework.org/schema/p”
xmlns:dwr=”http://www.directwebremoting.org/schema/spring-dwr”
xmlns:context=”http://www.springframework.org/schema/context”
xsi:schemaLocation=”http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.directwebremoting.org/schema/spring-dwr
http://www.directwebremoting.org/schema/spring-dwr-2.0.xsd

http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd”>

<bean id=”dwrJavaDate” class=”java.util.Date”>
<dwr:remote javascript=”javaDate”>
</dwr:remote>

</bean>

<dwr:configuration></dwr:configuration>
<dwr:controller id=”dwrController” debug=”true“ />
</beans>

注意配置文件中的黑体部分。

第二种配置方式
使用第一种方式的Spring配置文件看起来比较乱,不那么干净,在这种方式中,将Spring的配置与DWR的配置完全分开,看起来干净利落。DWR使用的servlet为:org.directwebremoting.servlet.DwrServlet ,这样就需要三个配置文件了:

web.xml文件:

<?xml version=”1.0″ encoding=”ISO-8859-1″?>
<!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 id=”simplelife.cn”>

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-
class>
org.springframework.web.context.ContextLoaderListener
</listener-
class>
</listener>

<servlet>
<servlet-name>dwr-invoker</servlet-name>
<display-name>DWR Servlet</display-name>
<description>Direct Web Remoter Servlet</description>
<servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>

<!– This should NEVER be present in live –>
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>

<!– Remove this unless you want to use active function reverse() {
[native code]
} ajax –>
<init-param>
<param-name>activeReverseAjaxEnabled</param-name>
<param-value>true</param-value>
</init-param>

<!– By default DWR creates application scope objects when they are first
used. This creates them when the app-server is started –>
<init-param>
<param-name>initApplicationScopeCreatorsAtStartup</param-name>
<param-value>true</param-value>
</init-param>

<!– This enables full streaming mode. It’s probably better to leave this
out if you are running across the internet –>
<init-param>
<param-name>maxWaitAfterWrite</param-name>
<param-value>-1</param-value>
</init-param>

<!–
For more information on these parameters, see:
- http://getahead.org/dwr/server/servlet
- http://getahead.org/dwr/function reverse() {
[native code]
}-ajax/configuration
–>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>dwr-invoker</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>

</web-app>

applicationContext.xml文件,这是一个纯粹的Spring配置文件:

<?xml version=”1.0″ encoding=”UTF-8″?>
<beans xmlns=”http://www.springframework.org/schema/beans”
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xmlns:p=”http://www.springframework.org/schema/p”
xmlns:context=”http://www.springframework.org/schema/context”
xsi:schemaLocation=”http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd”>

<bean id=”dwrJavaDate” class=”java.util.Date”>
</bean>
</beans>

最后一个文件是dwr.xml,在这个文件中,使用spring容器中的对象:

<?xml version=”1.0″ encoding=”UTF-8″?>
<!DOCTYPE dwr PUBLIC ”-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN”
“http://getahead.org/dwr/dwr20.dtd”>
<dwr>
<allow>
<create creator=”spring” javascript=”javaDate”>
<param name=”beanName” value=”dwrJavaDate”/>
</create>

</allow>
</dwr>

以上两种方式都可以完成Spring与DWR的集成,我比较喜欢第二种,“上帝的归上帝,恺撒的归恺撒”。
如果再需要配置MVC等其他功能,直接在web.xml中声明另外的Servlet即可,就合DWR没什么关系了。

附录:目录结构

javor@desktop:/data/servers/apache-tomcat-5.5.25/webapps/simplelife$ ls -l
-rw-r–r– 1 javor javor  663 2008-10-14 16:58 index.html
drwxr-xr-x 3 javor javor 4096 2008-10-14 17:52 WEB-INF
javor@desktop:/data/servers/apache-tomcat-5.5.25/webapps/simplelife$ ls -l WEB-INF/lib
total 12076
-rw-r–r– 1 javor javor  188671 2008-10-14 16:36 commons-beanutils.jar
-rw-r–r– 1 javor javor  571259 2008-10-14 16:36 commons-collections.jar
-rw-r–r– 1 javor javor  121757 2008-10-14 16:36 commons-dbcp.jar
-rw-r–r– 1 javor javor   38015 2008-10-14 16:36 commons-logging-1.0.4.jar
-rw-r–r– 1 javor javor   60841 2008-10-14 16:36 commons-logging.jar
-rw-r–r– 1 javor javor   62103 2008-10-14 16:36 commons-pool.jar
-rw-r–r– 1 javor javor   84462 2008-10-14 16:36 commons-validator-1.1.4.jar
-rw-r–r– 1 javor javor   84462 2008-10-14 16:36 commons-validator.jar
-rw-r–r– 1 javor javor  502402 2008-10-14 16:36 dwr.jar
-rw-r–r– 1 javor javor   65261 2008-10-14 16:36 jakarta-oro-2.0.8.jar
-rw-r–r– 1 javor javor  358085 2008-10-14 16:36 log4j-1.2.12.jar
-rw-r–r– 1 javor javor 2949316 2008-10-14 16:36 spring.jar
-rw-r–r– 1 javor javor  404466 2008-10-14 16:36 spring-webmvc.jar
-rw-r–r– 1 javor javor  393259 2008-10-14 16:36 standard.jar

[END]

鄙Mysql5.1的defaults-file

Posted by 猪头小队长 | 程序设计 | Friday 10 October 2008 10:40

为了试验Mysql的分区功能,所以下载了mysql-5.1.28-rc-linux-x86_64-glibc23.tar.gz,Mysql自5.1起才开始提供partition的功能,只不过现在还是rc版,并且这个特性一直都是试验性质的,not production-ready。最喜欢的就是tar.gz这种形式的二进制软件包了,不需要安装,解开压缩就可以用,data目录等都在当前目录下,很方便。

可是用这个5.1的时候,就出了一些小麻烦:

javor@desktop:/data/programs$ tar zxvf mysql-5.1.28-rc-linux-x86_64-glibc23.tar
javor@desktop:/data/programs$ ln -s mysql-5.1.28-rc-linux-x86_64-glibc23 mysql
javor@javor-desktop:/data/programs$ cd mysql
javor@desktop:/data/programs/mysql$ scripts/mysql_install_db

FATAL ERROR: Could not find /fill_help_tables.sql

If you compiled from source, you need to run ’make install’ to
copy the software into the correct location ready for operation.

If you are using a binary release, you must either be at the top
level of the extracted archive, or pass the –basedir option
pointing to that location.

javor@desktop:/data/programs/mysql$

还可能出现一些其他的错误:

081010 10:52:05 [ERROR] Can’t find messagefile ’/usr/share/mysql/english/errmsg.sys’
081010 10:52:05 [ERROR] /data/programs/mysql/bin/mysqld: unknown option ’–skip-bdb’

解决办法:

javor@desktop:/data/programs/mysql$ scripts/mysql_install_db \
–defaults-file=/etc/my.cnf \
–basedir=/data/programs/mysql \
–datadir=/data/programs/mysql/data \
–user=javor


同样,在启动Mysql服务的时候:

javor@desktop:/data/programs/mysql$ bin/mysqld_safe \
–defaults-file=/etc/my.cnf \
–basedir=/data/programs/mysql \
–datadir=/data/programs/mysql/data \
–user=javor

在进入mysql client的时候使用同样的方式。

Cannot convert value ‘0000-00-00 00:00:00′ from column 1 to TIMESTAMP

Posted by 猪头小队长 | 程序设计 | Tuesday 26 August 2008 15:05

在Mysql数据库中使用DATETIME类型来存储时间,使用JDBC中读取这个字段的时候,应该使用ResultSet.getTimestamp(),这样会得到一个java.sql.Timestamp类型的数据。在这里既不能使用ResultSet.getDate(),也不能使用ResultSet.getTime(),因为前者不包括time数据,后者不包括date数据。

但是在使用ResultSet.getTimestamp()时也不是完全安全的,例如,当数据库中的TIMESTAMP类型的字段值为’0000-00-00 00:00:00′时,使用此方法进行读取,会抛出异常:Cannot convert value ‘0000-00-00 00:00:00′ from column 1 to TIMESTAMP,这是因为JDBC不能将’0000-00-00 00:00:00′转化为一个为一个java.sql.Timestamp,在Java中,想创建一个java.util.Date,使其值为’0000-00-00′也是不可能的,最古老的日期应该是’0001-01-01 00:00:00′。

那么在程序中该怎么办捏? 解决方案在这里

Datetimes with all-zero components (0000-00-00 …) — These values can not be represented reliably in Java. Connector/J 3.0.x always converted them to NULL when being read from a ResultSet.

Connector/J 3.1 throws an exception by default when these values are encountered as this is the most correct behavior according to the JDBC and SQL standards. This behavior can be modified using the zeroDateTimeBehavior configuration property. The allowable values are:

  • exception (the default), which throws an SQLException with an SQLState of S1009.
  • convertToNull, which returns NULL instead of the date.
  • round, which rounds the date to the nearest closest value which is 0001-01-01.

Starting with Connector/J 3.1.7, ResultSet.getString() can be decoupled from this behavior via noDatetimeStringSync=true (the default value is false) so that you can retrieve the unaltered all-zero value as a String. It should be noted that this also precludes using any time zone conversions, therefore the driver will not allow you to enable noDatetimeStringSync and useTimezone at the same time.

所以,在JDBC URL中加入zeroDateTimeBehavior信息,既可以解决:
String url = "jdbc:mysql://10.149.51.80:3306/test?relaxAutoCommit=true&zeroDateTimeBehavior=convertToNull";

当然,也可以使用另外一个策略:round。

关于IE6、IE7、Firefox的css兼容性问题

Posted by 猪头小队长 | 程序设计 | Tuesday 6 May 2008 13:32

很不幸,最近遇到了不同浏览器的兼容性问题。原因是在Firefox下,将某某设为主页的功能很复杂,一般有两种实现方式:

  1. 提示用户修改about:config中的属性,让用户将[signed.applets.codebase_principal_support]
    设置为[true],我不知道会有多少浏览用户愿意这么干,我觉得这个提示挺二的。很少或者说几乎没有网站的价值已经足够使用户进行这么复杂的操作来将其
    设为主页。即使有这样的网站的话,用户也可以通过浏览器的收藏或者设置主页的功能来解决这个问题。
  2. 提示用户将某个链接(比如说一个图片链接,其链接地址为将要设为主页的URL)用鼠标拖动其到浏览器的"小房子(Home)"的图标上,然后放开,也可以完成这个功能。

相比较来说,第二个方法似乎可行性比较大,但是仍然复杂,于是最终的决定是:在Firefox下隐藏这个功能。




要使用这个功能,最简单的是通过CSS进行控制,很简单的就是用"!important"来实现,然而IE7对这个关键词的解释和Firefox差不多
了,已经不能用这个办法来区分IE和Firefox了。于是趁机整理了一下不同浏览器对CSS Hack的支持情况。测试页面的源代码如下:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<body>
<style>
#teststyle{
    background:blue;
    border:1px solid #FF0000;
}
</style>

<div id=teststyle>www.simplelife.cn</div>

</body>
</html>

 在这种情况下,不同浏览器的表现都是相同的,很正常。接下来做了一些测试,测试结果见表格:

simplelife.cn !important
!important! -(减号),_(下划线)
~,`,!,@,#,$,%,^,&,*
*html
*+html
html>body
IE6
× × × ×
IE7
× ×
Firefox
× × × × ×

说明:

  1. 在测试之前,在<html>的前面一定要声明DOCTYPE,如果没有声明这个,可能会使用浏览器自己缺省的DTD去解析,结果会有不同,具体缺省的是什么DTD,不清楚,没有去深究。DOCTYPE的一些文档见后面的参考文章。
  2. [!important]和[!important!]不同,后者是前后各有一个叹号。写法是:
    #teststyle{
      background:blue !important;
      background:green;
      border:1px solid #FF0000;
    }


    #teststyle{
      background:blue !important!;
      background:green;
      border:1px solid #FF0000;
    }

    只有IE7能够识别后者。

  3. [-]减号和[_]下划线,写法是:
    #teststyle{
      background:blue;
      _background:green;
      border:1px solid #FF0000;
    }


    #teststyle{
      background:blue;
      -background:green;
      border:1px solid #FF0000;
    }

    只有IE6能够识别,IE7和Firefox均不能识别。

  4. 其他的一些符号,我试验的有[~],[`],[!],[@],[#],[$],[%],[^],[&],[*],IE6和IE7能够识别,Firefox不能识别。写法如:
    #teststyle{
      background:blue;
      &background:green;
      border:1px solid #FF0000;
    }


  5. 对于[*html],[*+html],[html>body]还试验了一些这样的写法:
    *html #teststyle{
      background:blue;
      border:1px solid #FF0000;
    }

    测试结果见表格。

  6. 差不多就是这么多了,还有一个问题是,如果要利用上面的这些,语句的顺序该是什么,比如说要使用!important,是将带有此标记的放在前面,还是将不带有此标记的放在前面?我的比较肤浅的理解是这样的:
    • 对于浏览器能够识别的声明,按顺序,后面声明覆盖前面的声明;
    • [!important/!important!] > Normal > 其他字符[~],[`],[!],[@],[#],[$],[%],[^],[&],[*],琢磨一下,是可以理解这个顺序的;
  7. 通过电源(如果对DHTML有什么问题,可以直接去这里),还有一个发现就是:说IE6不支持!important的说法是不对的,对于下面的情况:
    #teststyle{
      background:blue !important;
    }
    #teststyle{

      background:green;

    }

    最终显示的颜色是蓝色,也就是说IE6也对!important提供了一定的支持。



参考文章:

页面中DOCTYPE的作用
http://www.blogjava.net/swingboat/archive/2006/04/11/40412.html 

DOCTYPE - Document Type Declaration

http://htmlhelp.com/reference/html40/html/doctype.html

Choosing a DOCTYPE
http://htmlhelp.com/tools/validator/doctype.html

CSS hacks
http://www.webdevout.net/css-hacks#in_css-selectors

Recommended list of DTDs
http://www.w3.org/QA/2002/04/valid-dtd-list.html

Comparing XHTML and HTML, Strict and Transitional
http://www.evotech.net/blog/2007/06/xhtml-html-strict-transitional-deprecated/

Linux下安装Apache2、SSL、Subversion

Posted by 猪头小队长 | 程序设计 | Tuesday 15 January 2008 17:04

重新安装了一下最新版本的SVN,把操作过程记录下来。

1、准备材料

[root@test]# pwd
/usr/local
[root@test]#  ll
-rw-r–r–   1 root root   6028951 Sep  6 19:31 httpd-2.2.6.tar.gz
-rw-r–r–   1 root root   3354792 Jan 15 15:11 openssl-0.9.8g.tar.gz
-rw-r–r–   1 root root   6337805 Dec 20 17:29 subversion-1.4.6.tar.gz
-rw-r–r–   1 root root   2899269 Dec 20 17:29 subversion-deps-1.4.6.tar.gz

这些东西可以到ApacheOpenSSHSubversion的网站上去下载。

2、安装OpenSSH

[root@test]# pwd
/usr/local
[root@test]# tar zxvf openssl-0.9.8g.tar.gz
[root@test]# cd openssl-0.9.8g
[root@test]# ./config shared
[root@test]# make
[root@test]# make test
[root@test]# make install
[root@test]# echo "/usr/local/ssl/lib" >> /etc/ld.so.conf
[root@test]# /sbin/ldconfig

openssl已经安装到/usr/local/ssl下面了 

3、安装apache

[root@test]# pwd
/usr/local
[root@test]# tar zxvf httpd-2.2.6.tar.gz 
[root@test]# cd httpd-2.2.6
[root@test]# ./configure –enable-dav –enable-so –prefix=/usr/local/apache –with-ssl=/usr/local/ssl –enable-ssl
[root@test]# make
[root@test]# make install

安装Apache比较容易,安装完之后,验证一下也可以,就是启动一下Apache看看是否安装成功。

 3、安装SVN

[root@test]# pwd
/usr/local
[root@test]# tar zxvf subversion-1.4.6.tar.gz 
[root@test]# tar zxvf sub

Linux下安装Apache、Subversion

Posted by 猪头小队长 | 程序设计 | Tuesday 15 January 2008 14:40

重新安装了一下最新版本的SVN,把操作过程记录下来。

1、准备材料

[root@test]# pwd
/usr/local
[root@test]#  ll
-rw-r–r–   1 root root   6028951 Sep  6 19:31 httpd-2.2.6.tar.gz
-rw-r–r–   1 root root   6337805 Dec 20 17:29 subversion-1.4.6.tar.gz
-rw-r–r–   1 root root   2899269 Dec 20 17:29 subversion-deps-1.4.6.tar.gz

这些东西可以到Apache的网站上和Subversion的网站上去下载。

 2、安装apache

[root@test]# pwd
/usr/local
[root@test]# tar zxvf httpd-2.2.6.tar.gz 
[root@test]# cd /usr/local/httpd-2.2.6
[root@test]# ./configure –enable-dav –enable-so –prefix=/usr/local/apache
[root@test]# make
[root@test]# make install

安装Apache比较容易,安装完之后,验证一下也可以,就是启动一下Apache看看是否安装成功。

 3、安装SVN

[root@test]# pwd
/usr/local
[root@test]# tar zxvf subversion-1.4.6.tar.gz 
[root@test]# tar zxvf subversion-deps-1.4.6.tar.gz 
[root@test]# cd /usr/local/subversion-1.4.6
[root@test]# ./configure –with-apxs=/usr/local/apache/bin/apxs 
               –prefix=/usr/local/subversion –with-apr=/usr/local/apache 
               –with-apr-util=/usr/local/apache –with-ssl –with-zlib 
               –without-berkeley-db –enable-maintainer-mode
[root@test]# make
[root@test]# make install

 这里面这些配置有些讲究:

  • –with-apr 和 –with-apr-util 一定要加上,不然会因为版本的问题导致编译失败,deps里面的apr和apr-util是0.9.17版本和0.9.15版本的,而Apache2需要1.x版本的,所以在这里要指定他们的路径。
  • –without-berkeley-db 不使用BDB来存储数据,那么就只能使用FSFS了,具体的区别去Google查一下就可以了,而且使用FSFS备份起来非常容易。

 接下来验证一下,是否SVN安装成功了:

[root@test]# pwd
/usr/local/subversion/bin
[root@test]# ./svnserve –version
svnserve, version 1.4.6 (r28521)
   compiled Jan 15 2008, 13:41:55

Copyright (C) 2000-2007 CollabNet.
Subversion is open source software, see http://subversion.tigris.or
This product includes software developed by CollabNet (http://www.C

The following repository back-end (FS) modules are available:

* fs_fs : Module for working with a plain file (FSFS) repository.

 4、创建SVN库

 把SVN的仓库放到/var/svn/repositories目录下,在此创建一个库,名叫test

[root@test]# mkdir /var/svn/repositories
[root@test]# ./svnadmin create /var/svn/repositories/test
[root@test]# chown daemon.daemon -R /var/svn/repositories

 
5、配置Apache以启动SVN服务

修改一下Apache的配置(/usr/local/apache/conf/httpd.conf):

LoadModule dav_svn_module     modules/mod_dav_svn.so
LoadModule authz_svn_module   modules/mod_authz_svn.so

<Location /svn>
    DAV svn
    SVNParentPath /var/svn/repositories
    AuthzSVNAccessFile /var/svn/authz.conf
    AuthType Basic
    AuthName "simplelife.cn"
    AuthUserFile /var/svn/authfile
    Require valid-user
</Location>

 注意Location里面,有三个配置的路径:

  • SVNParentPath SVN仓库的上一级目录,所有的SVN仓库都在/var/svn/repositories下面
  • AuthzSVNAccessFile SVN的访问权限设置,设置哪些用户可以访问哪些SVN库
  • AuthUserFile 用户认证,基于Apache来验证用户名和密码

 创建一个新用户:

[root@test]# pwd
/usr/local/apache/bin
[root@test]# ./htpasswd /var/svn/authfile javor
New password: ******
Re-type new password: ******
Adding password for user javor

 为此用户赋予权限:

[root@test]# pwd
/var/svn/
[root@test]# more authz.conf
[/] 
javor=rw

 6、启动服务

 其他Apache即可以启动SVN服务

[root@test]# pwd
/usr/local/apache/bin
[root@test]# ./apachectl start

 浏览器访问:http://www.simplelife.cn/svn/test,注意替换中间的服务器地址为自己的服务器地址。

 7、其他

  • 要建多个库,在/var/svn/repositories下创建就可以了,通过更改URL后面的库名就可以访问
  • 要备份库,直接将/var/svn/repositories下对应的文件夹打包就可以了,这就是使用fsfs的好处
Next Page »