Tomcat 9.0配置CGI processing servlet备忘

查阅Tomcat$CATALINA_BASE/conf/web.xml文件,很容易发现有个被注释的配置项,即:Common Gateway Includes (CGI) processing servlet,直译为通用网关包含处理servlet。有点拗口,又由于译文中动词“包含”和“处理”都在名词servlet之后,更加显得译文有点让人摸不着头脑;在网上搜索“CGI”,绝大多数返回的结果都是
Common Gateway Interface,在维基百科上找CGI对应的词条解释也是指的后者。

那么,两者有什么区别呢?既然这么相似,两者又有什么联系呢?

先说说通用网关接口,这是网上最常见的,也是广泛认可的说法,也就是说通常“CGI” = “Common Gateway Interface”(通用网关接口)。它能干嘛用呢?它其实是为web服务器定义了一种与外部程序交互的方法,而这类外部程序主要是产生网页内容,通常也被称为CGI程序或CGI脚本程序。简单地说,只要部署在web应用中的脚本程序服从CGI标准或规范,就能被该web服务器的软件调用,从而产生动态内容响应客户端请求。而关于通用网关接口的产生,一方面是由于服务器生成动态页面的需求,另一方面是由于生成动态页面的脚本程序不兼容不复用等问题。详细情况可查阅维基百科上Common Gateway Interface词条或者Tomcat文档User Guide的CGI How to

那Tomcat中通用网关包含处理servlet又是干嘛用的呢?如果查看了维基百科上的词条会发现,对于通用网关接口,很多著名的web服务器软件都是支持的,如Apache,IIS,Ngnix以及基于node.js服务器等。那么,作为使用较为广泛的Tomcat服务器肯定也是支持的,而Tomcat该如何支持呢?支持的思路也很简单,Tomcat本身不就是一个servlet容器么,它处理servlet的能力不是很好么,那就给它配置一个专门处理通用网关接口(CGI)的servlet就行了。这个配置的专门处理通用网关接口的servlet类就是通用网关包含处理servlet(Common Gateway Includes (CGI) processing servlet)。注意,这个servlet类的主要功能是处理,而处理对象是服务器上的实现了通用网关接口(CGI)的程序或脚本程序,即CGI脚本程序或CGIs。

简单总结下以上内容,通用网关接口(Common Gateway Interface,CGI)是一套专门针对web服务器上web应用中脚本程序的编写标准或规范,只要编写的程序或脚本程序符合该规范,那么web服务器软件就能够根据客户端请求而调用该程序或脚本程序输出结果,并作为动态页面的全部或一部分返回客户端。而Tomcat中,通用网关包含处理servlet(Common Gateway Includes (CGI) processing servlet,CGI processing servlet)是一个在Tomcat服务器上专门处理实现通用网关接口(CGI)的脚本程序的servlet类。

那么,下面以一个Python写的简单CGI脚本程序为例,不依托集成开发环境(IDE),“手动”在Tomcat 配置CGI处理servlet(以下简称CGI处理servlet)及CGI脚本程序。所使用的Tomcat版本为9.0.0.M8。

(1)新建一个web应用项目

$CATALINA_BASE/webapps/新建文件夹,文件夹名即为web应用名项目。如图1所示。

图1 在webapps文件夹下新建项目名为luckyweb的web应用

打开luckyweb文件夹,该文件夹即为项目“luckyweb”的web应用根目录,下面以$LUCKYWEB_BASE代指该目录。。

在该根目录下可以存放web应用的静态内容,如(HTML页面,JSP页面,JavaScript文件,CSS样式表文件和图像文件),客户端都可以直接对此进行访问,比如根目录下新建一个欢迎页面welcome.html,则可在启动Tomcat后从浏览器地址栏输入http://localhost:8080/luckyweb/welcome.html进行访问(可自行测试,此处略去)。其中,8080是Tomcat对一个特定连接器的默认端口号,这个连接器的功能非常重要,它是负责接收所有客户端请求和发送所有服务器响应,可以把它理解为一个“端点(endpoint)”,用于连接客户端和服务器。端口号就是显式告知对该连接器的使用。(详见$CATALINA_BASE/conf/server.xml

有了根目录,那么继续新建两个文件夹,分别为META-INFWEB-INF,其对应的文件路径分别为$LUCKYWEB_BASE/META-INF$LUCKYWEB_BASE/WEB-INF,如图2所示。

图2 在luckyweb项目根目录下新建`META-INF`和`WEB-INF`文件夹

META-INF的具体表示含义在Tomcat官方文档或其它资料上暂时没找到较为详细的解释(日后看到,立即补上),但可以肯定的是它应该是代指“metadata-information”,也就是“元数据信息”,文件夹里应包含对本web应用中各类数据的注解和说明。本例由于比较简单,且仅需服务器上本web应用能启用对CGI的使用,所以后面会看到,我们仅仅是在该文件夹中新建context.xml文件并对其进行配置,也无其它更多深度使用方法和技巧;

WEB-INF文件夹是该web应用的专属配置文件夹,可以包含web应用部署描述器(web.xml)、自行创建的定制标签库描述描述器,以及其它希望包含进本web应用的资源文件。servlet官方标准里明确禁止将此文件夹(及其子文件)直接提供给客户端,所以,这里是存储一些敏感配置信息(如数据库连接用户名和密码)的好地方。

(2)新建web.xml,并配置CGI处理servlet类及其servlet映射

$LUCKYWEB_BASE/WEB-INF路径下,新建web.xml文件,官方称呼该文件为web应用部署描述器Web Application Deployment Descriptor),它是一个描述web应用中servlet和其他组件的XML文件,包括初始化参数和容器管理安全限制等内容。详细内容可参考Tomcat官方文档。注意,若采用记事本新建该文件,其默认编码方式是ANSI,而不是UTF-8,为了避免日后出现字符不识别等问题,建议另存为UTF-8编码格式。

图3给出了在WEB-INF/文件夹下新建的web.xmlweb应用部署描述器:

图3 在`WEB-INF/`文件夹下新建web.xml文件

web.xml的具体内容如下面代码片所示:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
  version="4.0">

  <!-- The definition of CGI processing servlet -->
  <servlet>
        <servlet-name>cgi</servlet-name>
        <servlet-class>org.apache.catalina.servlets.CGIServlet</servlet-class>
        <init-param>
          <param-name>debug</param-name>
          <param-value>0</param-value>
        </init-param>
        <init-param>
          <param-name>cgiPathPrefix</param-name>
          <param-value>WEB-INF/cgi</param-value>
        </init-param>
    <!-- attach to python -->
        <init-param>
          <param-name>executable</param-name>
          <param-value>python</param-value>
        </init-param>
         <load-on-startup>5</load-on-startup>
  </servlet>

  <!-- The mapping for the CGI processing servlet --> 
  <servlet-mapping>
        <servlet-name>cgi</servlet-name>
        <url-pattern>/cgi-bin/*</url-pattern>
  </servlet-mapping>

</web-app>

其中,<servlet></servlet>部分是CGI处理servlet类的定义部分,包括servlet名<servlet-name>、servlet类<servlet-class>和若干个初始化参数<init-param><servlet-mapping></servlet-mapping>部分是CGI处理servlet类的servlet映射部分,包括servlet名<servlet-name>和URL格式<url-pattern>

这些内容基本都是Tomcat预先定义或编辑好的(除了参数executable及其值,后面会讲到),直接从$CATALINA_BASE/conf/web.xml相应位置复制过来的就行。

下面仅对几个重点问题进行说明:

①关于初始化参数executable及其值的设置问题。参数executable的默认值是perl,这意味着在不指定该参数值的情况下,访问本应用中后缀名为*.cgi的文件,默认采用perl编译器进行编译执行,而若要采用Python编译器编译执行*.cgi文件,则须将该值设置为python。另外,不可忽视的一点是,无论期望采用何种程序语言编译器运行CGI程序,首先要保证搭载服务器的计算机上配置好相应编译器的环境变量或启动路径,否则即使参数值正确,CGI程序也是无法运行。图4给出了已安装Python编译器的计算机命令行调用结果(Win10)。

图4 Windows命令行调用Python编译器

注:很多时候测试出现问题都是编译器未得到正确启动,所以请务必确认你的编译器正确安装,且启动命令参数值和你配置的executable参数值一致

②关于初始化参数cgiPathPrefix及其值的含义问题。参数cgiPathPrefix表示的是查找CGI程序的(部分)路径。它的完整路径表达应该是“web应用根目录”+“分隔符”+“参数cgiPathPrefix值”。简单地说,就是服务器判断出客户端要调用某个CGI程序了,它该去哪里找这个CGI程序。

③关于servlet映射问题。servlet映射其实就是针对特定格式的URL指定专门的servlet负责处理。具体来讲,访问本例中web应用的URL应包含http://localhost:8080/luckyweb*,“”部分就是需要指定的<url-patten>’部分,当“”为“/cgi-bin/*”时,服务器就将该请求交由servlet名为cgi的servlet类进行处理,而这恰恰是上文刚刚配置的servlet类,这样服务器就完成了一个“中间商”的作用,后续对CGI程序的调用和动态页面内容的生成都交由CGI处理servlet类和CGI程序完成。

注意,实际中,web.xml需要设置的内容或参数是非常多的,由于本例暂不涉及,故未设置,特此澄清,以免误解。

(3)新建cgi文件夹及CGI脚本程序

$LUCKYWEB_BASE/WEB-INF路径下新建“cgi”文件夹,如图5所示。

图5 新建cgi文件夹

用Python语言编写一简单脚本程序(输出不是很符合HTML文档的要素要求,这里主要是测试下最终调用效果),代码如下:

print ('Content-Type:text/html')
print ()
print ('<h1>Hello python</h1>')

Python文件名后缀通常为“.py”,而要作为CGI脚本运行,需将后缀名改为“.cgi”。故本例中,将该Python语言编写的脚本程序命名为“hello-python.cgi”,且存放路径为$LUCKYWEB_BASE/WEB-INF/cgi如图6所示:

图6 新建hello-python.cgi

(4)在web应用中的context.xml中配置Context的属性

CGI处理servlet类和CGI脚本程序就算基本配置完成了,但还有一个关键步骤需要做,是什么呢?那就是需要给本web应用设置“特权”。出于安全考虑,Tomcat服务器默认是不支持CGI脚本程序的(这也就是$CATALINA_BASE/conf/web.xmlCGI处理servlet部分为注释的原因),所以,当要启用CGI处理servlet时,需要对环境或上下文(Context)设置特权。怎么设置呢?很简单,在$LUCKYWEB_BASE/META-INF/路径下,新建context.xml文件,如图7所示。

图7 新建context.xml文件

context.xml文件内代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<Context privileged="true"> 
    
</Context>

其中,privileged是根元素Context的属性,将其设置为“true”,即可保证该web应用可启用CGI处理servlet及CGI脚本程序运行。

(5)启动Tomcat服务器,并访问CGI脚本程序,查看结果

大功告成,下面启动Tomcat服务器,输入http://localhost:8080/luckyweb/cgi-bin/hello-python.cgi看下效果吧。

基于IDE方式与此大致相同,建议有兴趣的也动手试试吧。

完。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容