feign简化远程调用

    没接触过feign之前,调用第三方接口都是通过httpclient,通过编写工具类实现,这种方式代码量很多,相比较feign调用来说特别繁琐,而feign简化底层http调用方式,通过feign.builder.target传入调用接口和地址即可完成调用吗,代码量相当少。

httpClient方式

httpclient工具类:

package com.fh.oa.apply.util;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.log4j.Log4j2;
import org.apache.http.StatusLine;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.util.Map;

/**
 * @author wangzewei
 * @ClassName HttpClientUtils
 * @Description 调用工具类,目前只提供get和post,其他请求方式,有需要在添加
 * @Date 2021/7/27 9:43
 */
@Log4j2
public class HttpClientUtils {

    /**
     * 发送get请求,无参
     * @param url 请求地址
     * @return
     */
    public static String get(String url){
        return getWithParam(url,null);
    }
    /**
     * 发送get请求,有参
     * @param url 请求地址
     * @param map 携带参数
     * @return 返回json串
     */
    public static String getWithParam(String url, Map<String,Object> map){
        //返回的json结果
        String jsonResponse="";
        //client对象
        CloseableHttpClient client = HttpClientBuilder.create().build();
        //get请求对象
        HttpGet hGet=null;
        String uri="";
        // 配置连接参数
        RequestConfig requestConfig = RequestConfig.custom()
                // 设置连接超时时间
                .setConnectTimeout(5000)
                // 设置请求超时时间
                .setConnectionRequestTimeout(5000)
                // socket读写超时时间
                .setSocketTimeout(5000)
                // 设置是否允许重定向
                .setRedirectsEnabled(true).build();
        //解析参数 key=xxx
        StringBuilder sb=new StringBuilder();
        if(null!=map){
            map.keySet().forEach(s -> sb.append(s).append("=").append(map.get(s)).append("&"));
            //去掉多于的&
            sb.deleteCharAt(sb.length() - 1);
            uri=url+"?"+sb.toString();
            hGet=new HttpGet(uri);
        }else{
            uri=url;
            hGet=new HttpGet(uri);
        }
        log.info("本次Get调用地址:"+uri);
        hGet.setConfig(requestConfig);
        //响应
        CloseableHttpResponse response=null;
        try {
            response = client.execute(hGet);
            StatusLine statusLine = response.getStatusLine();
            if(null!=response.getEntity()&&200==statusLine.getStatusCode()){
                jsonResponse = EntityUtils.toString(response.getEntity());
            }else{
                log.error("Get请求返回异常");
            }
        } catch (IOException e) {
            e.printStackTrace();
            log.error("Get请求执行失败");
        }finally {
            try {
                if(null!=client){
                    client.close();
                }
                if(null!=response){
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return jsonResponse;
    }

    /**
     * 发送post请求,无参
     * @param url 请求地址
     * @return
     */
    public static String post(String url){
        return postWithParam(url,null);
    }

    /**
     * 发送post请求,map参数转json格式传递
     * @param url 请求地址
     * @param map 请求参数
     * @return json字符串
     */
    public static String postWithParam(String url, Map<String,Object> map){
        //返回的json结果
        String jsonResponse="";
        //client对象
        CloseableHttpClient client = HttpClientBuilder.create().build();
        //post请求对象
        HttpPost hPost=new HttpPost(url);
        if(null!=map){
            //map对象转json字符串
            String jsonString = new JSONObject(map).toJSONString();
            StringEntity stringEntity=new StringEntity(jsonString,"UTF-8");
            //将参数放在post请求体中
            hPost.setEntity(stringEntity);
        }
        //设置请求头
        hPost.setHeader("Content-Type", "application/json;charset=utf-8");

        //响应
        CloseableHttpResponse response=null;
        try {
            response = client.execute(hPost);
            StatusLine statusLine = response.getStatusLine();
            if(null!=response.getEntity()&&200==statusLine.getStatusCode()){
                jsonResponse = EntityUtils.toString(response.getEntity());
            }else{
                log.error("Post请求执行异常");
            }
        } catch (IOException e) {
            e.printStackTrace();
            log.error("Post请求执行失败");
        }finally {
            try {
                if(null!=client){
                    client.close();
                }
                if(null!=response){
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return jsonResponse;
    }
}
/**
 * @author wangzewei
 * @ClassName Common
 * @Description 接口调用时通用参数
 * @Date 2021/7/27 15:29
 */
public class Common {

    public static Map<String,Object> getCommon(){
        Map<String ,Object> map=new HashMap<>();
        map.put("isEncrypt", false);
        map.put("random", UUID.randomUUID());
        map.put("timestamp", new Date().getTime());
        return map;
    }
}

调用方式:

public String getToken(){
    //common参数
    Map<String, Object> map = Common.getCommon();
    //登录认证
    AuthInfo info=new AuthInfo(){{
        setAccount("ab8d181174a942088616381525e078a7");
        setPassword("SHOCvfyYtjL5xFU5JAM4");
    }};
    map.put("param",info);
    String response = HttpClientUtils.postWithParam(tokenUrl, map);
    String accessToken="";
    // TODO: 2021/7/27 感觉这块不用存redis,获取的token有过期时间,而且在监听中可以直接取到token的值
    if(null!=response){
        //json转成map
        Map map1 = JSON.parseObject(response, Map.class);
        JSONObject data = (JSONObject)map1.get("data");
        accessToken= (String)data.get("accessToken");
        //存redis
        redisService.setKey("accessToken",accessToken);
    }
    //返回token串
    return accessToken;
}

feign简化调用方式

feign绑定接口:

参数对象:

 

返回值对象:

 

 

调用方式:

TongChengService t = Feign.builder().target(TongChengService.class, "http://api.qa.dttrip.cn/openapi/api");

这么调用会报异常

翻译过来就是带feign的调用方式是个mvc的调用方式不共通,可以采用编写service类,导入feign的配置解决 

 feign的实现类:

package com.fh.oa.feign;

import java.io.BufferedReader;
import java.io.IOException;
import java.util.Enumeration;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.openfeign.FeignClientsConfiguration;
import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.alibaba.fastjson.JSONObject;
import com.codingapi.txlcn.tracing.Tracings;

import feign.Client;
import feign.Contract;
import feign.Feign;
import feign.RequestInterceptor;
import feign.Response;
import feign.codec.Decoder;
import feign.codec.Encoder;
import feign.codec.ErrorDecoder;
import lombok.extern.log4j.Log4j2;

@Service
@Import(FeignClientsConfiguration.class)
@Log4j2
public class FeignServiceImpl implements FeignService {

   private final Feign.Builder urlBuilder;

   private final Feign.Builder nameBuilder;

   private HttpServletRequest cacheRequest;

   @Autowired
   public FeignServiceImpl(Decoder decoder, Encoder encoder, Client client, Contract contract) {
      // nameBuilder直接使用client,它会使用负载均衡
      nameBuilder = Feign.builder().client(client).encoder(encoder).decoder(decoder).contract(contract)
            .requestInterceptor(requestInterceptor()).errorDecoder(errorDecoder());

      if (client instanceof LoadBalancerFeignClient) { // 均衡负载
         client = ((LoadBalancerFeignClient) client).getDelegate();
      }
      urlBuilder = Feign.builder().client(client).encoder(encoder).decoder(decoder).contract(contract)
            .requestInterceptor(requestInterceptor()).errorDecoder(errorDecoder());
   }
   @Override
   public <T> T newInstanceByUrl(Class<T> apiType, String url) {
      return urlBuilder.target(apiType, url);
   }

   @Override
   public <T> T newInstanceByName(Class<T> apiType, String name) {
      return nameBuilder.target(apiType, name);
   }

   @Override
   public <T> T newInstanceByUrl(Class<T> apiType, String url, HttpServletRequest request) {
      this.cacheRequest = request;
      return urlBuilder.target(apiType, url);
   }

   @Override
   public <T> T newInstanceByName(Class<T> apiType, String name, HttpServletRequest request) {
      this.cacheRequest = request;
      return nameBuilder.target(apiType, name);
   }
}

 调用:

对比更简单 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Feign是一个声明式的Web服务客户端,它可以简化远程服务调用的过程。通过使用Feign,我们可以像调用本地方法一样调用远程服务。 Feign的远程调用过程如下: 1. 首先,我们需要在项目中引入Feign的依赖。 2. 然后,我们需要定义一个接口,该接口用于描述远程服务的API。在接口中,我们可以使用注解来定义请求的URL、请求方法、请求参数等信息。 3. 接着,我们需要创建一个Feign客户端,该客户端会根据接口的定义自动生成具体的实现代码。 4. 最后,我们可以在业务代码中直接调用该接口的方法,Feign会自动将方法调用转换为HTTP请求,并发送给远程服务。 下面是一个使用Feign进行远程调用的示例: 1. 引入Feign的依赖: ```xml <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> ``` 2. 定义远程服务的API接口: ```java @FeignClient(name = "service-provider") // 指定远程服务的名称 public interface UserService { @GetMapping("/users/{id}") User getUserById(@PathVariable("id") Long id); } ``` 3. 创建Feign客户端: ```java @Configuration @EnableFeignClients public class FeignConfig { } ``` 4. 在业务代码中调用接口方法: ```java @RestController public class UserController { @Autowired private UserService userService; @GetMapping("/users/{id}") public User getUserById(@PathVariable("id") Long id) { return userService.getUserById(id); } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值