在 Java 客户端中使用协议缓冲区进行异步 RESTful 请求
此示例展示如何使用 Java® 客户端 API、MATLAB® Production Server™ 用于 MATLAB 函数执行的 RESTful API 和协议缓冲区 (protobuf) 发出异步 RESTful 请求。该示例提供并解释了一个示例 Java 客户端 AsyncExample.java,用于评估部署在服务器上的 MATLAB 函数。
要在向服务器发出请求时使用 protobuf,请在客户端代码中将 HTTP Content-Type 标头设置为 application/x-google-protobuf。Java 客户端库提供帮助类,以根据 proto 格式内部创建 protobuf 消息并返回相应的字节数组。在 HTTP 请求正文中使用此字节数组。Java 客户端库提供了反序列化 protobuf 响应的方法和类。
要使用 Java 客户端库,必须在 mps_client.jar 中包含 CLASSPATH。
下表显示了在哪里可以找到示例的 mps_client.jar 文件、Javadoc 和示例代码。
mps_client.jar 的位置 |
|
| Javadoc 的位置 |
|
| 示例文件的代码位置 |
|
| |
该示例使用 java.net 包发出 HTTP 请求来评估在 http://localhost:9910 上运行的 MATLAB Production Server 实例上部署的 MATLAB 函数。
在服务器上部署您的 MATLAB 函数
编写一个使用 magic (MATLAB) 函数创建幻方的 MATLAB 函数 mymagic,然后将其部署在服务器上。
有关如何部署的信息,请参阅针对 MATLAB Production Server 创建可部署存档。
function m = mymagic(in) m = magic(in); end
函数 mymagic 接受单个 int32 输入并以二维 double 数组的形式返回一个幻方。
向服务器发出异步请求
构建请求 URL。
在 Java 客户端中,使用POST Asynchronous Request向服务器发出初始请求。请求 URL 包括服务器实例的地址、部署的存档的名称和要评估的 MATLAB 函数的名称。将 HTTP 请求的
mode设置为async,将client设置为查询参数中的用户定义的标识符值。String clientId = "123"; String mpsBaseUrl = "http://localhost:9910"; URL url; url = new URL(mpsBaseUrl + "/mymagic/mymagic?mode=async&client="+clientId);设置请求标头。
将 HTTP
Content-Type标头设置为application/x-google-protobuf,因为 API 返回协议缓冲区消息的字节数组。final static protected String CONTENT_TYPE = "application/x-google-protobuf"; HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); urlConnection.setDoOutput(true); urlConnection.setRequestProperty("Content-Type", CONTENT_TYPE);创建包含协议缓冲区消息的 HTTP 请求正文。
使用
newInstance(arg1, arg2, arg3)类中定义的MATLABParams方法来构建协议缓冲区消息。由于mymagic函数返回单个二维数组,因此将arg1设置为1,将arg2设置为double[][].class。为arg3指定一个整数值,它是mymagic函数的输入。MATLABParams mlMakeBody = MATLABParams.newInstance(1, double[][].class, 2);
将请求发送到服务器。
将
MATLABParamsmlMakeBody对象写入 HTTP 请求的输出流。OutputStream output = urlConnection.getOutputStream(); output.write(mlMakeBody.getRequestBody()); output.flush();接收并解释服务器响应。
成功执行 HTTP 请求后,服务器将使用协议缓冲区消息进行响应。使用
MATLABRequestHandle类中的方法解析协议缓冲区消息,以获取请求的状态、请求的 URL 以及请求的最后修改序列值等详细信息。MATLABRequestHandle mlInitialResponse = MATLABRequestHandle.newInstance(urlConnection.getInputStream()); System.out.println("First Request has been Sent. Initial response is below"); System.out.println("State: "+ mlInitialResponse.getState() + " " + "Request URL: " +mlInitialResponse.getRequestURL() + " Last modified sequence: " + mlInitialResponse.getLastModifiedSeq());
获取请求的状态信息
发出请求以获取请求状态信息。
使用GET State Information RESTful API 获取请求的状态。在请求 URL 中,将查询参数
format设置为protobuf,以便服务器以协议缓冲区格式返回输出。url = new URL(mpsBaseUrl + mlInitialResponse.getRequestURL() + "/info?" + "format=protobuf"); urlConnection = (HttpURLConnection) url.openConnection(); urlConnection.setRequestProperty("Content-Type", CONTENT_TYPE); urlConnection.setRequestMethod("GET"); urlConnection.connect();解析响应。
使用
MATLABRequest类中定义的方法解析响应以获取请求的状态和服务器上的当前lastModifiedSeq值。MATLABRequest requestInfoTmp = MATLABRequest.newInstance(urlConnection.getInputStream()); System.out.println("State: " + requestInfoTmp.getState() + " Last modified sequence: " + requestInfoTmp.getLastModifiedSeq());
在异步模式下,客户端能够向服务器发送多个请求。要获取每个 POST 请求的状态信息,必须向 GET State Information RESTful API 发出相应的请求。
查看特定客户端拥有的请求集合
使用 GET Collection of Requests RESTful API 查看由 clientId 代表的特定客户端发送的多个请求的信息。在请求 URL 中,将查询参数 format 设置为 protobuf,以便服务器以协议缓冲区格式返回输出。使用 MATLABRequests 类 newInstance 方法解析成功请求的响应主体。MATLABRequests 类有一个 getMATLABRequests 方法,它返回 Map 的 requestURL 和 MATLABRequest 对象。
url = new URL(mpsBaseUrl + mlInitialResponse.getInstanceId() + "requests" + "?since="
+ mlInitialResponse.getLastModifiedSeq() + "&format=protobuf&" + "clients=" + clientId);
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestProperty("Content-Type", CONTENT_TYPE);
urlConnection.setRequestMethod("GET");
urlConnection.connect();
MATLABRequests updates = MATLABRequests.newInstance(urlConnection.getInputStream());
Map<String, MATLABRequest> urlUpdates = updates.getMATLABRequests();
System.out.println("State of the Requests with the client: " + clientId);
for (String requestURL : urlUpdates.keySet()) {
System.out.println(requestURL + ":" + urlUpdates.get(requestURL).getState());
}检索请求的结果
发出请求以获取响应。
当请求状态变为
READY或ERROR后,使用GET Result of Request RESTful API 获取请求结果。在请求 URL 中,将查询参数format设置为protobuf,以便服务器以协议缓冲区格式返回输出。url = new URL(mpsBaseUrl + mlInitialResponse.getRequestURL() + "/result?" + "format=protobuf"); urlConnection = (HttpURLConnection) url.openConnection(); urlConnection.setRequestProperty("Content-Type", CONTENT_TYPE); urlConnection.setRequestMethod("GET"); urlConnection.connect();解析响应。
如果请求状态为
READY,则使用MATLABResult类中定义的方法来解析响应。要创建MATLABResult对象,请将MATLABParamsmlMakeBody对象和 Request 请求的 GET 结果的响应主体传递给newInstance方法。如果部署的 MATLAB 函数执行时出现错误,则对
getResult方法的调用将抛出包含来自 MATLAB 的错误消息的MATLABException。如果请求状态为
ERROR,则使用HTTPErrorInfo类而不是MATLABResult类来解析响应。使用HTTPErrorInfo类中定义的方法获取有关错误的信息。if (requestInfoTmp.compareTo(MATLABRequestState.ERROR_STATE) == 0) { HTTPErrorInfo httpErrorInfo = HTTPErrorInfo.newInstance(urlConnection.getInputStream()); System.out.println("ErrorCode: " + httpErrorInfo.getHttpErrorCode()); System.out.println("Error Message: " + httpErrorInfo.getHttpErrorMessage()); System.out.println("Error body: " + httpErrorInfo.getHttpBody()); } else{ MATLABResult<double[][]> mlFinalResult1 = MATLABResult.newInstance(mlMakeBody, urlConnection.getInputStream()); try{ double[][] magicSq1 = mlFinalResult1.getResult(); printResult(magicSq1); }catch(MATLABException e){ e.printStackTrace(); } }显示结果。
编写一个辅助方法
printResult,将从响应主体解析的结果作为输入并打印相应的二维数组。private static void printResult(double[][] result) { for (double[] row : result) { for (double element : row) { System.out.print(element + " "); } System.out.println(); } }
AsyncExample.java Java 客户端的示例代码如下。
代码:
