Open-Feign在实际工作中使用

公司系统与第三方合作多,需调用第三方接口,open - feign很实用。介绍了使用Java调用第三方接口的步骤,包括引入Jar包、application配置、Feign配置,因第三方接口有token限制,还说明了Token的存储、获取、调用及在Feign中设置token,解决Token刷新问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

引入Jar包

 <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
    <version>2.2.4.RELEASE</version>
</dependency>

<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-httpclient</artifactId>
    <version>10.10.1</version>
</dependency>

主要是引入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

启用Feign

# 启动程序加入注解
@EnableFeignClients

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 {
        }
    }
}

调用第三方接口

@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);
}

正常根据上面的代码,就能正常调用第三方接口,但是第三方接口做了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<String,String> 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);
    }
}

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");
    }
}

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);
        }
    }
}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值