• Open-Feign在实际工作中使用


    现在我们公司的系统跟第三方合作比较多,所以难以避免的需要调用第三方接口,open-feign这个就非常实用,刚好总结一下,在实际工作中,如何方便地调用第三方接口。

    引入Jar包

     
        org.springframework.cloud
        spring-cloud-starter-openfeign
        2.2.4.RELEASE
    
    
    
        io.github.openfeign
        feign-httpclient
        10.10.1
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    主要是引入openfeign,然后再用httpclient进行优化。

    application配置

    # 启用Httpclient
    feign.httpclient.enabled=true
    feign.httpclient.disable-ssl-validation=true
    # 超时时间设置
    feign.client.config.default.connectTimeout=5000
    feign.client.config.default.readTimeout=5000
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    启用Feign

    # 启动程序加入注解
    @EnableFeignClients
    
    • 1
    • 2

    Feign配置

    基础配置

    import feign.Client;
    import feign.Feign;
    import feign.Logger;
    import org.apache.http.conn.ssl.NoopHostnameVerifier;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLSocketFactory;
    import javax.net.ssl.TrustManager;
    import javax.net.ssl.X509TrustManager;
    
    @Configuration
    public class FeignConfig {
    
        @Bean
        Logger.Level feignLoggerLevel(){
            return Logger.Level.FULL;
        }
    
        //绕过HTTPS
        @Bean
        public Feign.Builder feignBuilder() {
            final Client trustSSLSockets = client();
            return Feign.builder().client(trustSSLSockets);
        }
    
        public static SSLSocketFactory feignTrustingSSLSocketFactory = null;
    
        @Bean
        public Client client() {
            if(feignTrustingSSLSocketFactory==null){
                try {
                    feignTrustingSSLSocketFactory = getFeignTrustingSSLSocketFactory();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return new Client.Default(feignTrustingSSLSocketFactory, new NoopHostnameVerifier());
        }
    
        public static SSLSocketFactory getFeignTrustingSSLSocketFactory() throws Exception {
            TrustManager[] trustAllCerts = new TrustManager[1];
            TrustManager tm = new miTM();
            trustAllCerts[0] = tm;
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, null);
            return sc.getSocketFactory();
        }
        static class miTM implements TrustManager, X509TrustManager {
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }
    
            public boolean isServerTrusted(java.security.cert.X509Certificate[] certs) {
                return true;
            }
    
            public boolean isClientTrusted(java.security.cert.X509Certificate[] certs) {
                return true;
            }
    
            public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType)
                    throws java.security.cert.CertificateException {
            }
    
            public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType)
                    throws java.security.cert.CertificateException {
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71

    调用第三方接口

    @FeignClient(name = "feign-api",
            url = "http://localhost:8081/",
            configuration = {FeignConfig.class, FeignInterceptor.class})
    public interface FeignApi {
    
        @GetMapping("/api/getToken")
        String getToken(@RequestParam("appKey") String appKey, @RequestParam("appSecret") String appSecret);
    
        @PostMapping("/api/pushInfo")
        String pushInfo(@RequestBody BoardMessage boardMessage);
    
        @PostMapping("/api/pushIndex")
        String pushIndex(@RequestBody WarnOrder warnOrder);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    正常根据上面的代码,就能正常调用第三方接口,但是第三方接口做了token限制,就是token是15分钟失效,调用接口header必须携带token,所以我们还需要对上述代码做一些调整。

    Token设置

    Token的存储和获取

    import java.util.concurrent.ConcurrentHashMap;
    
    public class TokenStore {
        public static final String TOKEN = "token";
    
        public static final ConcurrentHashMap TOKEN_STORE = new ConcurrentHashMap<>(1);
    
        public static void saveToken(String token){
            TOKEN_STORE.put(TOKEN,token);
        }
    
        public static String getToken(){
            return TOKEN_STORE.get(TOKEN);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    Token 的调用

    代码中要考虑到失效刷新和多线程并发问题

    @Component
    @Slf4j
    public class RefreshToken {
    
        @Value("${appKey}")
        private String appKey;
        @Value("${appSecret}")
        private String appSecret;
    
        //60s
        public final long MAX_TIME_INTERVAL = 60;
    
        @Resource
        private FeignApi feignApi;
    
        public synchronized void makeSureNoExpireToken(){
            long currentTime = System.currentTimeMillis()/1000;
            if(null == TokenStore.getToken() ||
                    (getExpireTime(TokenStore.getToken()) - currentTime) <= MAX_TIME_INTERVAL){
                // 获取Token
                String result = feignApi.getToken(appKey,appSecret);
                if(!StringUtils.isEmpty(result)){
                    JSONObject jsonObject = JSONUtil.parseObj(result);
                    if(jsonObject.getInt("code")==1){
                        log.info("正常获取Token");
                        TokenStore.saveToken(jsonObject.getStr("data"));
                    }
                }
            }
        }
    
        private long getExpireTime(String token){
            JWT jwt = JWTUtil.parseToken(token);
            return jwt.getPayloads().getLong("exp");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    Feign中设置token

    @Component
    public class FeignInterceptor implements RequestInterceptor {
    
        @Resource
        private RefreshToken refreshToken;
    
        @Override
        public void apply(RequestTemplate template) {
            String url = template.url();
            log.info("apply url is : {}",url);
            if(!url.startsWith("/api/getToken")){
                String name = "token";
                // 1.先确保Token在有效期内  2.获取token
                refreshToken.makeSureNoExpireToken();
                String value = TokenStore.getToken();
                log.info("current the cloud token is : {}",value);
                //同理可以放入Cookie
                template.header(name, value);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    这样我们就能正常调用第三方接口,而且不需要担心Token刷新问题。

  • 相关阅读:
    Intel E810 Advanced RSS介绍
    4、在docker容器内的tomcat 中发布项目
    程序员保密协议(合资合作)[范本]
    Layui快速入门之第八节 表格渲染与属性的使用
    【CSDN竞赛解析】使用n位定点数编码方案,最多能够.| 在同时涉及极大和极小浮点数值的算法.| 使用IEEE754标准,可以准确.| 路灯亮度:有一条长度为n米的街道.| 池塘水量:某地有n个池塘,
    JS中对象
    花呗不小心升级了信用购会影响什么
    网络拓扑图怎么画最好?
    Android ViewBinding和DataBinding的几个使用方式 - 上
    RDMA 优势
  • 原文地址:https://blog.csdn.net/flash_love/article/details/133276974