java开发cgi_編寫CGI小結(Java)

轉載請注明出處:http://blog.csdn.net/hungryhuang/article/details/6601684。

由於Carl要用到我的程序,我們便合作工作。但是他寫的程序是Python的,我寫的程序是Java的,必須得找一種方式進行通信。盡管有Jython這些東西,但是Carl認為還是CGI最簡便。於是,前陣子開始學學CGI怎么弄。剛開始,覺得好像也不是很難,但是后來進展沒有預期的順利。最后,由於學院的服務器有CGI模塊但是不允許隨便跑CGI,實驗室服務器又裝的是FastCGI,感覺麻煩,最后Carl說還是用socket吧... - - |||。

整體來說,用CGI進行通信這個計划算是破產了。雖然是很老舊、基本都不會再用的東西了,但是由於對我來說是新東西,還是很好奇,沒有實現,自然是一種惋惜。雖然最后沒能用上CGI,但是個人覺得如果學院服務器讓用戶自己跑CGI的話,應該還是沒問題的。無論怎樣,還是記錄下一些基本知識,免得以后又忘了。

CGI年代久遠,不過卻實現了動態網頁。CGI,准確說,應該是種協議(或者說接口),它使得server中的程序(cgi script)能夠通過標准I/O流(STDIN和STDOUT,比如在Java語言里就是System.in和System.out,在C里面就是printf等,只要是能夠進行標准I/O流讀寫的程序,都可以用來實現CGI)讀取到所需的信息和輸出信息給瀏覽器,而這些所要從客戶端讀取的信息則是包含在某些已經被定義好的環境變量中,我們只需要讀取這些環境變量,自然就能獲取想要的值了(這也就是CGI這個借口為我們所做的事)。而通常所說的CGI,也有可能泛指CGI程序,即CGI script,是開發者自己所寫的、處理用戶請求的程序。

總體來說,過程是這樣的:

1. 服務器接受到請求

2. 服務器發現這個請求是需要一個CGI程序來進行處理

3. 服務器建立一個環境,這個運行環境里有一些變量,也就是所謂的CGI程序所需要的環境變量

4. 服務器在這個環境下啟動相應的CGI程序

5. CGI程序解析自己想要的環境變量來獲取所提交的請求信息

6. CGI程序對這些請求信息做相應的處理

7. CGI程序將相應的結果輸出到標准輸出STDOUT,此結果將被輸出到用戶端,呈現給用戶結果。

8. CGI程序執行完畢,退出程序。

比較詳細來說,原理大概是這樣的:

1. 客戶端在瀏覽某個網頁的時候,提交表單(form)。而表單的action則指定了要處理該表單的CGI程序,比如:

上面的程序中,action="/cgi-bin/plus.cgi" 的意思就是說“這個表單里的數據,都交給plus.cgi這個程序處理了,然后它處理完這些數據后,再把結果返回給瀏覽器”。

需要說明的是,plus是一個可執行文件的文件名,比如可能是一個shell文件(例如 plus.sh),其后綴不一定是.cgi。那么為什么要取在這里取名.cgi呢?原因是這樣能說明,這個表單處理,是通過一個類型為cgi的程序進行處理,或者說,通過cgi這種方式讓這個可執行文件對提交的數據進行處理。一般來說,出於安全考慮,不是任何用戶都有權限去寫一個自己的cgi程序然后上傳到服務器、讓該服務器去運行的(比如我們學院的服務器就不行,哎...)。而只有放在服務器指定目錄(一般為cgi-bin)下的可執行文件,才會被被視為是cgi程序,才能被執行。而一般人是無法訪問這個目錄的。

2. 然后,name為“m”和“n”的這兩個變量以及他們的值,就通過某個環境變量輸入到CGI程序中,由CGI程序去進行該CGI程序所指定的處理了。GET和POST獲取“m”和“n”的方式有所不同。如果提交方法是GET的話,那么GET所提交的內容則被包含在名為QUERY_STRING的環境變量中,當得到這個環境變量的值后,將其內容解析出來就可以得到name/value這樣的值對了,就可以進行相應的處理了。而POST的話,則需要從標准輸入流STDIN里面讀取數據,而這些數據到底有多少呢?這個則需要通過讀取CONTENT_LENGTH這個環境變量的值來知道。

像在C語言里面,可以通過getenv函數來直接獲取環境變量的值,比如:getenv("QUERY_STRING"),  getenv("CONTENT_LENGTH")等等。Perl可能要算是寫CGI的最佳語言,但是不會Perl,此處略過。另外,由於我的程序是用Java寫的,就使得讀取環境變量的方式有點特殊,因為Java是沒有直接獲取這些環境變量的函數的。Java為何不能直接訪問環境變量?簡單說,因為Java內部還有一個屬於System這個類的屬性。因此,我們一個System.getProperty獲取的是Java中這個System類的屬性的,而不是環境變量的。這些System的屬性也是以name/value這樣的形式來存儲一些Java運行環境的信息的。因而,額外的環境變量(或者說屬性信息)需要用指令java -D的形式,詳見后面的wrapper程序。

常用的環境變量有:REQUEST_METHOD,QUERY_STRING,CONTENT_LENGTH,PATH_INFO。其他的有:SERVER_SOFTWARE,SERVER_NAME,GATEWAY_INTERFACE,SERVER_PROTOCOL,SERVER_PORT,PATH_TRANSLATED,SCRIPT_NAME,REMOTE_HOST,REMOTE_ADDR,AUTH_TYPE,REMOTE_USER,REMOTE_IDENT,CONTENT_TYPE。如果現在忘記這些是干嘛的了...額...google下吧...

現在,我們已經讀取到了所想要的環境變量。但是,這些環境變量的值,是需要我們進行解析的,因為當初在傳給我們的時候,就是進行了URL編碼的(URL encode)。比如,如果我們提交的表單是GET類型的話,再提交完信息后,可以在地址欄看來類似這樣的url地址:http://www.xxxxxxx.edu/cgi-bin/plus.cgi?m=5&n=6。其中,“m=5&n=6”就是被編碼的字符串,也就是我們想要獲取的值。而“http://www.xxxxxxx.edu/cgi-bin/plus.cgi”是處理該表單的cgi程序的地址。“?”說明后面的字符串(即“m=5&n=6”)是傳入的參數。不難看出,在編碼的時候,類似於這樣的規則“name1=value1&name2=value2&name3=value3”。此外,非西文的字符串將被“%XX”所代替,空格將被“+”代替。具體地,去參考URL encode的相關資料。

如何解析這些麻煩的字符串,不需要自己再動手去寫,網上有很多這樣的函數庫,各種語言。直接用網上現成的函數庫來解析就行了。就Java來說,推薦cgi_lib.java這個庫。很方便,應用也很廣泛,文件也很小。其中函數的功能是跟cgi_lib.pl一樣的。

3. 解析字符串后,我們可以知道變量m的值為5,變量n的值為6。然后就可以在CGI程序中進行相應的處理了。自己想怎么處理就怎么處理。比如,此處是想處理加法,則在自己的CGI程序里實現m和n的加法即可。

4. 處理完了數據,需要將結果呈現給瀏覽器端的用戶。這個簡單,直接用STDOUT就行了。比如,C語言用printf,Java語言用System.out.println之類的。但是需要注意的是,首先輸出的必須是"Content-type: text/plain"(也就是MIME頭信息,告訴server它隨后的輸出是以純ASCII文本的形式),然后下面空一行(必須空一行),再直接打印出要呈現給用戶的html語句。比如,在Java里面,就是:

System.out.println("Content-type: text/plain");

System.out.println("");

比如,要測驗自己是否有權限可以寫一個CGI放在服務器上運行,則可以寫一個最簡單的CGI程序,該程序暫時不處理任何來自用戶的請求,只是輸出"Hello, world"。

shell程序可以寫成:

#!/bin/sh

echo "Content-type: text/html"

echo ""

echo ""

echo "

"

echo "

Hello, world

"

echo ""

echo ""

C語言可以寫成:

#include

void main(void){

printf("Content-type: text/html\n");

printf("\n");

printf("\n");

printf("

\n");

printf("

Hello, world

\n");

printf("");

printf("/");

}

這樣,在客戶端運行就會呈現出

大小的“Hello, world”了。

Java的特別注意:

1.Java讀取環境變量,只能通過-D的option來加以讀取。

2.Java生成的.class文件(比如java_plus.class),這不是一個通常意義上的可執行文件,這個文件只是說通過JVM可以執行起來。而CGI程序是一個直接可以執行的文件。因此,我們需要寫一個wrapper,將這個.class文件封裝起來。當調用這個wrapper程序的時候,這個wrapper程序能通過Java指令運行該.class文件。

結合上訴兩點,則我們可以寫一個shell文件當做wrapper程序,如下:

#!/bin/sh

java \

-Dcgi.content_type=$CONTENT_TYPE \

-Dcgi.content_length=$CONTENT_LENGTH \

-Dcgi.request_method=$REQUEST_METHOD \

-Dcgi.query_string=$QUERY_STRING \

-Dcgi.server_name=$SERVER_NAME \

-Dcgi.server_port=$SERVER_PORT \

-Dcgi.script_name=$SCRIPT_NAME \

-Dcgi.path_info=$PATH_INFO \

java_plus

然后將上面的文件保存為plus.sh,並且放在指定的目錄(比如cgi-bin)即可。這樣,當表單提交新的時候,就會到這個目錄中(因為后綴名為cgi)去尋找名為plus的文件,然后執行這個文件。而在java_plus這個文件中,我們用System.getProperty("cgi.query_string")就可以訪問到QUERY_STRING這個環境變量了。

推薦一些鏈接:

http://www.jmarshall.com/easy/cgi/

http://www.eli.sdsu.edu/courses/spring96/cs596/notes/andrew/cgi.html

http://www.javaworld.com/javaworld/jw-01-1997/jw-01-cgiscripts.html

http://apps.hi.baidu.com/share/detail/18814484

http://www.jaguarpc.com/forums/showthread.php?t=2553

http://httpd.apache.org/docs/current/howto/cgi.html

至於FastCGI,這個效率比傳統CGI高很多。但是,比較麻煩,需要用循環,還要設置端口什么的,就沒動手搞那個,只是看了下相關資料。還是放在這里吧。

http://www.phpchina.com/download/handbook/linux-html/1272.html

http://www.20cn.net/ns/wz/net/data/20030615005558.htm

http://www.fastcgi.com/devkit/doc/fcgi-java.htm

http://www.citycat.ru/doc/FastCGI/fcdk/index.html

http://hi.baidu.com/coffeefoam/blog/item/1446493be749f3e814cecbb8.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/431846.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

腾讯后台开发面试总结,原创,吐血推荐!!

前段时间专心面过腾讯,经过了N轮的技术面,结果还是挂了,但没挂在技术面,比较欣慰,回来之后写一点总结,以供有梦想进入腾讯做后台服务器开发的同学参考,本文章为胡成精心总结,胡成原创…

java 6大原则_java 6大设计原则 一:观察者模式

解耦常用的模式OrderService.javaServicepublic class OrderService{AutowiredApplicationContext applicationContext ;public void saveOrder(){//1.创建订单System.out.println(“1.创建订单”);OrderEvent event new OrderEvent("参数")application…

jbb是什么梗_子水是什么意思,子水命理

子水是十二地支之一,那么命中有子水的代表的是什么呢?适合什么方位呢?有什么喜忌吗?怎么分析你呢?现在金宝贝起名网为你介绍子水是什么意思,子水命理的相关文章。子水是什么意思,子水命理八字地支:子水是什么意思1、对…

java语言实现一个长度为n_Java语言实现求解一元n次多项式的方法示例[Java代码]...

本文主要向大家介绍了Java语言实现求解一元n次多项式的方法示例,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助。项目需要做趋势预测,采用线性拟合、2阶曲线拟合和指数拟合的算法,各种线性拟合算法写成矩阵大概是这么…

java rmi 是否 必要_Java学习之路-RMI学习

Java远程方法调用,即Java RMI(Java Remote Method Invocation)是Java编程语言里,一种用于实现远程过程调用的应用程序编程接口。它使客户机上运行的程序可以调用远程服务器上的对象。远程方法调用特性使Java编程人员能够在网络环境中分布操作。RMI全部的…

c++将文本中的字符串一次读入到内存

这段代码是将文本文件中的全部字符读入到内存中&#xff0c;这样的速度是很快的 char buf[1024*800];int MAXS 10000000;freopen("d:\\4.txt", "rb", stdin);int len fread(buf, 1, 100000, stdin);buf[len] \0;cout << buf[10]; 转载于:https://…

JAVA写同步栈_tomcat实现的同步队列和同步栈

tomcat实现的同步队列&#xff0c;同步栈用于数据量比较固定且基本很少删除的场景&#xff0c;尽可能减少内存消耗。同步队列/** Licensed to the Apache Software Foundation (ASF) under one or more* contributor license agreements. See the NOTICE file distributed with…

IOS高级编程之二:IOS的数据存储与IO

一、应用程序沙盒 IOS应用程序职能在系统为该应用所分配的文件区域下读写文件&#xff0c;这个文件区域就是应用程序沙盒。所有的非代码文件如&#xff1a;图片、声音、映象等等都存放在此。 在mac中command&#xff0b;shift&#xff0b;G命令&#xff0c;然后输入users/用户名…

安卓投屏大师_苹果,安卓手机如何免费投屏?只要悄悄按下这里,便能轻松实现...

现在很多手机都有自带投屏功能&#xff0c;这样一来我们便可以将所看的视频&#xff0c;所玩的游戏投屏到电脑或电视上了&#xff0c;当然也需要这些设备支持投屏才行。一、无线投屏1、苹果手机苹果手机的投屏功能在哪里呢&#xff1f;只要打开苹果手机从下往上滑动&#xff0c…

java 反射解析xml_java反射获取xml元素

类名:class Person {public void run(String who){System.out.println("Person::run()" who);}public void jump(String who){System.out.println("Person::jump()" who);}public void run(){System.out.println("Person::run()");}public voi…

怎样的中奖算法能让人信服

话说写一个抽奖程序还不容易&#xff0c;不就是生成一个随机数吗&#xff0c;哪需什么算法之类的。 从技术上说&#xff0c;这确实不难。事实上&#xff0c;你怎么写都可以&#xff0c;因为程序只运行在特定的设备上&#xff0c;外人根本无法了解其中的细节。 那么问题就来了&a…

b站电脑客户端_如何将B站的flv格式的视频转换成mp4格式

经常看到B站有精彩的视频片段&#xff0c;于是想把这些视频下载保存到电脑&#xff0c;但是发现没有下载按钮&#xff0c;是不是很悲催。有些时候想从优酷、土豆网这些视频网站下载视频&#xff0c;结果却提示要先下载视频客户端才能继续下载视频&#xff0c;运气差的话&#x…

linux Packet socket (1)简单介绍

本文主要来自于linux自带的man packet手冊&#xff1a; http://man7.org/linux/man-pages/man7/packet.7.html 平时常常使用的INET套接字提供的是7层的抓包能力&#xff0c;抓上来的data直接就是tcp或者udp的payload&#xff0c;无需关心L3和L4的头部信息。 Packet套接字提供的…

asp.net 设置 excel alignment_教你如何用Python轻轻松松操作Excel、Word、CSV,一文就够了,赶紧码住!!!...

作者&#xff1a;奈何缘浅wyjhttps://juejin.im/post/6868073137263607821Python 操作 Excel常用工具数据处理是 Python 的一大应用场景&#xff0c;而 Excel 又是当前最流行的数据处理软件。因此用 Python 进行数据处理时&#xff0c;很容易会和 Excel 打起交道。得益于前人的…

java 页面输出一个页面_java学习之:一个完整页面输出信息的过程(以输出Doctor表中信息为例)...

最近在练习java程序&#xff0c;总结一下从数据库查询信息并输出到jsp页面的过程。主要数据处理在src.cn.javatest包下面项目预览1&#xff0c;配置项目根目录src目录下的druid.properties数据库信息(相当于一个数据库配置文件)里面的信息可以在下载druid中获得&#xff0c;只需…

[xsd学习]xsd介绍

一直以来项目中对xml格式的判断使用的都是dtd格式&#xff0c;直到最近才发现&#xff0c;不知何时都已经转为xsd来进行判断和校验&#xff0c;于是今天专门找资料看下&#xff0c;不得不说&#xff0c;对于这类资料的入门&#xff0c;w3cschool真是个不错的资料库&#xff0c;…

教学目标四个维度_【深度好文】体育教案中的教学目标与学习目标应如何表述...

体育教师大本营教学/训练/职业/成长强 烈 建 议 大 家 星 标 我 们教 学 路 上 ☆ 不 离 不 弃在以往看到的体育课的教案上&#xff0c;目标部分不是用教学目标就是用学习目标来表述&#xff0c;然而&#xff0c;这两种目标表达形式有没有本质区别&#xff1f;分别该如何表述…

java中检查性异常类_Java异常处理、java语言推崇使用检查类型异常

异常处理是java语言的重要特性之一&#xff0c;《Three Rules for effective Exception Handling》一文中是这么解释的&#xff1a;它主要帮助我们在debug的过程中解决下面的三个问题。什么出错了哪里出错了为什么出错java语言可以说是提供了过于完善的异常处理机制&#xff0c…

why I need a flow learn note.

1.其实学网站学安卓也写了txt的学习笔记。然后扔着&#xff0c;&#xff08;没有时间线和互动性&#xff09;&#xff0c;然后就没有然后了。 2.知识体系&#xff0c;一个月后&#xff0c;哎呦我擦&#xff0c;我会啥来着&#xff08;搞了这么久&#xff0c;深有体会&#xff0…

nodejs readfilesync 路径_Linux 磁盘多路径聚合multipath

在日常工作中我们经常遇到配置存储的多路径聚合。多路径的目的是&#xff0c;当主机HBA卡、线缆、交换机或者存储设备的控制器故障等原因造成一条物理路径失效时,服务器可以将通过此物理路径的I/O转移到其他正常的物理路径上面,应用程序不会觉察到这种改变&#xff0c;从而提高…