在实际Restful项目中,通常都会定义一个通用的响应体对象,该对象内包括了本次调用的结果码,异常信息,业务数据对象等。对于一般的Controller接口的响应,我们都会自定义一个RestControllerAdvice,并实现ResponseBodyAdvice接口,来将Controller接口返回的业务对象统一封装成CommonResponse对象,并返回给客户端。所以为了简化Feign接口的响应的处理,我们可以自定义OpenFeign的Decoder来统一地从CommonResp中解构出业务对象。
实现思路:
1、 自定义Decoder:
1.1、 自定义Decoder,并且持有一个原先Decoder的引用;
1.2、 在decode时,首先先把decode处理委派给原来的Decoder(装饰器模式),并获取到decode后的结果对象;
1.3、 判断1.2步得出的结果对象是否是CommonResp,如果是,则从CommonResp取出业务数据对象并返回;
2、将该Decoder通过配置类注册到IOC容器中,并将该配置类设置为Feign的默认配置类;
示例代码如下:
package com.ljc.conf;
import com.ljc.common.CommonResp;
import com.ljc.util.JsonUtil;
import feign.FeignException;
import feign.RequestInterceptor;
import feign.Response;
import feign.codec.DecodeException;
import feign.codec.Decoder;
import feign.optionals.OptionalDecoder;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Lookup;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.FeignClientsConfiguration;
import org.springframework.cloud.openfeign.support.HttpMessageConverterCustomizer;
import org.springframework.cloud.openfeign.support.ResponseEntityDecoder;
import org.springframework.cloud.openfeign.support.SpringDecoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Primary;
import java.io.IOException;
import java.lang.reflect.Type;
@Configuration
@EnableFeignClients(basePackages = "com.ljc" ,defaultConfiguration = CommonFeignConfig.class) // 设置EnableFeignClients的defaultConfiguration,将该配置类设置为Feign的默认配置类,这样FeignClient用的Decoder就是该配置类注入的Decoder
@Import(FeignClientsConfiguration.class) // 把原先的配置类的配置内容引入到该配置类中
public class CommonFeignConfig {
@Resource
private Decoder originalDecoder; // 获取原先的Decoder
@Bean
public RequestInterceptor commonRequestInterceptor() {
return new MyHeaderInterceptor();
}
@Bean
public Decoder customDecoder() {
return new CommonDecoder(originalDecoder);
}
private static class CommonDecoder implements Decoder {
private Decoder delegate;
public CommonDecoder(Decoder delegate) {
this.delegate = delegate;
}
@Override
public Object decode(Response response, Type type) throws IOException, FeignException {
Object decode = delegate.decode(response, type);
if (decode instanceof String) {
CommonResp<?> resp = (CommonResp<?>) JsonUtil.toObject((String) decode, CommonResp.class);
return resp == null ? decode : resp.getData();
}
return (decode instanceof CommonResp ? ((CommonResp<?>) decode).getData() : decode);
}
}
}