首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 呼叫 Java 類完整實戰 (二):自訂 Java 類編譯、部署與 PHP 整合

     編輯:PHP 相關知識

前言

上一篇建立了 PHP-Java Bridge 環境。本篇實作「編寫自訂 Java 類 → 編譯 → 放入 classpath → PHP 實例化呼叫」完整流程,並解決型別映射、例外處理、效能等實戰議題。

步驟 1:編寫 Java 類


// 檔名: PhpTest.java (類名必須與檔名一致)
package com.example;  // 建議加套件名,避免預設套件問題

public class PhpTest {
    // 公開欄位:PHP 可直接讀寫
    public String foo = "初始值";
    
    // 公開方法:PHP 可呼叫
    /**
     * 接收字串,空字串回傳預設訊息
     */
    public String test(String str) {
        if (str == null || str.isEmpty()) {
            return "Your string was empty.";
        }
        return "Java received: " + str;
    }
    
    /**
     * 回傳欄位值
     */
    public String whatIsFoo() {
        return "foo is " + foo;
    }
    
    // 靜態方法:PHP 可透過類名呼叫
    public static String staticGreet(String name) {
        return "Hello from static Java, " + name + "!";
    }
    
    // main 方法:命令列測試用,PHP 不會呼叫
    public static void main(String[] args) {
        PhpTest p = new PhpTest();
        if (args.length == 0) {
            System.out.println(p.test(""));
        } else {
            for (String arg : args) {
                System.out.println(p.test(arg));
            }
        }
    }
}

步驟 2:編譯與部署

# 1. 進入原始碼目錄
cd /path/to/java/src

# 2. 編譯 (產生 com/example/PhpTest.class)
javac -d /path/to/classes com/example/PhpTest.java

# 3. 確認 class 檔位置
ls -la /path/to/classes/com/example/PhpTest.class

# 4. 設定 classpath (php.ini 或執行時)
# php.ini [java] 區段
java.class.path = "/path/to/classes:/usr/share/php/java/php_java.jar"

# 或運行時動態設定 (需在 new Java() 前)
ini_set('java.class.path', '/path/to/classes:' . ini_get('java.class.path'));

步驟 3:PHP 整合呼叫

<?php
// 1. 載入 Java 擴充 (php.ini 已啟用 extension=java.so)
// 2. 實例化 Java 類 (完整類名含套件)
$javaObj = new Java("com.example.PhpTest");

// 3. 呼叫實例方法
echo "Test result: " . $javaObj->test("Hello World") . "\n";
// 輸出: Java received: Hello World

// 4. 讀寫公開欄位
$javaObj->foo = "新的字串值";
echo "Foo value: " . $javaObj->foo . "\n";

// 5. 呼叫另一實例方法
echo "whatIsFoo: " . $javaObj->whatIsFoo() . "\n";
// 輸出: foo is 新的字串值

// 6. 呼叫靜態方法 (PHP 5.3+ 支援)
echo "Static greet: " . Java("com.example.PhpTest")->staticGreet("PHP") . "\n";
// 或
$class = new Java("com.example.PhpTest");
echo $class->staticGreet("PHP") . "\n";

// 7. 型別轉換關鍵:PHP 弱型別 → Java 強型別
// 整數傳給 String 參數會報錯,必須強制轉字串
$javaObj->foo = (string) 123456;      // 正確
$javaObj->foo = "123456";             // 正確
// $javaObj->foo = 123456;             // 錯誤: Java 端接收 String,無法自動轉換

// 8. 例外處理
try {
    $result = $javaObj->test(null); // Java 端拋出例外會轉為 PHP Exception
} catch (JavaException $e) {
    echo "Java 例外: " . $e->getMessage() . "\n";
} catch (Exception $e) {
    echo "PHP 例外: " . $e->getMessage() . "\n";
}

型別映射對照表

Java 型別 PHP 對應 注意事項
booleanbool自動轉換
byte, short, int, longintPHP int 為 64-bit (64位元系統),long 安全
float, doublefloat精度可能差異
charstring (長度1)
StringstringPHP 傳數字需 (string) 強轉
Object[] / Listarray索引陣列自動轉 Java 陣列/ArrayList
Maparray (關聯)關聯陣列轉 HashMap
nullnull

常見錯誤與排查

  1. java.lang.ClassNotFoundException:classpath 未包含編譯輸出目錄。檢查 php.ini java.class.path、ini_get()、實際檔案存在性。
  2. java.lang.NoClassDefFoundError:依賴類缺失 (如第三方 jar)。需將所有依賴 jar 加入 classpath。
  3. 型別不匹配:PHP 傳 int 給 Java String 參數。永遠在 PHP 端強制轉型:(string)$val、(int)$val、(float)$val。
  4. 編碼亂碼:Java 預設 UTF-8,PHP 內部編碼若非 UTF-8 需 mb_convert_encoding()。
  5. 效能問題:每次 new Java() 會啟動/連接 JVM。單例模式重用實例,或使用 PHP-Java Bridge Servlet 模式 (Tomcat + Java 端常駐)。

效能優化:單例包裝類

<?php
class JavaBridge {
    private static $instances = [];
    
    public static function get($class_name) {
        if (!isset(self::$instances[$class_name])) {
            self::$instances[$class_name] = new Java($class_name);
        }
        return self::$instances[$class_name];
    }
}

// 使用
$test = JavaBridge::get("com.example.PhpTest");
$test->foo = "value";
echo $test->test("input");

現代替代方案:避免 PHP-Java Bridge

PHP-Java Bridge (PECL java) 已多年未更新,相容性差。新專案建議:

  • REST/gRPC 微服務:Java 寫 Spring Boot 服務,PHP 透過 HTTP/gRPC 呼叫,解耦、可獨立擴容、技術棧自由。
  • 命令列呼叫:exec('java -jar app.jar arg1 arg2'),簡單任務適用。
  • 訊息佇列:RabbitMQ/Kafka 非同步處理。
  • JPHP / Quercus:在 JVM 上跑 PHP (反向思維),共享 Java 庫零成本。

總結

PHP 呼叫自訂 Java 類核心流程:寫 Java → javac 編譯 → 放入 classpath → new Java("完整類名") → 強制型別轉換 → 呼叫方法/存取欄位。關鍵坑點在 classpath 設定 與 PHP→Java 強型別轉換。現代架構強烈建議改用微服務/REST/gRPC替代進程內橋接,獲得更好維護性、擴展性與故障隔離。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved