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 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 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 getCommon(){
        Map 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 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绑定接口:

feign简化远程调用_第1张图片

参数对象:

feign简化远程调用_第2张图片

feign简化远程调用_第3张图片 

返回值对象:

feign简化远程调用_第4张图片 

 

调用方式:

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 newInstanceByUrl(Class apiType, String url) {
      return urlBuilder.target(apiType, url);
   }

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

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

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

 调用:

feign简化远程调用_第5张图片

对比更简单 

你可能感兴趣的:(基础,spring,cloud,java)