public <R, P> ResponseResult<R> post(String url, P body, ParameterizedTypeReference<ResponseResult<R>> typeReference) throws JsonProcessingException { if (environment.acceptsProfiles(Profiles.of(EnvProfilesEnum.PROD.getValue()))) { HttpHeaders hexSignHeader = getHeader(body); hexSignHeader.setContentType(MediaType.APPLICATION_JSON); HttpEntity<P> request = new HttpEntity<>(body, hexSignHeader); log.debug("大趋智能接口请求的request:{}", request); ResponseResult<R> printRequestResult = new RestTemplate().exchange(url, HttpMethod.POST, request, typeReference).getBody(); if (printRequestResult == null) { log.error("大趋智能接口请求失败,请求URL:{},请求参数:{}", url, objectMapper.writeValueAsString(body)); } else if (!SUCCESS_CODE.equals(printRequestResult.getCode())) { log.error("大趋智能接口请求错误,请求URL:{},请求参数:{},返回值:{},返回的错误消息:{}", url, objectMapper.writeValueAsString(body), objectMapper.writeValueAsString(printRequestResult), printRequestResult.getMessage()); } return printRequestResult; } else { log.info("当前环境不是生产环境,不调用外部接口打印小票和播报,URl:{},请求参数: {}", url, objectMapper.writeValueAsString(body)); return null; } }帮我把这段代码改成<dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>4.12.0</version> </dependency>这个依赖包实现
时间: 2025-06-10 14:06:55 浏览: 21
<think>好的,我现在需要将用户提供的基于Spring RestTemplate的HTTP POST请求代码,改用OkHttp 3来实现。首先,我得仔细分析原始代码的结构和功能,然后找出OkHttp中对应的实现方式。
首先,原方法是一个泛型方法,接受URL、请求体body和类型引用typeReference。返回类型是ResponseResult<R>。方法首先检查环境是否是生产环境,如果是,则构造请求头,发送POST请求,处理响应,否则记录日志并返回null。
我需要用OkHttp的依赖替换RestTemplate。首先,要引入OkHttpClient实例。通常,OkHttpClient应该被重用,所以可能需要将其作为单例或者通过依赖注入来管理。但在这个方法中,用户可能希望直接使用,所以可能需要在方法内部创建,不过更高效的方式是从外部传入或使用一个单例。
接下来,处理请求头。原代码中使用了HttpHeaders,并设置了Content-Type为APPLICATION_JSON。在OkHttp中,这对应于构建Request时添加Header,并且设置MediaType为application/json。
然后,构建请求体。原代码中的body是泛型P,需要将其转换为JSON字符串。原代码使用了objectMapper(可能是Jackson的ObjectMapper),所以在OkHttp中,需要将body对象序列化为JSON字符串,作为RequestBody。
发送POST请求,原代码使用exchange方法,而OkHttp中需要构建Request对象,使用client.newCall(request).execute()来同步执行请求。
处理响应时,原代码通过RestTemplate的exchange获取ResponseResult<R>,而OkHttp需要读取响应体的JSON字符串,并用ObjectMapper反序列化为对应的泛型类型。这里需要注意,原方法使用了ParameterizedTypeReference来处理泛型,因此在使用ObjectMapper时,也需要构造相应的JavaType来处理泛型类型。
错误处理部分,原代码检查响应体是否为null,或者code是否不等于SUCCESS_CODE,并记录相应的日志。在OkHttp中,需要检查响应是否成功(比如HTTP 200),然后解析响应体。此外,OkHttp的Response需要关闭,否则可能造成资源泄漏,所以应该使用try-with-resources或者手动关闭。
环境判断部分,原代码在非生产环境下不发送请求,直接记录日志并返回null。这部分逻辑可以保持不变,但需要调整日志记录的代码,确保使用OkHttp后相关的参数正确输出。
另外,原代码中的objectMapper用于序列化和反序列化JSON,需要确保在修改后的代码中正确使用,特别是在将body对象转换为JSON字符串,以及将响应体解析为ResponseResult<R>对象时。
可能的难点在于处理泛型类型的反序列化。OkHttp的响应体是ResponseBody对象,需要将其转换为字符串,再通过ObjectMapper读取为所需的泛型类型。这里需要利用TypeFactory或JavaType来构建正确的类型信息,类似于原代码中的ParameterizedTypeReference。
另外,异常处理方面,原方法声明抛出JsonProcessingException,这可能在序列化body或解析响应时发生。在OkHttp的实现中,需要捕获可能的IOException,比如网络问题,或者JSON处理异常,并根据情况抛出或处理。
最后,测试和验证修改后的代码是否与原功能一致,包括正确的头信息、请求体、环境判断以及错误日志记录。</think>我帮您将代码改写为使用OkHttp实现,以下是分步解释和完整代码:
```java
public <R, P> ResponseResult<R> post(String url, P body, ParameterizedTypeReference<ResponseResult<R>> typeReference)
throws JsonProcessingException {
// 环境检查(保持原有逻辑)
if (!environment.acceptsProfiles(Profiles.of(EnvProfilesEnum.PROD.getValue()))) {
log.info("当前环境不是生产环境,不调用外部接口打印小票和播报,URL:{},请求参数: {}",
url, objectMapper.writeValueAsString(body));
return null;
}
// 1. 创建OkHttpClient(建议实际使用单例)
OkHttpClient client = new OkHttpClient();
try {
// 2. 构建请求头
Headers headers = getOkHttpHeaders(body); // 转换原有header生成逻辑
// 3. 序列化请求体
String jsonBody = objectMapper.writeValueAsString(body);
RequestBody requestBody = RequestBody.create(
jsonBody,
MediaType.parse(MediaType.APPLICATION_JSON_VALUE)
);
// 4. 构建请求
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.headers(headers)
.build();
log.debug("大趋智能接口请求的request:{}", request);
// 5. 发送请求
try (Response response = client.newCall(request).execute()) {
// 6. 处理响应
if (!response.isSuccessful()) {
log.error("大趋智能接口请求失败,HTTP状态码:{},请求URL:{}",
response.code(), url);
return null;
}
ResponseBody responseBody = response.body();
if (responseBody == null) {
log.error("大趋智能接口返回空响应体,请求URL:{}", url);
return null;
}
// 7. 反序列化响应
String responseString = responseBody.string();
JavaType javaType = TypeFactory.defaultInstance()
.constructType(typeReference.getType());
ResponseResult<R> result = objectMapper.readValue(responseString, javaType);
// 8. 处理业务错误码
if (!SUCCESS_CODE.equals(result.getCode())) {
log.error("大趋智能接口请求错误,请求URL:{},请求参数:{},返回值:{},错误消息:{}",
url,
objectMapper.writeValueAsString(body),
objectMapper.writeValueAsString(result),
result.getMessage());
}
return result;
}
} catch (IOException e) {
log.error("大趋智能接口请求异常,URL:{},错误信息:{}", url, e.getMessage());
throw new RuntimeException("接口请求失败", e);
}
}
// 转换header生成方法(需要根据原getHeader()方法调整)
private Headers getOkHttpHeaders(P body) {
Headers.Builder builder = new Headers.Builder();
// 这里添加原有header的生成逻辑,例如:
// builder.add("Content-Type", "application/json");
// builder.add("Authorization", "Bearer ...");
return builder.build();
}
```
主要修改点说明:
1. **依赖变更**:
```xml
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.12.0</version>
</dependency>
```
2. **核心改动**:
- 使用`OkHttpClient`代替`RestTemplate`
- 请求构建改为`Request.Builder`
- 响应处理使用`Response`对象
- 使用try-with-resources确保资源释放
3. **类型处理**:
```java
JavaType javaType = TypeFactory.defaultInstance()
.constructType(typeReference.getType());
```
该代码段可以正确处理泛型类型的反序列化
4. **异常处理**:
- 显式处理IOException
- 保持原有的业务错误码检查逻辑
5. **性能优化**:
- 建议将`OkHttpClient`实例化为单例复用
- 使用`response.body().string()`时注意只能调用一次
注意:实际使用时需要根据原有`getHeader()`方法的实现补充请求头生成逻辑,并确保`objectMapper`(Jackson ObjectMapper)已正确注入。
阅读全文