springboot使用feign调用不依赖cloud

在使用spring boot调用第三方api中,常用的是okhttp、apache http client等,但是直接使用下来还是有点繁琐,需要手动转换实体。

在springcloud中有个openfeign调用,第一次体验到调用接口还能这么丝滑。注解写道接口上,配置一下,其他交给框架处理。搜了一下这种方式叫做声明式调用。类似的还有Retrofit、forest框架。

openfeign集成到springboot中有何优点:openfeign吸收了Retrofit框架的优点,做了声明式API,但是没有Retrofit多余的Call层。forest是一款国产优秀的框架,单独使用问题不大,但对于后续升级到cloud的boot项目,共存时存在不少问题,并且对上传大文件部分场景的支持有点问题。

这里分两步,先介绍@RequestLine注解调用,后介绍@GetMapping的spring注解调用。

一、传统注解@RequestLine调用

1.加依赖

复制代码
        <!-- feign -->
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-core</artifactId>
            <version>11.0</version>
        </dependency>
        <dependency>
            <groupId>com.netflix.feign</groupId>
            <artifactId>feign-jackson</artifactId>
            <version>8.18.0</version>
        </dependency>

2.写代码

以天气api接口为例

controller层

复制代码
package com.vvvtimes.demo.controller;

import com.vvvtimes.demo.common.dto.RestResponse;
import com.vvvtimes.demo.domain.dto.WeatherCityDTO;
import com.vvvtimes.demo.domain.mybatis.City;
import com.vvvtimes.demo.domain.vo.WeatherVo;
import com.vvvtimes.demo.service.WeatherService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/weather")
public class WeatherController {

    @Autowired
    private WeatherService weatherService;

    @RequestMapping(value = "city/{id:1[0-9]{8}}", method = {RequestMethod.POST, RequestMethod.GET})
    public RestResponse<WeatherVo> loadApi(@PathVariable("id") String id) {
        return weatherService.loadApi(id);
    }


}

service层

复制代码
/**
     * 获取数据
     * @param id
     * @return
     */
    @Cacheable(cacheNames = "weather_cache", key = "#id")// 从缓存获取,key为ID,缓存具体看 ehcache.xml 配置文件
    public RestResponse<WeatherVo> loadApi(String id) {
        RestResponse<WeatherVo> result =new RestResponse<>();
        WeatherVo weatherVo = sojsonApiClient.getCityWeather(id);
        if(weatherVo!=null && weatherVo.isSuccess()){
            result.setResult(weatherVo);
        }
        return result;
    }

//client层

复制代码
package com.vvvtimes.demo.client;

import com.vvvtimes.demo.domain.vo.WeatherVo;
import feign.Param;
import feign.RequestLine;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

import java.util.Map;

@Component
public interface SojsonApiClient {

    //@GetMapping(value = "/api/weather/city/{id}")
    @RequestLine("GET /api/weather/city/{id}")
    WeatherVo getCityWeather(@Param("id") String id);

}

client拦截器

复制代码
package com.vvvtimes.demo.client.interception;

import feign.RequestInterceptor;
import feign.RequestTemplate;

public class SojsonInterceptor implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {

    }
}

feign配置

复制代码
package com.vvvtimes.demo.config;

import com.vvvtimes.demo.client.IpinfoApiClient;
import com.vvvtimes.demo.client.SojsonApiClient;
import com.vvvtimes.demo.client.interception.IpinfoInterceptor;
import com.vvvtimes.demo.client.interception.SojsonInterceptor;
import feign.Feign;
import feign.jackson.JacksonDecoder;
import feign.jackson.JacksonEncoder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ApiRegisterConfig {

    @Value("${sojson.base.url:http://t.weather.sojson.com/}")
    private String sojsonRegisterUrl;



    @Bean
    public SojsonApiClient sojsonApiRegister() {
        return Feign.builder().encoder(new JacksonEncoder())
                .decoder(new JacksonDecoder())
                .requestInterceptor(new SojsonInterceptor())
                .target(SojsonApiClient.class, sojsonRegisterUrl);
    }


}

3.测试访问

http://localhost:9000/weather/city/101010100

二、spring注解@GetMapping使用

上面使用的注解多少有点别扭,实际上我们可以通过feign-contract Feign的契约方式来使用spring的注解。

这里只对比上的代码讲解改造过程,不给出全代码

1.改造依赖

上面的feign依赖替换如下

复制代码
      <!-- feign -->
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-core</artifactId>
            <version>11.6</version>
        </dependency>
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-spring4</artifactId>
            <version>11.6</version>
        </dependency>
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-jackson</artifactId>
            <version>11.6</version>
        </dependency>
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-httpclient</artifactId>
            <version>11.6</version>
        </dependency>
        <dependency>
            <groupId>io.github.openfeign.form</groupId>
            <artifactId>feign-form</artifactId>
            <version>3.8.0</version>
        </dependency>

2.配置契约

ApiRegisterConfig的Bean加一句.contract(new SpringContract())

对应bean代码如下

复制代码
    @Bean
    public SojsonApiClient sojsonApiRegister() {
        return Feign.builder().encoder(new JacksonEncoder())
                .decoder(new JacksonDecoder())
                .requestInterceptor(new SojsonInterceptor())
                .contract(new SpringContract())
                .target(SojsonApiClient.class, sojsonRegisterUrl);
    }

3.改注解

将@RequestLine注解改成@GetMapping注解,代码如下

复制代码
    @GetMapping(value = "/api/weather/city/{id}")
        //@RequestLine("GET /api/weather/city/{id}")
    WeatherVo getCityWeather(@PathVariable("id") String id);

至此改造完成。

注意:本文没有设置feign的全局拦截器,因为在第三方接口中,每种接口的鉴权方式不一样,建议每种类型的接口单独设置拦截器做鉴权

相关推荐
無限進步D43 分钟前
Java 运行原理
java·开发语言·入门
難釋懷1 小时前
安装Canal
java
是苏浙1 小时前
JDK17新增特性
java·开发语言
不光头强1 小时前
spring cloud知识总结
后端·spring·spring cloud
GetcharZp4 小时前
告别 Python 依赖!用 LangChainGo 打造高性能大模型应用,Go 程序员必看!
后端
阿里加多4 小时前
第 4 章:Go 线程模型——GMP 深度解析
java·开发语言·后端·golang
likerhood4 小时前
java中`==`和`.equals()`区别
java·开发语言·python
小小李程序员4 小时前
Langchain4j工具调用获取不到ThreadLocal
java·后端·ai