python_jpype1 调用java代码

论坛 期权论坛 编程之家     
选择匿名的用户   2021-6-2 16:40   1607   0

python 调用 java代码有多种方式,暂且说一下使用jpype类库进行python对java代码的使用

一. 环境配置

S1:先查看当前电脑python的版本,我的是python 64位

S2: 安装 Jpype1 类库

我本地pip install jpype1 的时候报错,所以本次通过下载 jpype1的离线安装包进行安装

jpype1下载地址:https://www.lfd.uci.edu/~gohlke/pythonlibs/#jpype

下载成功之后pip进行安装:pip install JPype11.0.2cp37cp37mwin32-amd64.whl

备注:1.选择与自己python相匹配的进行下载

(比如:我的python是37就选择cp37,命名中带有amd64是适应python64位的,没有amd64的是适应python32位的,所以下载:JPype11.0.2cp37cp37mwin32-amd64.whl )

2.如果安装失败,请先安装wheel,才能安装whl离心安装包:pip install wheel

S3: java的jre虚拟环境

python运行java代码,需要启用java的jre虚拟环境,这个jre虚拟环境依赖于 jvm.dll。所以我们需要拿到jvm.dll的路径用于后续的python代码。

第一种情况:如果本地安装了jdk,并且版本也是64位,也设置了java_home 的环境变量,这一步可以直接跳过。

第二种情况:下载 jre,找到相关的jvm.dll 路径。

jre下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jre8-downloads-2133155.html

备注:安装jre 要与python版本位数保持一致

S4: 准备java的 jar包:编写java项目,发版生成 jar包。比如:pythonCall.jar

二. 代码实现

def demo():
'''
python 调用 java代码的demo
'''
# 获取环境变量的jvm.dll 路径,
# 从下载的jre中获取jvm.dll:jvmPath = C:\a_Python\AAA\calljavaproject\jre\XX\jvm.dll
jvmPath = jpype.getDefaultJVMPath()
# 启动java的jvm虚拟环境
jpype.startJVM(jvmPath)
# 模拟java的代码,打印 字符串
jpype.java.lang.System.out.println("hello world!")
# 关闭java虚拟环境
jpype.shutdownJVM()

因为我代码多出的case用到java的加密,所以多次调用的时候报错:JVM is already started 或者 JVM cannot be restarted,所以修改代码如下:

def start_jvm(self, sysname=""):
try:

# 如果 jvm环境已经启动,则直接返回成功;如没有启动,则进入else,开启java的虚拟环境
if jpype.isJVMStarted():
return True
else:
# 启动java的jvm
# S1: 加载 java的jar包(java程序的打包)
jarpath = os.path.join(JAVA_JAR_PATH, "pythonCall.jar")
# S2: 开启 jvm 虚拟环境
jpype.startJVM(self.jvmpath, "-Djava.class.path=" + jarpath)
return True

except Exception as e:
log.error(sysname + "系统启动java的jvm虚拟环境出现错误,错误原因:" + str(e))
return False

具体代码如下:

import os
import jpype

from common.util.logHelper import log



class CallJava():
    def __init__(self):
        # 获取 jvm.dll 路径:使用环境变量
        self.jvmpath = jpype.getDefaultJVMPath()

    def start_jvm(self, sysname=""):
        try:
            # 如果已经启动jvm的虚拟环境则跳过;否则进入else,启动java的虚拟环境
            if jpype.isJVMStarted():
                return True
            else:
                # 启动java的jvm
                # S1: 加载 java的jar包(java程序的打包)
                jarpath = os.path.join(JAVA_JAR_PATH, "pythonCall.jar")
                # S2: 开启 jvm 虚拟环境
                jpype.startJVM(self.jvmpath, "-Djava.class.path=" + jarpath)
                return True

        except Exception as e:
            log.error(sysname + "系统启动java的jvm虚拟环境出现错误,错误原因:" + str(e))
            return False

    def java_encrypt(self, sysname, body, keys):
        """
        加密方法: des(key).encrypt("system=sysname(系统名),time=body(当前时间)")

        注意:调用java方法,由于我写的是静态方法,直接使用类名就可以调用方法;
        如果不是静态,需要先初始化类,在调用类方法。
        sysname: "系统名"
        body:"待加密内容"
        keys:"密钥"
        """
        response = ""
        try:
            if self.start_jvm(sysname):
                # S3: 加载 java 内相关的类文件(参数是java内的长类名)
                javaclass = jpype.JClass("com.pythoncalljava.JavaClass")

                # 加密方法:javaClass.encrypt("系统名", "明文", "密钥")
                response = str(javaclass.encrypt(sysname, body, keys))

        except Exception as e:
            log.error(sysname + "系统调用java加密方法出错,错误原因:" + str(e))

        return response

    def java_encrypt_accesssecret(self, sysname, body, accesssecret, key):
        """
        加密方法: 加密后的内容 = des(key).encrypt(system=sysname,time=body,accessSecret=accessSecret)
        sysname: "系统名"
        body:"待加密内容"
        keys:"密钥"
        accesssecret: "访问密码"
        """
        response = ""
        try:
            if self.start_jvm(sysname):
                javaclass = jpype.JClass("com.pythoncalljava.SignJavaClass")
                response = str(javaclass.encrypt(sysname, body, accesssecret, key))
        except Exception as e:
            log.error(sysname + "系统调用java加密方法出错,错误原因:" + str(e))

        return response

    def java_decrypt(self, sysname, keys, encrypt_body):
        """
        解密: des(秘钥).decrypt(encrypt_body(加密的报文))
        keys:"密钥"
        encrypt_body:"加密内容"
        """
        response = ""
        try:
            if self.start_jvm(sysname):
                javaclass = jpype.JClass("com.pythoncalljava.JavaClass")
                #  解密方法:javaClass.decrypt("密钥","加密内容")
                response = javaclass.decrypt(keys, encrypt_body)
        except Exception as e:
            log.error(sysname + "系统调用java解密方法出错,错误原因:" + str(e))

        return response

    def java_decrypt_accesssecret(self, sysname, keys, encrypt_body):
        """
        解密: des(秘钥).decrypt(encrypt_body(加密的报文))
        keys:"密钥"
        encrypt_body:"加密内容"
        """
        response = ""
        try:
            if self.start_jvm(sysname):
                javaclass = jpype.JClass("com.pythoncalljava.SignJavaClass")
                #  解密方法:javaClass.decrypt("密钥","加密内容")
                response = javaclass.decrypt(keys, encrypt_body)
        except Exception as e:
            log.error(sysname + "系统调用java解密方法出错,错误原因:" + str(e))

        return response

    def shutdown_java_jvm(self):
        """
        关闭java虚拟环境
        """
        try:
            if self.start_jvm():
                jpype.shutdownJVM()
        except Exception as e:
            log.error("关闭java的jvm虚拟环境出错,错误原因:" + str(e))
            return False

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP