SpringCloud实战之Feign 2.x 迁移到 4.x

从官方文档中去发现变化的点:

官方关于Okhttp from 3.x to 4.x
官方关于Spring-cloud+feign from 2.2.x
官方关于Spring-cloud+feign from 4.1.x

  • spring-cloud-openfeign 变化对比
    • 如何引入feign?
    • 如何加载feign?
    • 如何申明一个client?
    • 关于load-balancer
    • 关于资源加载
    • 关于启动默认的httpclient和okhttp的配置
    • 关于 SpringEncoder 配置
    • 关于熔断的配置
    • 关于请求/响应的压缩
    • 关于SpringData的支持
  • 其他 4.1.x的新特性
  • SpringBoot + SpringCloud + Feign + Okhttp 实践示例

spring-cloud-openfeign 变化对比

如何引入feign?

        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-openfeignartifactId>
        dependency>

如何加载feign?

通过注解:@EnableFeignClients,开始feign的注入

如何申明一个client?

@FeignClient("stores")
public interface StoreClient {
    @RequestMapping(method = RequestMethod.GET, value = "/stores")
    List<Store> getStores();

    @RequestMapping(method = RequestMethod.GET, value = "/stores")
    Page<Store> getStores(Pageable pageable);

    @RequestMapping(method = RequestMethod.POST, value = "/stores/{storeId}", consumes = "application/json")
    Store update(@PathVariable("storeId") Long storeId, Store store);

    @RequestMapping(method = RequestMethod.DELETE, value = "/stores/{storeId:\\d+}")
    void delete(@PathVariable Long storeId);
}

关于load-balancer

2.2.x中
@FeignClient 会创建一个Ribbon load-balancerSpring Cloud LoadBalancer. 取决于spring.cloud.loadbalancer.ribbon.enabled 配置项,如果true则使用Ribbon load-balancer ,如果false则使用Spring Cloud LoadBalancer

4.1.x中
@FeignClient 直接创建一个 Spring Cloud LoadBalancer client

关于资源加载

4.1.x中
@FeignClient 注解被解析的时间更早,便于很多逻辑的处理,如果想要懒加载需要显式指定
spring.cloud.openfeign.lazy-attributes-resolution=true

springcloud 会通过 FeignClientsConfiguration ,将feignclient加入应用上下文
配置包含三部分,一个 feign.Decoder, 一个 feign.Encoder, 和 一个 feign.Contract
可以通过 @FeignClient 的contextId来覆盖这几个默认的
springcloud支持不同的client指定不同配置,@FeignClient(name = "stores", configuration = FooConfiguration.class)
FooConfiguration 不需要用 @Configuration 进行注释,否则他将成为client的默认配置

spring-cloud-starter-openfeign 支持 spring-cloud-starter-loadbalancer,去除了spring-cloud-starter-netflix-ribbon 的默认支持

关于启动默认的httpclient和okhttp的配置

配置项的label上有比较大的区别,从feign的配置迁移到了spring.cloud.openfeign的命名上,主要还是源于feign自身的调整

配置项 2.2.x 4.1.x
ApacheHttpClient feign.httpclient.enabled=true spring.cloud.openfeign.httpclient.enabled=true
ApacheHC5 feign.httpclient.hc5.enabled=true spring.cloud.openfeign.httpclient.hc5.enabled=true
OkHttpClient feign.okhttp.enabled=true spring.cloud.openfeign.okhttp.enabled=true
Http2Client - spring.cloud.openfeign.http2client.enabled=true

Spring Cloud OpenFeign 4开始,HttpClient 4将不再支持,建议使用HttpClient 5

2.2.x application.yaml 示例:

feign:
  client:
    config:
      feignName:
        connectTimeout: 5000
        readTimeout: 5000
        loggerLevel: full
        errorDecoder: com.example.SimpleErrorDecoder
        retryer: com.example.SimpleRetryer
       defaultQueryParameters:
          query: queryValue
        defaultRequestHeaders:
          header: headerValue
        requestInterceptors:
          - com.example.FooRequestInterceptor
          - com.example.BarRequestInterceptor
        decode404: false
        encoder: com.example.SimpleEncoder
        decoder: com.example.SimpleDecoder
        contract: com.example.SimpleContract

4.1.x application.yaml 示例:

spring:
    cloud:
        openfeign:
            client:
                config:
                    feignName:
                        url: http://remote-service.com
                        connectTimeout: 5000
                        readTimeout: 5000
                        loggerLevel: full
                        errorDecoder: com.example.SimpleErrorDecoder
                        retryer: com.example.SimpleRetryer
                        defaultQueryParameters:
                            query: queryValue
                        defaultRequestHeaders:
                            header: headerValue
                        requestInterceptors:
                            - com.example.FooRequestInterceptor
                            - com.example.BarRequestInterceptor
                        responseInterceptor: com.example.BazResponseInterceptor
                        dismiss404: false
                        encoder: com.example.SimpleEncoder
                        decoder: com.example.SimpleDecoder
                        contract: com.example.SimpleContract
                        capabilities:
                            - com.example.FooCapability
                            - com.example.BarCapability
                        queryMapEncoder: com.example.SimpleQueryMapEncoder
                        micrometer.enabled: false

关于 SpringEncoder 配置

配置项 2.2.x 4.1.x
改变默认utf-8的配置 feign.encoder.charset-from-content-type=true spring.cloud.openfeign.encoder.charset-from-content-type=true

关于熔断的配置

配置项 2.2.x 4.1.x
熔断 feign.hystrix.enabled=true spring.cloud.openfeign.circuitbreaker.enabled=true

从2020.0.2开始,熔断器的命名规则从 _ 变为 #(),比如FooClient#bar()

关于请求/响应的压缩

配置项 2.2.x 4.1.x
配置压缩 feign.compression.request.enabled=true
feign.compression.response.enabled=true
spring.cloud.openfeign.compression.request.enabled=true
spring.cloud.openfeign.compression.response.enabled=true

4.1.x
由于 OkHttpClient 使用“透明”压缩,如果存在 content-encoding 或 accept-encoding 标头,则禁用该压缩,因此当类路径上存在 feign.okhttp.OkHttpClient 并且 spring.cloud.openfeign.okhttp.enabled 设置为 true 时,我们不会启用压缩

关于SpringData的支持

2.2.x中
feign.autoconfiguration.jackson.enabled=true 开启

4.1.x中
只要Jackson Databind 和 Spring Data Commons 被引入了,就会自动开启,如果想禁用,主动配置 spring.cloud.openfeign.autoconfiguration.jackson.enabled=false

其他 4.1.x的新特性

  • 支持Spring @RefreshScope spring.cloud.openfeign.client.refresh-enabled=true
  • 支持 OAuth2 spring.cloud.openfeign.oauth2.enabled=true
  • 转换负载均衡的 HTTP 请求,定义并实现LoadBalancerFeignRequestTransformer
  • 支持X-Forwarded Headers spring.cloud.loadbalancer.x-forwarded.enabled=true

SpringBoot + SpringCloud + Feign + Okhttp 实践示例

基础对象:

public class PostInfo {
    private Integer id;
    private Integer userId;
    private String title;
    private String body;

    public Integer getId() {
        return id;
    }

    public void setId(final Integer id) {
        this.id = id;
    }

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(final Integer userId) {
        this.userId = userId;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(final String title) {
        this.title = title;
    }

    public String getBody() {
        return body;
    }

    public void setBody(final String body) {
        this.body = body;
    }

    @Override
    public String toString() {
        return "PostInfo{" +
            "id=" + id +
            ", userId=" + userId +
            ", title='" + title + '\'' +
            ", body='" + body + '\'' +
            '}';
    }
}

@FeignClient(value = "jplaceholder", url = "https://jsonplaceholder.typicode.com/")
public interface PostService {

    @RequestMapping(method = RequestMethod.GET, value = "/posts")
    List<PostInfo> getPosts();

    @RequestMapping(method = RequestMethod.GET, value = "/posts/{postId}", produces = "application/json")
    PostInfo getPostById(@PathVariable("postId") Long postId);

    @RequestMapping(method = RequestMethod.POST, value = "/posts", produces = "application/json")
    PostInfo savePost(@RequestBody PostInfo postInfo);

    @RequestMapping(method = RequestMethod.PATCH, value = "/posts", produces = "application/json")
    PostInfo updatePost(@RequestBody PostInfo postInfo);

    @RequestMapping(method = RequestMethod.DELETE, value = "/posts/{postId}", produces = "application/json")
    void deletePost(@PathVariable("postId") Long postId);
}

@RestController
@RequestMapping("/v1")
public class TestController {
    @Autowired
    private PostService postService;

    @GetMapping("/feign/post")
    public String feignPostRequest(){
        return postService.getPostById(1L).toString();
    }
}

差异基本就在配置项上

springboot2.x pom.xml

   <properties>
        <java.version>1.8java.version>
        <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
        <spring-boot.version>2.3.12.RELEASEspring-boot.version>
        <spring-cloud.version>Hoxton.SR12spring-cloud.version>
    properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-openfeignartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintagegroupId>
                    <artifactId>junit-vintage-engineartifactId>
                exclusion>
            exclusions>
        dependency>
        <dependency>
            <groupId>io.github.openfeigngroupId>
            <artifactId>feign-okhttpartifactId>
            <version>10.12version>
        dependency>
    dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-dependenciesartifactId>
                <version>${spring-cloud.version}version>
                <type>pomtype>
                <scope>importscope>
            dependency>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-dependenciesartifactId>
                <version>${spring-boot.version}version>
                <type>pomtype>
                <scope>importscope>
            dependency>
        dependencies>
    dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.pluginsgroupId>
                <artifactId>maven-compiler-pluginartifactId>
                <version>3.8.1version>
                <configuration>
                    <source>1.8source>
                    <target>1.8target>
                    <encoding>UTF-8encoding>
                configuration>
            plugin>
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
                <version>${spring-boot.version}version>
                <configuration>
                    <mainClass>com.learning.cloudforfeignokhttp3.CloudForFeignOkhttp3ApplicationmainClass>
                    <skip>trueskip>
                configuration>
                <executions>
                    <execution>
                        <id>repackageid>
                        <goals>
                            <goal>repackagegoal>
                        goals>
                    execution>
                executions>
            plugin>
        plugins>
    build>

springboot2.x application.yaml

server:
  port: 8088
feign:
  okhttp:
    enabled: true
  httpclient:
    enabled: false
debug: true

springboot3.x pom.xml

 <properties>
        <java.version>17java.version>
        <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
        <spring-boot.version>3.2.0spring-boot.version>
        <spring-cloud.version>2023.0.0spring-cloud.version>
    properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-openfeignartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
        dependency>
        <dependency>
            <groupId>io.github.openfeigngroupId>
            <artifactId>feign-okhttpartifactId>
            <version>13.0version>
        dependency>
    dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-dependenciesartifactId>
                <version>${spring-cloud.version}version>
                <type>pomtype>
                <scope>importscope>
            dependency>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-dependenciesartifactId>
                <version>${spring-boot.version}version>
                <type>pomtype>
                <scope>importscope>
            dependency>
        dependencies>
    dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.pluginsgroupId>
                <artifactId>maven-compiler-pluginartifactId>
                <version>3.8.1version>
                <configuration>
                    <source>17source>
                    <target>17target>
                    <encoding>UTF-8encoding>
                configuration>
            plugin>
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
                <version>${spring-boot.version}version>
                <configuration>
                    <mainClass>com.learning.cloudforfeign4.CloudForFeignOkhttp4ApplicationmainClass>
                    <skip>trueskip>
                configuration>
                <executions>
                    <execution>
                        <id>repackageid>
                        <goals>
                            <goal>repackagegoal>
                        goals>
                    execution>
                executions>
            plugin>
        plugins>
    build>
    <repositories>
        <repository>
            <id>spring-milestonesid>
            <name>Spring Milestonesname>
            <url>https://repo.spring.io/milestoneurl>
            <snapshots>
                <enabled>falseenabled>
            snapshots>
        repository>
    repositories>

springboot3.x application.yaml

server:
  port: 8089
spring:
  cloud:
    openfeign:
      okhttp:
        enabled: true
      httpclient:
        enabled: false
debug: true

你可能感兴趣的:(SpringCloud,架构设计,spring,cloud,spring,后端)