做Python开发时遇到需求实现,必须调用Java方法,可以这么做

之前在公司做框架及全自动化测试工具开发时,需要测试结束后,回传结果及日志到测试平台与云存储平台。但是云存储平台没有相关Python的服务接口开放,而且构造参数时及其复杂,经沟通之前其他类似需求业务是通过Java封装的一个服务方法进行调用上传日志。所以需要后端Java开发打包个jar包,我们只需传指定的几个参数即可,然后使用Python进行方法调用,根据返回结果判断是否上传成功就行。

或者我们在做安卓逆向过程中也会遇到签名算法,但是Python或其他语言又不好还原,只能通过原有Java方法进行调用。接下来以某安卓练习app为例,演示如何进行Java打包及Python调用。

1、IDEA打包Jar包

默认Java工程是正常的,直接说明如何将项目或某个包名打包为Jar

点击菜单栏File,选择Project Structure进入

点击Artifacts,选择“+”号添加JAR,点击“From module with dependencies...”

填写选择需要打包的模块及包信息,最后填写jar输出路径

选择菜单栏Build,点击“Build Artifacts...”,生成Jar文件

Build进度,生成成功

终端模拟调用,检查是否可用


2、Python调用Java方法

前提条件

需要提前安装好Java环境,配置JAVA环境变量 或者 准备好Java环境资源文件,直接使用绝对路径

安装JPype1

pip install jpype1

温馨提示:如果无法通过pip进行安装,需要到官方pypi库(
https://pypi.org/project/JPype1/#files)下载whl包文件,通过pip install whl后缀文件进行安装

调用方法

  • 启动JVM

jpype.getDefaultJVMPath()实例化Java虚拟机,这个方法可能会遇到报错,原因就是Java环境没有配置好;如果配置好Java环境及环境变量后还出现报错,采用直接添加路径的方式;在接下来调用的方法中直接写提示缺少的文件路径,如:(我的是macOS,Windows问题少些)

"/jdk8.0.362-macosx_aarch64/zulu-8.jdk/Contents/Home/jre/lib/jli/libjli.dylib"

  • 加载jar文件
jpype.startJVM(jpype.getDefaultJVMPath(), "-ea", "-Djava.class.path=./master.jar")
# 或
jpype.startJVM(/jdk8.0.362-macosx_aarch64/zulu-8.jdk/Contents/Home/jre/lib/jli/libjli.dylib, "-ea", "-Djava.class.path=./master.jar")
  • 调用函数Class包名指定并实例化类方法
jpype.JPackage("com.yuanrenxue.match2022.fragment.challenge").ChallengeTwoFragment()
  • 调用方法并关闭Java虚拟机
ChallengeTwoFragment.sign(data)
jpype.shutdownJVM()

完整调用代码:

import jpype
import requests
import time


def main():
    # jpype.startJVM(jpype.getDefaultJVMPath(), "-ea", "-Djava.class.path=./master.jar")
    jpype.startJVM("/jdk8.0.362-macosx_aarch64/zulu-8.jdk/Contents/Home/jre/lib/jli/libjli.dylib", "-ea", "-Djava.class.path=./master.jar")
    jclass = jpype.JPackage("com.yuanrenxue.match2022.fragment.challenge").ChallengeTwoFragment
    ChallengeTwoFragment = jclass(False)
    url = 'api接口地址'
    for page in range(1, 6):
        data = {
            "page": page,
            "ts": int(time.time())
        }
        data["sign"] = str(ChallengeTwoFragment.sign(f'{data["page"]}:{data["ts"]}'.encode()))
        print(data)
        response = requests.post(url, data=data).json()
        print(response)
    jpype.shutdownJVM()

if __name__ == '__main__':
    main()

连续调用sign方法,请求5次,均不相同,说明已经成功


结语

学会欣赏别人,就是尊重自己;学会呵护别人,就是疼爱自己。

相关文章

我做java面试官时,常问的问题

大家好,我是贠学文,点击右上方“关注”,每天为您分享java程序员需要掌握的知识点干货。前不久,我写了一篇《如何成为一个优秀面试官》的文章,具体可点击如下链接阅读:如何成为一个优秀的面试官那么今天,在...

java程序员面试时经常被问到的10个问题

java程序员,尤其是做web开发的,面试时,面试官最喜欢问到以下10个问题,掌握面试的动态和技巧,有利于提高我们面试的成功率,了解以下10个问题,有利于java程序员的面试。1、简单描述一下Log4...

从“线程小白”到“池主”:Java线程与线程池的修炼秘籍

线程:并发世界的基础在 Java 的编程宇宙中,线程是一个不可或缺的重要概念。它就像是并发编程的 “超级英雄”,赋予程序同时执行多个任务的超能力,极大地提升了程序的效率和响应性。想象一下,你去一家餐厅...

记一次CPU使用率低负载高的排查过程

一、背景历史原因,当前有一个服务专门用于处理mq消息,mq使用的阿里云rocketmq,sdk版本1.2.6(2016年)。随着业务的发展,该应用上的consumer越来越多,接近200+,导致该应用...

面试官:核心线程数为0时,线程池如何执行?

线程池是 Java 中用于提升程序执行效率的主要手段,也是并发编程中的核心实现技术,并且它也被广泛的应用在日常项目的开发之中。那问题来了,如果把线程池中的核心线程数设置为 0 时,线程池是如何执行的?...