SpringBoot脫離SpringCloud使用Feign

快速導(dǎo)航

添加依賴

Maven

Feign 聲明式http請求調(diào)用輕量級框架

在項目的 pom.xml 的 dependencies 中加入以下內(nèi)容:

<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-core</artifactId>
    <version>9.5.1</version>
</dependency>
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-slf4j</artifactId>
    <version>9.5.1</version>
</dependency>
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-hystrix</artifactId>
    <version>9.5.1</version>
</dependency>
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-jackson</artifactId>
    <version>9.5.1</version>
</dependency>
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-okhttp</artifactId>
    <version>9.5.1</version>
</dependency>

添加核心配置類

在項目中新增 TestFeignConfig 核心配置類俯艰,代碼如下:

package com.boot.component.test.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.boot.component.test.client.TestApiFeignClient;
import com.boot.component.test.log.TestApiFeignLogger;

import feign.Feign;
import feign.Logger;
import feign.Request;
import feign.Retryer;
import feign.jackson.JacksonDecoder;
import feign.jackson.JacksonEncoder;
import feign.okhttp.OkHttpClient;

/**
 * @Description: FeignClient的配置類
 * @author Lord
 * @date 2019年12月16日
 */
@Configuration
public class TestFeignConfig {

    /**
     * FeignClient 配置
     * @return
     */
    @Bean
    TestApiFeignClient testApiFeignClient() {
        return Feign.builder()
                .client(new OkHttpClient())
                .logger(new TestApiFeignLogger())
                .logLevel(Logger.Level.FULL)
                .encoder(new JacksonEncoder())
                .decoder(new JacksonDecoder())
                .options(new Request.Options(1000, 3500))
                .retryer(new Retryer.Default(5000, 5000, 3))
                .target(TestApiFeignClient.class, "http://127.0.0.1:8085");
    }
}

添加日志配置類

在項目中新增 TestApiFeignLogger 日志配置類谓娃,代碼如下:

package com.boot.component.test.log;

import java.io.IOException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import feign.Request;
import feign.Response;

public class TestApiFeignLogger extends feign.Logger {

    private final Logger logger;

    public TestApiFeignLogger() {
        this(feign.Logger.class);
    }

    public TestApiFeignLogger(Class<?> clazz) {
        this(LoggerFactory.getLogger(clazz));
    }

    public TestApiFeignLogger(String name) {
        this(LoggerFactory.getLogger(name));
    }

    TestApiFeignLogger(Logger logger) {
        this.logger = logger;
    }

    @Override
    protected void logRequest(String configKey, Level logLevel, Request request) {
        if (logger.isInfoEnabled()) {
            super.logRequest(configKey, logLevel, request);
        }
    }

    @Override
    protected Response logAndRebufferResponse(String configKey, Level logLevel, Response response, long elapsedTime)
            throws IOException {
        if (logger.isInfoEnabled()) {
            return super.logAndRebufferResponse(configKey, logLevel, response, elapsedTime);
        }
        return response;
    }

    @Override
    protected void log(String configKey, String format, Object... args) {
        // Not using SLF4J's support for parameterized messages (even though it
        // would be more efficient) because it would
        // require the incoming message formats to be SLF4J-specific.
        if (logger.isInfoEnabled()) {
            logger.info(String.format(methodTag(configKey) + format, args));
        }
    }
}

添加遠(yuǎn)程調(diào)用服務(wù)類

在項目中新增 TestApiFeignClient 遠(yuǎn)程調(diào)用服務(wù)類零蓉,代碼如下:

package com.boot.component.test.client;

import java.util.List;
import java.util.Map;

import com.boot.component.test.common.CommonReturnType;
import com.boot.component.test.model.response.AccessTokenOutput;
import com.boot.component.test.model.response.area.AddressOutput;

import feign.Headers;
import feign.QueryMap;
import feign.RequestLine;

/**
 * @Description: feignClient的接口(遠(yuǎn)程調(diào)用服務(wù)類)
 * @author Lord
 * @date 2019年12月16日
 */
@Headers("Content-Type:application/x-www-form-urlencoded")
public interface TestApiFeignClient {

    @RequestLine("POST /oauth2/accessToken")
    CommonReturnType<AccessTokenOutput> getAccessToken(@QueryMap Map<String, Object> params);

    @RequestLine("POST /oauth2/refreshToken")
    CommonReturnType<AccessTokenOutput> getRefreshToken(@QueryMap Map<String, Object> params);
}

請求返回的最外層對象

在項目中新增 CommonReturnType<T> 請求返回的最外層對象類侠仇,代碼如下:

package com.boot.component.jd.common;

import java.io.Serializable;

/**
 * @Description: 請求返回的最外層對象
 * @author Lord
 * @date 2019年12月13日
 */
public class CommonReturnType<T> implements Serializable {

    private static final long serialVersionUID = -8797234859999337279L;

    /** 執(zhí)行結(jié)果成功炉媒,還是失敗. */
    private Boolean success;

    /** 錯誤碼. */
    private String resultCode;

    /** 提示信息. */
    private String resultMessage;

    private T result;

    public Boolean getSuccess() {
        return success;
    }

    public void setSuccess(Boolean success) {
        this.success = success;
    }

    public String getResultCode() {
        return resultCode;
    }

    public void setResultCode(String resultCode) {
        this.resultCode = resultCode;
    }

    public String getResultMessage() {
        return resultMessage;
    }

    public void setResultMessage(String resultMessage) {
        this.resultMessage = resultMessage;
    }

    public T getResult() {
        return result;
    }

    public void setResult(T result) {
        this.result = result;
    }

    @Override
    public String toString() {
        return "CommonReturnType [success=" + success + ", resultCode=" + resultCode + ", resultMessage="
                + resultMessage + ", result=" + result + "]";
    }

}

獲取AccessToken返回對象

在項目中新增 AccessTokenOutput 獲取AccessToken返回對象類,代碼如下:

package com.boot.component.test.model.response;

import java.io.Serializable;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;

/**
 * @Description: 獲取AccessToken返回對象
 * @author Lord
 * @date 2019年12月16日
 */
@JsonIgnoreProperties(ignoreUnknown = true)
public class AccessTokenOutput implements Serializable {

    private static final long serialVersionUID = 388723550621265373L;

    /**
     * 業(yè)務(wù)id
     */
    private String uid;

    /**
     * 訪問令牌精居,用于業(yè)務(wù)接口調(diào)用棒搜。(有效期24小時)
     */
    @JsonProperty("access_token")
    private String accessToken;

    /**
     * 當(dāng)access_token過期時,用于刷新access_token
     */
    @JsonProperty("refresh_token")
    private String refreshToken;

    /**
     * 當(dāng)前時間嘿般,時間戳格式:1551663377887
     */
    private Long time;

    /**
     * access_token的有效期段标,單位:秒,有效期24小時
     */
    @JsonProperty("expires_in")
    private Integer expiresIn;

    /**
     * refresh_token的過期時間炉奴,毫秒級別,時間戳
     */
    @JsonProperty("refresh_token_expires")
    private Long refreshTokenExpires;

    public String getUid() {
        return uid;
    }

    public void setUid(String uid) {
        this.uid = uid;
    }

    public String getAccessToken() {
        return accessToken;
    }

    public void setAccessToken(String accessToken) {
        this.accessToken = accessToken;
    }

    public String getRefreshToken() {
        return refreshToken;
    }

    public void setRefreshToken(String refreshToken) {
        this.refreshToken = refreshToken;
    }

    public Long getTime() {
        return time;
    }

    public void setTime(Long time) {
        this.time = time;
    }

    public Integer getExpiresIn() {
        return expiresIn;
    }

    public void setExpiresIn(Integer expiresIn) {
        this.expiresIn = expiresIn;
    }

    public Long getRefreshTokenExpires() {
        return refreshTokenExpires;
    }

    public void setRefreshTokenExpires(Long refreshTokenExpires) {
        this.refreshTokenExpires = refreshTokenExpires;
    }

}

調(diào)用示例

TestController

FeignTestController 測試Feign遠(yuǎn)程調(diào)用

FeignTestController 代碼如下:

package com.boot.controller.test;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.boot.component.test.client.TestApiFeignClient;
import com.boot.component.test.common.CommonReturnType;
import com.boot.component.test.model.response.AccessTokenOutput;
import com.xiaoleilu.hutool.json.JSONUtil;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@RestController
@RequestMapping("/feign/test")
public class FeignTestController {

    @Resource
    private TestApiFeignClient testApiFeignClient;

    @GetMapping
    public CommonReturnType<AccessTokenOutput> test() {
        String statDate = LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME);

        log.info("進(jìn)入Feign遠(yuǎn)程調(diào)用服務(wù)測試類逼庞,當(dāng)前時間:[{}]", statDate);

        Map<String, Object> params = new HashMap<>(2);
        params.put("username", "admin");
        params.put("password", "admin123");

        CommonReturnType<AccessTokenOutput> accessTokenResult = testApiFeignClient.getAccessToken(params);
        log.info("[測試] 獲取 AccessToken 響應(yīng)結(jié)果:[{}]", JSONUtil.toJsonStr(accessTokenResult));

        return accessTokenResult;
    }

}

參考資料

Spring Cloud Feign設(shè)計原理

Feign基礎(chǔ)教程

SpringBoot脫離SpringCloud使用Feign

Feign真正正確的使用方法

Spring Cloud通過Feign請求返回值LocalDateTime異常處理

spring-boot 調(diào)用第三方接口

Feign 日期格式轉(zhuǎn)換錯誤

Feign輸出Info級別日志

Feign基礎(chǔ)入門及特性講解

禁用feign retryer

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市盆佣,隨后出現(xiàn)的幾起案子往堡,更是在濱河造成了極大的恐慌,老刑警劉巖共耍,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件虑灰,死亡現(xiàn)場離奇詭異,居然都是意外死亡痹兜,警方通過查閱死者的電腦和手機(jī)穆咐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來字旭,“玉大人对湃,你說我怎么就攤上這事∫糯荆” “怎么了拍柒?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長屈暗。 經(jīng)常有香客問我拆讯,道長脂男,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任种呐,我火速辦了婚禮宰翅,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘爽室。我一直安慰自己汁讼,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布阔墩。 她就那樣靜靜地躺著嘿架,像睡著了一般。 火紅的嫁衣襯著肌膚如雪戈擒。 梳的紋絲不亂的頭發(fā)上眶明,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天,我揣著相機(jī)與錄音筐高,去河邊找鬼搜囱。 笑死,一個胖子當(dāng)著我的面吹牛柑土,可吹牛的內(nèi)容都是我干的蜀肘。 我是一名探鬼主播,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼稽屏,長吁一口氣:“原來是場噩夢啊……” “哼扮宠!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起狐榔,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤坛增,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后薄腻,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體收捣,經(jīng)...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年庵楷,在試婚紗的時候發(fā)現(xiàn)自己被綠了罢艾。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,015評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡尽纽,死狀恐怖咐蚯,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情弄贿,我是刑警寧澤春锋,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站差凹,受9級特大地震影響看疙,放射性物質(zhì)發(fā)生泄漏豆拨。R本人自食惡果不足惜直奋,卻給世界環(huán)境...
    茶點故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一能庆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧脚线,春花似錦搁胆、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至船逮,卻和暖如春顾腊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背挖胃。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工杂靶, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人酱鸭。 一個月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓吗垮,卻偏偏與公主長得像,于是被迫代替她去往敵國和親凹髓。 傳聞我的和親對象是個殘疾皇子烁登,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,969評論 2 355

推薦閱讀更多精彩內(nèi)容