本文最早发布在CSDN的博客上,是我为LAJP写的第一篇文章,说明了当时创建LAJP的思路,现在 迁移到这里。
PHP和Java各自有着鲜明的特点:
PHP简单、易学,开发动态网页效率高,草根文化气息浓重,是语言世界的平民英雄。
Java强大而复杂,有众多高端功能,又有IMB、Oracle等企业大颚的追捧,是语言世界的贵族王子。
不管是平民英雄还是贵族王子,都不满足在各自领域称王,于是平民英雄祭出LAMP大旗,在PHP5新的对象模型帮衬下,硬要往上层阶层闯一闯,无奈 金融、电信等王侯们不大欢迎;而贵族王子也非常重视WEB这个广大的基层社会,先制定Servlet/JSP法令,跟着又推出struts、JSF、 Taglib、JSTL、Spring等系列政策,试图消除阶级等级概念,但实施手法贵族气太浓无法深得民心。平民就是平民,贵族就是贵族,硬要将自己也 视为对方阵营里的一员,只有一个结果:牵强。
PHP结合Java是早已有的想法,PHP负责WEB层,Java负责业务和数据逻辑层,真是一对黄金组合。但PHP和Java是两个不同的语言, 如何将他们结合在一起是个问题。实际上已经有了一些手段:如PHP中内置了调用Java的方法,开源的也有php-java-bridge,这里介绍的一 个新的解决思路。
从操作系统层面观察: PHP和Java是系统中运行的不同进程,他们之间沟通属于进程间通信技术(IPC):
在传统的Unix环境中,IPC技术有:管道、消息队列、共享内存、信号量等,在当今TCP/IP流行的大背景下,IPC已经鲜有耳闻了,但在同一 个系统中,IPC通信比基于TCP的socket通信在性能、资源占用方面有相当大的优势,所以今天我们重新挖掘IPC这门传统工艺,让它还发出新的光 芒。
本文介绍的思路即是使用IPC技术来结合PHP和Java。
在Unix/Linux中,PHP基本提供了所有IPC的访问接口,这点不难想象,因为PHP可以看作是以C语言为核心的一个壳,而IPC是系统内 核的组成部分,对外提供了一组C函数接口,因此PHP可以非常顺畅的运用IPC技术。而Java没那么幸运,为了追求夸平台性(Windows的IPC技 术和Unix的不同),没有提供系统级的IPC访问,这也体现了Java的文化特色:为追求统一可牺牲效能。
好在Java有和C对接的JNI接口,可利用它来实现我们的设想,最后的思路如下图:
从上图中看出,PHP承担HTTP层的职责,而Java承担业务层的职责,他们通过System V Message Queue(消息队列,进程间通讯IPC中的一种)相互沟通,Java需要JNI的支持。
通信问题解决了,下来就需要考虑通信内容的问题了。PHP和Java各有其语言内部定义的数据类型,当PHP数据传送到Java,或Java数据传 送到PHP时,怎样进行转换呢? 很多人马上会想到使用xml,xml确是一种夸平台、能够很好描述对象模型的数据封装技术,但xml体积大传输速率慢,通讯两端解析也比较麻烦。
实际上,无论是PHP还是Java,在语言设计时都考虑了数据怎样传输和存储的问题,那就是序列化,例如EJB调用就是通过Java的序列化对象来 传输数据的。
PHP的序列化非常巧妙,例如:
整形: $i = 5 序列化后是 i:5
字符串: $s = “abcd” 序列化后是 s:4:”abcd”
数组:$arr = array(”a” => “value1″, “b” => “value2″) 序列化后是 a:2:{s:1:”a”;s:6:”value1″;s:1:”b”;s:6:”value2″;}
对象: class aaa{var $attr1 = 5; var $attr2 = “ABCD”;} 序列化后是 O:3:”aaa”:2:{s:5:”attr1″;i:5;s:5:”attr2″;s:4:”ABCD”;}
简单而明了,不仅描述了数据结构,并带有数据原来的类型,问题得以解决。使用PHP序列化数据作为PHP和Java的通讯数据格式,不仅效能高,而 且更加接近语言本意。
开源项目LAJP 就是以上述思想为核心的实现技术,使用起来也非常简单,下面是一个示例程序:
php端程序
-
-
<?php
-
require_once ( "../lajp/php_java.php" ); //LAJP提供的程序脚本
-
-
//php类,映射到JavaBean 类:cn.com.ail.test.Bean
-
class cn_com_ail_test_Bean
-
{
-
var $a = "v1";
-
var $b = "v2";
-
}
-
-
$p1 = "a";
-
-
$p2 [ ] = 10;
-
$p2 [ ] = 20;
-
-
$p3 = new cn_com_ail_test_Bean;
-
-
//调用java服务
-
//lajp_call是“php_java.php”脚本提供的函数
-
//参数 cn.com.ail.test.Objtest::method1表示调用java的cn.com.ail.test.Objtest类中的 method1方法
-
//后面的$p1,$p2,$p3是向method1方法传递的参数。
-
$ret = lajp_call ( "cn.com.ail.test.Objtest::method1", $p1, $p2, $p3 );
-
-
?>
-
java端程序
-
-
//对应php中$p3的JavaBean
-
package cn. com. ail. test;
-
public class Bean
-
{
-
private String a;
-
private String b;
-
-
{
-
return a;
-
}
-
{
-
this. a = a;
-
}
-
{
-
return b;
-
}
-
{
-
this. b = b;
-
}
-
}
-
-
//java端服务
-
-
package cn. com. ail. test;
-
public class Objtest
-
{
-
//服务方法,只是简单的打印入参并返回简单字符串
-
{
-
for ( int i = 0; i < param2. size ( ); i++ )
-
{
-
}
-
-
//返回
-
return "OK, 收到并返回字符串应答";
-
}
-
}
-
LAJP的相关资料,可查看其网站:http://code.google.com/p/lajp/