美文网首页
SpringBoot脱离SpringCloud使用Feign

SpringBoot脱离SpringCloud使用Feign

作者: Lord丶轩莫言弃 | 来源:发表于2020-01-10 15:49 被阅读0次

快速导航

添加依赖

Maven

Feign 声明式http请求调用轻量级框架

在项目的 pom.xml 的 dependencies 中加入以下内容:

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

添加远程调用服务类

在项目中新增 TestApiFeignClient 远程调用服务类,代码如下:

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的接口(远程调用服务类)
 * @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;

    /** 执行结果成功,还是失败. */
    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;

    /**
     * 业务id
     */
    private String uid;

    /**
     * 访问令牌,用于业务接口调用。(有效期24小时)
     */
    @JsonProperty("access_token")
    private String accessToken;

    /**
     * 当access_token过期时,用于刷新access_token
     */
    @JsonProperty("refresh_token")
    private String refreshToken;

    /**
     * 当前时间,时间戳格式: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;
    }

}

调用示例

TestController

FeignTestController 测试Feign远程调用

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("进入Feign远程调用服务测试类,当前时间:[{}]", 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 响应结果:[{}]", JSONUtil.toJsonStr(accessTokenResult));

        return accessTokenResult;
    }

}

参考资料

Spring Cloud Feign设计原理

Feign基础教程

SpringBoot脱离SpringCloud使用Feign

Feign真正正确的使用方法

Spring Cloud通过Feign请求返回值LocalDateTime异常处理

spring-boot 调用第三方接口

Feign 日期格式转换错误

Feign输出Info级别日志

Feign基础入门及特性讲解

禁用feign retryer

相关文章

网友评论

      本文标题:SpringBoot脱离SpringCloud使用Feign

      本文链接:https://www.haomeiwen.com/subject/xnxmactx.html