主要内容

本页采用了机器翻译。点击此处可查看英文原文。

在 Java 客户端中使用协议缓冲区对 RESTful 请求进行结构支持

R2026b

此示例显示当您使用 MATLAB® 客户端 API、MATLAB Production Server™ 用于 MATLAB 函数执行的 RESTful API 和协议缓冲区 (protobuf) 发出同步请求时,如何发送以 Java® 对象数组表示的 Java 结构体 (struct (MATLAB)) 作为输入。该示例提供并解释了一个示例 Java 客户端 SortStudentsSyncREST.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 的位置
  • MPS_INSTALL/client/java

  • MATLABProductionServer_<release>_Clients/java

Javadoc 的位置
  • MPS_INSTALL/client/java/doc

  • MATLABProductionServer_<release>_Clients/java/doc

示例文件的代码位置
  • MPS_INSTALL/client/java/examples

  • MATLABProductionServer_<release>_Clients/java/examples/SortStudents

该示例使用 java.net 包发出 HTTP 请求来评估在 http://localhost:9910 上运行的 MATLAB Production Server 实例上部署的 MATLAB 函数。

在服务器上部署您的 MATLAB 函数

编写一个 MATLAB 函数 sortstudents,以结构体数组作为输入,并根据学生分数返回已排序的学生数组。学生姓名、分数和成绩构成输入结构体的字段。在服务器上部署此函数。有关如何部署的信息,请参阅针对 MATLAB Production Server 创建可部署存档。

function sorted = sortstudents(unsorted)

scores = {unsorted.score};
scores = cell2mat(scores);
[s i] = sort(scores);
sorted = unsorted(i);

创建辅助类

  1. 创建一个具有与输入结构体相同数据成员的 Java 类 Student。

    class Student {
        String name;
        int score;
        String grade;
    }
    
  2. 创建一个扩展接口 StudentMarshaller 的 Java 类 MWDefaultMarshalingRules。由于 Java 本身不支持结构体,因此扩展 MWDefaultMarshalingRules 接口可让您为被编组的类列表实现一组新的编组规则,并将 Java 对象序列化为结构体,将结构体反序列化为 Java 对象。

        public class StudentMarshaller extends MWDefaultMarshalingRules {
            @override
            public List<Class> getStructTypes() {
            List structType = new ArrayList();
            structType.add(Student.class);
            return structType;
            }
        }

  3. 创建一个想要排序的 Student 类型的数组。

        Student[] students = new Student[]{new Student("Toni Miller", 90, "A"),
        new Student("Ed Plum", 80, "B+"),
        new Student("Mark Jones", 85, "A-")};

向服务器发出同步请求

  1. 构建请求 URL。

    在 Java 客户端中,使用 POST Synchronous Request RESTful API 向服务器发出初始请求。请求 URL 包括服务器实例的地址、部署的存档的名称和要评估的 MATLAB 函数的名称。

        String mpsBaseUrl = "http://localhost:9910";
        URL url;
        url = new URL(mpsBaseUrl + "/sortstudents/sortstudents");

  2. 设置请求标头。

    将 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);
  3. 创建 HTTP 请求主体。

    要创建 HTTP 请求正文,请将 StudentMarshaller 类作为参量传递给 MATLABParamsnewInstance 方法。StudentMarshaller 类将 Student 类的 Java 对象数组序列化为结构体数组,并将结构体数组反序列化为 Student 类的 Java 对象数组。

        MATLABParams mlMakeBody = MATLABParams.newInstance(1, Student[].class, new StudentMarshaller(), new Object[]{students});

  4. 将请求发送到服务器。

    将 MATLABParams mlMakeBody 对象写入 HTTP 请求的输出流。

        OutputStream output = urlConnection.getOutputStream();
        output.write(mlMakeBody.getRequestBody());
        output.flush();
    

接收并解释服务器响应

成功执行 HTTP 请求后,服务器将使用协议缓冲区消息进行响应。使用 MATLABResult 类的方法解析协议缓冲区消息以获取请求的结果。使用 MATLABResult 方法创建一个 newInstance 对象。newInstance 方法将 MATLABParams mlMakeBody 对象和 HTTP 请求的响应主体作为输入参量。将 MATLABResult 对象的返回类型设置为 Student[]。

    MATLABResult<Student[]> mlFinalResult = MATLABResult.newInstance(mlMakeBody, urlConnection.getInputStream());
    try{
        Student[] magicSq = mlFinalResult.getResult();
        for (Student student : magicSq) {
        System.out.println(student);
        }
    }catch(MATLABException e){
        e.printStackTrace();
    }

以下是 SortStudentsSyncREST.java Java 客户端和 Student.java 帮助类的示例代码。

代码:

import com.mathworks.mps.client.MATLABException;
import com.mathworks.mps.client.MWDefaultMarshalingRules;
import com.mathworks.mps.client.rest.MATLABParams;
import com.mathworks.mps.client.rest.MATLABResult;

import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;


class StudentMarshaller extends MWDefaultMarshalingRules {
    @Override
    public List<Class> getStructTypes() {
        List structType = new ArrayList();
        structType.add(Student.class);
        return structType;
    }
}


public class SortStudentsSyncREST {
	final static protected String CONTENT_TYPE = "application/x-google-protobuf";

    public static void main(String[] args) {

        //Creating a Student Array
        Student[] students = new Student[]{new Student("Toni Miller", 90, "A"),
                new Student("Ed Plum", 80, "B+"),
                new Student("Mark Jones", 85, "A-")};

        // Use the java.net package's URLConnection as HTTP Client in this example
        try {
            String mpsBaseUrl = "http://localhost:9910";
            URL url;
            url = new URL(mpsBaseUrl + "/sortstudents/sortstudents");
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setDoOutput(true);
            //Content-Type needs to be set to protobuf
            urlConnection.setRequestProperty("Content-Type", CONTENT_TYPE);


            // This class makes the initial POST request body.
            MATLABParams mlMakeBody = MATLABParams.newInstance(1, Student[].class,
                                                               new StudentMarshaller(), new Object[]{students});

            // Write the MATLABParams object into the output stream of the HTTP request.
            OutputStream output = urlConnection.getOutputStream();
            output.write(mlMakeBody.getRequestBody());
            output.flush();

            // Parse the response body of the above HTTP request with the help of MATLABResult. The newInstance method
            // here also takes MATLABParams object that was initially created.
            // If there is any error in MATLAB, call to getResult() will throw MATLABException which contains 
            // the error message displayed in MATLAB.
            MATLABResult mlFinalResult = MATLABResult.newInstance(mlMakeBody, urlConnection.getInputStream());
            Student[] magicSq = (Student[]) mlFinalResult.getResult();
            for (Student student :
                    magicSq) {
                System.out.println(student);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } 

    }
}
class Student {
    String name;
    int score;
    String grade;

    public Student() {
    }

    public Student(String name, int score, String grade) {
        this.name = name;
        this.score = score;
        this.grade = grade;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

    public String getGrade() {
        return grade;
    }

    public void setGrade(String grade) {
        this.grade = grade;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", score=" + score +
                ", grade='" + grade + '\'' +
                '}';
    }
}

另请参阅

主题