背景: 本人在做毕设时需要实现以下场景,web前端接收数据,传到Jsp后端后,接着需要将前端传递来的数据送到matlab算法函数中,使用matlab进行算法的计算,得到结果后,再次将数据传到JSP后端,最终实现结果数据在前端网页的显示。最初考虑的是将matlab程序直接编译成jar文件,然后导入到Myeclip中,网上也有很多类似的文章,但是感觉有点复杂。然后就发现有人使用matlabcontrol控件,实现java调用matlab软件进行计算,看起来比上一种方法简单些,于是有了今天这篇文章。PS:本人机械专业,编程技术很弱,因毕设论文牵涉到java,jsp,matlab,故硬着头皮学了这些,花费了很长时间,才实现上述功能。我会尽量详细记录,希望这篇文章能帮到你。本人程序应用了hibernate、struts2框架。
1.站内文章:
https://blog.csdn.net/qq_27731689/article/details/81068516
https://blog.csdn.net/qq_28104379/article/details/78887109
2.站外网站:
https://wenku.baidu.com/view/defcdc33eff9aef8951e0605.html
https://stackoverflow.com/questions/32588130/matlabcontrol-in-java#
1.有积分/C币的可以站内下载。
2.像我这样穷学生的话直接去以下网址下载好了。https://code.google.com/archive/p/matlabcontrol/downloads
我的论文用到了NSGAII算法程序,一般用matlab计算时,需要用到的数据直接在程序里声明赋值即可,但是我的数据来自于前端网页,所以需要对编写好的算法进行小小的修改,即将需要用到的数据变量写到算法函数的输入变量中,如下:
function [v_best ,f_best]=Main_NSGA2(d1 ,d2),v_best ,f_best分别为算法计算后的结果,d1,d2为输入变量。修改前的函数形式为
function Main_NSGA2。
在Eclipse中建好项目后,将matlabcontrol文件导入到项目的Web App Libraries中,如下图:
若是java项目,只需要将matlab文件放入到该项目的根目录下即可,放入后效果如下图,(PS:matlabcontrol控件不需要放入该目录,我是放m文件时顺手拖进去了。。):
若是web项目(我举的的例子),需要将matlab函数文件放入到tomcat服务器的bin文件下(例如:我的F:\Tomcat7.0\bin),调用matlab程序时,默认从tomcat\bin文件下调用m函数,理解如下图:
从下图可以看出matlab被java调用时,默认从tomact的bin文件下调用:
(PS:可以看到我的function函数的输入变量有很多,这里举例子时,只是简单用d1,d2两个简单变量示意下,另外,function函数的输入变量是形式参数,在实际应用时,需要在多个m文件之间调用这些变量,即需要将这些变量定义为全局变量,但是形式参数不能直接定义成全局变量。这里,我的方法是,将变量稍微改变形式,比如,m文件中其中一个全局变量为d1,那么它对应的形参写成d11,然后将d1=d11,再将d1作为全局变量。简单说,就是d11作为形式参数接收java传来的值,d1定义为全局变量,接收d11的值,参与计算。怕大家在这出问题,有点啰嗦了。)
jquery代码从网页输入框获取数据,并通过$.post方法将数据传到后端(应用了struts2),部分重要代码如下:
前端:
后端:
package capp.action;
import matlabcontrol.*;
import java.text.DecimalFormat;//用于数据格式化:保留两位小数
import java.util.HashMap;
import java.util.Map;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class ModelTest extends ActionSupport{
private double d1;
public void setD1(double d1) {//普通属性驱动,提供set方法进行接收,,d=Double.parseDouble(d)
this.d1 = d1;
}
private double r_s1;
public void setR_s1(double r_s1) {//普通属性驱动,提供set方法进行接收,,d=Double.parseDouble(d)
this.r_s1 = r_s1;
}
private double xx1;
public void setXx1(double xx1) {
this.xx1 = xx1;
}
private double yy1;
public void setYy1(double yy1) {
this.yy1 = yy1;
}
private double zz1;
public void setZz1(double zz1) {
this.zz1 = zz1;
}
......(省略部分参数的代码)
private double C_T1;
public void setC_T1(double C_T1) {
this.C_T1 = C_T1;
}
public String matlab() throws MatlabConnectionException, MatlabInvocationException{
Map result = new HashMap();//这是声明一个集合result,用来存放matlab计算反馈来的结果v_best和f_best
try{
MatlabProxyFactory factory = new MatlabProxyFactory();
MatlabProxy proxy = factory.getProxy();
Object[] result1 = proxy.returningFeval("Main_NSGA2",2,d1,r_s1,xx1,yy1,zz1,x_Fc1,y_Fc1,n_Fc1,k_Fc1,nl1,nu1);//这里有很多参数,仅保留部分参数供大家理解用。proxy.returningFeva方法是执行m文件。
double[] r=(double[]) result1[0];
System.out.print("v_best:");
for (int i = 0; i < r.length; i++) {
DecimalFormat df = new DecimalFormat("######0.00");//使结果保留两位小数
String v_best = df.format(r[i]);
System.out.print(v_best);
result.put("v_best", v_best);/*将v_best值放入result集合中;下同。*/
}
double[] rr=(double[]) result1[1];
System.out.print("f_best:");
for (int i = 0; i < rr.length; i++) {
DecimalFormat df = new DecimalFormat("######0.00");
String f_best = df.format(rr[i]);
System.out.print(f_best);
result.put("f_best", f_best);
}
//proxy.feval("Main_NSGA2");
//Disconnect the proxy from MATLAB
proxy.disconnect();
} catch (Exception e) {
e.printStackTrace();
//result.put("success",false);
//失败原因
//result.put("msg",e.getMessage());//对应保存数据失败时的提示信息
}
ActionContext.getContext().getValueStack().push(result);/*这里是将result集合传递到前台,即为data,即$。post的回调函数function(data)中的data,然后通过data.f_best得到f_best的值。具体操作不是太懂。。*/
return SUCCESS;
}
}