Archive

Archive for the ‘WebTech’ Category

Ajax应用中CKEDITOR多实例问题的解决

September 3rd, 2010 CoCoWool No comments

著名的Fckeditor升级之后就改名叫了CKEDITOR,界面和功能有了很大的提升,所以我在最近的项目中应用CKEDITOR。随着项目的深入,在Ajax应用较多的一个部分使用CKEDITOR时发现了问题,描述如下:

通过单击一个链接,调入需要显示的内容,其中包括一个富文本编辑器,这里使用了CKEDITOR。第一次调入时,一切正常。噩梦从第二次开始,在Firefox3.5+中,第二次的时候提示 i.contentWindow is null ,而在IE系列中则是一些模糊的错误提示。

出现这个问题后,分析的方向一直集中在CKEDITOR多实例的问题。因为第一次点击链接,调用内容时,已经进行了一次CKEDITOR的实例化,第二次调入时必然会与第一次的冲突。查阅了CKEDITOR的样例资料,试了下面的方法:

if( editor ){

  editor.destroy();

  editor = null;

}

editor = CKEDITOR.replace(‘content’);

但是没有用,问题依然发生。后来google之,得到了目前可以正常解决这个问题的方法

if( CKEDITOR.instances['content'] ){
    CKEDITOR.remove(CKEDITOR.instances['content']);
}

 

CKDEITOR.replace(‘content’);

应用了这个方法之后,不管是多少次调用,都不会再发生错误,应该就是正确的解决方法了,但是可惜的是在CKEDITOR的官方文档和论坛中均为看到相关的说明,遗憾…

Technorati 标签: ,,

参考资料:

1、CKEDITOR

2、CKEDITOR instance already exists

Categories: WebTech Tags: , ,

利用MapabcAPI实现基于浏览器的地理定位

August 30th, 2010 CoCoWool No comments

现在互联网中有了越来越多的地理位置服务,正在制定中的HTML5规范也试图在浏览器中内置嵌入地理位置共享服务,而且幸运的是,我们已经能够在Firefox 3.5+、Chrome 5.0+、Opera 10.60+、Safari 5.0+ 以及一些移动终端,注入IPhone、Android上使用这项服务,那么这个服务能否有Mapabc的API结合,来实现用户的地理定位呢?

传统上,地图应用上为用户定位的方式一般是:

用户访问时获得用户的IP。
用这个IP到IP库中匹配用户的城市信息。
根据获取的城市信息去已有的城市中心点字典中进行匹配。
匹配完成后将用户地图的中心点进行相应的切换。

这个过程繁琐,而且准确性极大程度上依赖于我们IP库的准确程度。现在有了浏览器的位置共享服务,我们可以更容易的实现用户的地理定位。

Geolocation对象介绍

正如开头所讲的,到目前为止,W3C中deGeolocation API规范已经在非IE的浏览中得到了实现。规范中提到,浏览器提供位置信息的来源是不固定的,可能是GPS、也可能来自于IP地址、RFID、WiFi、蓝牙或者GSM\CDMA的定位信息,也不保证返回的结果一定准确。Geolocation的API同时对“只获得一次”定位和“持续监督”定位都做出了规定。

Geolocation的一些方法

Geolocation对象位于浏览器Navigator对象下,可以通过 navigator.geolcation 来访问,不支持 geolocation 的浏览器不会包含这一对象,不会造成错误,可以用来做浏览器的区分。

if ( navigator.geolcation ){

    alert(‘ Your Browser dosent support geolcocation ‘);

} else{

    alert(‘ Your Browser support geolocation’);

}

在访问 geolocation 对象时,浏览器会进行提示,询问用户使用许可对网站提供位置服务,得到用户的许可后,访问才会继续,否则会被停止。而且,我们可以捕捉到用户同意或者拒绝的事件。

在获得用户的学科之后,就可以利用Geolocation获取当前位置,核心方法如下:

navigator.geolocation.getCurrentPosition( getPositionSuccess , getPositionError );

上面的代码中,调用了 getCurrentPosition 方法,并且传递了两个回调函数的参数,分别用来处理位置获取成功和失败时的情况。实事上,这个函数还可以接受第三个参数,用来传入一些配置信息,包括对于超时的设置等。下面来看两个获取成功和获取失败时,回调函数的处理。

获取地理信息成功的错误处理信息

function getPositionSuccess ( position ) {

  var lat = position.coords.latitude;

  var lng = position.coords.longitude;

  alert( ‘Now you are lat – lng ‘);

}

 

获取地理位置失败的回调函数

function getPositionError( error ){

    switch(error.code)

         case error.TIMEOUT;

          //Do something

          break;

          case error.PERMISSION_DENIED;

          //Do something

          break;

          case error.POSITION_UNAVAILIABLE;

          //Do something

          break;

}

获取地理位置信息的配置变量。在填入获取地理位置信息变量时,能够对获取地理位置的一些细节进行影响。下面是目前包括的几个具体参数

In ECMAScript, the enableHighAccuracy, timeout and maximumAge properties are all optional: when creating a PositionOptions object, the developer may specify any of these properties.

刚才也提到,我们还可以对地理位置进行持续的追踪,这是需要用到 watchPosition 方法。

因为对于移动设备的用户来说,位置并不是固定的,我们需要来处理这种移动客户端的情况,而不是每次要提醒用户去刷新浏览器来更新位置。

navigator.geolocation.watchPosition( refreshPosition );

与Mapabc API的整合

看完上面的关于 geolocation 的介绍之后,我们就可以将这个服务与Mapabc API一起,整合到我们的应用中了。下面是一个具体的实现样例,供参考:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<div>
    <div id="mapobj" style="width:500px; height:500px; border:1px solid black;"></div>
    <div id="info"></div>
    <input type="button" id="getPos" value="Get My Position" />
</div>
<script src="http://app.mapabc.com/apis?&t=flashmap&v=2.3.4&key=0c3235346b1e00772eafe1c099f4b23fe5ec1202d393f952395e628567934baceedcaf1508ea044f" type="text/javascript"></script>
<script type="text/javascript">
    function getPositionSuccess( position ){
        var lat = position.coords.latitude;
        var lng = position.coords.longitude;
        //alert( "您所在的位置: 经度" + lat + ",纬度" + lng );

        var mapOptions = new MMapOptions();//构建地图辅助类
        mapOptions.zoom=13;//设置地图zoom级别
        mapOptions.center=new MLngLat(lng,lat);   //设置地图中心点
        mapOptions.toolbar = MINI;//工具条
        mapOptions.toolbarPos = new MPoint(15,15);  //工具条偏移
        mapOptions.overviewMap = SHOW;//是否显示鹰眼
        mapOptions.scale = SHOW;//是否显示比例尺
        mapOptions.returnCoordType = COORD_TYPE_OFFSET;//返回偏移明码坐标
        mapOptions.zoomBox = true;//鼠标滚轮缩放和双击放大时是否有红框动画效果。
        mapabc.map=new MMap("mapobj",mapOptions); //地图初始

        if(typeof position.address !== "undefined"){
                var country = position.address.country;
                var province = position.address.region;
                var city = position.address.city;
                alert(’ 您位于 ‘ + country + province + ‘省’ + city +’市’);
        }
    }

    function getPositionError( error ){
        switch(error.code){
            case error.TIMEOUT :
                alert( " 连接超时,请重试 " );
                break;
            case error.PERMISSION_DENIED :
                alert( " 您拒绝了使用位置共享服务,查询已取消 " );
                break;
            case error.POSITION_UNAVAILABLE :
                alert( " 亲爱的火星网友,非常抱歉,我们暂时无法为您所在的星球提供位置服务 " );
                break;
        }
    }

    var dom = {
        btn    : document.getElementById("getPos"),
        info: document.getElementById("info"),
        map    : document.getElementById("mapObj")
    };

    var mapabc = {
        map        : null,
        marker    : null
    };

    dom.btn.onclick = function(){
        if( navigator.geolocation ){
            dom.info.innerHTML = "Waiting for the geolocation result…";
            navigator.geolocation.getCurrentPosition( getPositionSuccess, getPositionError );       
        } else {
            dom.info.innerHTML = "Your browser doesn’t support geolocation.";
        }
    }
</script>
</body>
</html>

上面的代码,会在地图显示后询问用户是否共享位置信息,如果共享则会切换地图中心点到相应的位置。当然,我们可以在自己的应用中更加灵活的使用位置共享服务,既然有了这么 Cool 的服务支持,我们还等什么呢。

 

 

 

参考资料:

1、Blueidea BBS
2、Geolocation API Specification
3、Mapabc API

Categories: WebTech Tags: ,

VIM在多窗口编辑时的几个快捷键

June 25th, 2010 CoCoWool No comments

image

使用VI提供的多窗口编辑在项目文件比较多的情况下非常方便。今天总结了几个比较好用的快捷键。

最基本的是打开分割窗口 :sp a.pl

切换窗口 Ctrl + w 按一次加上下键可以自己选择切换方向,按两次则从上到下自动遍历窗口

扩大窗口 Ctrl-w + 扩大窗口

缩小窗口 Ctrl-w – 缩小当前编辑窗口

在vim中执行shell命令 :! ls 这样可以执行shell命令,或者也可以 :shell top

放大当前窗口,缩小其他窗口 :res ,后面可以设置行数,比如 :res 10 则将当前窗口设置为10行

有了这几个功能,在vim中编辑复杂的项目也变得非常简单了

Categories: WebTech Tags:

PHP性能监测的工具介绍 – XHProf

June 2nd, 2010 CoCoWool No comments

XHProf

这个软件本是Facebook内部的一个应用工具,2009年3月份开源,为PHP的性能监测提供了很好的工具。官方的介绍中提到:

XHProf is a hierarchical profiler for PHP. It reports function-level call counts and inclusive and exclusive metrics such as wall (elapsed) time, CPU time and memory usage.

XHProf’s light-weight nature and aggregation capabilities make it well suited for collecting "function-level" performance statistics from production environments.

 

可以先来看看 XHProf 提供的图形界面的截图

 

XHProf的一些特性:

1、Flat Profile. 提供函数级的汇总信息,比如调用次数、执行时间、内存使用、CPU占用等。

2、Hierarchical Profile。 对每个程序,进行了父级调用和子级调用的分解。

3、Diff Reports(差异报告)。有很多种情况,我们希望能够对比,比如新版本比旧版本提升了多少速度,两个版本的差距究竟在哪里。Diff Report 就是这样的工具,接收两个输入,并且分别给出各自的 Flat Profile 和 Hierarchical Profile 报告。

4、Callgraph View(调用视图)。性能监测的数据可以绘制成调用视图,方便我们查看。

5、Memory Profile(内存监控)。这个特性帮助我们了解PHP如何分配和释放内存。值得注意的是,XHProf并不是严格的监测内存的分配和释放动作,而是计算每个函数进入和退出时的内存状况,这是一个相对简单的实现方式,但是基本上也能够满足我们日常的监控需求。

6、如何处理外部文件。XHProf将 include,require,include_once,require_once进来的文件视作是一个 function。

XHProf目前只支持一个级别的函数追踪,但是貌似也没有特别大的影响。

XHProf的安装配置

xhprof的安装配置很简单,我们首先在 PECL 的网站上下载 源码包 然后执行安装过程

% cd <xhprof_source_directory>/extension/
% phpize
% ./configure --with-php-config=<path to php-config>
% make
% make install
% make test

php.ini file: You can update your php.ini file to automatically load your extension. Add the following to your php.ini file.

[xhprof]
extension=xhprof.so
;
; directory used by default implementation of the iXHProfRuns
; interface (namely, the XHProfRuns_Default class) for storing
; XHProf runs.
;
xhprof.output_dir=<directory_for_storing_xhprof_runs>

 

xhprof的使用也很简单,只要将需要监控的脚本放在 xhprof_enable() 和 xhprof_disable() 中间,就可以得到相应的结果,同时也提供了一些参数可以让我们设置是否监控 Memory, CPU 的使用,是否监控PHP内置的函数,从 0.9.2 之后,还可以设置跳过一些特定的函数。

XHProf 生成的数据,可以用 XHProf UI 来进行简单的显示。

XHProf使用也很简单,下面是一个官方的例子:

<?php

function bar($x) {

  if ($x > 0) {

    bar($x – 1);

  }

}

function foo() {

  for ($idx = 0; $idx < 2; $idx++) {

    bar($idx);

    $x = strlen("abc");

  }

}

xhprof_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY);

foo();

$xhprof_data = xhprof_disable();

//

// Saving the XHProf run

// using the default implementation of iXHProfRuns.

//

include_once "xhprof_lib/utils/xhprof_lib.php";

include_once "xhprof_lib/utils/xhprof_runs.php";

$xhprof_runs = new XHProfRuns_Default();

// Save the run under a namespace "xhprof_foo".

//

// **NOTE**:

// By default save_run() will automatically generate a unique

// run id for you. [You can override that behavior by passing

// a run id (optional arg) to the save_run() method instead.]

//

$run_id = $xhprof_runs->save_run($xhprof_data, "xhprof_foo");

echo "—————\n".

     "Assuming you have set up the http based UI for \n".

     "XHProf at some address, you can view run at \n".

     "http://<xhprof-ui-address>/index.php?run=$run_id&source=xhprof_foo\n".

     "—————\n";

?>

 

我们可以持久化记录的数据,数据以文件的形式保存在指定的目录,如下图:

image 有了这个工具,我们可以根据其提供的数据,与相应的通知接口整合,在程序运行出现问题时,及时的发送通知信息。

 

PHP性能监控,还有两个可用的工具,一个是 XDebug,另外一个是 ZendServer,我会在接下来继续进行介绍。

Technorati 标签: ,,

参考文档:

1、Speed UP your php with xhprof

2、xhprof document

Categories: WebTech Tags: , , , ,

利用PUT方式上传文件的方法研究

May 30th, 2010 CoCoWool No comments

虽然没有POST方法使用广泛,但是PUT方法却是向服务器上传文件最有效率的方法。POST上传文件时,我们通常需要将所有的信息组合成 multipart 传送过去,然后服务器再解码这些信息,解码过程则必不可少的会消耗内存和CPU资源,这种现象在上传大文件时尤其明显。而PUT方法则允许你通过与服务器建立的socket链接传递文件的内容,而不附带其他的信息。

最近一个项目上需要利用这种方式来进行文件的上传,下面介绍一下在 Apache + PHP 的环境下如何进行PUT方式的文件上传。

Apache 有一个模块 mod_actions,先看看官方的说明:

This module has two directives. The Action directive lets you run CGI scripts whenever a file of a certain MIME content type is requested. The Script directive lets you run CGI scripts whenever a particular method is used in a request. This makes it much easier to execute scripts that process files.

也就是说,这个模块可以指定对于特定 MIME 类型的文件处理,或者对于特定脚本的请求进行指定的处理。我用到的就是 Script 这个选项。

在Apache 配置文件的 Directory 中指定

Script PUT /receive.php

这个含义就是,对于所有对服务器的PUT请求,都交给根目录下的 receive.php 去处理,当然我们也可以选择 perl 或者其他的CGI脚本来进行处理。

接下来就是这个 receive.php 脚本的编写了,他的主要任务就是将请求的文件写到指定的位置

<?php
/**
* Process The PUT File, receive and move a file to corresponsed location
* Created by shiqiang<cocowool@gmail.com> at 2010-05-24
*
**/

class Receive {
    var $default_log_file = "logs/error.log";
    var $default_server_info = "logs/server.log";
    var $default_header_info = "logs/header.log";
    var $default_prefix = "/data1/vhosts";    //Default project location prefix;
    var $default_module = "test.cn";
    var $max_filesize = 2048000;
    var $request_uri;

    function Receive(){
        $this->request_uri = $_SERVER['REQUEST_URI'];
    }
    function saveFile(){
        //receive data and save
        $putdata = fopen("php://input", "r");

        $path = $this->getPath($this->request_uri);
        $fp = fopen($path, ‘w’);
        while($data = fread($putdata, 1024) ){
            fwrite($fp, $data);
        }

        fclose($fp);
        fclose($putdata);

        //Log The filesize check and limit check
        if( filesize($path) != $_SERVER['CONTENT_LENGTH'] ){
            $this->errorLog( "[warn] " . date("Y-m-d H:i:s")  . " The file’s ($path) size dosen’t match Server Filesize = " . filesize($path) . "; Put Filesize = " . $_SERVER['CONTENT_LENGTH']. "\r\n" );
            header(’HTTP/1.1 526 Receive Data Error’);
        }

        if( filesize($path) > $this->max_filesize ){
            $this->errorLog( "[warn] " . date("Y-m-d H:i:s")  . " The file’s ($path) size exceed the system limit");
        }
    }

    //Log Error Info
    function errorLog( $info ){
        $f = fopen($this->default_log_file, ‘a+’);
        fwrite($f, $info);
        flcose($f);
    }

    function serverLog(){
        $f = fopen($this->default_server_info, ‘w’);
        $info = $_SERVER;
        $str = "The Last Request Server Info:\r\n";
        foreach ($info as $key => $value){
            $str .= "$key = $value\r\n";
        }
        $str .= $this->getPath($this->request_uri) . "\r\n";
        $str .= "PHP_UPLOADED_FILE_NAME=" . $PHP_UPLOADED_FILE_NAME . "\r\n";
        fwrite($f , $str);
        fclose($f);
    }

    //Log the Request Header info
    function headerLog(){
        $f = fopen($this->default_header_info, ‘w’);
        $info = get_headers();
        $str = "The Last Request header Info:\r\n";
        foreach ($info as $key => $value){
            $str .= "$key = $value\r\n";
        }
        fwrite($f , $str);
        fclose($f);
    }

    //get the path where the file should be
    function getPath($uri){
        $module = $this->defalt_module;    //Default storage module

        $referer = $this->request_uri;
        preg_match(’/(?<=\/)(.*?)(?=\/)/s’, $referer, $match);

        if( !empty($match) && !empty($match[0]) ){
            $module = $match[0];
        }

        $path = $this->default_prefix;
        $path .= ‘/’ . $module . ‘/htdocs’;
        $fullpath = substr($uri, strlen($match[0]) + 1, strlen($uri) );

        $arr = explode(’/', ltrim($fullpath, ‘/’));
        foreach($arr as $v){
            if( !strstr($v, ‘.’) ){
                $path .= ‘/’ . $v;
                //exec("echo $path >> dir.txt");
                if( !is_dir($path) ){
                    //For php > 5.0
                    //mkdir($path, "0766", true);
                    mkdir($path, 0766);
                }
            }else{
                $path .= ‘/’ . $v;
            }
        }

        return $path;
    }

}

$instance = new Receive();
$instance->serverLog();
//$instance->headerLog();
$instance->saveFile();

?>

这个脚本,使用PHP手册中的接收PUT方式的方法,详细的使用,GOOGLE的时候,并没有找到很多,所以可能对于错误情况,考虑的也不是很全面,如果有使用过这个方法的欢迎和我讨论。

Technorati 标签: ,,

参考资料:
1、PUT Upload
2、RFC 2616

Categories: WebTech Tags: , , ,

通过设置双网卡实现VirtualBox虚机上网及主宿互访

May 26th, 2010 CoCoWool No comments

最近,经过一些研究,终于调通了VirtualBox虚拟机互连、主宿机互连、以及主宿机连接互联网。下面分享一下。

1、VirtualBox中的虚拟网卡。VirtualBox安装完成后,会在系统中装一块虚拟网卡,我们在管理->全局设定中可以看到。这块网卡是在 Host-Only 连接方式中,主宿机互访的桥梁。

0GNO4}~D]5R]S32KPW37B}7

2、主机访问虚拟机通过Host Only的方式实现。

主机访问虚拟机这个是最简单的。通过在网络连接1中选择 Host-only Adapter ,我们的虚拟机就可以获得一个内网的地址,主机可以直接访问这个地址。我们可以使用DHCP,也可以自己指定IP,多数情况下,都会指定一个固定的IP。

PUB}7VB28B%2SQS4)E%EXDY

3、现在要想实现虚拟机上网,我们可以为虚拟机再添加一块网卡,通过Bridge方式,达到虚拟机上网的目的。

9)N`XA15%{3UJIGA}D~IW3N

4、但是笔者在这样设置以后,测试 ping www.baidu.com 时,发现网络并没有通,仔细检查后发现,需要在我们的第二块网卡的配置上,指定他的网关。我在 /etc/sysconfig/network-scripts/ifcfg-eth1 中添加

GATEWAY=10.207.0.11

重启网络之后,就可以PING通了。

这样,我们既能访问虚拟机,又可以访问互联网,利用各种在线更新的工具,大大的方便了 Linux 的使用。

基于Mapabc API的周边查询应用

May 23rd, 2010 CoCoWool No comments

现在,越来越多的 Location Based 应用,或者Geolocation的应用出现在网络、手机等各种各样的终端上,为人们的日常生活、出行和工作都提供了不少的便利。最常见的就是出门前,利用地图工具,看看合适的公共交通路线,寻找一个自己最满意的方案,既方便有低碳环保。有时候,对周边环境不熟悉,想要找到周边的医院、银行、学校等一些单位的时候,地图同样可以帮上我们的大忙。

今天,我就做了一个基于Mapabc地图API的周边查询工具,利用Mapabc详尽的基础地物信息,为我查找周边的便民信息提供了有利的帮助。

开始之前,我大概需要知道最后的结果是什么样子的,可以借助传统的纸和笔,也可以用现代的原型工具,当然PS这样的重量级工具就不太需要了。下面是效果图:

1131

有了效果图,接下来需要稍微规划一下代码。Mapabc的API在页面加载完成后,需要初始化地图,所以初始化的操作放在一个函数 pageInit() 中。周边查询的操作,希望通过用户输入一个关键词,然后通过点选地图设置中心点的方式实现。那么就需要一个函数来监听鼠标在地图上的单击事件,然后一个负责查询的函数和一个负责显示结果的函数。程序的结构大致如此,接下来就进入实质的编码过程。

编码的重点函数有以下几个:

mapObj.addEventListener(mapObj, MOUSE_CLICK, searchAround);

对地图添加监听事件。

mls.poiSearchByCenterXY(new MLngLat(cordx, cordy),keyword,citycode,mlsp);

利用中心点坐标查询查找周边信息

利用这两个函数,加上参考Mapabc官方的示例,我们就可以完成这个应用。

1132

通过修改区号和关键字,可以在不同城市之间切换,怎么样,简单吧。

Technorati 标签: ,,,
Categories: WebTech Tags:

彻底理解Doctype

March 15th, 2010 CoCoWool No comments

写了很多年的CSS,但是对于页面中的第一段话从来都是模模糊糊的认识。仿佛是记得,不同doctype模式,就会触发不同的验证级别。实际的编码过程中,貌似遇到过一两次模式不同,代码解释不一样的情况,但是并没有去细细的追究。今天想起来,这个问题乃是一个最基本的问题,所以花了点时间整理一些知识,消化一下,今后不能够在这个方面有半点的马虎。

首先,看一段典型的Doctype

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

 

DOCTYPE是document type的简写,在网页制作中,用来说明你用的XHTML或者HTML是什么版本。其作用是指出阅读程序应该用什么规则集来解释文档中的标记。要建立符合标准的网页,DOCTYPE声明是必不可少的关键部分,如果没有正确的DOCTYPE,你的标识和CSS可能都不会正常工作。

其中的DTD,例如上例中的xhtml1-transitional.dtd,叫做文档类型定义,里面包含了文档的规则,浏览器就根据你定义的DTD来解释你页面的标识,并展现出来。

完整的DOCTYPE类型如下图所示:

0021

XHTML 1.0 提供了三种DTD声明可供选择:

1、过渡的(Transitional):要求非常宽松的DTD,它允许你继续使用HTML4.01的标识(但是要符合xhtml的写法),完整代码如下:

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” "

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

2、严格的(Strict):要求严格的DTD,不能使用任何表现层的标识和属性,完整的代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

那么表现层的标识和属性都有哪些呢,资料1中说 <br>不能够正常识别,但是笔者实验过后,发现在IE6和Firefox3.5中,即使使用strict模式,<br>仍能够被正常解析为一个换行。而且,<b>、<em>这些标签都可以正常生效,所以这里就存疑了,什么属于表现层的标识和属性呢?

“表现层的标识和属性”是指那些纯粹用来控制表现的tag。

经过Google,上面实验发现的问题是这个原因引起的:不同网页的不同呈现模式

现代浏览器包括不同的呈现模式,目的是既支持遵循标准的网页,也支持为老式浏览器而设计的网页。其中,Standard(标准)模式(也就是严格呈现模式)用于呈现遵循最新标准的网页,而Quirks(包容)模式(也就是松散呈现模式或者兼容模式)用于呈现为传统浏览器而设计的网页。另外,Mozilla新增了一种 Almost Standards(近似标准)模式,用于支持为标准的某个老版本而设计的网页。

nternet Explorer 6+ 支持两种呈现模式,分别叫做 Quirks 模式和 Standards 模式。当 Internet Explorer 呈现包含有效 XHTML(或 HTML 4.0)DOCTYPE 的页时,它会以 Standards 模式呈现该页;否则,它会以 Quirks模式呈现该页(有关详细信息,请参阅 CSS Enhancements in Internet Explorer 6)。

Opera 浏览器 (Opera 7+) 支持与 Internet Explorer 相同的两种呈现模式:Quirks 和 Standards(有关详细信息,请参阅 http://www.opera.com/docs/specs/doctype/)。

Mozilla Firefox 1+ 支持三种呈现模式:Quirks 模式、Almost Standards 模式和 Standards 模式。Firefox 的 Almost Standards 模式对应于 Internet Explorer 和 Opera 的 Standards 模式。当页包含有效的 XHTML 1.0 Transitional DOCTYPE(并且该页被分配为 text/html MIME 类型)时,Firefox 会以 Almost Standards 模式呈现该页。当页包含 XHTML 1.0 Strict 或 XHTML 1.1 DOCTYPE(或者该页被分配为 XML MIME 类型)时,该页将以 Standards 模式呈现(有关详细信息,请参阅 http://www.mozilla.org/docs/web-developer/quirks/doctypes.html)。

可以通过脚本来检测浏览器当前的呈现模式

<script type=’text/javascript’>alert(document.compatMode);</script>

 

3、框架的(Frameset):专门针对框架页面设计使用的DTD,如果页面中包含有框架,最好使用这种DTD,完整代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">

关于DOCTYPE切换

顶部的doctype声明是让浏览器进入正确呈现模式的关键,理论上浏览器应该能够正确的识别出doctype并作出自然地切换。实际上,由于多方面的原因,有的时候浏览器并不能够正常的进行doctype的切换,原因如下

1、doctype声明不在第一行。

IE,Opera和旧版Safari都希望文档的第一行是doctype声明。所以,如果在它之前还有其他任何东西 (包括XML prolog),就无法识别doctype。因此,XML prolog的存在会使IE,Opera和Safari进入Quirks模式。XML prolog并非必需的,所以你可在XHTML网页中安全地省略它。注意:一定要在http-equiv meta标记中包括一个charset属性,以弥补XML prolog中缺失的encoding属性。

2、丢失或相对的URL。

在完整的doctype声明中,要包括相应的文档类型定义(DTD)文件的URL。如果URL丢失,或者指定的是一个相对路径(而不是完全限定的Internet地址),大多数浏览器都会进入Quirks模式,不管doctype声明规定的是什么模式。

3、形式错误的doctype。

浏览器对doctype声明的形式和格式非常敏感,如果不能识别一个形式错误的doctype,就会强制进入Quirks模式(正是因为这个原因,所以我们建议将一个已知正确的doctype拷贝和粘贴到文档中,而不是亲自输入它)。之所以出现形式错误的doctype,一个常见的原因是在 doctype 的第一部分与URL之间缺少一个空格。将一个分两行的doctype折叠成单独一行,常常会丢失那个空格。

4、过渡期的doctype。

浏览器处理过渡期的doctype时,最容易出现不一致的问题。IE和Opera使用Standards模式;Netscape 6和旧版本的Safari使用Quirks模式;Netscape 7、Mozilla 1和新版本的Safari使用Netscape的Almost Standards模式,它是Standards模式的一个具有更好容错性的版本。

5、未知的doctype。

浏览器在处理不能识别的doctype时,也存在不一致的现象。IE和Opera会进入Standards模式;换言之,它假定不能识别的 doctype 是尚未在浏览器中集成的一个新标准。Netscape 6则相反,会在遇到不能识别的doctype时切换到Quirks模式。

doctype切换也许是让浏览器进入正确呈现模式并正确显示网页的一种有效手段,前提是你注意到了各种浏览器的不一致,并能积极主动地避免各种问题。

参考资料:
1、什么是Doctype,他对网页起何作用
2、DOCTYPE声明的作用及用法详解
3、XHTML的DOCTYPE切换
4、Mozilla’s DOCTYPE sniffng

Categories: WebTech Tags: , , ,

Eclipse Galileo SR2 参数配置

March 10th, 2010 CoCoWool No comments

要崩溃了,下载了 eclipse-jee-galileo-SR2-win32.zip ,解压缩,运行后提示:

JVM   terminated. Exit   code=-1

Google了一下,问题出在 eclipse.ini 上,但是发现大家解决这个问题的方法真是千奇百怪:

先来看一下原始的配置文件

-startup
plugins/org.eclipse.equinox.launcher_1.0.201.R35x_v20090715.jar
–launcher.library
plugins/org.eclipse.equinox.launcher.win32.win32.x86_1.0.200.v20090519
-product
org.eclipse.epp.package.jee.product
–launcher.XXMaxPermSize
256M
-showsplash
org.eclipse.platform
–launcher.XXMaxPermSize
256m
-vmargs
-Dosgi.requiredJavaVersion=1.5
-Xms40m
-Xmx512m

方法一:

将换行的部分改成不换行+空格

–launcher.XXMaxPermSize
256M
-showsplash
org.eclipse.platform
–launcher.XXMaxPermSize
256m

方法二:

调整内存设置

-vmargs
-Dosgi.requiredJavaVersion=1.5
-Xms40m
-Xmx256m

方法三:

添加虚拟机

-vm
E:\Program Files\Java\jdk1.6.0_16\bin\javaw.exe

这三个方法都可以使 Galileo 正常启动,由此可见,这个配置文件实在是很难搞明白。

最后,经过试验,如果我希望能够调整 vm 的内存限制的话,必须采用第三种方法,最后的配置文件如下:

-startup
plugins/org.eclipse.equinox.launcher_1.0.201.R35x_v20090715.jar
–launcher.library
plugins/org.eclipse.equinox.launcher.win32.win32.x86_1.0.200.v20090519
-product
org.eclipse.epp.package.jee.product
–launcher.XXMaxPermSize
256M
-showsplash
org.eclipse.platform
–launcher.XXMaxPermSize
256m
-vm
E:\Program Files\Java\jdk1.6.0_16\bin\javaw.exe
-vmargs
-Dosgi.requiredJavaVersion=1.5
-Xms512m
-Xmx1024m
-XX:+UseParallelGC
-XX:PermSize=256M
-XX:MaxPermSize=512M

Resin介绍及其使用配置

March 8th, 2010 CoCoWool No comments

Resin是一个提供高性能的,支持 Java/PHP 的应用服务器。目前有两个版本:一个是GPL下的开源版本,提供给一些爱好者、开发人员和低流量网站使用;一种是收费的专业版本,增加了一些更加适用于生产环境的特性。

Resin的一些特性:

可靠性:Resin包含了很多可靠的特性,包括服务器自动重启、检测并重启死锁的服务器、管理JVM内存以防止内存泄露等。

集群:Resin可以将多个服务器作为一个服务器来对客户进行响应,从而增强服务器的扩展能力。

持久和分布的sessions:持久的session能够在服务器重启的时候保持现有的Http会话,分布式的session可以在多个服务器之间共享Http会话的状态。

增强的本地代码:同时为Windows和Linux系统提供了本地的代码增强支持。能够改善Socket链接、持久链接和文件读写方面的性能。

OpenSSL:提供原生的OpenSSL库支持,比JSSE提供的方案要好很多。

HTTP代理缓存:能够通过内存和磁盘缓存系统提高服务器的性能表现,将动态页面的速度提高到接近静态页面。

Gzip过滤器:通过gzip来减少带宽。

 

Resin服务器的安装(Windows – 独立版)

1、安装JDK1.5或更高

2、确保JDK的安装以及正确设置了环境变量JAVA_HOME

3、解压Resin文件

4、执行 java –jar resin-3.1.8/lib/resin.jar

5、或者运行 http.exe

6、在浏览器地址栏中输入 http://localhost:8080 即可进行访问

 

我们也可以将Resin设置为系统服务。

 

虚拟机的配置

Resin的配置文件位于 ./conf/ 下,默认的配置文件为 resin.conf。

配置简单的虚拟机,我们只要加入

  <host host-name="test.heep.com" root-directory="D:\workspaces\java\testsys">
    <access-log path="logs/test.access.log"
          format=’%h %l %u %t "%r" %s %b "%{Referer}i" "%{User-Agent}i"’
          rollover-period="1W"/>

    <web-app id="/" root-directory="WebRoot/">

    </web-app>
  </host>
</cluster>

另外在host文件中加入对应的记录,这样,我们就可以访问 http://test.heep.com

 

参考资料:

1、Resin Documetation
2、轻松搭建Resin开发平台
3、Windows下的Resin配置详解
4、Resin学习笔记

Categories: WebTech Tags: , ,