非springboot项目使用原生feign减少模板代码(十五)

说明

对于老项目 比如非spring boot项目,我们不能使用spring cloud的feign 可以采用原生的写法。spring cloud feign本质也是用原生,只是进行了封装 让我们可以采用更友好的方式使用

调用远程接口传统写法

为了保证复用性,会手动将外部依赖服务写入

 /**
     * 实人认证
     * @param verifyThreeMetaAndBindReqDto
     * @return
     */
    @Override
    public VerifyThreeMetaAndBindResDto verifyThreeMetaAndBind(VerifyThreeMetaAndBindReqDto verifyThreeMetaAndBindReqDto) {
        VerifyThreeMetaAndBindResDto verifyThreeMetaAndBindResDto = null;
        try {
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
            headers.add("Accept", MediaType.APPLICATION_JSON.toString());
            String contentStr = JsonUtils.obj2Json(verifyThreeMetaAndBindReqDto);
            HttpEntity<String> requestEntity = new HttpEntity<>(contentStr, headers);
            LocalLoadBalanceRestTemplate restTemplate = oauth2RestTemplateFactory.create(projectCode);

            ResponseEntity<String> responseEntity = restTemplate.postForEntity("/openapi/members/verifyThreeMetaAndBind", requestEntity, String.class);

            JSONObject jsonObjectResult = JSONObject.parseObject(responseEntity.getBody());

            if(log.isDebugEnabled()){
                log.debug("入参:{}",JSON.toJSONString(requestEntity));
                log.debug("预约返回结果:{}",JSON.toJSONString(jsonObjectResult));
            }
            if (jsonObjectResult != null) {
                if ((Integer) jsonObjectResult.get("code") == 200) {
                    verifyThreeMetaAndBindResDto = JSONObject.parseObject(jsonObjectResult.get("data").toString(), VerifyThreeMetaAndBindResDto.class);
                } else {
                    verifyThreeMetaAndBindResDto = new VerifyThreeMetaAndBindResDto();
                    verifyThreeMetaAndBindResDto.setVerifyMsg(jsonObjectResult.get("msg") != null ? jsonObjectResult.get("msg").toString() : null);
                    verifyThreeMetaAndBindResDto.setVerifyResult(jsonObjectResult.get("code").toString());
                }
            } else {
                String traceId = ArmsUtils.getTraceId();
                verifyThreeMetaAndBindResDto = new VerifyThreeMetaAndBindResDto();
                verifyThreeMetaAndBindResDto.setVerifyResult("notResponse");
                verifyThreeMetaAndBindResDto.setVerifyMsg(String.format("未返回数据异常编号:%s", traceId));
                log.error("异常编号:{}接口调用/verifyThreeMetaAndBind数据异常,返回数据null,入参:{}", traceId, JSON.toJSONString(verifyThreeMetaAndBindReqDto));
            }
        } catch (Exception e) {
            String traceId = ArmsUtils.getTraceId();
            verifyThreeMetaAndBindResDto = new VerifyThreeMetaAndBindResDto();
            verifyThreeMetaAndBindResDto.setVerifyResult("notReponse");
            verifyThreeMetaAndBindResDto.setVerifyMsg(String.format("未返回数据异常编号:%s", traceId));
            log.error("异常编号:{}接口调用/verifyThreeMetaAndBind数据异常,入参:{}", traceId, JSON.toJSONString(verifyThreeMetaAndBindReqDto),e);
        }
        return verifyThreeMetaAndBindResDto;
    }

改为feign

引入pom依赖

<!--feign核心包依赖-->
        <dependency>
            <groupId>com.netflix.feign</groupId>
            <artifactId>feign-core</artifactId>
            <version>8.18.0</version>
        </dependency>
        <!--使用包里里面封装的对于请求响应参数的序列化和反序列化处理-->
        <dependency>
            <groupId>com.netflix.feign</groupId>
            <artifactId>feign-jackson</artifactId>
            <version>8.18.0</version>
        </dependency>
        <!--使用扩展功能熔断降级-->
        <dependency>
            <groupId>com.netflix.feign</groupId>
            <artifactId>feign-hystrix</artifactId>
            <version>8.18.0</version>
        </dependency>
        <!--使用feign接入slf4j的功能-->
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-slf4j</artifactId>
            <version>9.7.0</version>
            <scope>compile</scope>
        </dependency>

定义接口

/**
 * @author liqiang
 * @date 2020/9/7 10:26
 * @Description: (what) 外部接口的抽象定义,以及定义调用形式
 * (why)使用feign的方式生成代理调用api 减少模板代码
 * (how)FeignApiConfig 定义
 */
public interface PromotionApi {

    @Headers({"Content-Type: application/json", "Accept: application/json"})
    @RequestLine("POST /promotion/app/maotaiBooking/getActivityInfo")
    public JsonResult<GetActivityInfoResVo> getActivityInfo(GetActivityInfoReqVo getActivityInfoReqVo);

    @Headers({"Content-Type: application/json", "Accept: application/json"})
    @RequestLine("POST /publicapi/v2/promotion/activity/list")
    public JsonResult<SpringPageVO<PromotionInfoVo>> list(PromotionQueryVo promotionQueryVo);

    @Headers({"Content-Type: application/json", "Accept: application/json"})
    @RequestLine("POST /publicapi/v2/promotion/activity/enable")
    public JsonResult enable(PromotionOperateVo promotionOperateVo);

    @Headers({"Content-Type: application/json", "Accept: application/json"})
    @RequestLine("POST /publicapi/v2/promotion/activity/detailedQuery/{id}")
    public JsonResult<PromotionDetailedInfoVo> detailedQuery(@Param("id") Long id);

    @Headers({"Content-Type: application/json", "Accept: application/json"})
    @RequestLine("POST /publicapi/v2/promotion/activity/saveOrUpdate")
    public JsonResult saveOrUpdate(PromotionCreateVo promotionCreateVo);


    @Headers({"Content-Type: application/json", "Accept: application/json"})
    @RequestLine("POST /publicapi/v2/promotion/activity/delete")
    public JsonResult delete(PromotionOperateVo promotionOperateVo);

    @Headers({"Content-Type: application/json", "Accept: application/json"})
    @RequestLine("POST /publicapi/v2/promotion/activity/riskEs")
    public JsonResult<List<PromotionActiveMatchRespVo>> riskEs(PromotionActiveMatchSearchReqVo reqVo);
}

配置

package com.biz.bbc.config.feign;

import com.biz.bbc.config.ApiAddressConfig;
import com.biz.bbc.service.external.PromotionApi;
import com.biz.bbc.service.external.TestHttpsApi;
import com.biz.ut.helper.Oauth2ResourceServerExecutor;
import feign.*;
import feign.hystrix.HystrixFeign;
import feign.jackson.JacksonDecoder;
import feign.jackson.JacksonEncoder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author liqiang
 * @date 2020/9/7 10:24
 * @Description: (what)
 * (why)
 * (how)
 */
//demo

/**
 * HystrixFeign.builder()
 * .encoder(new JacksonEncoder()) //编码
 * .decoder(new JacksonDecoder()) //解码
 * //建立链接http超时1秒 请求处理3秒超时
 * .options(new Request.Options(1000, 3500))
 * //每次重试间隔和最大间隔 默认是5次
 * .retryer(new Retryer.Default(5000, 5000, 3))
 * //降级
 * .target(PromotionApi.class, "http://localhost:9905", new PromotionApi() {
 *
 * @Override public JsonResult<GetActivityInfoResVo> getActivityInfo(GetActivityInfoReqVo getActivityInfoReqVo) {
 * log.error("com.biz.bbc.service.external.PromotionApi.getActivityInfoHttp异常降级,入参:{}", JSON.toJSON(getActivityInfoReqVo));
 * return JsonResult.of(null);
 * }
 * });
 */

@Configuration
@Slf4j
public class FeignApiConfig {

    @Autowired
    private ApiAddressConfig apiAddressConfig;

    @Autowired
    private Oauth2ResourceServerExecutor oauth2ResourceServerExecutor;

    @Bean
    public PromotionApi initPromotionApi() {
        return HystrixFeign.builder()
                .encoder(new JacksonEncoder())
                .decoder(new JacksonDecoder())
                .logger(new feign.slf4j.Slf4jLogger(PromotionApi.class))
                .requestInterceptor(new RequestInterceptor() {
                    @Override
                    public void apply(RequestTemplate requestTemplate) {
                        //设置token
                        requestTemplate.header("Authorization", "accessToken" + oauth2ResourceServerExecutor.getAccessToken());
                    }
                })//默认会重试5次 不重试
                .retryer(NeverRetry.neverRetry)
                .logLevel(Logger.Level.FULL)
                //建立链接http超时1秒 请求处理3秒超时
                .options(new Request.Options(1000, 3500))
                .target(PromotionApi.class, apiAddressConfig.promotionCenterDomain);
    }

    @Bean
    public TestHttpsApi TestHttpsApi() {
        return HystrixFeign.builder()
                .encoder(new JacksonEncoder())
                .decoder(new JacksonDecoder())
                .logger(new feign.slf4j.Slf4jLogger(PromotionApi.class))
                .requestInterceptor(new RequestInterceptor() {
                    @Override
                    public void apply(RequestTemplate requestTemplate) {
                        //设置token
                        requestTemplate.header("Authorization", "accessToken" + oauth2ResourceServerExecutor.getAccessToken());
                    }
                })//默认会重试5次 不重试
                .retryer(NeverRetry.neverRetry)
                .logLevel(Logger.Level.FULL)
                //建立链接http超时1秒 请求处理3秒超时
                .options(new Request.Options(1000, 3500))
                .target(TestHttpsApi.class, " https://swagger-hub.1919.cn");
    }

    /**
     * 自定义实现不重试的Retryer
     */
    public static class NeverRetry implements Retryer {

        public final static NeverRetry neverRetry = new NeverRetry();

        private NeverRetry() {

        }

        @Override
        public void continueOrPropagate(RetryableException e) {
            //不重试
            throw e;
        }

        @Override
        public Retryer clone() {
            return this;
        }
    }
}
原文地址:https://www.cnblogs.com/LQBlog/p/13722529.html