fegin报错传递
This commit is contained in:
@@ -26,7 +26,7 @@ public class BuyerAccountController {
|
||||
}
|
||||
|
||||
@PostMapping("/register")
|
||||
@Operation(summary = "注册")
|
||||
@Operation(summary = "获取验证码后注册")
|
||||
public Boolean register(@Valid @RequestBody RegisterDTO dto) {
|
||||
return buyerAccountService.register(dto);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
package com.aida.buyer.module.feign.config;
|
||||
|
||||
import com.aida.buyer.module.feign.decoder.BusinessErrorFeignDecoder;
|
||||
import com.aida.buyer.module.feign.interceptor.InternalCallInterceptor;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import feign.RequestInterceptor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* Feign 全局配置:注册所有 Feign 拦截器。
|
||||
* Feign 全局配置:注册所有 Feign 拦截器和 Decoder。
|
||||
*/
|
||||
@Configuration
|
||||
public class FeignConfig {
|
||||
@@ -15,4 +17,9 @@ public class FeignConfig {
|
||||
public RequestInterceptor internalCallInterceptor() {
|
||||
return new InternalCallInterceptor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public BusinessErrorFeignDecoder businessErrorFeignDecoder(ObjectMapper objectMapper) {
|
||||
return new BusinessErrorFeignDecoder(objectMapper);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
package com.aida.buyer.module.feign.decoder;
|
||||
|
||||
import com.aida.buyer.common.exception.BusinessException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import feign.FeignException;
|
||||
import feign.Request;
|
||||
import feign.Response;
|
||||
import feign.codec.DecodeException;
|
||||
import feign.codec.Decoder;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Feign 全局 Decoder。
|
||||
*
|
||||
* <p>背景:seller 端使用 {@code @RestControllerAdvice} 将 {@code BusinessException}
|
||||
* 转为 HTTP 200 + {@code Response.fail(code, msg)} 返回。
|
||||
* 默认 Decoder 只看 HTTP 状态码,2xx 一律视为成功,导致 buyer 端无法感知远程业务错误。</p>
|
||||
*
|
||||
* <p>本 Decoder 在解析响应体时:
|
||||
* <ul>
|
||||
* <li>若 HTTP 状态码为 2xx,先将 body 读取为字符串并解析为标准 {@code Response};</li>
|
||||
* <li>若 {@code errCode != 0},抛出 {@link BusinessException},错误信息为远程返回的 errMsg;</li>
|
||||
* <li>否则使用 {@link ObjectMapper} 将 body 反序列化为目标类型 {@code T}。</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*
|
||||
* <p>HTTP 非 2xx 状态码(如 500、服务不可用)由 Feign 默认 ErrorDecoder 抛出
|
||||
* {@link FeignException},不在本 Decoder 处理范围内。</p>
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class BusinessErrorFeignDecoder implements Decoder {
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object decode(Response response, Type type) throws IOException, DecodeException, FeignException {
|
||||
if (!is2xx(response.status())) {
|
||||
throw FeignException.errorStatus(requestKey(response), response);
|
||||
}
|
||||
|
||||
String body = readBody(response);
|
||||
if (body == null || body.isBlank()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 先按标准 Response 格式解析,校验 errCode
|
||||
com.aida.buyer.common.result.Response<?> genericResp = objectMapper.readValue(body, com.aida.buyer.common.result.Response.class);
|
||||
if (genericResp.getErrCode() != 0) {
|
||||
throw new BusinessException(
|
||||
genericResp.getErrCode(),
|
||||
genericResp.getErrMsg() != null ? genericResp.getErrMsg() : "远程服务业务错误"
|
||||
);
|
||||
}
|
||||
|
||||
// errCode == 0,ObjectMapper 反序列化为目标类型
|
||||
return objectMapper.readValue(body, objectMapper.getTypeFactory().constructType(type));
|
||||
}
|
||||
|
||||
private boolean is2xx(int status) {
|
||||
return status >= 200 && status < 300;
|
||||
}
|
||||
|
||||
private String readBody(Response response) throws IOException {
|
||||
if (response.body() == null) {
|
||||
return null;
|
||||
}
|
||||
try (BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(response.body().asInputStream(), StandardCharsets.UTF_8))) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
sb.append(line);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private String requestKey(Response response) {
|
||||
Request request = response.request();
|
||||
return request.method() + " " + request.url();
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.aida.buyer.module.order.service.impl;
|
||||
|
||||
import com.aida.buyer.common.context.UserContext;
|
||||
import com.aida.buyer.common.exception.BusinessException;
|
||||
import com.aida.buyer.common.result.PageResponse;
|
||||
import com.aida.buyer.common.result.Response;
|
||||
import com.aida.buyer.module.account.entity.BuyerAccount;
|
||||
@@ -46,10 +45,6 @@ public class BuyerOrderServiceImpl implements IBuyerOrderService {
|
||||
dto.setBuyerUsername(account.getUsername());
|
||||
|
||||
Response<CreateOrderResultVO> orderResp = orderFeignClient.createOrder(dto);
|
||||
if (orderResp == null || orderResp.getErrCode() != 0) {
|
||||
throw new BusinessException("创建订单失败");
|
||||
}
|
||||
|
||||
CreateOrderResultVO result = orderResp.getData();
|
||||
// TODO:调用支付模块,传入buyerId,result.getOrderIds(),result.getTotalAmount()
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# ============================================================
|
||||
|
||||
nacos:
|
||||
namespace: ltx
|
||||
namespace: dev
|
||||
host: 18.167.251.121:28848
|
||||
username: nacos
|
||||
password: Aidlab123123!
|
||||
|
||||
Reference in New Issue
Block a user