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;
}
我一直 运行 遇到一个问题,我似乎无法在任何地方找到解决方案。 我有一个 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;
}