如果您已經(jīng)成功的運(yùn)行了教程第二部分的helloworld,一定會(huì)感覺(jué)到LAJP的使用非常簡(jiǎn)單,但對(duì)于一項(xiàng)新技術(shù)做出評(píng)價(jià)不能只停留在Hello World層面,本節(jié)教程將帶您更深入地了解LAJP。
PHP和Java都是很優(yōu)秀的夸平臺(tái)的編程語(yǔ)言,LAJP在這點(diǎn)上沒(méi)有限制,凡是能夠運(yùn)行PHP的環(huán)境,凡是能夠運(yùn)行Java的環(huán)境,就可以運(yùn)行LAJP。
LAJP有兩套傳輸機(jī)制:消息隊(duì)列和socket,消息隊(duì)列方式可運(yùn)行在Unix/Linux/BSD系統(tǒng),編譯PHP時(shí)需要加上 --enable-sysvsem,--enable-sysvshm和--enable-sysvmsg 編譯選項(xiàng),使PHP支持信號(hào)量、共享內(nèi)存和消息隊(duì)列。socket方式對(duì)系統(tǒng)平臺(tái)沒(méi)有限制,編譯PHP最好加上--enable-sockets 編譯選項(xiàng) ,使PHP支持socket。
PHP版本需要高于4.3,這是PHP對(duì)使用信號(hào)量、共享內(nèi)存和消息隊(duì)列的版本要求。
Java環(huán)境不需安裝任何WEB容器(Tomcat等),LAJP的Java端本身即是帶有main方法的,標(biāo)準(zhǔn)的Java應(yīng)用程序,且全部壓縮在唯一的jar文件中,不需要任何的第三方的類(lèi)庫(kù)。
JDK版本要求在1.5以上,這是因?yàn)長(zhǎng)AJP的Java端代碼中使用了諸如泛形等語(yǔ)法結(jié)構(gòu)。
windows環(huán)境“called to undefined function socket_create” 錯(cuò)誤:
在使用socket函數(shù)時(shí),經(jīng)常會(huì)報(bào)出“called to undefined function socket_create”,在網(wǎng)上搜一下發(fā)現(xiàn)此錯(cuò)誤非常頻繁(PHP不認(rèn)為這是個(gè)bug),當(dāng)遇到這個(gè)錯(cuò)誤時(shí),請(qǐng)按下列步驟解決:
嘗試運(yùn)行:<?php var_dump(extension_loaded("sockets")); ?> 如果輸出false,是php_sockets.dll沒(méi)有加載。
1. 檢查php.ini,確保extension=php_sockets.dll前沒(méi)有";"。
2. 檢查httpd.conf有下面幾行:
# c:/PHP/是php的安裝路徑(PHPzip解壓方式安裝)
LoadModule php5_module c:/PHP/php5apache2_2.dll
# 按模塊模式加載
PHPIniDir "c:/PHP/"
AddType application/x-httpd-php .php
# 按CGI模式加載, c:/php/是php的安裝目錄
#ScriptAlias /php/ "c:/php/"
#AddType application/x-httpd-php .php
#Action application/x-httpd-php "/php/php-cgi.exe"
3. 檢查php目錄下有沒(méi)有php_sockets.dll文件,如果沒(méi)有從ext目錄中copy過(guò)來(lái),php5默認(rèn)搜索路徑在php,而不是php/ext。
4. 嘗試以命令行方式運(yùn)行,如果命令行可以,將php.ini復(fù)制到c:\windows。
//命令行方式運(yùn)行, php.exe和php.ini在php安裝目錄下
php.exe -c php.ini <路徑>\php文件
PHP通過(guò)lajp_call()函數(shù)調(diào)用Java端方法,函數(shù)的第一個(gè)參數(shù)格式為:"類(lèi)名::方法名",從第二個(gè)參數(shù)起是向Java方法傳參。
例如Java端:
001 package aaa.bbb.ccc
002 public class MyClass
003 {
004 public static final int myMethod(int a, int b)
005 {
006 return a + b;
007 }
008 }
PHP的調(diào)用方式:
001 <?php
002 $c = lajp_call("aaa.bbb.ccc.MyClass::myMethod", 10, 20);
003 ?>
Java服務(wù)方法必須聲明為public static final
,在LAJP設(shè)計(jì)中Java端服務(wù)方法是無(wú)狀態(tài)的,強(qiáng)制聲明static表明了這個(gè)態(tài)度;強(qiáng)制聲明final是LAJP的另一個(gè)設(shè)計(jì)理念:簡(jiǎn)單、直白,不希望被封裝為“反轉(zhuǎn)控制”等復(fù)雜模式,這點(diǎn)和PHP一貫的簡(jiǎn)約風(fēng)格相一致。
php語(yǔ)言規(guī)范定義了8中數(shù)據(jù)類(lèi)型:boolean、int、float、string、array、object、resource、 NULL;java語(yǔ)言的數(shù)據(jù)類(lèi)型分為2類(lèi):基本數(shù)據(jù)類(lèi)型和對(duì)象類(lèi)型,基本數(shù)據(jù)類(lèi)型有byte、short、int、long、 char、boolean、float、double, 對(duì)象類(lèi)型包括數(shù)組、集合、javaBean等。在LAJP架構(gòu)中,php數(shù)據(jù)以參數(shù)形式傳遞給Java方法,Java方法的返回值再回傳給php調(diào)用程序,在調(diào)用過(guò)程中,php數(shù)據(jù)“自動(dòng)”轉(zhuǎn)換為Java數(shù)據(jù),反之亦然。
并不是所有數(shù)據(jù)類(lèi)型都可以轉(zhuǎn)換,在LAJP中建立了以下轉(zhuǎn)換規(guī)則:
php | java | 說(shuō)明 | |
布爾 | boolean | boolean | |
整形 | int | int | |
浮點(diǎn) | float | double | 在php中float和double含義相同 |
字符串 | string | java.lang.String | |
順序集合 | array(key:int ) | java.util.List | php中array的每個(gè)元素的key類(lèi)型必須是int |
key-value集合 | array(key:string ) | java.util.Map | php中array的每個(gè)元素的key類(lèi)型必須是string |
對(duì)象 | object | JavaBean | |
空 | NULL | null |
需要說(shuō)明的是PHP中的array、object和Java數(shù)據(jù)類(lèi)型的轉(zhuǎn)換。
array:
在PHP中,array可以描述多種結(jié)構(gòu): 順序集合(類(lèi)似Java的ArrayList),key-value集合(類(lèi)似Java的Hashtable或HashMap),棧等。在LAJP中只能使用兩種結(jié)構(gòu):
1. 順序集合 集合元素的key類(lèi)型為int類(lèi)型。
$a = array();
$a[0] = 10;
$a[1] = 20;
$a[2] = 30;
// 也可以:
$a = array();
$a[] = 10;
$a[] = 20;
$a[] = 30;
//但不能
$a = array();
$a['A'] = 20;
$a[1] = 10;
$a[2] = 30;
2. key-value集合 集合元素的key類(lèi)型為string類(lèi)型。
$a = array();
$a["a"] = 10;
$a["b"] = 20;
$a["c"] = 30;
在PHP的array轉(zhuǎn)換為Java時(shí),LAJP內(nèi)部是通過(guò)查看array的第一個(gè)元素的key,如果key是int類(lèi)型,被轉(zhuǎn)換為java.util.ArrayList;如果key是string類(lèi)型,被轉(zhuǎn)換為java.util.HashMap,反過(guò)來(lái)也一樣,Java的List轉(zhuǎn)換為PHP的以KEY為int的數(shù)組,Map轉(zhuǎn)換為PHP的以KEY為String的數(shù)組。
在PHP的array中的元素,可以是表1中的任何一種類(lèi)型,包括array和Object,這意味著可以構(gòu)建出復(fù)雜的結(jié)構(gòu),如數(shù)組中的數(shù)組(通常稱(chēng)為二維或多維數(shù)組)。
object:
PHP對(duì)象被映射到Jave的JavaBean對(duì)象,這意味著PHP類(lèi)中的每一個(gè)屬性,在Java對(duì)應(yīng)類(lèi)中都有一個(gè)同名,同類(lèi)型(符合表1映射關(guān)系)的屬性,且此屬性有g(shù)etter和setter方法。
目前只支持PHP4規(guī)范對(duì)象轉(zhuǎn)換到Java,這是因?yàn)樵贚AJP內(nèi)部轉(zhuǎn)換時(shí)需要將PHP對(duì)象數(shù)據(jù)序列化,PHP5對(duì)象不能轉(zhuǎn)換,這點(diǎn)尤其要注意。
目前也不支持PHP中的命名空間(Namespaces),在PHP中用"_"表示Java中的".",如要映射到Java的"com.foo.MyClass"類(lèi),需要在PHP中定義類(lèi)"com_foo_MyClass"。
在LAJP中提供了一個(gè)小工具,將Java的JavaBean類(lèi)自翻譯為對(duì)應(yīng)的PHP類(lèi),例如在Java中有這樣的一個(gè)JavaBean:
001 package cn.com.aili;
002 public class PhpObject
003 {
004 private int a;
005 private double b;
006 private boolean c;
007 private String d;
008
009 ...getter和setter方法
010 }
編寫(xiě)一個(gè)PHP文件:
001 <?php
002 require_once("../lajp/php_java.php");
003 $ret = lajp_call("lajp.ReflectUtil::javaBean2Php", "cn.com.aili.PhpObject");
004 echo "{$ret}";
005 ?>
運(yùn)行后,會(huì)在頁(yè)面輸出對(duì)應(yīng)的PHP類(lèi):
cn_com_aili_PhpObject
{
var $a;
var $b;
var $c;
var $d;
}
在LAJP體系中,PHP充當(dāng)客戶(hù)端(調(diào)用者),Java充當(dāng)服務(wù)端(服務(wù)提供者)。
* PHP
負(fù)責(zé)和瀏覽器客戶(hù)端的交互,編寫(xiě)HTML頁(yè)面、表單,接收瀏覽器提交的數(shù)據(jù),對(duì)提交數(shù)據(jù)的合法性交驗(yàn),Cookie/Session的維護(hù),Ajax服務(wù)等是其固有的職責(zé)。PHP不應(yīng)該編寫(xiě)復(fù)雜業(yè)務(wù)邏輯程序,不應(yīng)出現(xiàn)連接接數(shù)據(jù)庫(kù)相關(guān)代碼。
* Java
負(fù)責(zé)編寫(xiě)業(yè)務(wù)邏輯,數(shù)據(jù)對(duì)象,數(shù)據(jù)庫(kù)程序。在Java中不應(yīng)該出現(xiàn)和瀏覽器交互的代碼,例如不能出現(xiàn)Servlet/JSP API代碼,不應(yīng)編寫(xiě)Ajax服務(wù)。
如對(duì)本文有疑問(wèn),請(qǐng)?zhí)峤坏浇涣髡搲?,廣大熱心網(wǎng)友會(huì)為你解答!! 點(diǎn)擊進(jìn)入論壇