• Java调用Javascript、Python算法总结


    最近项目中经常需要将Javascript或者Python中的算法发布为服务,而发布Tomcat服务则需要在Java中调用这些算法,因此就不免要进行跨语言调用,即在Java程序中调用这些算法。

    不管是调用Javascript文件还是python脚本,都需要将原来的算法文件进行适当的更改,以便可以在Java中传入参数,并且得到算法运算结果。

    一、Java调用Javascript

    需要注意的是Javascript是弱类型语言,定义变量只需要一个var就可以搞定,但是在Java中却要注意变量类型,不同的输入参数会有不同的类型。

    调用js文件时,需要对其进行调整,设置好需要调用的function和相关参数,使用的js文件代码如下(其中有些核心算法不能展示):

     1 function get3DCode(Latitude,Longitude,Height,level){
     2     var latcode=[];var lngcode=[];
     3     latcode=GeoSOTCode1D(Latitude,level);
     4     lngcode=GeoSOTCode1D(Longitude,level);
     5     var heicode=[];var geosot3Dcode=[];
     6     heicode=Altcode(Height,level);
     7     geosot3Dcode=GeoSOT3D(latcode,lngcode, heicode,level);//三维网格编码
     8     var d3code=[];
     9     d3code=getQuantcodeString(geosot3Dcode);
    10     return d3code;
    11 }

    在Java中使用对应的接口就可以调用,需要设置js文件路径和输入参数,调用的代码如下;

     1 package whu.get.three.beidou;
     2 
     3 import java.io.FileReader; 
     4 import javax.script.Invocable;
     5 import javax.script.ScriptEngine;
     6 import javax.script.ScriptEngineManager;
     7 
     8 /**  * Java调用并执行js文件,传递参数,并获得返回值    */ 
     9 public class ThreeD_GetBeidouCode {
    10     //获取经纬度及高度,返回三维码
    11     public static String main(String Latitude,String Longitude,String Height,int CodeSize) throws Exception {      
    12         //获取经纬度及高度,保存为double类型
    13         Double latitude = Double.parseDouble(Latitude);
    14         Double longitude = Double.parseDouble(Longitude);
    15         Double height = Double.parseDouble(Height);
    16         int level = CodeSize;
    17 
    18         //调用js文件
    19         ScriptEngineManager manager = new ScriptEngineManager();   
    20         ScriptEngine engine = manager.getEngineByName("javascript");     
    21         String jsFileName = System.getProperty("catalina.home") + "/webapps/3DBeiDouCode/WEB-INF/classes/3Dcode.js";   // 读取js文件
    22         FileReader reader = new FileReader(jsFileName);   // 执行指定脚本   
    23         engine.eval(reader); 
    24         String c = "";
    25         if(engine instanceof Invocable) {    
    26             Invocable invoke = (Invocable)engine;    // 调用merge方法,并传入两个参数    
    27             c = String.valueOf(invoke.invokeFunction("get3DCode", latitude, longitude, height, level));    
    28             }
    29         reader.close();  
    30         return c; //返回三维码
    31     }
    32 }

    这里的ThreeD_GetBeidouCode类只是一个普通的类,需要在其他可运行的主函数中调用这个类的main方法,传入运行参数就可以得到结果。

    二、Java调用Python

    Java调用python脚本有好几种方法,最简单的是通过Jython来直接运行python代码,但是这种方法不支持python中引用的第三方库,因此我使用了Runtime来调用的方法,这也相当于是在控制台执行脚本。

    需要注意的是,Java调用python时,不能通过return语句来获取返回值,而只能通过print将结果写入到标准输出流中,然后在Java中通过标准输入流来读取到返回结果。

    如果对python环境有要求,比如在特定的环境中安装了需要引用的第三方库,则还要在Java工程中添加运行环境,在eclipse中点击Run->Run Configurations->environment,添加Path,值设置为python安装的路径。

    在python程序中做适当修改:添加引用 import sys,将调用的函数参数设定为sys.argv[1],sys.argv[2]...注意必须是从1开始计数,将需要返回的结果用print函数打印。

    本例中python代码如下:

     1 # -*- coding:utf-8 -*-
     2 import BaseFunction
     3 import numpy as np
     4 import itertools
     5 import math
     6 import sys
     7 
     8 #计算中心要素
     9 def cal_central_feature(path,x,y):
    10     sf = BaseFunction.open_shpfile(path)
    11     x_records = BaseFunction.get_attr_records(sf,x)
    12     y_records = BaseFunction.get_attr_records(sf,y)
    13 
    14     dis = []
    15     for x0,y0 in zip(x_records,y_records):
    16         distance = 0
    17 
    18         for x1,y1 in zip(x_records,y_records):
    19             distance = distance + get_distance(x0,y0,x1,y1)
    20 
    21         dis.append(distance)
    22 
    23     i = dis.index(np.min(dis))
    24 
    25     result = [x_records[i],y_records[i]]
    26 
    27     return result
    28 
    29 #计算两点之间的距离
    30 def get_distance(x0,y0,x1,y1):
    31     xd = x1 - x0
    32     yd = y1 - y0
    33     distance = math.sqrt(xd**2+yd**2)
    34     return distance
    35 
    36 if __name__ == '__main__':
    37     result = cal_central_feature(sys.argv[1],sys.argv[2],sys.argv[3])
    38     print(result[0])
    39     print(result[1])

    Java中调用的代码如下:

     1 package whu.get.three.beidou;
     2 
     3 import java.io.BufferedReader;
     4 import java.io.InputStreamReader;
     5 
     6 /**  * Java调用并执行js文件,传递参数,并活动返回值    */ 
     7 public class CalCentralFeatureClass {
     8     //输入shp路径,获取坐标
     9     public static String main(String filepath) {
    10         String pyPath = System.getProperty("catalina.home") + "/webapps/CalCentralFeature/WEB-INF/classes/CalCentralFeature.py"; //python文件路径
    11         String[] args = new String[] { "python", pyPath, filepath, "x","y"};
    12         String c = "";  //记录返回值
    13         try {    
    14             Process proc = Runtime.getRuntime().exec(args);  //执行py文件
    15             BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream())); 
    16             String line = null;
    17             while ((line = in.readLine()) != null) {
    18                 c = c+line+' ';
    19             }
    20             in.close();
    21             proc.waitFor();
    22         } catch (Exception e) {
    23             e.printStackTrace();
    24         }
    25         return c; //返回结果
    26     }
    27 }

    得到的运算结果中,每一个python中print的结果,对应一个in.readLine(),可以按照需要获取自己想要的结果。

    如果需要将调用python的程序用tomcat发布为服务,也需要配置tomcat的运行环境,同样是添加一个Path,赋值为python安装路径。

  • 相关阅读:
    前端资源
    WCF常见异常-The maximum string content length quota (8192) has been exceeded while reading XML data
    Asp.Net MVC路由调试工具-RouteDebugger
    Java中String 的equals 和==详解
    记一次高级java工程师职位的面试
    java中Class对象详解和类名.class, class.forName(), getClass()区别
    2014读书计划
    Javascript quiz
    CSS3 Flexbox布局那些事
    前端开发中的图片优化
  • 原文地址:https://www.cnblogs.com/MatthewHome/p/10783002.html
Copyright © 2020-2023  润新知