文章目录
  1. 1. 需求背景
  2. 2. PHP/Java Bridge
    1. 2.1. 示例
    2. 2.2. 注意事项
  3. 3. 相关资料

需求背景

之前介绍过我们项目的架构,由于历史原因,架构演变成这样:

1
ActionScript <--> Java <--> PHP

Java 与 AS 通过 TCP 长连接通信,Java 与 PHP 通过两条 HTTP 通道来通信:Java 与 PHP 各自有个 HTTP Server,并各自作为对方的 HTTP Client,Java 转发 AS 以前的 post 给 PHP;PHP 需要跨 session 推送或者广播时变为 HTTP Client 向 Java 的 HTTP Server 做 post。

在这之前的架构是 AS 的功能逻辑大部分直接与 PHP 进行 HTTP 通信。

项目的目标是慢慢将 PHP 部分写的糟糕的已有逻辑(例如帮派这种交互和广播同步比较多的)改到 Java 服务器上。项目人员配备跟不上,所以不能一下子全转了。

如果用之前的两条 HTTP 通道来小步快跑式的移逻辑,就需要再封装这两个通道之间的通信,费时间还不一定好使,所以我们需要一个 Java 直接调用 PHP 的技术。 Google 了解后,最终决定试试 PHP/Java Bridge。

PHP/Java Bridge

示例

  • CallPhp.java:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    package me.clawz.study; 

    import java.io.ByteArrayOutputStream;
    import java.io.FileReader;

    import javax.script.ScriptEngine;
    import javax.script.ScriptEngineManager;

    public class CallPhp {
                    
    public static void main(String[] args) throws Exception {
    test(1104);
    test(531);
    test(1221);
    test(110);
    }
                    
    public static void test(int id) throws Exception {
    Response rep = new Response();
    call(new Request(id), rep);
    System.out.println("CallPhp.test, id=" + id + " message=" + rep.message);
    }
                    
    public static void call(Request req, Response rep) throwsException {
    ScriptEngineManager engineManager = new ScriptEngineManager();
    ScriptEngine engine = engineManager.getEngineByName("php-invocable");
                
    ByteArrayOutputStream log = new ByteArrayOutputStream();
                
    try {
    engine.put("phpRootDir""data/php");
    engine.put("log", log);
    engine.put("req", req);
    engine.put("rep", rep);
    FileReader reader = new FileReader("data/php/gate.php");
    engine.eval(reader);
    System.out.println("CallPhp.call phpLog=" + log.toString());
    }
    catch(Exception e) {
     System.out.println("CallPhp.call phpLog=" + log.toString());
     throw e;
    }
    }
    }
                
    class Request
    {

    public Request(int id) {
    this.id = id;
    }
    public int id;
    }
                
    class Response {
    public String message;
    }
  • 脚本统一入口 java-bin/data/php/gate.php:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <?php
    define('PHP_ROOT_DIR', java_context()->get('phpRootDir'));
    $log = java_context()->get('log');
    $log->write("\n\tjava give phpRootDir is " . PHP_ROOT_DIR);

    require_once(PHP_ROOT_DIR . '/function.php');

    $log->write(getDoomsday());

    $rep = java_context()->get('rep');
    $rep->message = handle(java_context()->get('req'), $log);
    ?>
  • 具体功能举例 java-bin/data/php/function.php:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <?php
    function getDoomsday() {
    return "\n\tdoomsday is 20121221";  
    }

    function handle($req, $log) {
    $id = $req->id;
    $log->write("\n\tfunction.php handle id=$id");
    if('1104' == $id)
     return 'guess?';
    else if('531' == $id)
     return 'score';
    else if('1221' == $id)
     return 'maybe doomsday';
    else
     return '404 not found';
    }

?>

  • 输出:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    CallPhp.call phpLog=
    java give phpRootDir is data/php
    doomsday is 20121221
    function.php handle id=1104
    CallPhp.test, id=1104 message=guess?
    CallPhp.call phpLog=
    java give phpRootDir is data/php
    doomsday is 20121221
    function.php handle id=531
    CallPhp.test, id=531 message=score
    CallPhp.call phpLog=
    java give phpRootDir is data/php
    doomsday is 20121221
    function.php handle id=1221
    CallPhp.test, id=1221 message=maybe doomsday
    CallPhp.call phpLog=
    java give phpRootDir is data/php
    doomsday is 20121221
    function.php handle id=110
    CallPhp.test, id=110 message=404 not found

注意事项

  • 由于是 Java 调用的 PHP,所以 PHP 里当前工作路径变成了 Java 的。
  • FileReader 加载 *.php 文件之后 ScriptEngine.evel(FileReader) 的耗时大概为 230ms+,StringReader 时为 180ms+,速度都不咋滴,但是这不是我们项目急着考虑的问题,之前的 HTTP 方式也好不到哪去,优化留到以后再说。
  • PHP 的解释器运行路径配置:-Dphp.java.bridge.php_exec=

相关资料

文章目录
  1. 1. 需求背景
  2. 2. PHP/Java Bridge
    1. 2.1. 示例
    2. 2.2. 注意事项
  3. 3. 相关资料