说明
对于老项目 比如非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; } } }