我正在尝试使用com.gluonhq.connect.provider.RestClient来查询启用了 Elastic Search 的 API。
Maven:
<dependency>
<groupId>com.gluonhq</groupId>
<artifactId>connect</artifactId>
<version>2.0.1</version>
</dependency>
我尝试使用以下方法发出请求:
private GluonObservableObject<Item> getData() {
RestClient myApiClient = RestClient.create()
.method("POST")
.host(applicationProperties.getAPIURL())
.path("search")
.header("accept", "application/json")
.header("Content-type", "application/json")
.queryParam("private_key", applicationProperties.getAPIKEY())
.dataString(ITEMREQUEST);
return DataProvider.retrieveObject(
myApiClient.createObjectDataReader(Item.class));
}
...其中 dataString 是一个 json 格式的字符串,表示请求的主体(我可以假设请求的格式正确,因为我在 Postman 中对其进行了测试并且请求返回了预期的数据)。如果有帮助,这里是弹性搜索请求正文:
{
"indexes": "idx1, idx2",
"columns": "col1,col2,col3,col4,col5",
"body": {
"query": {
"bool": {
"must": [
{
"wildcard": {
"NameCombined_en": "*"
}
}
],
"filter": [
{
"range": {
"ID": {
"gte": "20000"
}
}
}
]
}
},
"from": 0,
"size": 100
}
}
我遇到的问题是(胶子) RestClient 以及扩展的 DataProvider.retrieveObject 方法完全返回......什么都没有。
我很确定我做错了什么,并且我相当确定它是 .dataString() 方法(它需要一个“实体”),但我还没有找到一种替代方法来用作传递正文的方法进入请求。
使用com.gluonhq.connect库背后的原因是为了避免也必须创建我自己的 Observable 列表(手动)——如果数据格式合适......并且存在,库会自动吐出一个。至少,这是我对它的理解。
有人可以指出我正确的方向吗?我没有发现有关如何使用该库执行 POST 请求的指示或解释。
更新 20220117
主.java
public class Main extends Application {
ApplicationProperties applicationProperties = new ApplicationProperties();
private static final String RESTLIST_VIEW = HOME_VIEW;
private static final String RESTOBJECT_VIEW = "RestObjectView";
private final AppManager appManager = AppManager.initialize(this::postInit);
@Override
public void init() {
appManager.addViewFactory(RESTOBJECT_VIEW, () -> new RestObjectView(applicationProperties.APIURL, applicationProperties.APIKEY));
updateDrawer();
}
@Override
public void start(Stage stage) {
appManager.start(stage);
}
private void postInit(Scene scene) {
Swatch.BLUE.assignTo(scene);
((Stage) scene.getWindow()).getIcons().add(new Image(Objects.requireNonNull(Main.class.getResourceAsStream("/icon.png"))));
}
private void updateDrawer() {
NavigationDrawer navigationDrawer = appManager.getDrawer();
NavigationDrawer.Header header = new NavigationDrawer.Header("Gluon Mobile", "Gluon Connect Rest Provider Sample",
new Avatar(21, new Image(getClass().getResourceAsStream("/icon.png"))));
navigationDrawer.setHeader(header);
NavigationDrawer.Item listItem = new NavigationDrawer.Item("List Viewer", MaterialDesignIcon.VIEW_LIST.graphic());
NavigationDrawer.Item objectItem = new NavigationDrawer.Item("Object Viewer", MaterialDesignIcon.INSERT_DRIVE_FILE.graphic());
navigationDrawer.getItems().addAll(listItem, objectItem);
navigationDrawer.selectedItemProperty().addListener((obs, oldItem, newItem) -> {
if (newItem.equals(listItem)) {
appManager.switchView(RESTLIST_VIEW);
} else if (newItem.equals(objectItem)) {
appManager.switchView(RESTOBJECT_VIEW);
}
});
}
public static void main(String[] args) {
System.setProperty("javafx.platform", "Desktop");
launch(args);
}
RestObjectView.java
public class RestObjectView extends View {
public RestObjectView(String apiurl, String apikey) {
Label lbItemId = new Label();
Label lbName = new Label();
Label lbDescription = new Label();
Label lbLvlItem = new Label();
Label lbLvlEquip = new Label();
GridPane gridPane = new GridPane();
gridPane.setVgap(5.0);
gridPane.setHgap(5.0);
gridPane.setPadding(new Insets(5.0));
gridPane.addRow(0, new Label("Item ID:"), lbItemId);
gridPane.addRow(1, new Label("Name:"), lbName);
gridPane.addRow(2, new Label("Description:"), lbDescription);
gridPane.addRow(3, new Label("Item Level:"), lbLvlItem);
gridPane.addRow(4, new Label("Equip Level:"), lbLvlEquip);
gridPane.getColumnConstraints().add(new ColumnConstraints(75));
lbItemId.setWrapText(true);
lbName.setWrapText(true);
lbDescription.setWrapText(true);
lbLvlItem.setWrapText(false);
lbLvlEquip.setWrapText(false);
setCenter(gridPane);
// create a RestClient to the specific URL
RestClient restClient = RestClient.create()
.method("POST")
.host(apiurl)
.path("Item")
.queryParam("private_key", apikey);
// create a custom Converter that is able to parse the response into a single object
InputStreamInputConverter<Item> converter = new SingleItemInputConverter<>(Item.class);
// retrieve an object from the DataProvider
GluonObservableObject<Item> item = DataProvider.retrieveObject(restClient.createObjectDataReader(converter));
// when the object is initialized, bind its properties to the JavaFX UI controls
item.initializedProperty().addListener((obs, oldValue, newValue) -> {
if (newValue) {
lbItemId.textProperty().bind(item.get().itemIdProperty().asString());
lbName.textProperty().bind(item.get().nameProperty());
lbDescription.textProperty().bind(item.get().descriptionProperty());
lbLvlItem.textProperty().bind(item.get().levelItemProperty().asString());
lbLvlEquip.textProperty().bind(item.get().levelEquipProperty().asString());
}
});
}
@Override
protected void updateAppBar(AppBar appBar) {
appBar.setNavIcon(MaterialDesignIcon.MENU.button(e -> getAppManager().getDrawer().open()));
appBar.setTitleText("Rest Object Viewer");
}
}