【ParameterizedTypeReference的用法及场景】

文章介绍了ParameterizedTypeReference在Java中如何解决远程调用返回泛型类型的问题,通过实例展示了如何避免类型擦除导致的强转,提高代码效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ParameterizedTypeReference的用法及场景

一,类的描述

超类型标记模式会捕获类信息中的泛型参数,以避免Java语言中类型擦除的限制。

关于这个类的描述,可以百度翻译一下。大概意思就是能确定返回对象的类型,而不受范型擦除的影响。
也可以参考这个文章的描述:
https://blog.youkuaiyun.com/m0_37607945/article/details/126598116

二,类的用法

场景:
当远程调用,返回的对象是范型确定的,则可以使用这个。避免了对返回对象的强转。
统一的返回类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ResponseShow<T> {

    private String code;
    private String message;
    private T data;

}

返回data的一个类型

@Data
@AllArgsConstructor
@NoArgsConstructor
public class BackArray {

    private String name;
}

方法比较:

package com.madorangecat.artmartxt.use.parameterized;

import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

import java.util.List;

public class ParameterizedTe {

    /**
     * 为什么要使用 ParameterizedTypeReference
     * 举例:
     * 远程调用接口,接口返回的对象为一个统一的封装对象,但对象内部包装但为List的一个对象
     * ResponseShow<List<BackArray>>
     */
    private static void parameterizedTe(){

        HttpEntity<String> request = new HttpEntity<String>("");

        // 使用直接请求方式:得到List<BackArray> backResult结果需要强转
        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<ResponseShow> listResponseEntity = restTemplate.postForEntity("url", request, ResponseShow.class, "");
        ResponseShow body = listResponseEntity.getBody();
        Object data = body.getData();
        // 要强转
        List<BackArray> backResult = (List<BackArray>) data;

        // 使用ParameterizedTypeReference方式

        ParameterizedTypeReference<ResponseShow<List<BackArray>>> backBodyType = new ParameterizedTypeReference<ResponseShow<List<BackArray>>>(){};
        ResponseEntity<ResponseShow<List<BackArray>>> exchange = restTemplate.exchange("url", HttpMethod.POST, request, backBodyType);
        ResponseShow<List<BackArray>> body1 = exchange.getBody();
        // 非常完美
        List<BackArray> data1 = body1.getData();

    }

}

<think>嗯,用户想用RestTemplate创建一个支持泛型的HTTP请求模板类。首先,我需要理解用户的需求。他们可能希望有一个通用的工具类,能够处理不同类型的请求和响应,避免重复代码。比如,发送POST请求时,可以指定返回的类型,比如String、自定义对象或者泛型集合。 首先,RestTemplate本身已经支持泛型,但用户可能需要一个更高级的封装,让调用更简便。比如,通过传递参数化的类型,自动处理响应反序列化。例如,使用exchange方法,配合ParameterizedTypeReference来捕获泛型信息。 然后,我需要参考用户提供的引用内容。引用[1]提到RestTemplate的各种方法,如getForObject、postForEntity等。引用[3]展示了put和post的用法,但没有涉及泛型。用户的问题是需要支持泛型,所以可能需要使用exchange方法,因为它允许指定响应类型,包括泛型集合。 接下来,构建一个通用模板类。可能需要一个工具类,包含静态方法,接受URL、HTTP方法、请求体、参数等。关键点在于处理泛型返回类型,比如使用ParameterizedTypeReference来包装泛型类型。例如,当返回的是一个List<User>时,可以通过TypeReference来指定。 然后,考虑异常处理。RestTemplate可能会抛出HttpStatusCodeException,需要捕获并处理错误状态码,可能抛出自定义异常或者返回错误信息。 另外,引用[2]提到@LoadBalanced注解,但用户的问题中没有提到负载均衡,可能暂时不需要考虑,但如果有需要的话,可以提示用户添加该注解。 示例代码方面,需要展示如何定义通用方法,使用exchange,处理不同类型的响应。比如,创建一个RestTemplateUtil类,包含execute方法,接受Method参数(GET、POST等),请求实体,以及TypeReference来指定返回类型。 测试部分,需要展示如何调用这个工具类,比如发送GET请求获取User对象列表,或者POST请求提交数据并接收响应。 还要注意,用户可能遇到类型擦除的问题,所以必须使用ParameterizedTypeReference来保留泛型信息。例如,new ParameterizedTypeReference<List<User>>() {} 这样的写法可以获取到具体的泛型类型。 最后,总结可能的相关问题,比如如何处理复杂嵌套泛型,或者如何集成负载均衡,这些都可以作为相关问题提出。</think>### 基于RestTemplate的泛型HTTP请求模板类实现 #### 1. 泛型模板类设计思路 通过`ParameterizedTypeReference`保留泛型信息,结合`RestTemplate.exchange()`方法实现泛型响应解析。核心代码如下: ```java public class RestTemplateUtil { private static final RestTemplate restTemplate = new RestTemplate(); // 通用请求方法 public static <T> T execute(String url, HttpMethod method, HttpEntity<?> requestEntity, ParameterizedTypeReference<T> responseType, Object... uriVariables) { ResponseEntity<T> response = restTemplate.exchange( url, method, requestEntity, responseType, uriVariables ); return response.getBody(); } } ``` #### 2. 使用示例 ##### (1) 获取泛型集合 ```java // 定义返回类型 ParameterizedTypeReference<List<User>> typeRef = new ParameterizedTypeReference<List<User>>() {}; // 发送GET请求 List<User> users = RestTemplateUtil.execute( "http://api.example.com/users", HttpMethod.GET, null, typeRef ); ``` ##### (2) 提交泛型请求体 ```java // 构建请求体 HttpEntity<PageRequest<User>> requestEntity = new HttpEntity<>( new PageRequest<>(1, 20) ); // 发送POST请求 PageResponse<User> response = RestTemplateUtil.execute( "http://api.example.com/search", HttpMethod.POST, requestEntity, new ParameterizedTypeReference<PageResponse<User>>() {} ); ``` #### 3. 增强功能实现 ##### (1) 异常处理 ```java try { return restTemplate.exchange(...); } catch (HttpStatusCodeException e) { throw new ApiException( "请求失败: " + e.getStatusCode(), e.getResponseBodyAsString() ); } ``` ##### (2) 负载均衡支持 在RestTemplate实例化时添加注解[^2]: ```java @Bean @LoadBalanced public RestTemplate loadBalancedRestTemplate() { return new RestTemplate(); } ``` #### 4. 方法对比分析 | 方法类型 | 适用场景 | 泛型支持 | |----------------|-----------------------------------|----------| | getForObject() | 简单GET请求,直接返回对象 | 基础类型 | | postForEntity()| 需要获取完整响应头/状态码的POST请求| 基础类型 | | exchange() | 需要精确控制请求/响应类型的场景 | 完全支持 |
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值