Skip to content

OpenFeign支持

微服务场景下,如需调用平台的Feign接口,请确保依赖了以下组件:

Maven坐标

xml
<dependency>
    <groupId>com.ikingtech.framework</groupId>
    <artifactId>sdk-rpc</artifactId>
</dependency>

自定义ErrorDecoder

当FeignClient调用失败时,平台将失败信息包装为自定义异常FrameworkException向外抛出。

java
@RequiredArgsConstructor
public class FeignErrorDecoder implements ErrorDecoder {

    private final FeignErrorReason feignErrorReason;

    @Override
    public Exception decode(String methodKey, Response response) {
        return new FrameworkException(feignErrorReason.is(methodKey, response));
    }
}

错误信息扩展

当FeignClient调用失败时,平台默认将远程接口返回的信息作为异常信息进行抛出,业务方如需自定义返回结果,可实现FeignErrorReason接口,自行返回错误信息。

java
public interface FeignErrorReason {

    /**
     * 获取失败原因
     *
     * @param methodKey 方法名
     * @param response 响应体
     * @return 失败原因
     */
    String is(String methodKey, Response response);
}
java
public class DefaultFeignReason implements FeignErrorReason {

    @Override
    public String is(String methodKey, Response response) {
        try {
            return null == response.body() ?
                    response.reason() :
                    Util.toString(response.body().asReader(StandardCharsets.UTF_8));
        } catch (IOException e) {
            return "未知错误";
        }
    }
}

请求头透传

微服务的场景下,一次用户行为可能涉及多个服务之间的远程调用,因此需要确保每个服务都可以获取当前发起请求的用户的身份信息。而OpenFeign底层基于RestTemplate实现,每次调用相当于发起了一次新的Http请求,因此,需要将前一个服务接收到的用户信息透传至下一个服务内。

平台通过OpenFeign提供的请求拦截器来实现请求头透传,具体如下:

java
@Slf4j
@RequiredArgsConstructor
public class FeignClientInterceptor implements RequestInterceptor {

    @Override
    public void apply(RequestTemplate requestTemplate) {
        //feign接口默认设置为内部调用,方便security模块鉴权通过
        requestTemplate.header(HEADER_CALLER, INNER_CALLER);
        // 获取请求中的请求头
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (null == attributes) {
            //内部调用设置默认用户信息
            try {
                requestTemplate.header(HEADER_IDENTITY, URLEncoder.encode(Tools.Json.toJsonStr(Identity.defaultUser()), Charset.defaultCharset().name()));
            } catch (UnsupportedEncodingException e) {
                log.error("[N/A]set default user error[{}]", e.getMessage());
            }
            return;
        }
        requestTemplate.header(HEADER_IDENTITY, attributes.getRequest().getHeader(HEADER_IDENTITY));
    }
}