虫语~~

Main | Next page »

http://blog.matrix.org.cn/ljhj210423/date/20061101 星期三 2006年11月01日

apache + resin 对SSI进行支持

     搞了几天,终于弄明白了,首先就是将apache与resin各自安装好,并能各自运行,之后运行resin下setup.exe(在根目录或bin目录 下)使之与apache集成,再运行apache看看有没有问题 (之前好多次都失败,后来发现是resin目前只有支持apache2.0或2.0以下版本的模块,而我用的是apache2.2,后来换成2.0版本的 就可以了),然后按照apache文档中的方法,开启apache 对SSI的支持就可以了.
    运行的时候需要将要运行的project放在apache的部署文件夹下,然后依次运行resin和apache就可以了(当然二者的端口号不能相同,要不就冲突了),

http://blog.matrix.org.cn/ljhj210423/date/20061030 星期一 2006年10月30日

关于web.xml中url-pattern

在servlet 2.4 specification中找到

SRV.11.2 Specification of Mappings

In theWeb application deployment descriptor, the following syntax is used to define
mappings:
• A string beginning with a ‘/’ character and ending with a ‘/*’ suffix is used
for path mapping.
• A string beginning with a ‘*.’ prefix is used as an extension mapping.
• A string containing only the ’/’ character indicates the “default” servlet of
the application. In this case the servlet path is the request URI minus the context
path and the path info is null.
• All other strings are used for exact matches only.
看来是不能使用正则表达式的,只能使用有限的几个通配符

http://blog.matrix.org.cn/ljhj210423/date/20061025 星期三 2006年10月25日

Apache学习笔记

转自[http://www.chedong.com/tech/apache_install.html]

内容摘要:

Apache 是一个历史悠久并且功能十分强大的WEB服务器,但其丰富的功能对于一个新手来说往往不知道从何下手。我个人感觉Apache的设计充分体现了模块化设计 的优势,通过在动态模块加载(DSO)模式下的安装,任何子应用模块都可以通过配置文件的简单修改进行积木式的灵活配置。安装的过程可以从简单的静态 html服务开始,一个模块一个模块的学习使用。从单纯的HTML静态服务(core),到复杂的动态页面服务(core + php, core + resin, core + php + mod_gzip, core + resin + mod_expire)。


本文主要从简化安装==>性能调优==>维护方便的角度,介绍了WEB服务的规划、HTTPD安装/应用模块配置、升级/维护等过程。让Apache和PHP,Resin等应用模块的独立升级,完全互不影响。

WEB应用容量规划:根据硬件配置和WEB应用的特点进行WEB服务的规划及一些简单的估算公式;
Apache安装过程:apache的通用的简化安装选项,方便以后的应用的模块化配置;
修改 HARD_SERVER_LIMIT:
vi /path/to/apache_src/src/include/httpd.h
#define HARD_SERVER_LIMIT 2560 <===将原来的 HARD_SERVER_LIMIT 256 后面加个“0”
apache编译:
./configure --prefix=/home/apache --enable-shared=max --enable-module=most
可选应用模块/工具的安装:php resin mod_gzip mod_expire及各个模块之间的配合;
mod_php安装:./configure --with-apxs=/home/apache/bin/apxs --enable-track-vars --with-mysql
mod_resin安装:./configure --with-apxs=/home/apache/bin/apxs
mod_gzip安装:修改Makefile中的 apxs路径:然后make make install
工具:日志轮循工具cronolog安装:http://www.cronolog.org
升级/维护:看看通用和模块化的安装过程如何简化了日常的升级/维护工作;
按照以上的方法:系统管理员和应用管理员的职责可以清楚的分开,互相独立。
系统安装:系统管理员的职责就是安装好一台DSO模式的Apache,然后COLON即可,
应用安装:由应用管理员负责具体应用所需要的模块,比如PHP Resin等,并设置httpd.conf中相关的配置。
系统升级:系统管理员:升级操作系统/升级Apache
应用升级:应用管理员:升级应用模块,PHP Resin等。
WEB应用的容量规划

Apache主要是一个内存消耗型的服务应用,我个人总结的经验公式:
apache_max_process_with_good_perfermance < (total_hardware_memory / apache_memory_per_process ) * 2
apache_max_process = apache_max_process_with_good_perfermance * 1.5

为 什么会有一个apache_max_process_with_good_perfermance和apache_max_process呢?原因是在低 负载下系统可以使用更多的内存用于文件系统的缓存,从而进一步提高单个请求的响应速度。在高负载下,系统的单个请求响应速度会慢不少,而超过 apache_max_process,系统会因为开始使用硬盘做虚拟内存交换空间而导致系统效率急剧下降。此外,同样的服务:2G内存的机器的 apache_max_process一般只设置到1G内存的1.7倍,因为Apache本身会因为进程过多导致性能下降。

例子1:
一个apache + mod_php的服务器:一个apache进程一般需要4M内存
因此在一个1G内存的机器上:apache_max_process_with_good_perfermance < (1g / 4m) * 2 = 500
apache_max_process = 500 * 1.5 = 750
所以规划你的应用让服务尽量跑在500个进程以下以保持比较高的效率,并设置Apache的软上限在800个。

例子2:
一个apache + mod_resin的服务器: 一个apache进程一般需要2M内存
在一个2G内存的机器上:
apache_max_process_with_good_perfermance < (2g / 2m ) * 2 = 2000
apache_max_process = 2000 * 1.5 = 3000

以上估算都是按小文件服务估算的(一个请求一般大小在20k以下)。对于文件下载类型站点,可能还会受其他因素:比如带宽等的影响。

Apache安装过程

服务器个数的硬上限HARD_SERVER_LIMIT的修改:
在Apache的源代码中缺省的最大进程数是256个,需要修改apache_1.3.xx/src/include/httpd.h
#ifndef HARD_SERVER_LIMIT
#ifdef WIN32
#define HARD_SERVER_LIMIT 1024
#elif defined(NETWARE)
#define HARD_SERVER_LIMIT 2048
#else
#define HARD_SERVER_LIMIT 2560 <===将原来的HARD_SERVER_LIMIT 256 后面加个“0”
#endif
#endif

解释:
Apache 缺省的最大用户数是256个:这个配置对于服务器内存还是256M左右的时代是一个非常好的缺省设置,但随着内存成本的急剧下降,现在大型站点的服务器内 存配置一般比当时要高一个数量级不止。所以256个进程的硬限制对于一台1G内存的机器来说是太浪费了,而且Apache的软上限 max_client是受限于HARD_SERVER_LIMIT的,因此如果WEB服务器内存大于256M,都应该调高Apache的 HARD_SERVER_LIMIT。根据个人的经验:2560已经可以满足大部分小于2G内存的服务器的容量规划了(Apache的软上限的规划请看后 面)。

Apache的编译:以下通用的编译选项能满足以后任意模块的安装
./configure --prefix=/another_driver/apache/ --enable-shared=max --enable-module=most
比如:
./configure --prefix=/home/apache/ --enable-shared=max --enable-module=most


解释:
-- prefix=/another_driver/apache/:建议将apache服务安装在另外一个驱动设备上的目的在于硬盘往往是一个系统使用寿命 最低的设备,因此:将服务数据和系统完全分开,不仅能提高了数据的访问速度,更重要的,大大方便系统升级,应用备份和恢复过程。

--shared-module=max:使用动态加载方式载入子模块会带来5%的性能下降,但和带来的配置方便相比更本不算什么:比如模块升级方便,系统升级风险降低,安装过程标准化等

--enable-module=most:用most可以将一些不常用的module编译进来,比如后面讲到的mod_expire是就不在 apache的缺省常用模块中

如果不想build so, 也可以这样:
./configure \
"--with-layout=Apache" \
"--prefix=/path/to/apache" \
"--disable-module=access" \
"--disable-module=actions" \
"--disable-module=autoindex" \
"--disable-module=env" \
"--disable-module=imap" \
"--disable-module=negotiation" \
"--disable-module=setenvif" \
"--disable-module=status" \
"--disable-module=userdir" \
"--disable-module=cgi" \
"--disable-module=include" \
"--disable-module=auth" \
"--disable-module=asis"

但结果会发现,这样编译对服务性能只能有微小的提高(5%左右),但却失去了以后系统升级和模块升级的灵活性,无论是模块还是Apache本身升级都必须把Apache和PHP的SOURCE加在一起重新编译。

apache的缺省配置文件一般比较大:可以使用去掉注释的方法精简一下:然后再进入具体的培植过程能让你更快的定制出你所需要的。
grep -v "#" httpd.conf.default >httpd.conf

需要修改的通用项目有以下几个:

#服务端口,缺省是8080,建议将整个Apache配置调整好后再将服务端口改到正式服务的端口
Port 8080 => 80

#服务器名:缺省没有
ServerName name.example.com

#最大服务进程数:根据服务容量预测设置
MaxClients 256 => 800

#缺省启动服务后的服务进程数:等服务比较平稳后,按平均负载下的httpd个数设置就可以
StartServers 5 => 200

不要修改:
以前有建议说修改:
MinSpareServers 5 => 100
MaxSpareServers 10 => 200

但从我的经验看来:缺省值已经是非常优化的了,而且让Apache自己调整子共享进程个数还是比较好的。

特别修改:
在solaris或一些比较容易出现内存泄露的应用上:
MaxRequestsPerChild 0 =>3000

应用模块和工具的安装配置:

由于使用模块动态加载的模式,所以可以方便的通过简单的配置调整来把Apache定制成你需要的:最好把不常用模块全部清除(无论处于安全还是效率)。
比如:对于静态页面服务器:就什么其他子模块都不加载,对于PHP应用就加上PHP模块,对于JAVA应用就把Resin模块加载上。而且各种模块的插拔非常简单,这样调试过程中就可以简单的通过注释掉不需要的模块,而不用重新编译。

一般说来,可以不需要的模块包括:
#LoadModule env_module libexec/mod_env.so
#LoadModule negotiation_module libexec/mod_negotiation.so
#LoadModule status_module libexec/mod_status.so
#server side include已经过时了
#LoadModule includes_module libexec/mod_include.so
#不需要将没有缺省index文件的目录下所有文件列出
#LoadModule autoindex_module libexec/mod_autoindex.so
#尽量不使用CGI:一直是Apache安全问题最多的地方
#LoadModule cgi_module libexec/mod_cgi.so
#LoadModule asis_module libexec/mod_asis.so
#LoadModule imap_module libexec/mod_imap.so
#LoadModule action_module libexec/mod_actions.so
#不使用安全认证可以大大提高访问速度
#LoadModule access_module libexec/mod_access.so
#LoadModule auth_module libexec/mod_auth.so
#LoadModule setenvif_module libexec/mod_setenvif.so

最好保留的有:
#用于定制log格式
LoadModule config_log_module libexec/mod_log_config.so
#用于增加文件应用的关联
LoadModule mime_module libexec/mod_mime.so
#用于缺省index文件:index.php等
LoadModule dir_module libexec/mod_dir.so

可用可不用的有:
#比如:需要在~/username/下调试php可以将
LoadModule userdir_module libexec/mod_userdir.so
#比如:需要将以前的URL进行转向或者需要使用CGI script-alias
LoadModule alias_module libexec/mod_alias.so


常用的模块:
最 常用的可能就是php和JAVA应用服务器的前端,此外,从性能上讲利用mod_gzip可以减少40%左右的流量,减少机器用于传输的负载,而 mod_expires可以减少10%左右的重复请求,让重复的用户对指定的页面请求结果都CACHE在本地,根本不向服务器发出请求。

建议将所有MODULE的配置都放到相应模块的配置内部:<IfModule some_module.c>some_module config </IfModule>

PHP的安装:
/path/to/php_src/configure --with-apxs=/path/to/apache/bin/apxs --with-other-modules-you-need
需要修改的配置:
AddType application/x-httpd-php .php .php3 .any_file_in_php

resin的安装设置:
/path/to/resin/src/configure --with-apxs=/path/to/apache/bin/apxs

具体的resin设置放在另外一个文件中:比如/home/resin/conf/resin.conf
<IfModule mod_caucho.c>
CauchoConfigFile /path/to/apache/conf/resin.conf
</IfModule>

mod_expires的安装配置:
<IfModule mod_expires.c>
    ExpiresActive on
    ExpiresByType image/gif "access plus 1 month"
    ExpiresByType text/css "now plus 1 month"
    ExpiresDefault "now plus 1 day"
</IfModule>

注释:
所有的.gif文件1个月以后过期
所有的文件缺省1天以后过期


mod_gzip的安装
http://www.chedong.com/tech/compress.html


日志的轮循:cronolog的安装和设置

cronolog可以非常整齐的将日志按天轮循存储
缺省编译安装到/usr/local/bin/下,只需要将配置改成:

CustomLog "|/usr/local/sbin/cronolog /home/apache/logs/%w/access_log" combined


日志将按天截断并存放在以星期为目录名的目录下:比如:log/1是周一,log/5是周五, log/0是周日

用gzip压缩每天的日志:
30 4 * * * /usr/bin/gzip -f /home/apache/logs/`date -d yesterday +%w`/access_log

日志的定期删除:
30 5 * * */usr/bin/find /home/apache/logs/ -name access_log.gz -mtime +3 |xargs -r /bin/rm -f

升级维护:

由于使用动态模块加载方式(DSO模式)安装Apache,Apache的HTTPD核心服务和应用模块以及应用模块之间都变的非常灵活,建议将所有独立模块的配置都放在
<IfModule mod_name>
CONFIGURATIONS..
</IfModule>
里,这样配置非常容易通过屏蔽某个模块来进行功能调整:比如:
#AddModule mod_gzip.c
就屏蔽了mod_gzip,而其他模块不首任何影响。

安装和维护过程:

系统安装:系统管理员的职责就是安装系统和一个按照DSO模式安装的Apache,然后COLON。
应用安装:由应用管理员负责具体应用所需要的模块并设置HTTPD。
系统升级:系统管理员:升级系统/升级Apache
应用升级:应用管理员:升级应用模块:PHP CAUCHO等
系统备份/恢复:如果Apache不在缺省的系统盘上,只需要将Apache目录备份就可以了,遇到系统分区的硬件问题直接使用预先准备好的系统COLON,再直接将Apache所在物理盘恢复就行了。
系统管理员:Apache的最简化安装 OS + Apache (httpd core only)
应用管理员:应用模块定制 纯静态页面服务
core
 PHP动态页面
core+so
+php
 JAVA应用
core+so
+caucho
+ssl
应用例子: www.example.com
image.example.com
 bbs.example.com mall.example.com

 


例子:Apache和PHP模块的独立升级。

如果Apache是按照以下方式安装:
./configure --prefix=/home/apache --enable-shared=max --enable-module=most
PHP是按照以下方式安装:
./configure --with-apxs=/home/apache/bin/apxs --enable-track-vars --with-mysql

以后单独升级Apache的时候,仍然是:
./configure --prefix=/home/apache --enable-shared=max --enable-module=most
make
su
#/home/apache/bin/apachectl stop
#make install

单独升级php时,仍然是:
./configure --with-apxs=/home/apache/bin/apxs --enable-track-vars --with-mysql
make
su
#/home/apache/bin/apachectl stop
#make install
#/home/apache/bin/apachectl start


基于反相代理的WEB加速:
squid和mod_proxy都可以实现反相代理加速。而基于缓存的代理加速比起原有WEB服务,速度会有数量级的提升。

 

小提示:

Apache安装后,缺省根目录下没有但很有用的2个文件:

favicon.ico: favicon.ico是一个16x16的站点图标文件,如果浏览器发现有这个文件,在地址栏中会用这个图标替换调浏览器的网页图标。IE6和 MOZILLA等主流浏览器都支持这个功能。
例如: http://www.chedong.com/favicon.ico

robots.txt: 用于告诉搜索引擎的爬虫程序(spider)网站那些页面可以被索引,那些不可以。
具体说明请参考:http://www.robotstxt.org/wc/robots.html
参考文档:

Apache项目
http://httpd.apache.org

PHP
http://www.php.net

Resin
http://www.caucho.com

mod_gzip
http://sourceforge.net/projects/mod-gzip/

Cronolog
http://www.cronolog.org

mod_expires
http://httpd.apache.org/docs/mod/mod_expires.html


面向搜索引擎的CMS设计:
http://www.chedong.com/tech/cms.html


原文出处:<a href="http://www.chedong.com/tech/apache_install.html">http://www.chedong.com/tech/apache_install.html</a>

http://blog.matrix.org.cn/ljhj210423/date/20061023 星期一 2006年10月23日

关于二级域名解析及tomcat虚拟主机

最近公司要搞个类似blog里面二级域名的东西,对这方面不太了解,打电话咨询了一下万网,发现万网是可以支持二级域名解析的,配合着URL转发使用感觉挺好用的,打算在服务器的tomcat里配置虚拟主机,然后将二级域名映射过来,应该能满足公司的要求

Tomcat配置SSI[收藏]

一、介绍:
  SSI是Server Side Includes的缩写,是嵌入到HTML页面的一组指令的集合。在返回请求的页面(包含SSI指令)前,服务器会处理这些指令,并用处理的结果替换指 令,然  后把页面返回。这样就允许在HTML页面中添加动态产生的内容。
  SSI是向页面中添加小的信息片段的很好的方法。如果页面的大部分都是产生的则需要选择其它的解决方案。
二、主要用途
  目前,主要有以下几种用用途:
  1、显示服务器端环境变量<#echo>
  2、将文本内容直接插入到文档中<#include>
  3、显示WEB文档相关信息<#flastmod #fsize> (如文件制作日期/大小等)
  4、直接执行服务器上的各种程序<#exec>(如CGI或其他可执行程序)
  5、设置SSI信息显示格式<#config>(如文件制作日期/大小显示方式) 高级SSI<XSSI>可设置变量使用if条件语句。
三、设置Tomcat
     Tomcat对SSI提供了支持,但在默认的情况下这种支持是关闭的。如果你用Tomcat做为HTTP服务器并且需要SSI,那么需要自己来设置。

四、设置方法如下:

        在$CATALINA_BASE/server/lib/目录下找到servlets-ssi.renametojar文件 
        将这个文件重命名为servlets-ssi.jar 
        在$CATALINA_BASE/conf/目录下找到web.xml文件 
        使用SSI Servlet就删除在SSI servlet和servlet-mapping周围的注释 
        使用SSI filter就删除在SSI filter和filter-mapping周围的注释

五、基本指令
       1、SSI指令的语法格式如下:
           <!--#element [attribute=value] [attribute=value] ... -->
                这些指令以HTML注释的形式出现,所以如果你没有正确设置SSI,浏览器会忽略这些指令。如果你正确设置了SSI,这些指令会被相应的结果替换。
       2、config
           <!--#config timefmt="%B %Y" -->
           config用来指定返回给客户端浏览器的错误信息、日期和文件大小的格式。
        常用指令:
           <!--#config errmsg="自定义错误信息"--> 
           <!--#config sizefmt="显示单位"--> 
           <!--#config timefmt="显示格式"--> 
        参数: 
            errmsg 自定义SSI执行错误信息,可以为任何你喜欢的方式。 
            sizefmt 文件大小显示方式,默认为字节方式("bytes")可以改为千字节方式("abbrev") 
            timefmt 时间显示方式,最灵活的配置属性。 
        Eg:
            <!--#config errmsg="服务器执行错误,请联系管理员 yiho@126.com,谢谢!"--> 
            <!--#fsize file="不存在的文件.htm"-->

            以千字节方式显示文件大小 
            <!--#config sizefmt="abbrev"--> 
            <!--#fsizefile="news.htm"--> 
           以特定的时间格式显示时间
   <!--#config timefmt="%Y年/%m月%d日 星期%W 北京时间%H:%M:%s,%Y年已过去了%j天 今天是%Y年的第%U个星期"-->
   <!--#echo var="DATE_LOCAL"--> 显示今天是星期几,几月,时区
   <!--#config timefmt="今天%A, %B ,服务器时区是 %z,是"-->
   <!--#echo var="DATE_LOCAL"-->   
 3、echo
   echo用来输出变量的值。
    <!--#echo var="VARIABLE_NAME" -->
    <!--#echo var="变量名称"-->
   本文档名称:程序代码:
    <!--#echo var="DOCUMENT_NAME"-->
   现在时间:程序代码:
    <!--#echo var="DATE_LOCAL"-->
   你的IP地址是程序代码:
    <!--#echo var="REMOTE_ADDR"-->
 4、exec
  <!--#exec cmd="COMMOND" -->
  exec用来执行命令。 将某一外部程序的输出插入到页面中。可插入CGI程序或者是常规应用程序的输入,这取决于使用的参数是cmd还是cgi。
   <!--#exec cmd="文件名称"-->
   <!--#exec cgi="文件名称"-->
   <!--#exec cmd="文件名称"-->
   <!--#exec cgi="文件名称"-->
  参数:
   cmd 常规应用程序
   cgi CGI脚本程序
  Eg:
   <!--#exec cmd="cat /etc/passwd"-->将会显示密码文件
   <!--#exec cmd="dir /b"-->将会显示当前目录下文件列表
   <!--#exec cgi="/cgi-bin/gb.cgi"-->将会执行CGI程序gb.cgi。
   <!--#exec cgi="/cgi-bin/access_log.cgi"-->将会执行CGI程序access_log.cgi。
  注意:
   从上面的示例可以看出,这个指令相当方便,但是也存在安全问题。
  禁止方法:
   .Apache,将access.conf中的"Options Includes ExecCGI"这行代码删除;
   .在IIS中,要禁用 #exec 命令,可修改 SSIExecDisable 元数据库;  
 5、flastmod
  <!--#flastmod file="FILE_NAME" -->
  flastmod返回FILE_NAME所代表的文件的最后修改时间。
  Eg:
   <!--#flastmod file="news.htm"-->
    将当前目录下news.htm文件的最近更新日期插插入到当前页面
 6、fsize
  <!--#fsize file="FILE_NAME" -->
  fsize返回FILE_NAME所代表的文件的大小。
  <!--#flastmod file="文件名称"-->
  <!--#fsize file="文件名称"-->
  参数:
   file 指定包含文件相对于本文档的位置 如 info.txt 表示当前目录下的的info.txt文档
   virtual 指定相对于服务器文档根目录的位置 如 /hoyi/info.txt 表示
  注意:
   文件名称必须带有扩展名。
  Eg: 
   <!--#fsize file="news.htm"-->
    将当前目录下news.htm的文件大小入到当前页面
 7、include
  <!--#include file="文件名称"-->
  <!--#include virtual="文件名称"-->
  include插入FILE_NAME所代表的文件的内容。
  file 文件名是一个相对路径,该路径相对于使用 #include 指令的文档所在的目录。被包含文件可以在同一级目录或其子目录中,但不能在上一级目录中。如表示当前目  录下的的 nav_head.htm文档,则为file="nav_head.htm"。
  virtual 文件名是 Web 站点上的虚拟目录的完整路径。如表示相对于服务器文档根目录下hoyi目录下的nav_head.htm文件;则为file="/hoyi/nav_head.htm"
  参数:
   file 指定包含文件相对于本文档的位置
   virtual 指定相对于服务器文档根目录的位置
  注意:
   1、文件名称必须带有扩展名。
   2、被包含的文件可以具有任何文件扩展名,我觉得直接使用htm扩展名最方便
 8、printenv
  <!--#printenv -->
   printenv返回所有定义的变量的列表。
 9、set
  <!--#set var="VARIABLE_NAME" value="VARIABLE_VALUE" -->
  set用来自定义变量。在SSI中有许多标准的变量(如DATE_LOCAL),其中也包括对于CGI程序有效的环境变量。
 10、if elif endif else
  if elif endif else用来条件选择。
  #if
  作用: 创建可以改变数据的页面,这些数据根据使用if语句时计算的要求予以显示。
    语法: 程序代码:
   <!--#if expr="$变量名="变量值A""-->
   显示内容
    <!--#elif expr="$变量名="变量值B""-->
   显示内容
    <!--#else-->
   显示内容
    <!--#endif"-->
   Eg:
    <!--#if expr="$SERVER_NAME="hoyi.zb169.net""-->
     中华E搜网http://www.eshoo.com.cn
    <!--#elif expr="$SERVER_NAME="linux.cqi.com.cn"" -->
     中华E搜网http://www.eshoo.com.cn/bbs
    <!--#else-->
     中华E搜网http://www.eshoo.com.cn
    <!--#endif"-->
注意: 用于前面指令中的反斜杠,是用来代换内部的引号,以便它们不会被解释为结束表达式。不可省略。
  
六、普通用法
 1、下面是一些比较常规的SSI的用法:
  最后修改时间
   有两种方法:
   This file last modified <!--#flastmod file="ssi.shtml" -->
   This file last modified <!--#echo var="LAST_MODIFIED" -->
  包含一个footer
   <!--#include virtual="/footer.html" -->
  设置errmsg
   <!--#config errmsg="[error message!]" -->
  设置sizefmt
   <!--#config sizefmt="bytes|abbrev" -->
  执行命令
  <!--#exec cmd="dir" -->
 2、高级SSI
  XSSI(Extended SSI)是一组高级SSI指令,内置于Apache 1.2或更高版本的mod-include模块之中。
   其中可利用的的指令有:
   <!--#printenv-->
   <!--#printenv-->
   <!--#printenv-->
   <!--#printenv-->
  作用: 显示当前存在于WEB服务器环境中的所有环境变量。
  (1)#set
   作用:可给变量赋值,以用于后面的if语句。
   语法:程序代码:
     <!--#set var="变量名"value="变量值"-->
   参数:无
   示例: 程序代码:
    <!--#set var="color"value="红色"-->
    SSI允许自定义变量,这些变量可以用来进行比较和条件判断。
   定义变量
    <!--#set var="date" value="${DATE_LOCAL}_${DATE_GMT}" -->
   条件表达式
    <!--#if expr="test_condition" -->
    <!--#elif expr="test_condition" -->
     <!--#else -->
    <!--#endif -->

配置tomcat支持ssi

Introduction

SSI (Server Side Includes) are directives that are placed in HTML pages, and evaluated on the server while the pages are being served. They let you add dynamically generated content to an existing HTML page, without having to serve the entire page via a CGI program, or other dynamic technology.

Within Tomcat SSI support can be added when using Tomcat as your HTTP server and you require SSI support. Typically this is done during development when you don't want to run a web server like Apache.

Tomcat SSI support implements the same SSI directives as Apache. See the Apache Introduction to SSI for information on using SSI directives.

SSI support is implemented using the servlet class org.apache.catalina.ssi.SSIServlet. Traditionally, this servlet is mapped to the URL pattern "*.shtml".

By default SSI support is disabled in Tomcat.

Installation

CAUTION - SSI directives can be used to execute programs external to the Tomcat JVM. If you are using the Java SecurityManager this will bypass your security policy configuration in catalina.policy.

Rename $CATALINA_BASE/server/lib/servlets-ssi.renametojar to $CATALINA_BASE/server/lib/servlets-ssi.jar.

Remove the XML comments from around the SSI servlet and servlet-mapping configuration in $CATALINA_BASE/conf/web.xml.

Configuration

There are several servlet init parameters which can be used to configure the behaviour of the SSI servlet.

  • buffered - Should output from this servlet be buffered? (0=false, 1=true) Default 0 (false).
  • debug - Debugging detail level for messages logged by this servlet. Default 0.
  • expires - The number of seconds before a page with SSI directives will expire. Default behaviour is for all SSI directives to be evaluated for every request.
  • isVirtualWebappRelative - Should "virtual" SSI directive paths be interpreted as relative to the context root, instead of the server root? (0=false, 1=true) Default 0 (false).

SSI 详解[z]

什么是 SHTML
使用SSI(Server Side Include)的html文件扩展名,SSI(Server Side Include),通常称为“服务器端嵌入”或者叫“服务器端包含”,是一种类似于ASP的基于服务器的网页制作技术。

SSI工作原理:
将 内容发送到浏览器之前,可以使用“服务器端包含 (SSI)”指令将文本、图形或应用程序信息包含到网页中。例如,可以使用 SSI 包含时间/日期戳、版权声明或供客户填写并返回的表单。对于在多个文件中重复出现的文本或图形,使用包含文件是一种简便的方法。将内容存入一个包含文件中 即可,而不必将内容输入所有文件。通过一个非常简单的语句即可调用包含文件,此语句指示 Web 服务器将内容插入适当网页。而且,使用包含文件时,对内容的所有更改只需在一个地方就能完成。

因为包含 SSI 指令的文件要求特殊处理,所以必须为所有 SSI 文件赋予 SSI 文件扩展名。默认扩展名是 .stm、.shtm 和 .shtml。

Web 服务器在处理网页的同时处理 SSI 指令。当 Web 服务器遇到 SSI 指令时,直接将包含文件的内容插入 HTML 网页。如果“包含文件”中包含 SSI 指令,则同时插入此文件。除了用于包含文件的基本指令之外,还可以使用 SSI 指令插入文件的相关信息(如文件的大小)或者运行应用程序或 shell 命令。

网站维护常常碰到的一个问题是,网站的结构已经固定,却 为了更新一点内容而不得不重做一大批网页。SSI提供了一种简单、有效的方法来解决这一问题,它将一个网站的基本结构放在几个简单的HTML文件中(模 板),以后我们要做的只是将文本传到服务器,让程序按照模板自动生成网页,从而使管理大型网站变得容易。

所以,利用SHTML格式的页面 目的和 ASP 差不多,但是因为是 API 所以运转速度更快,效率更高,比ASP快,比HTML慢,但由于可以使用服务器端包含,因此使页面更新容易(特别是批量更新banner,版权等),想象 一下吧,你有一段 HTML,要在中间穿插一些特殊的服务端脚本,比如插入其他 HTML 段落,你选择 ASP 来完成这个任务,但是如果任务更繁重,需要更多的时间,比如 5 s,这个时候你不用 ASP 而用 SHTML,或许处理时间就只用 4s 了。

SSI有什么用?
之 所以要扯到ssi,是因爲 shtml--server-parsed HTML 的首字母缩略词。包含有嵌入式服务器方包含命令的 HTML 文本。在被传送给浏览器之前,服务器会对 SHTML 文档进行完全地读取、分析以及修改。shtml和asp 有一些相似,以shtml命名的文件里,使用了ssi的一些指令,就像asp中的指令,你可以在SHTML文件中写入SSI指令,当客户端访问这些 shtml文件时,服务器端会把这些SHTML文件进行读取和解释,把SHTML文件中包含的SSI指令解释出来比如:你可以在SHTML文件中用SSI 指令引用其他的html文件(#i nclude ),服务器传送给客户端的文件,是已经解释的SHTML不会有SSI指令。它实现了HTML所没有的功能,就是可以实现了动态的SHTML,可以说是 HTML的一种进化吧。像新浪的新闻系统就是这样的,新闻内容是固定的但它上面的广告和菜单等就是用#i nclude引用进来的。

目前,主要有以下几种用用途:

显示服务器端环境变量<#e cho>
将文本内容直接插入到文档中<#i nclude>
显示WEB文档相关信息<#f lastmod #f size> (如文件制作日期/大小等)
直接执行服务器上的各种程序<#e xec>(如CGI或其他可执行程序)
设置SSI信息显示格式<#c onfig>(如文件制作日期/大小显示方式)
高级SSI<XSSI>可设置变量使用if条件语句。

使用SSI
SSI是为WEB服务器提供的一套命令,这些命令只要直接嵌入到HTML文档的注释内容之中即可。如:

<!--#i nclude file="info.htm"-->

就 是一条SSI指令,其作用是将"info.htm"的内容拷贝到当前的页面中,当访问者来浏览时,会看到其它HTML文档一样显示info.htm其中的 内容。其它的SSI指令使用形式基本同刚才的举例差不多,可见SSI使用只是插入一点代码而已,使用形式非常简单。当然,如果WEB服务器不支持SSI, 它就会只不过将它当作注释信息,直接跳过其中的内容;浏览器也会忽略这些信息。

如何在我的WEB服务器上配置SSI功能?
在一些 WEB服务器上(如IIS 4.0/SAMBAR 4.2),包含 #i nclude 指令的文件必须使用已被映射到 SSI 解释程序的扩展名;否则,Web 服务器将不会处理该SSI指令;默认情况下,扩展名 .stm、.shtm 和 .shtml 被映射到解释程序(Ssinc.dll)。
Apache则是根据你的设置情况而定,修改srm.conf如:

AddType text/x-server-parsed-html .shtml 将只对.shtml扩展名的文件解析SSI指令
AddType text/x-server-parsed-html .html 将对所有HTML文档解析SSI指令

Netscape WEB服务器直接使用 Administration Server(管理服务器)可打开SSI功能。
Website 使用 Server Admin 程序中的 Mapping 标签,扩展名添加内容类型为:wwwserver/html-ssi
Cern 服务器不支持SSI,可用SSI诈骗法,到 http://sw.cse.bris.ac.uk/WebTools/fakessi.html 上下载一个PERL脚本,即可使你的CERN服务器使用一些SSI指令。(不支持exec指令。)


SSI指令基本格式
程序代码:

<!-- 指令名称="指令参数">

示例:

<!--#i nclude file="info.htm"-->

说明:

<!-- -->是HTML语法中表示注释,当WEB服务器不支持SSI时,会忽略这些信息。
#i nclude 为SSI指令之一。
file 为include的参数, info.htm为参数值,在本指令中指将要包含的文档名。
注意:

<!--与#号间无空格,只有SSI指令与参数间存在空格。
上面的标点="",一个也不能少。
SSI指令是大小写敏感的,因此参数必须是小写才会起作用。
SSI指令使用详解
#e cho 示范

作用:将环境变量插入到页面中。

语法:

<!--#e cho var="变量名称"-->

示例:

<!--#e cho var="DOCUMENT_NAME"--> 本文档名称
<!--#e cho var="DATE_LOCAL"--> 现在时间
<!--#e cho var="REMOTE_ADDR"--> 你的IP地址

#i nclude 示范

作用:将文本文件的内容直接插入到文档页面中。

语法:

<!--#i nclude file="文件名称"-->
<!--#i nclude virtual="文件名称"-->

file 文件名是一个相对路径,该路径相对于使用 #i nclude 指令的文档所在的目录。被包含文件可以在同一级目录或其子目录中,但不能在上一级目录中。如表示当前目录下的的nav_head.htm文档,则为file="nav_head.htm"。
virtual 文件名是 Web 站点上的虚拟目录的完整路径。如表示相对于服务器文档根目录下hoyi目录下的nav_head.htm文件;则为file="/hoyi/nav_head.htm"

参数:
file 指定包含文件相对于本文档的位置
virtual 指定相对于服务器文档根目录的位置

注意:

文件名称必须带有扩展名。
被包含的文件可以具有任何文件扩展名,我觉得直接使用htm扩展名最方便,微软公司推荐使用 .inc 扩展名(这就看你的爱好了)。
示例:

<!--#i nclude file="nav_head.htm"--> 将头文件插入到当前页面
<!--#i nclude file="nav_foot.htm"--> 将尾文件插入到当前页面

#f lastmod 和 #f size 示范

作用:

#f lastmod 文件最近更新日期
#f size 文件的长度

语法:

<!--#f lastmod file="文件名称"-->
<!--#f size file="文件名称"-->

参数:
file 指定包含文件相对于本文档的位置 如 info.txt 表示当前目录下的的info.txt文档
virtual 指定相对于服务器文档根目录的位置 如 /hoyi/info.txt 表示

注意:
文件名称必须带有扩展名。

示例:

<!--#f lastmod file="news.htm"-->
<!--#f lastmod file="news.htm"-->

将当前目录下news.htm文件的最近更新日期插插入到当前页面

<!--#f size file="news.htm"-->
<!--#f size file="news.htm"-->

将当前目录下news.htm的文件大小入到当前页面

#e xec 示范

作用:将某一外部程序的输出插入到页面中。可插入CGI程序或者是常规应用程序的输入,这取决于使用的参数是cmd还是cgi。

语法:

<!--#e xec cmd="文件名称"-->
<!--#e xec cgi="文件名称"-->

参数:
cmd 常规应用程序
cgi CGI脚本程序

示例:

<!--#e xec cmd="cat /etc/passwd"--> 将会显示密码文件
<!--#e xec cmd="dir /b"--> 将会显示当前目录下文件列表
<!--#e xec cgi="/cgi-bin/gb.cgi"--> 将会执行CGI程序gb.cgi。
<!--#e xec cgi="/cgi-bin/access_log.cgi"--> 将会执行CGI程序access_log.cgi。

注意:从上面的示例可以看出,这个指令相当方便,但是也存在安全问题。

禁止方法:

Apache,将access.conf中的"Options Includes ExecCGI"这行代码删除;
在IIS中,要禁用 #e xec 命令,可修改 SSIExecDisable 元数据库;
#c onfig

作用: 指定返回给客户端浏览器的错误信息、日期和文件大小的格式。

语法:

<!--#c onfig errmsg="自定义错误信息"-->
<!--#c onfig sizefmt="显示单位"-->
<!--#c onfig timefmt="显示格式"-->

参数:

errmsg 自定义SSI执行错误信息,可以为任何你喜欢的方式。
sizefmt 文件大小显示方式,默认为字节方式("bytes")可以改为千字节方式("abbrev")
timefmt 时间显示方式,最灵活的配置属性。

示例:显示一个不存在文件的大小

<!--#c onfig errmsg="服务器执行错误,请联系管理员 yiho@126.com,谢谢!"-->
<!--#f size file="不存在的文件.htm"-->

以千字节方式显示文件大小

语法:

<!--#c onfig sizefmt="abbrev"-->
<!--#f sizefile="news.htm"-->

以特定的时间格式显示时间

<!--#c onfig timefmt="%Y年/%m月%d日 星期%W 北京时间%H:%M:%s,%Y年已过去了%j天 今天是%Y年的第%U个星期"-->
<!--#e cho var="DATE_LOCAL"--> 显示今天是星期几,几月,时区
<!--#c onfig timefmt="今天%A, %B ,服务器时区是 %z,是"-->
<!--#e cho var="DATE_LOCAL"-->

XSSI
XSSI(Extended SSI)是一组高级SSI指令,内置于Apache 1.2或更高版本的mod-include模块之中。

其中可利用的的指令有:
#printenv
#set
#if

#printenv

作用: 显示当前存在于WEB服务器环境中的所有环境变量。

语法:

<!--#printenv-->

#set

作用:可给变量赋值,以用于后面的if语句。

语法:

<!--#set var="变量名" value="变量值"-->
<!--#set var="变量名"value="变量值"-->

示例:

<!--#set var="color" value="红色"-->
<!--#set var="color" value="红色"-->

#if

作用:创建可以改变数据的页面,这些数据根据使用if语句时计算的要求予以显示。

语法:

<!--#if expr="$变量名=\"变量值A\""-->
显示内容
<!--#elif expr="$变量名=\"变量值B\""-->
显示内容
<!--#else-->
显示内容
<!--#endif"-->

示例:

<!--#if expr="$SERVER_NAME=\"hoyi.zb169.net\""-->
欢迎光临好易CGI工厂在淄博热线的分站 http://hoyi.zb169.net
<!--#elif expr="$SERVER_NAME=\"linux.cqi.com.cn\"" -->
欢迎光临好易CGI工厂在太阳城的分站 http://linux.cqi.com.cn/~hoyi
<!--#else-->
欢迎光临好易CGI工厂!
<!--#endif"-->

注意:用于前面指令中的反斜杠,是用来代换内部的引号,以便它们不会被解释为结束表达式。不可省略。

1、Config 命令

Config 命令主要用于修改SSI的默认设置。其中:

Errmsg:设置默认错误信息。为了能够正常的返回用户设定的错误信息,在HTML文件中Errmsg参数必须被放置在其它SSI命令的前面,否则客户端只能显示默认的错误信息,而不是由用户设定的自定义信息。

<!--#c onfig errmsg="Error! Please email webmaster@mydomain.com" -->

Timefmt:定义日期和时间的使用格式。Timefmt参数必须在echo命令之前使用。

<!--#c onfig timefmt="%A, %B %d, %Y"-->
<!--#e cho var="LAST_MODIFIED" -->

显示结果为:

Wednesday, April 12, 2000

也许用户对上例中所使用的%A %B %d感到很陌生,下面我们就以表格的形式总结一下SSI中较为常用的一些日期和时间格式。

Sizefmt:决定文件大小是以字节、千字节还是兆字节为单位表示。如果以字节为单位,参数值为"bytes";对于千字节和兆字节可以使用缩写形式。同样,sizefmt参数必须放在fsize命令的前面才能使用。

<!--#c onfig sizefmt="bytes" -->
<!--#f size file="index.html" -->

2、Include 命令

Include 命令可以把其它文档中的文字或图片插入到当前被解析的文档中,这是整个SSI的关键所在。通过Include命令只需要改动一个文件就可以瞬间更新整个站点!

Include 命令具有两个不同的参数:

Virtual:给出到服务器端某个文档的虚拟路径。
File:给出到当前目录的相对路径,其中不能使用"../",也不能使用绝对路径。

<!--#i nclude virtual="/includes/header.html" -->
<!--#i nclude file="header.html" --> 这就要求每一个目录中都包含一个header.html文件。

3、Echo 命令

Echo 命令可以显示以下各环境变量:

DOCUMENT_NAME:显示当前文档的名称。
DOCUMENT_URI:显示当前文档的虚拟路径。例如:

<!--#e cho var="DOCUMENT_NAME" -->
<!--#e cho var="DOCUMENT_URI" -->

随着网站的不断发展,那些越来越长的URL地址肯定会让人头疼。如果使用SSI,一切就会迎刃而解。因为我们可以把网站的域名和SSI命令结合在一起显示完整的URL,即:

http://YourDomain<;!--#e cho var="DOCUMENT_URI" -->

QUERY_STRING_UNESCAPED:显示未经转义处理的由客户端发送的查询字串,其中所有的特殊字符前面都有转义符"\"。例如:

<!--#e cho var="QUERY_STRING_UNESCAPED" -->

DATE_LOCAL:显示服务器设定时区的日期和时间。用户可以结合config命令的timefmt参数,定制输出信息。例如:

<!--#c onfig timefmt="%A, the %d of %B, in the year %Y" -->
<!--#e cho var="DATE_LOCAL" -->

显示结果为:

Saturday, the 15 of April, in the year 2000

DATE_GMT:功能与DATE_LOCAL一样,只不过返回的是以格林尼治标准时间为基准的日期。例如:

<!--#e cho var="DATE_GMT" -->

LAST_MODIFIED:显示当前文档的最后更新时间。同样,这是SSI中非常实用的一个功能,只要在HTML文档中加入以下这行简单的文字,就可以在页面上动态的显示更新时间。

<!--#e cho var="LAST_MODIFIED" -->

CGI环境变量

除了SSI环境变量之外,echo命令还可以显示以下CGI环境变量:

SERVER_SOFTWARE:显示服务器软件的名称和版本。例如:
<!--#e cho var="SERVER_SOFTWARE" -->
SERVER_NAME: 显示服务器的主机名称,DNS别名或IP地址。例如:
<!--#e cho var="SERVER_NAME" -->
SERVER_PROTOCOL:显示客户端请求所使用的协议名称和版本,如HTTP/1.0。例如:
<!--#e cho var="SERVER_PROTOCOL" -->
SERVER_PORT:显示服务器的响应端口。例如:
<!--#e cho var="SERVER_PORT" -->
REQUEST_METHOD:显示客户端的文档请求方法,包括GET, HEAD, 和POST。例如:
<!--#e cho var="REQUEST_METHOD" -->
REMOTE_HOST:显示发出请求信息的客户端主机名称。
<!--#e cho var="REMOTE_HOST" -->
REMOTE_ADDR:显示发出请求信息的客户端IP地址。
<!--#e cho var="REMOTE_ADDR" -->
AUTH_TYPE:显示用户身份的验证方法。
<!--#e cho var="AUTH_TYPE" -->
REMOTE_USER:显示访问受保护页面的用户所使用的帐号名称。
<!--#e cho var="REMOTE_USER" -->

4、Fsize:显示指定文件的大小,可以结合config命令的sizefmt参数定制输出格式。

<!--#f size file="index_working.html" -->

5、Flastmod:显示指定文件的最后修改日期,可以结合config 命令的timefmt参数控制输出格式。

<!--#c onfig timefmt="%A, the %d of %B, in the year %Y" -->
<!--#f lastmod file="file.html" -->

这里,我们可以利用flastmod参数显示出一个页面上所有链接页面的更新日期。方法如下:

<!--#c onfig timefmt=" %B %d, %Y" -->
<A HREF="/directory/file.html">File</A>
<!--#f lastmod virtual="/directory/file.html" -->
<A HREF="/another_directory/another_file.html">Another File</A>
<!--#f lastmod virtual="/another_directory/another_file.html" -->

显示结果为:

File April 19, 2000
Another File January 08, 2000

6、Exec

Exec命令可以执行CGI脚本或者shell命令。使用方法如下:

Cmd:使用/bin/sh执行指定的字串。如果SSI使用了IncludesNOEXEC选项,则该命令将被屏蔽。
Cgi:可以用来执行CGI脚本。例如,下面这个例子中使用服务端cgi-bin目录下的counter.pl脚本程序在每个页面放置一个计数器:

<!--#e xec cgi="/cgi-bin/counter.pl" -->

关于SHTML和HTML的区别
让我们先来看看SHTML和HTML的区别,如果用一句话来解释就是:SHTML 不是HTML而是一种服务器 API,shtml是服务器动态产成的html.

虽 然两者都是超文本格式,但shtml是一种用于SSI技术的文件。也就是Server Side Include--SSI 服务器端包含指令。如果Web Server有SSI功能的话,大多数(尤其是基于Unix平台)的WEB服务器,如Netscape Enterprise Server等均支持SSI命令。

http://blog.matrix.org.cn/ljhj210423/date/20060928 星期四 2006年09月28日

我不黑

我老婆是世界上最好的老婆!

我老婆是老大,都别欺负我老婆啊,要不然我抽你丫挺的!

我不是神经病!

http://blog.matrix.org.cn/ljhj210423/date/20060911 星期一 2006年09月11日

DWR使用新的--改变LoadMessage样式

今天在使用DWR是用到了载入的效果
DWRUtil.useLoadingMessage("测试中");
默认的字体都是在util文件中设置好的,看了下源码发现没有提供配置样式的接口,于是察看了下jar包的结构,发现了模版文件util.js在dwr.jar\uk\ltd\getahead\dwr目录下,打开该文件,找到以下部分:
/**
 * Setup a GMail style loading message.
 * @see http://getahead.ltd.uk/dwr/browser/util/useloadingmessage
 */
DWRUtil.useLoadingMessage = function(message) {
  var loadingMessage;
  if (message) loadingMessage = message;
  else loadingMessage = "Loading";
  DWREngine.setPreHook(function() {
    var disabledZone = $('disabledZone');
    if (!disabledZone) {
      disabledZone = document.createElement('div');
      disabledZone.setAttribute('id', 'disabledZone');
      disabledZone.style.position = "absolute";
      disabledZone.style.zIndex = "1000";
      disabledZone.style.left = "0px";
      disabledZone.style.top = "0px";
      disabledZone.style.width = "100%";
      disabledZone.style.height = "100%";
      document.body.appendChild(disabledZone);
      var messageZone = document.createElement('div');
      messageZone.setAttribute('id', 'messageZone');
      messageZone.style.position = "absolute";
      messageZone.style.top = "0px";
      messageZone.style.right = "0px";
      messageZone.style.background = "blue";
      messageZone.style.color = "white";
      messageZone.style.fontFamily = "宋体,Arial,Helvetica,sans-serif";
      messageZone.style.padding = "4px";
      disabledZone.appendChild(messageZone);
      var text = document.createTextNode(loadingMessage);
      messageZone.appendChild(text);
    }
    else {
      $('messageZone').innerHTML = loadingMessage;
      disabledZone.style.visibility = 'visible';
    }
  });
  DWREngine.setPostHook(function() {
    $('disabledZone').style.visibility = 'hidden';
  });
}
修改其中相关的样式配置,然后保存,一切OK了:)

http://blog.matrix.org.cn/ljhj210423/date/20060904 星期一 2006年09月04日

信息采集系统的技术实现[z]

        最近公司要做个页面信息采集的东西,没什么好的思路,所以在网上找了点东西,学习一下。

        信息采集系统指的是按标准格式采集指定网络信息,同搜索引擎的区别在于其采集的目的性更强,采集源范围也比较小。这里简单介绍一下信息采集系统实现上的几个关键问题:

1) 采集网页数据
        VC,Java,VB的网络通讯功能都足够实现信息采集,VC中的Get/Post方式可采集网页信息,也可以直接用socket方式采集,但一般用前一 种模式,另外为了提高采集效率都采用多线程技术,在网上的一些Spider程序都是多线程的,可以借鉴.

2) 如何按关键字来信息
        信息采集的一大特点是按多个关键字将信息拆分出来,例如供求信息中的商机标题、联系 人、电话、Email、内容等,实现时需要事先定义好这些关键字,然后在网页中搜索,将夹在两个关键字当中的信息采集出来,另外还要注意,网页中的许多关 键字是包含空格的,空格数量也不能确定,例如"邮   件",这就要求在查找关键字时要把关键字按单个汉字拆开来匹配,遇到中间的空格要跳过去.这一步实现了,信息就会变的非常有规则,也就可以导入本地库了.

3) 网页中的链结获取算法
        了解HTML的应该清楚,网页中的链结都是通过<a href =..>的标签定义的,但也会分很多情况,例如:  < a href = "...">  这是常见的链结格式,但要注意采集出来的链结可能是完整的http://...,也可能是相对路径,要分别处理;  < a href = ''> 用单引号分隔的,所以用算法获取链结的时候要根据双引号和单引号两种标记来分隔;< a href = .. onclick = javascript:view('..','')> 通过javascript的函数处理链结,算法上就麻烦了许多。

4) 无效数据的过滤
        即使通过关键字的方式摒弃了许多广告信息,但在关键字信息中也会有不少无效数据,包括一些信息开头的空格

5) 特定数据的获取算法
        Email,电话等数据符合一定的规范,一般可以用一些算法提取出来,也可以 用正则表达式技术来获取,在网络上有不少此类算法.在信息采集中,Email和电话等关键信息是比较分散的,需要用提取算法把这些信息提取出来放在正确的 位置.这是非常有必要的,因为信息采集系统往往会有邮件群发的功能.

信息采集的整个流程可总结如下:

 a) 首先,获取网页的完整信息
 b) 用算法获取网页中的正文信息,即抛弃HTML的标签文本
 c) 去除多余的空行
 d) 按定义好的关键字将信息分隔开
 e) 对信息进行无效数据过滤
 f) 信息入本地库
 g) 获取网页中的链结,对该链结从a)步骤开始重复,但注意网页中的许多链结是广告或无效的,因此要事先定义好一些链结关键字,只有包含关键字的链结才处理



http://blog.matrix.org.cn/ljhj210423/date/20060823 星期三 2006年08月23日

处理404错误页面

:)今天从jr上学了一招:
在web.xml中加一个 
<error-page>
 <error-code>
  404
 </error-code>
 <location>
  /404.html
 </location>
</error-page>

试了一下,效果不错,看来自己很多地方的技术还比较粗糙阿,要继续努力

http://blog.matrix.org.cn/ljhj210423/date/20060815 星期二 2006年08月15日

关于session的好文章[收藏]

 摘要:虽然session机制在web应用程序中被采用已经很长时间 了,但是仍然有很多人不清楚session机制的本质,以至不能正确的应用这一技术。本文将详细讨论session的工作机制并且对在 Java web application中应用session机制时常见的问题作出解答。

目录:
一、术语session
二、HTTP协议与状态保持
三、理解cookie机制
四、理解session机制
五、理解javax.servlet.http.HttpSession
六、HttpSession常见问题
七、跨应用程序的session共享
八、总结
参考文档

一、术语session
在我的经验里,session这个词被滥用的程度大概仅次于transaction,更加有趣的是transaction与session在某些语境下的含义是相同的。

session, 中文经常翻译为会话,其本来的含义是指有始有终的一系列动作/消息,比如打电话时从拿起电话拨号到挂断电话这中间的一系列过程可以称之为一个  session。有时候我们可以看到这样的话“在一个浏览器会话期间,...”,这里的会话一词用的就是其本义,是指从一个浏览器窗口打开到关闭这个期 间 ①。最混乱的是“用户(客户端)在一次会话期间”这样一句话,它可能指用户的一系列动作(一般情况下是同某个具体目的相关的一系列动作,比如从登录到 选购商品到结账登出这样一个网上购物的过程,有时候也被称为一个transaction),然而有时候也可能仅仅是指一次连接,也有可能是指含义①,其中 的差别只能靠上下文来推断②。

然而当session一词与网络协议相关联时,它又往往隐含了“面向连接”和/或“保持状态”这样两个含 义, “面向连接”指的是在通信双方在通信之前要先建立一个通信的渠道,比如打电话,直到对方接了电话通信才能开始,与此相对的是写信,在你把信发出去的 时候你并不能确认对方的地址是否正确,通信渠道不一定能建立,但对发信人来说,通信已经开始了。“保持状态”则是指通信的一方能够把一系列的消息关联起 来,使得消息之间可以互相依赖,比如一个服务员能够认出再次光临的老顾客并且记得上次这个顾客还欠店里一块钱。这一类的例子有“一个 TCP session”或者 “一个POP3 session”③。

而到了web服务器蓬勃发展的时代,session在web开发语 境下的语义又有了新的扩展,它的含义是指一类用来在客户端与服务器之间保持状态的解决方案④。有时候session也用来指这种解决方案的存储结构,如 “把xxx保存在session 里”⑤。由于各种用于web开发的语言在一定程度上都提供了对这种解决方案的支持,所以在某种特定语言的语境下, session也被用来指代该语言的解决方案,比如经常把Java里提供的javax.servlet.http.HttpSession简称为 session⑥。

鉴于这种混乱已不可改变,本文中session一词的运用也会根据上下文有不同的含义,请大家注意分辨。
在本文中,使用中文“浏览器会话期间”来表达含义①,使用“session机制”来表达含义④,使用“session”表达含义⑤,使用具体的“HttpSession”来表达含义⑥

二、HTTP协议与状态保持
HTTP  协议本身是无状态的,这与HTTP协议本来的目的是相符的,客户端只需要简单的向服务器请求下载某些文件,无论是客户端还是服务器都没有必要纪录彼此过去 的行为,每一次请求之间都是独立的,好比一个顾客和一个自动售货机或者一个普通的(非会员制)大卖场之间的关系一样。

然而聪明(或者贪 心?)的人们很快发现如果能够提供一些按需生成的动态信息会使web变得更加有用,就像给有线电视加上点播功能一样。这种需求一方面迫使HTML逐步添加 了表单、脚本、DOM等客户端行为,另一方面在服务器端则出现了CGI规范以响应客户端的动态请求,作为传输载体的HTTP协议也添加了文件上载、  cookie这些特性。其中cookie的作用就是为了解决HTTP协议无状态的缺陷所作出的努力。至于后来出现的session机制则是又一种在客户 端与服务器之间保持状态的解决方案。

让我们用几个例子来描述一下cookie和session机制之间的区别与联系。笔者曾经常去的一家咖啡店有喝5杯咖啡免费赠一杯咖啡的优惠,然而一次性消费5杯咖啡的机会微乎其微,这时就需要某种方式来纪录某位顾客的消费数量。想象一下其实也无外乎下面的几种方案:
1、该店的店员很厉害,能记住每位顾客的消费数量,只要顾客一走进咖啡店,店员就知道该怎么对待了。这种做法就是协议本身支持状态。
2、发给顾客一张卡片,上面记录着消费的数量,一般还有个有效期限。每次消费时,如果顾客出示这张卡片,则此次消费就会与以前或以后的消费相联系起来。这种做法就是在客户端保持状态。
3、发给顾客一张会员卡,除了卡号之外什么信息也不纪录,每次消费时,如果顾客出示该卡片,则店员在店里的纪录本上找到这个卡号对应的纪录添加一些消费信息。这种做法就是在服务器端保持状态。

由 于HTTP协议是无状态的,而出于种种考虑也不希望使之成为有状态的,因此,后面两种方案就成为现实的选择。具体来说cookie机制采用的是在客户端保 持状态的方案,而session机制采用的是在服务器端保持状态的方案。同时我们也看到,由于采用服务器端保持状态的方案在客户端也需要保存一个标识,所 以session机制可能需要借助于cookie机制来达到保存标识的目的,但实际上它还有其他选择。

三、理解cookie机制 
cookie机制的基本原理就如上面的例子一样简单,但是还有几个问题需要解决:“会员卡”如何分发;“会员卡”的内容;以及客户如何使用“会员卡”。

正统的cookie分发是通过扩展HTTP协议来实现的,服务器通过在HTTP的响应头中加上一行特殊的指示以提示浏览器按照指示生成相应的cookie。然而纯粹的客户端脚本如JavaScript或者VBScript也可以生成cookie。

而cookie  的使用是由浏览器按照一定的原则在后台自动发送给服务器的。浏览器检查所有存储的cookie,如果某个cookie所声明的作用范围大于等于将要请求的 资源所在的位置,则把该cookie附在请求资源的HTTP请求头上发送给服务器。意思是麦当劳的会员卡只能在麦当劳的店里出示,如果某家分店还发行了自 己的会员卡,那么进这家店的时候除了要出示麦当劳的会员卡,还要出示这家店的会员卡。

cookie的内容主要包括:名字,值,过期时间,路径和域。
其中域可以指定某一个域比如.google.com,相当于总店招牌,比如宝洁公司,也可以指定一个域下的具体某台机器比如www.google.com或者froogle.google.com,可以用飘柔来做比。
路径就是跟在域名后面的URL路径,比如/或者/foo等等,可以用某飘柔专柜做比。
路径与域合在一起就构成了cookie的作用范围。
如 果不设置过期时间,则表示这个cookie的生命期为浏览器会话期间,只要关闭浏览器窗口,cookie就消失了。这种生命期为浏览器会话期的  cookie被称为会话cookie。会话cookie一般不存储在硬盘上而是保存在内存里,当然这种行为并不是规范规定的。如果设置了过期时间,浏览 器就会把cookie保存到硬盘上,关闭后再次打开浏览器,这些cookie仍然有效直到超过设定的过期时间。

存储在硬盘上的 cookie 可以在不同的浏览器进程间共享,比如两个IE窗口。而对于保存在内存里的cookie,不同的浏览器有不同的处理方式。对于IE,在一个打 开的窗口上按 Ctrl-N(或者从文件菜单)打开的窗口可以与原窗口共享,而使用其他方式新开的IE进程则不能共享已经打开的窗口的内存cookie; 对于 Mozilla Firefox0.8,所有的进程和标签页都可以共享同样的cookie。一般来说是用javascript的 window.open打开的窗口会与原窗口共享内存cookie。浏览器对于会话cookie的这种只认cookie不认人的处理方式经常给采用 session机制的web应用程序开发者造成很大的困扰。

下面就是一个goolge设置cookie的响应头的例子
HTTP/1.1 302 Found
Location: http://www.google.com/intl/zh-CN/
Set-Cookie: PREF=ID=0565f77e132de138:NW=1:TM=1098082649:LM=1098082649:S=KaeaCFPo49RiA_d8; expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/; domain=.google.com
Content-Type: text/html




这是使用HTTPLook这个HTTP Sniffer软件来俘获的HTTP通讯纪录的一部分




浏览器在再次访问goolge的资源时自动向外发送cookie




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




IE也可以设置在接受cookie前询问




这是一个询问接受cookie的对话框。

四、理解session机制
session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。

当 程序需要为某个客户端的请求创建一个session的时候,服务器首先检查这个客户端的请求里是否已包含了一个session标识 - 称为  session id,如果已包含一个session id则说明以前已经为此客户端创建过session,服务器就按照session id把这个  session检索出来使用(如果检索不到,可能会新建一个),如果客户端请求不包含session id,则为此客户端创建一个session并且生 成一个与此session相关联的session id,session id的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个  session id将被在本次响应中返回给客户端保存。

保存这个session id的方式可以采用cookie,这样在交互过程中 浏览器可以自动的按照规则把这个标识发挥给服务器。一般这个cookie的名字都是类似于SEEESIONID,而。比如weblogic对于web应用 程序生成的cookie,JSESSIONID=  ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764,它的名字就是  JSESSIONID。

由于cookie可以被人为的禁止,必须有其他机制以便在cookie被禁止时仍然能够把session id 传递回服务器。经常被使用的一种技术叫做URL重写,就是把session id直接附加在URL路径的后面,附加方式也有两种,一种是作为URL路径的 附加信息,表现形式为http://...../xxx;jsessionid= ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
另一种是作为查询字符串附加在URL后面,表现形式为http://...../xxx?jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
这两种方式对于用户来说是没有区别的,只是服务器在解析的时候处理的方式不同,采用第一种方式也有利于把session id的信息和正常程序参数区分开来。
为了在整个交互过程中始终保持状态,就必须在每个客户端可能请求的路径后面都包含这个session id。

另一种技术叫做表单隐藏字段。就是服务器会自动修改表单,添加一个隐藏字段,以便在表单提交时能够把session id传递回服务器。比如下面的表单
<form name="testform" action="/xxx">
<input type="text">
</form>
在被传递给客户端之前将被改写成
<form name="testform" action="/xxx">
<input type="hidden" name="jsessionid" value="ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764">
<input type="text">
</form>
这种技术现在已较少应用,笔者接触过的很古老的iPlanet6(SunONE应用服务器的前身)就使用了这种技术。
实际上这种技术可以简单的用对action应用URL重写来代替。

在 谈论session机制的时候,常常听到这样一种误解“只要关闭浏览器,session就消失了”。其实可以想象一下会员卡的例子,除非顾客主动对店家提 出销卡,否则店家绝对不会轻易删除顾客的资料。对session来说也是一样的,除非程序通知服务器删除一个session,否则服务器会一直保留,程序 一般都是在用户做log off的时候发个指令去删除session。然而浏览器从来不会主动在关闭之前通知服务器它将要关闭,因此服务器根本不会有机会 知道浏览器已经关闭,之所以会有这种错觉,是大部分session机制都使用会话cookie来保存session id,而关闭浏览器后这个  session id就消失了,再次连接服务器时也就无法找到原来的session。如果服务器设置的cookie被保存到硬盘上,或者使用某种手段改 写浏览器发出的HTTP请求头,把原来的session id发送给服务器,则再次打开浏览器仍然能够找到原来的session。

恰恰是由于关闭浏览器不会导致session被删除,迫使服务器为seesion设置了一个失效时间,当距离客户端上一次使用session的时间超过这个失效时间时,服务器就可以认为客户端已经停止了活动,才会把session删除以节省存储空间。

五、理解javax.servlet.http.HttpSession
HttpSession 是Java平台对session机制的实现规范,因为它仅仅是个接口,具体到每个web应用服务器的提供商,除了对规范支持之外,仍然会有一些规范里没有 规定的细微差异。这里我们以BEA的Weblogic Server8.1作为例子来演示。

首 先,Weblogic Server提供了一系列的参数来控制它的HttpSession的实现,包括使用cookie的开关选项,使用URL重写的开关 选项,session持久化的设置,session失效时间的设置,以及针对cookie的各种设置,比如设置cookie的名字、路径、域,  cookie的生存时间等。

一般情况下,session都是存储在内存里,当服务器进程被停止或者重启的时候,内存里的session 也会被清空,如果设置了session的持久化特性,服务器就会把session保存到硬盘上,当服务器进程重新启动或这些信息将能够被再次使用,  Weblogic Server支持的持久性方式包括文件、数据库、客户端cookie保存和复制。

复制严格说来不算持久化保存,因为session实际上还是保存在内存里,不过同样的信息被复制到各个cluster内的服务器进程中,这样即使某个服务器进程停止工作也仍然可以从其他进程中取得session。

cookie生存时间的设置则会影响浏览器生成的cookie是否是一个会话cookie。默认是使用会话cookie。有兴趣的可以用它来试验我们在第四节里提到的那个误解。

cookie的路径对于web应用程序来说是一个非常重要的选项,Weblogic Server对这个选项的默认处理方式使得它与其他服务器有明显的区别。后面我们会专题讨论。

关于session的设置参考[5] http://e-docs.bea.com/wls/docs70/webapp/weblogic_xml.html#1036869

六、HttpSession常见问题
(在本小节中session的含义为⑤和⑥的混合)


1、session在何时被创建
一 个常见的误解是以为session在有客户端访问时就被创建,然而事实是直到某server端程序调用  HttpServletRequest.getSession(true)这样的语句时才被创建,注意如果JSP没有显示的使用 <%  @page session="false"%> 关闭session,则JSP文件在编译成Servlet时将会自动加上这样一条语句  HttpSession session = HttpServletRequest.getSession(true);这也是JSP中隐含的  session对象的来历。

由于session会消耗内存资源,因此,如果不打算使用session,应该在所有的JSP中关闭它。

2、session何时被删除
综 合前面的讨论,session在下列情况下被删除a.程序调用HttpSession.invalidate();或b.距离上一次收到客户端发送的 session id时间间隔超过了session的超时设置;或c.服务器进程被停止(非持久session)

3、如何做到在浏览器关闭时删除session
严格的讲,做不到这一点。可以做一点努力的办法是在所有的客户端页面里使用javascript代码window.oncolose来监视浏览器的关闭动作,然后向服务器发送一个请求来删除session。但是对于浏览器崩溃或者强行杀死进程这些非常规手段仍然无能为力。

4、有个HttpSessionListener是怎么回事
你 可以创建这样的listener去监控session的创建和销毁事件,使得在发生这样的事件时你可以做一些相应的工作。注意是session的创建和销 毁动作触发listener,而不是相反。类似的与HttpSession有关的listener还有  HttpSessionBindingListener,HttpSessionActivationListener和  HttpSessionAttributeListener。

5、存放在session中的对象必须是可序列化的吗
不是必需 的。要求对象可序列化只是为了session能够在集群中被复制或者能够持久保存或者在必要时server能够暂时把session交换出内存。在  Weblogic Server的session中放置一个不可序列化的对象在控制台上会收到一个警告。我所用过的某个iPlanet版本如果  session中有不可序列化的对象,在session销毁时会有一个Exception,很奇怪。

6、如何才能正确的应付客户端禁止cookie的可能性
对所有的URL使用URL重写,包括超链接,form的action,和重定向的URL,具体做法参见[6]
http://e-docs.bea.com/wls/docs70/webapp/sessions.html#100770

7、开两个浏览器窗口访问应用程序会使用同一个session还是不同的session
参见第三小节对cookie的讨论,对session来说是只认id不认人,因此不同的浏览器,不同的窗口打开方式以及不同的cookie存储方式都会对这个问题的答案有影响。

8、如何防止用户打开两个浏览器窗口操作导致的session混乱
这 个问题与防止表单多次提交是类似的,可以通过设置客户端的令牌来解决。就是在服务器每次生成一个不同的id返回给客户端,同时保存在session里,客 户端提交表单时必须把这个id也返回服务器,程序首先比较返回的id与保存在session里的值是否一致,如果不一致则说明本次操作已经被提交过了。可 以参看《J2EE核心模式》关于表示层模式的部分。需要注意的是对于使用javascript window.open打开的窗口,一般不设置这个id, 或者使用单独的id,以防主窗口无法操作,建议不要再window.open打开的窗口里做修改操作,这样就可以不用设置。

9、为什么在Weblogic Server中改变session的值后要重新调用一次session.setValue
做这个动作主要是为了在集群环境中提示Weblogic Server session中的值发生了改变,需要向其他服务器进程复制新的session值。

10、为什么session不见了
排 除session正常失效的因素之外,服务器本身的可能性应该是微乎其微的,虽然笔者在iPlanet6SP1加若干补丁的Solaris版本上倒也遇到 过;浏览器插件的可能性次之,笔者也遇到过3721插件造成的问题;理论上防火墙或者代理服务器在cookie处理上也有可能会出现问题。
出现这一问题的大部分原因都是程序的错误,最常见的就是在一个应用程序中去访问另外一个应用程序。我们在下一节讨论这个问题。

七、跨应用程序的session共享

常 常有这样的情况,一个大项目被分割成若干小项目开发,为了能够互不干扰,要求每个小项目作为一个单独的web应用程序开发,可是到了最后突然发现某几个小 项目之间需要共享一些信息,或者想使用session来实现SSO(single sign on),在session中保存login的用户信息,最自 然的要求是应用程序间能够访问彼此的session。

然而按照Servlet规范,session的作用范围应该仅仅限于当前应用程序 下,不同的应用程序之间是不能够互相访问对方的session的。各个应用服务器从实际效果上都遵守了这一规范,但是实现的细节却可能各有不同,因此解决 跨应用程序session共享的方法也各不相同。

首先来看一下Tomcat是如何实现web应用程序之间session的隔离的,从  Tomcat设置的cookie路径来看,它对不同的应用程序设置的cookie路径是不同的,这样不同的应用程序所用的session id是不同 的,因此即使在同一个浏览器窗口里访问不同的应用程序,发送给服务器的session id也可以是不同的。


  

根据这个特性,我们可以推测Tomcat中session的内存结构大致如下。




笔 者以前用过的iPlanet也采用的是同样的方式,估计SunONE与iPlanet之间不会有太大的差别。对于这种方式的服务器,解决的思路很简单,实 际实行起来也不难。要么让所有的应用程序共享一个session id,要么让应用程序能够获得其他应用程序的session id。

iPlanet中有一种很简单的方法来实现共享一个session id,那就是把各个应用程序的cookie路径都设为/(实际上应该是/NASApp,对于应用程序来讲它的作用相当于根)。
<session-info>
<path>/NASApp</path>
</session-info>

需 要注意的是,操作共享的session应该遵循一些编程约定,比如在session attribute名字的前面加上应用程序的前缀,使得  setAttribute("name", "neo")变成setAttribute("app1.name", "neo"),以防止命名空间冲 突,导致互相覆盖。


在Tomcat中则没有这么方便的选择。在Tomcat版本3上,我们还可以有一些手段来共享 session。对于版本4以上的Tomcat,目前笔者尚未发现简单的办法。只能借助于第三方的力量,比如使用文件、数据库、JMS或者客户端 cookie,URL参数或者隐藏字段等手段。

我们再看一下Weblogic Server是如何处理session的。


  

从 截屏画面上可以看到Weblogic Server对所有的应用程序设置的cookie的路径都是/,这是不是意味着在Weblogic Server中 默认的就可以共享session了呢?然而一个小实验即可证明即使不同的应用程序使用的是同一个session,各个应用程序仍然只能访问自己所设置的那 些属性。这说明Weblogic Server中的session的内存结构可能如下




对于这样一种结构,在  session机制本身上来解决session共享的问题应该是不可能的了。除了借助于第三方的力量,比如使用文件、数据库、JMS或者客户端  cookie,URL参数或者隐藏字段等手段,还有一种较为方便的做法,就是把一个应用程序的session放到ServletContext中,这样 另外一个应用程序就可以从ServletContext中取得前一个应用程序的引用。示例代码如下,

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

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

值 得注意的是这种用法不可移植,因为根据ServletContext的JavaDoc,应用服务器可以处于安全的原因对于 context.getContext("/appA");返回空值,以上做法在Weblogic Server 8.1中通过。

那 么Weblogic Server为什么要把所有的应用程序的cookie路径都设为/呢?原来是为了SSO,凡是共享这个session的应用程序都可 以共享认证的信息。一个简单的实验就可以证明这一点,修改首先登录的那个应用程序的描述符weblogic.xml,把cookie路径修改为 /appA 访问另外一个应用程序会重新要求登录,即使是反过来,先访问cookie路径为/的应用程序,再访问修改过路径的这个,虽然不再提示登录,但 是登录的用户信息也会丢失。注意做这个实验时认证方式应该使用FORM,因为浏览器和web服务器对basic认证方式有其他的处理方式,第二次请求的认 证不是通过 session来实现的。具体请参看[7] secion 14.8 Authorization,你可以修改所附的示例程序来做这些试验。

八、总结
session机制本身并不复杂,然而其实现和配置上的灵活性却使得具体情况复杂多变。这也要求我们不能把仅仅某一次的经验或者某一个浏览器,服务器的经验当作普遍适用的经验,而是始终需要具体情况具体分析。。

http://blog.matrix.org.cn/ljhj210423/date/20060803 星期四 2006年08月03日

使用Apache Commons-email组件发送邮件[z]

commons-email是apache提供的一个开源的API,是对javamail的封装,因此在使用时要将javamail.jar加到 class path中,主要包括SimpleEmail,MultiPartEmail,HtmlEmail,EmailAttachment四个类。
 
SimpleEmail:发送简单的email,不能添加附件
MultiPartEmail:文本邮件,可以添加多个附件
HtmlEmail:HTML格式邮件,同时具有MultiPartEmail类所有“功能”
EmailAttchment:附件类,可以添加本地资源,也可以指定网络上资源,在发送时自动将网络上资源下载发送。
 
发送基本文本格式邮件:
==============
SimpleEmail email = new SimpleEmail();
//smtp host 
email.setHostName("mail.test.com");
//登陆邮件服务器的用户名和密码
email.setAuthentication("test","testpassword");
//接收人
email.addTo("jdoe@somewhere.org", "John Doe");
//发送人
email.setFrom("me@apache.org", "Me");
//标题
email.setSubject("Test message");
//邮件内容
email.setMsg("This is a simple test of commons-email");
//发送
email.send();

发送文本格式,带附件邮件:
==================
//附件,可以定义多个附件对象
EmailAttachment attachment = new EmailAttachment();
attachment.setPath("e:\\1.pdf");
attachment.setDisposition(EmailAttachment.ATTACHMENT);
attachment.setDescription("Picture of John");
//
MultiPartEmail email = new MultiPartEmail();
//smtp host 
email.setHostName("mail.test.com");
//登陆邮件服务器的用户名和密码
email.setAuthentication("test","testpassword");
//接收人
email.addTo("jdoe@somewhere.org", "John Doe");
//发送人
email.setFrom("me@apache.org", "Me");
//标题
email.setSubject("Test message");
//邮件内容
email.setMsg("This is a simple test of commons-email");
//添加附件
email.attach(attachment);
//发送
email.send();
 
发送HTML格式带附件邮件:
=================
//附件,可以定义多个附件对象
EmailAttachment attachment = new EmailAttachment();
attachment.setPath("e:\\1.pdf");
attachment.setDisposition(EmailAttachment.ATTACHMENT);
attachment.setDescription("Picture of John");
//
HtmlEmail email = new HtmlEmail ();
//smtp host 
email.setHostName("mail.test.com");
//登陆邮件服务器的用户名和密码
email.setAuthentication("test","testpassword");
//接收人
email.addTo("jdoe@somewhere.org", "John Doe");
//发送人
email.setFrom("me@apache.org", "Me");
//标题
email.setSubject("Test message");
//邮件内容
email.setHtmlMsg("This is a simple test of commons-email");
//添加附件
email.attach(attachment);
//发送
email.send();

http://blog.matrix.org.cn/ljhj210423/date/20060712 星期三 2006年07月12日

常用的匹配正则表达式和实例[z]

匹配中文字符的正则表达式: [\u4e00-\u9fa5]
匹配双字节字符(包括汉字在内):[^\x00-\xff]
应用:计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)
String.prototype.len=function(){return this.replace([^\x00-\xff]/g,"aa").leng