Java Spring RestTemplate 从 api 获取 1 个对象

Java Spring RestTemplate get 1 object from api

我一直 运行 遇到一个问题,我似乎无法在任何地方找到解决方案。 我有一个 api 响应对象 EmployeeAuthenticatedResponse。这是一个单一的对象,其中包含用户的信息,例如他的姓名和角色。只能有 1 个响应,因此它将始终发送 1 个。

这是其余控制器中的代码api:

@GetMapping("/authenticate")
public EmployeeAuthenticatedResponse getAuthenticated(@RequestHeader(value = "email") String requestMail, @RequestHeader(value = "password") String requestPassword){
    return employeeService.signin(requestMail, requestPassword);
}

这是我用来尝试检索它的方法:

public class LoginController {
    @FXML
    private Label errorText;
    @FXML
    private TextField email;
    @FXML
    private PasswordField password;

    @FXML
    protected void login(ActionEvent event) throws NoSuchAlgorithmException {
        if(email != null && email.getText() != "" && password != null && password.getText() != ""){

            //Hash password before sending it out(This is just extra for during the connection, the server hashed it again with Bcrypt)
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            byte[] digest = md.digest(password.getText().getBytes(StandardCharsets.UTF_8));
            String passwordHash = String.format("%064x", new BigInteger(1,digest));

            //Initiate Spring stuff
            RestTemplate restTemplate = new RestTemplate();
            HttpHeaders headers = new HttpHeaders();

            //maak headers
            headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.add("user-agent", "My app");
            headers.add("email", email.getText());
            headers.add("password", passwordHash);
            HttpEntity<?> entity = new HttpEntity<Object>("parameters", headers);

            //Send it away and retrieve
            ResponseEntity<EmployeeAuthenticatedResponse> loginResponse = restTemplate.exchange("http://localhost:8080/employee/authenticate", HttpMethod.GET, entity, EmployeeAuthenticatedResponse.class);

            //If else stuffs
            if(loginResponse.getStatusCode() == HttpStatus.OK){
                errorText.setText("it works");
            } else if(loginResponse.getStatusCode() == HttpStatus.FORBIDDEN) {
                errorText.setText("wrong password");
            } else if(loginResponse.getStatusCode() == HttpStatus.REQUEST_TIMEOUT){
                errorText.setText("error");
            }
        }
    }

}

现在,当我尝试使用它时,我收到了一些警告和错误。 第一个“警告”

18:04:56.170 [JavaFX Application Thread] WARN org.springframework.http.converter.json.MappingJackson2HttpMessageConverter - Failed to evaluate Jackson deserialization for type [[simple type, class link.to.class.DTO.EmployeeAuthenticatedResponse]]
java.lang.reflect.InaccessibleObjectException: Unable to make public link.to.class.EmployeeAuthenticatedResponse() accessible: module link.to.class does not "exports link.to.class.DTO" to unnamed module @13f33d2d

然后它会提供一些额外的信息:

18:04:56.171 [JavaFX Application Thread] DEBUG org.springframework.web.client.RestTemplate - Accept=[]
18:04:56.173 [JavaFX Application Thread] DEBUG org.springframework.web.client.RestTemplate - Writing [parameters] as "application/json"
18:04:56.683 [JavaFX Application Thread] DEBUG org.springframework.web.client.RestTemplate - Response 200 OK

然后它两次给出相同的未能评估 Jackson 反序列化类型警告,然后我得到一个无法提取响应:没有找到适合响应类型 error/exception 的 HttpMessageConverter,这是它结束的地方。

当我在 EmployeeAuthenticatedResponse 后面添加 [] 时,我在 Stack overflow 和其他网站上查找了很多,例如:

ResponseEntity<EmployeeAuthenticatedResponse[]> loginResponse = restTemplate.exchange("http://localhost:8080/employee/authenticate", HttpMethod.GET, entity, EmployeeAuthenticatedResponse[].class);

我在没有警告的情况下直接进入异常。这让我觉得问题是当像这样使用 RestTemplate 时我需要一个列表作为响应而不是单个对象,但是我如何获得单个实体?我在网上能找到的所有内容都是关于消费列表的。

EmployeeAuthenticatedResponse class:

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties(ignoreUnknown = true)
public class EmployeeAuthenticatedResponse {
    private int employeeId;
    private String employeeFirstName;
    private String employeeLastName;
    private int employeeDarkMode;
    private int employeeRoleId;
    private String employeeRoleName;
    private int employeePermissionSales;
    private int employeePermissionSending;
    private int employeePermissionManager;
    private int employeePermissionProductManagement;
    private String JWTToken;

//Getters and setters

}

Json:

{
    "employeeId": 1,
    "employeeFirstName": "TestFname",
    "employeeLastName": "TestLname",
    "employeeDarkMode": 1,
    "employeeRoleId": 1,
    "employeeRoleName": "owner",
    "employeePermissionSales": 1,
    "employeePermissionSending": 1,
    "employeePermissionManager": 1,
    "employeePermissionProductManagement": 1,
    "jwttoken": "JWTTOKEN"
}

模块-info.java:

module com.windsoftware.kassa.windkassadesktop {
    requires javafx.controls;
    requires javafx.fxml;
    requires javafx.web;

    requires org.controlsfx.controls;
    requires com.dlsc.formsfx;
    requires validatorfx;
    requires org.kordamp.ikonli.javafx;
    requires org.kordamp.bootstrapfx.core;
    requires eu.hansolo.tilesfx;
    requires spring.boot;
    requires spring.web;
    requires com.fasterxml.jackson.databind;
    requires com.fasterxml.jackson.annotation;
    requires spring.boot.autoconfigure;

    opens link.to.class to javafx.fxml;
    exports link.to.class;
    exports link.to.class.controllers;
    opens link.to.class.controllers to javafx.fxml;
}

问题可能与对象反序列化 EmployeeAuthenticatedResponse

ResponseEntity<String> loginResponse = restTemplate.exchange(URL, HttpMethod.GET, request, String.class);

String loginResponse = restTemplate.exchange(URL, HttpMethod.GET, request, String.class).getBody();

使用它并记录 loginResponse 然后您将了解对象问题

由于您使用的是 Java 16,因此您必须在模块设置中导出 DTO 包,以便其余模板中的 jackson 对象映射器能够访问您的 DTO class 并且它的反射领域

模块-info.java:

module com.windsoftware.kassa.windkassadesktop {
    requires javafx.controls;
    requires javafx.fxml;
    requires javafx.web;

    requires org.controlsfx.controls;
    requires com.dlsc.formsfx;
    requires validatorfx;
    requires org.kordamp.ikonli.javafx;
    requires org.kordamp.bootstrapfx.core;
    requires eu.hansolo.tilesfx;
    requires spring.boot;
    requires spring.web;
    requires com.fasterxml.jackson.databind;
    requires com.fasterxml.jackson.annotation;
    requires spring.boot.autoconfigure;

    opens link.to.class to javafx.fxml;
    exports link.to.class;
    exports link.to.class.controllers;
    exports link.to.class.DTO;
    opens link.to.class.controllers to javafx.fxml;
}