Python调用java代码

部署运行你感兴趣的模型镜像

毫无疑问用的是Jpype,因为百度一搜都是它。

github:https://github.com/jpype-project/jpype
官方文档:https://jpype.readthedocs.io/en/latest/

安装:pip install JPype1

被调用的Java代码

RSAUtils.java

package com.commonsdk.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Base64;
import java.math.BigInteger;
import java.util.UUID;


public class RSAUtils {
    private int keySize;

    private String publicKey = "919b6b41f2814f25b5e5fb7c64b03d67602dc07001e5d42aff525c743fdf8434a8b751a7849d5dafb3c3cda4309d739bbb86702214c110a4a431df6f3b8374fd";
    private String temp = "1f5cec6336a772cadf5e887eb1c9fea2675393c0986796f7628a72157b02643a9968518ee54f8171fcb074aa4bd75becc2284028c59c3a8a900d976760823105017beae3a3a1a31be16a18c0892fc1c9e05657ff16ad9c9e7888a6ce9a6fadde73ba4da0ec87a84267ed518da60978dbab3b97641c0f80f3385bf38873d35565";


    public RSAUtils(int i) {
        this.keySize = i;
    }

    public BigInteger[] genKeys() throws Throwable {
        SecureRandom secureRandom = new SecureRandom();
        return genKeys(BigInteger.probablePrime((this.keySize / 2) - 1, secureRandom), BigInteger.probablePrime((this.keySize / 2) - 1, secureRandom), BigInteger.probablePrime(this.keySize / 2, secureRandom));
    }

    public String getKey(String valueOf) {
        String uuid = UUID.randomUUID().toString();
        String substring = valueOf.substring(valueOf.length() - 6, valueOf.length());
        String substring2 = uuid.substring(0, 10);
        return substring + substring2;
    }


    public BigInteger[] genKeys(BigInteger bigInteger, BigInteger bigInteger2, BigInteger bigInteger3) throws Throwable {
        if (bigInteger3.compareTo(BigInteger.ONE) > 0) {
            BigInteger[] bigIntegerArr = new BigInteger[3];
            BigInteger multiply = bigInteger.multiply(bigInteger2);
            BigInteger add = multiply.subtract(bigInteger).subtract(bigInteger2).add(BigInteger.ONE);
            if (bigInteger3.compareTo(add) >= 0) {
                throw new Throwable("e must be smaller than (p-1)*(q-1)");
            } else if (add.gcd(bigInteger3).compareTo(BigInteger.ONE) == 0) {
                BigInteger modInverse = bigInteger3.modInverse(add);
                bigIntegerArr[0] = bigInteger3;
                bigIntegerArr[1] = modInverse;
                bigIntegerArr[2] = multiply;
                return bigIntegerArr;
            } else {
                throw new Throwable("e must be coprime with (p-1)*(q-1)");
            }
        } else {
            throw new Throwable("e must be larger than 1");
        }
    }

    public String encode(String str) throws Throwable {
        DataOutputStream dataOutputStream;
		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        dataOutputStream = new DataOutputStream(byteArrayOutputStream);
        byte[] bArr = str.getBytes();
        BigInteger bigInteger = new BigInteger(this.publicKey, 16);
        BigInteger bigInteger2 = new BigInteger(this.temp, 16);
        try {
            try {
                int i = this.keySize / 8;
                int i2 = i - 11;
                int i3 = 0;
                while (bArr.length > i3) {
                    int min = Math.min(bArr.length - i3, i2);
                    byte[] encodeBlock = encodeBlock(bArr, i3, min, bigInteger, bigInteger2, i);
                    dataOutputStream.writeInt(encodeBlock.length);
                    dataOutputStream.write(encodeBlock);
                    i3 += min;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            dataOutputStream.close();
            byte[] result = byteArrayOutputStream.toByteArray();
            return Base64.getEncoder().encodeToString(result);
        } catch (Throwable th) {
            dataOutputStream.close();
            throw th;
        }
    }

    public byte[] encodeBlock(byte[] bArr, int i, int i2, BigInteger bigInteger, BigInteger bigInteger2, int i3) throws Throwable {
        try {
            if (!(bArr.length == i2 && i == 0)) {
                byte[] bArr2 = new byte[i2];
                System.arraycopy(bArr, i, bArr2, 0, i2);
                bArr = bArr2;
            }
            BigInteger bigInteger3 = new BigInteger(paddingBlock(bArr, i3));
            if (bigInteger3.compareTo(bigInteger2) <= 0) {
                return bigInteger3.modPow(bigInteger, bigInteger2).toByteArray();
            }
            throw new Throwable("the message must be smaller than the modulue");
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    private byte[] paddingBlock(byte[] bArr, int i) throws Throwable {
        if (bArr.length <= i - 1) {
            try {
                byte[] bArr2 = new byte[i];
                bArr2[0] = 1;
                int length = bArr.length;
                bArr2[1] = (byte) (length >> 24);
                bArr2[2] = (byte) (length >> 16);
                bArr2[3] = (byte) (length >> 8);
                bArr2[4] = (byte) length;
                System.arraycopy(bArr, 0, bArr2, i - length, length);
                return bArr2;
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        } else {
            throw new Throwable("Message too large");
        }
    }

    public byte[] decode(byte[] bArr) throws Throwable {
        DataInputStream dataInputStream = new DataInputStream(new ByteArrayInputStream(bArr));
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        BigInteger bigInteger = new BigInteger(this.publicKey, 16);
        BigInteger bigInteger2 = new BigInteger(this.temp, 16);
        while (dataInputStream.available() > 0) {
            byte[] bArr2 = new byte[dataInputStream.readInt()];
            dataInputStream.readFully(bArr2);
            byteArrayOutputStream.write(decodeBlock(bArr2, bigInteger, bigInteger2));
        }
        dataInputStream.close();
        byteArrayOutputStream.close();
        return byteArrayOutputStream.toByteArray();
    }

    public byte[] decodeBlock(byte[] bArr, BigInteger bigInteger, BigInteger bigInteger2) throws Throwable {
        return recoveryPaddingBlock(new BigInteger(bArr).modPow(bigInteger, bigInteger2).toByteArray());
    }

    private byte[] recoveryPaddingBlock(byte[] bArr) throws Throwable {
        if (bArr[0] == 1) {
            int i = ((bArr[1] & 255) << 24) + ((bArr[2] & 255) << 16) + ((bArr[3] & 255) << 8) + (bArr[4] & 255);
            byte[] bArr2 = new byte[i];
            System.arraycopy(bArr, bArr.length - i, bArr2, 0, i);
            return bArr2;
        }
        throw new Throwable("Not RSA Block");
    }
}

我的需求就一个文件,也没有什么依赖。所以调用应该没什么问题。

打包Jar包

目录结构: com\commonsdk\utils\RSAUtils.java

先生成class文件(需要运行在java代码同目录下)
javac -encoding utf-8 RSAUtils.java
删除java代码文件,保留class文件

然后返回到com同级目录运行,就能生成RSAUtils.jar文件
jar -cvf RSAUtils.jar com

调用jar包
import jpype
import time

def get_rsa_sign():
    # 获取系统环境变量中的java jvm.dll的路径
    jvmPath = jpype.getDefaultJVMPath()
    # 加载jar包
    jpype.startJVM(jvmPath, "-ea", "-Djava.class.path=RSAUtils1.jar")
    # 指定main class
    JDClass = jpype.JClass("com.commonsdk.utils.RSAUtils")
    # 创建类实例对象
    jd = JDClass(1024)
    key = str(jd.getKey(str(int(time.time()))))
    print(key)
    # 引用jar包类中的方法 rsa_sign
    signature = str(jd.encode(key))
    # 关闭JVM
    jpype.shutdownJVM()
    return signature


if __name__ == '__main__':
    print("rsa 签名结果:",get_rsa_sign())

因为java代码没什么依赖,所以也没遇到什么坑,试了试就过了

多进程调用jar包

单进程没啥问题,但是一用多进程调用就一直报错。懒得找解决方法了,突发奇想,既然只能单进程调用,那么我单独开个进程只调jar包的方法是不是可以,其他进程只需要和这个进程通信。试了试用fastapi开个http接口确实可行

from fastapi import FastAPI, Request
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse
from pydantic import BaseModel, constr
from pyjava import get_rsa_sign

app = FastAPI()


class JavaItem(BaseModel):
    t: constr()

@app.exception_handler(RequestValidationError)
async def request_validation_exception_handler(request: Request, exc: RequestValidationError):
    print(f"参数不对{request.method} {request.url}")
    return JSONResponse({"code": "400", "message": "参数不正确!请将图片用base64放在image字段"})


@app.post("/pyjava")
async def read_item(user_info: JavaItem):
    t = user_info.t
    if not t:
        return {"code": "400", "message": "t格式错误!"}
    key, signature = get_rsa_sign(t)
    print(f"key: {key}")
    return {"code":"200", "key":key, "signature":signature}


if __name__ == "__main__":
    import uvicorn

    uvicorn.run(app='api:app', host="0.0.0.0", port=8196)

pyjava这个文件就是调用jar的,但是不能像上面一样调用,需要改一下。让jvm只被初始化一次

import jpype
import time

jvmPath = jpype.getDefaultJVMPath()
jpype.startJVM(jvmPath, "-ea", "-Djava.class.path=RSAUtils1.jar")
JDClass = jpype.JClass("com.commonsdk.utils.RSAUtils")
jd = JDClass(1024)

def get_rsa_sign(t):
    """
    调用java jar包,对入参进行rsa签名
    :param sign_raw:待签名字符串
    :return:signature:签名后的加密字符串
    """
    key = str(jd.getKey(t))
    # 引用jar包类中的方法 rsa_sign
    signature = str(jd.encode(key))
    # 关闭JVM
    #jpype.shutdownJVM()
    return key, signature

这样我开多进程请求这个接口即可获取到了,还是挺方便的

aardio调用java

aardio应该是需要32位的java,因为即使设置了环境变量,依然会自动下载java。但是代码设置的java下载地址已经失效了,抓个包看到地址是:https://mirrors.tuna.tsinghua.edu.cn/AdoptOpenJDK/8/jre/x32/windows/OpenJDK8U-jre_x86-32_windows_hotspot_8u312b07.zip,

去掉后面的文件名访问链接,发现只是版本变化了而已,搜一下aardio的源码,改一下地址和路径即可

调用jar包的代码大致和Python的一样,都是使用的jvm虚拟机

import console; 
import java; 

//创建 Java 虚拟机
var jvm = java();
//查找jar路径,可以放在代码同级(打包后则是exe同级) java\目录下,就不用添加了
jvm.addClassLoaderUrl("D:\jar"); 
//导入 Java 类
RSAUtils = jvm.import( "com.commonsdk.utils.RSAUtils");
var rsa = RSAUtils(1024);
var String = jvm.import( "java.lang.String"); 
var t = tostring(tonumber(time()));
var key = rsa.getKey(t);
console.log("key: ", key);
console.log("signature: ", rsa.encode(key))
console.pause();

您可能感兴趣的与本文相关的镜像

Python3.10

Python3.10

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值