RestTemplate调用返回PagedResources<Resource<EmployeeDto>>接口无内容问题
看起来你遇到的问题是RestTemplate默认配置没法处理Spring HATEOAS返回的HAL格式分页数据——毕竟Postman能拿到完整响应,说明接口本身没问题,问题出在客户端的反序列化环节。
核心原因
Spring HATEOAS返回的PagedResources对应的JSON是HAL格式,包含_embedded、_links和page这些特殊字段,而RestTemplate默认的MappingJackson2HttpMessageConverter没有配置对应的HAL模块,没法把这些特殊字段映射到PagedResources和Resource对象里,导致反序列化后拿不到有效内容。
解决方案步骤
1. 确保依赖到位
首先检查项目依赖,确保引入了Spring HATEOAS相关包(以Maven为例):
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-hateoas</artifactId> </dependency>
这个依赖会自动引入HAL序列化/反序列化的核心模块。
2. 正确配置RestTemplate
不要直接new RestTemplate(),而是通过RestTemplateBuilder构建,它会自动注册处理HAL格式的HalMessageConverter:
@Bean public RestTemplate restTemplate(RestTemplateBuilder builder) { return builder.build(); }
如果是在非Spring容器环境下手动创建,也可以手动添加转换器:
ObjectMapper objectMapper = new ObjectMapper() .registerModule(new Jackson2HalModule()); MappingJackson2HttpMessageConverter halConverter = new MappingJackson2HttpMessageConverter(objectMapper); halConverter.setSupportedMediaTypes(Collections.singletonList(MediaTypes.HAL_JSON)); RestTemplate template = new RestTemplate(); // 把HAL转换器放到最前面,确保优先处理HAL格式响应 template.getMessageConverters().add(0, halConverter);
3. 正确使用ParameterizedTypeReference
调用接口时,用ParameterizedTypeReference明确指定泛型类型(和你之前用的TypeReferences.PagedResourcesType本质一致,确保类型匹配即可):
String uri = "http://localhost:8080/employee-api/employees/160166/employees?page=0&size=25"; // 使用上面配置好的RestTemplate实例 RestTemplate template = restTemplate; ResponseEntity<PagedResources<Resource<EmployeeDto>>> response = template.exchange( uri, HttpMethod.GET, null, new ParameterizedTypeReference<PagedResources<Resource<EmployeeDto>>>() {} ); PagedResources<Resource<EmployeeDto>> pagedResources = response.getBody(); // 现在可以正常读取内容了 pagedResources.getContent().forEach(resource -> { EmployeeDto dto = resource.getContent(); System.out.println("员工编号: " + dto.getEmployeeNumber() + ", 状态: " + dto.getStatus()); });
4. 检查EmployeeDto的序列化配置
确保EmployeeDto类有无参构造函数,并且字段名称和JSON响应中的键匹配(如果有名称不一致的情况,可以用@JsonProperty注解调整):
public class EmployeeDto { private String employeeNumber; private String status; // 必须保留无参构造函数,否则Jackson无法反序列化 public EmployeeDto() {} // Getter & Setter public String getEmployeeNumber() { return employeeNumber; } public void setEmployeeNumber(String employeeNumber) { this.employeeNumber = employeeNumber; } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } }
为什么用String能正常获取?
因为指定String.class作为响应类型时,RestTemplate不会执行任何反序列化操作,直接返回HTTP响应的原始JSON字符串,所以能看到完整内容,但无法直接拿到结构化的PagedResources对象。
内容的提问来源于stack exchange,提问作者PAA

