Using native Feign is appropriate for SpringMVC projects. The time spent on configuration and a few potholes didn’t feel like it was worth it. Wish there were not so many configurations in the world.

Add dependencies

 <! -- Feign client -->
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-httpclient</artifactId>
            <version>9.7.0</version>
        </dependency>
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-core</artifactId>
            <version>9.7.0</version>
        </dependency>
        <! -- Jackson serialization () -- Jackson serialization ()
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-jackson</artifactId>
            <version>9.7.0</version>
        </dependency>
        <! -- okHTTP is used by the client.
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-okhttp</artifactId>
            <version>11.1</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.48. Sec06</version>
        </dependency>

        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>22.0</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.8</version>
            <scope>provided</scope>
        </dependency>
Copy the code

Second, Feign configuration HTTP

/ * * *@author chris wang
 * @dateApril 23, 2021 9:17 *@descriptionFeign HTTP configuration */
@Configuration
public class FeignClientConfiguration {

    @Autowired
    private Contract environmentFeignContract;

    @Bean
    public Feign feign(a) {
        return Feign.builder() // Create the feign builder
                .encoder(new JacksonEncoder())  / / JSON encoding
                .decoder(new MyDecoder()) / / JSON decode
                .options(new Request.Options(1000.3500))  // Set timeout
                .retryer(new Retryer.Default(5000.5000.2)).contract(environmentFeignContract).
                        build();  // Set retry}}Copy the code
/ * * *@author chris wang
 * @dateApril 23, 2021 9:16 *@descriptionCustom parse ApiClient annotation placeholder $vipToken */
public abstract class AbstractFeignContract extends Contract.Default {

    @Override
    protected void processAnnotationOnClass(MethodMetadata data, Class
        targetType) {
        super.processAnnotationOnClass(data, targetType);
        handleHeaders(data);
    }

    @Override
    protected void processAnnotationOnMethod(MethodMetadata data, Annotation annotation, Method method) {
        super.processAnnotationOnMethod(data, annotation, method);
        handleHeaders(data);
    }

    @Override
    protected boolean processAnnotationsOnParameter(MethodMetadata data, Annotation[] annotations, int paramIndex) {
        return super.processAnnotationsOnParameter(data, annotations, paramIndex);
    }

    private void handleHeaders(MethodMetadata data) {
        if (data == null || CollectionUtils.isEmpty(data.template().headers())) return;
        for (Map.Entry<String, Collection<String>> entry : data.template().headers().entrySet()) {
            if (StringUtils.isEmpty(entry.getKey())) continue;
            Collection<String> values = entry.getValue();
            if (CollectionUtils.isEmpty(values)) continue;
            Collection<String> result = Lists.newArrayList();
            Collection<String> exludes = Lists.newArrayList();
            for (String val : values) {
                exludes.add(val);
                if (val.startsWith(PlaceholderConfigurerSupport.DEFAULT_PLACEHOLDER_PREFIX) && val.endsWith(PlaceholderConfigurerSupport.DEFAULT_PLACEHOLDER_SUFFIX)) {
                    String placeholder = val.substring(val.indexOf(PlaceholderConfigurerSupport.DEFAULT_PLACEHOLDER_PREFIX) + 2, val.indexOf(PlaceholderConfigurerSupport.DEFAULT_PLACEHOLDER_SUFFIX)); val = findProperty(placeholder); } result.add(val); } values.removeAll(exludes); values.addAll(result); }}public abstract String findProperty(String key);
}
Copy the code
/ * * *@author chris wang
 * @dateApril 27, 2021 12:55 *@descriptionThe properties for * /
@Configuration
public class EnvironmentFeignContract extends AbstractFeignContract {

    @Autowired
    private Environment environment;

    @Override
    public String findProperty(String key) {
        returnenvironment.getProperty(key); }}Copy the code
/ * * *@author chris wang
 * @dateApril 23, 2021 9:17 *@descriptionDefine decoding rules */
public class MyDecoder extends JacksonDecoder {

    @Override
    public Object decode(Response response, Type type) throws IOException {
        // Wrap an IocResponse
      
        Type wapperType = ParameterizedTypeImpl.make(MyResponse.class, new Type[]{
                type
        }, null);
        Object decodeObj = super.decode(response, wapperType);
        if(decodeObj ! =null && decodeObj instanceof MyResponse) {
            MyResponse iocResponse = (MyResponse) decodeObj;
            if(! iocResponse.isSuccess())throw new RuntimeException(iocResponse.getMessage());
            return iocResponse.getData();
        }
        throw newRuntimeException(JSON.toJSONString(decodeObj)); }}Copy the code

Define an ApiClient

/ * * *@author chris wang
 * @dateApril 23, 2021 9:16 *@descriptionAPI client */
public interface ApiClient {

    @Headers({"Content-Type: application/json", "Accept: application/json", "viptoken: ${viptoken}"})
    @RequestLine("POST /my/api/system_metric/continuous_build")
    List<ContinuousBuildResp> getContinuousBuild(ContinuousBuildReq req);
}

Copy the code

Define a Client factory

/ * * *@author chris wang
 * @dateApril 23, 2021 9:16 *@descriptionDefine a Client factory */
@Configuration
public class FeignClientApiFactory {

    @Value("${myUrl}")
    private String myUrl;

    @Autowired
    private Feign feign;

    @Bean
    public ApiClient getMyApi(a) {
        return feign.newInstance(newTarget.HardCodedTarget<>(ApiClient.class, myUrl)); }}Copy the code

5, generic Response

/ * * *@author chris wang
 * @dateApril 27, 2021 9:28 *@descriptionUse a return */ of generics
public class MyResponse<T> {

    private String message;
    private boolean success;
    private T data;

    public String getMessage(a) {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public boolean isSuccess(a) {
        return success;
    }

    public void setSuccess(boolean success) {
        this.success = success;
    }

    public T getData(a) {
        return data;
    }

    public void setData(T data) {
        this.data = data; }}Copy the code

Other categories

/ * * *@author chris wang
 * @dateApril 27, 2021 9:28 *@description* /
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ContinuousBuildResp {

    private int ci_num;
    private int ci_score;
    private int ci_success_num;
    private String ci_success_rate;
    private String rank;
}
Copy the code
/ * * *@author chris wang
 * @dateApril 27, 2021 9:28 *@description* /
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
public class ContinuousBuildReq {

    private String date_type;
    private String start_time;
    private String end_time;
}
Copy the code

Seven, application properties

MyUrl =http://localhost:8090 vipToken = XXXXXXXXX reference:

www.hicode.club/articles/20… www.cnblogs.com/zby9527/p/1… Blog.csdn.net/weixin_3406…