中文字幕精品亚洲无线码二区,国产黄a三级三级三级看三级,亚洲七七久久桃花影院,丰满少妇被猛烈进入,国产小视频在线观看网站

springboot~feign模擬(ni)multipart/form-data

openfeign介紹

在微服(fu)(fu)務(wu)設計里(li),服(fu)(fu)務(wu)之間的(de)調用(yong)是很(hen)正常的(de),通常我們(men)使用(yong)httpClient來實(shi)現對遠程資源(yuan)的(de)調用(yong),而(er)這種方法需要知識服(fu)(fu)務(wu)的(de)地址,業務(wu)接口地址等,而(er)且需要等他開(kai)發完成后你才可以去調用(yong)它,這對于集成開(kai)發來說,不是什么(me)(me)好事 ,產生了A業務(wu)與B業務(wu)的(de)強依(yi)賴(lai)性,那么(me)(me)我們(men)如何進(jin)行解耦呢,答案就是openfeign框架(jia),它與是springcloudy里(li)的(de)一部分(fen)。

    springcloud的(de)服(fu)務消費者指的(de)就是服(fu)務間的(de)調用,實現(xian)的(de)方(fang)式有兩種:一種就是上一章(zhang)講(jiang)(jiang)的(de)restTemplate+ribbon,另一種就是本章(zhang)要(yao)講(jiang)(jiang)的(de)feign,feign默(mo)認集成了ribbon,所以feign也默(mo)認實現(xian)了負載均(jun)衡。

服務發現/注冊里的服務名

通過服(fu)(fu)務(wu)名來進(jin)行請求(qiu)的發送要(yao)(yao)比(bi)配(pei)置域(yu)名發http更直(zhi)(zhi)觀,并且你不需要(yao)(yao)知道它的域(yu)名和(he)端口,這(zhe)也(ye)是各(ge)個微服(fu)(fu)務(wu)之前直(zhi)(zhi)觀調用(yong)的一種方(fang)式,而且A服(fu)(fu)務(wu)可以不依賴于B服(fu)(fu)務(wu),只要(yao)(yao)知道接口簽名即可。

graph TD
B(服務b)-->C(eureka注冊中心)
D-->|在服務a中建立client服務名為服務b|E(openfeign服務端)
A(服務a)-->|配置某個服務中心的服務名稱|D(調用服務b的某個接口)
D-->C

添加包引用

'org.springframework.cloud:spring-cloud-starter-openfeign'

添加配置bootstrap.yml

feign:
  client:
    config:
      default:
        connectTimeout: 2000
        readTimeout: 10000

2 定義profile相關配置

//默認的一些文件路徑的配置
sourceSets {
    integTest {
        java.srcDir file('src/test/java')
        resources.srcDir file('src/test/resources')
    }
}

task integTest(type: Test) {
    testClassesDirs = sourceSets.test.output.classesDirs
    classpath = sourceSets.test.runtimeClasspath
}

定義服務接口

定義偽(wei)方(fang)法,就是(shi)服務(wu)里的方(fang)法,你(ni)要知識方(fang)法參數和它的返回值,實現不用(yong)管,只在單元測試(shi)里MOCK就可以.

package test.lind.javaLindDay.feignClientDemo;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.context.annotation.Profile;
import org.springframework.web.bind.annotation.GetMapping;

/**
 * 模擬其他服務.
 */
@Profile("!integTest")
@FeignClient(name = "serviceName",primary=false)
public interface MockClient {
  @GetMapping(path = "/balanceSheet/{clientCode}")
  String balanceSheet(String clientCode);
}

Profile的作用

profile就是環境變量,你在類上通過ActiveProfile去(qu)激活它,在使用(yong)(yong)它時,有過Profile注(zhu)解(jie)來(lai)使用(yong)(yong)上,上面(mian)代碼中(zhong)MockClient對象(xiang)不能(neng)在integTest環境下使用(yong)(yong)。

添加MOCK實現,它是自動注入的,所以聲明@Bean注解

它(ta)是為了(le)在單元測(ce)試(shi)環境下(xia)使用client,而又不希望(wang)與外部 網(wang)絡(luo)資源通訊,所以需要mock一下(xia)本(ben)地(di)資源去實現client.

package test.lind.javaLindDay;

import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import test.lind.javaLindDay.feignClientDemo.MockClient;

@Configuration
@Profile("integTest")
public class MockClientTest {
  @Bean
  @Primary
  public MockClient mockClient() {
    MockClient client = mock(MockClient.class);
    when(client.balanceSheet(
        anyString()))
        .thenReturn("OK");
    return client;
  }
}

添加單元測試,注意在單元測試上一定要指定它的環境變量

package test.lind.javaLindDay;

import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import test.lind.javaLindDay.feignClientDemo.MockClient;

@RunWith(SpringRunner.class)
@SpringBootTest
//指定profile環境
@ActiveProfiles("integTest")
public class JavaLindDayApplicationTests {

  @Autowired
  MockClient mockClient;

  @Test
  public void testMockClient() {
    assertEquals(mockClient.balanceSheet("OK"), "OK");
  }
}

運行測試后,MockClient將會被注入,它將使用Mock實現類,因為只有Mock實現類的Profile是指向integtest環境的。
有了openfeign,以后開發服務對服務調用就可以解耦了!

feignClient發送multipart/form-data請求

  1. 需要先安裝插件,默認是不能發送文件流的
<dependencies>
    ...
    <dependency>
        <groupId>io.github.openfeign.form</groupId>
        <artifactId>feign-form</artifactId>
        <version>3.3.0</version>
    </dependency>
    <dependency>
        <groupId>io.github.openfeign.form</groupId>
        <artifactId>feign-form-spring</artifactId>
        <version>3.3.0</version>
    </dependency>
    ...
</dependencies>
  1. 添加bean
@FeignClient(name = "file-upload-service", configuration = FileUploadServiceClient.MultipartSupportConfig.class)
public interface FileUploadServiceClient extends IFileUploadServiceClient {

    public class MultipartSupportConfig {

        @Autowired
        private ObjectFactory<HttpMessageConverters> messageConverters;

        @Bean
        public Encoder feignFormEncoder() {
            return new SpringFormEncoder(new SpringEncoder(messageConverters));
        }
    }
}

如果不需要Spring標(biao)準的編碼,也可(ke)以(yi)這樣實現

@FeignClient(name = "file-upload-service", configuration = FileUploadServiceClient.MultipartSupportConfig.class)
public interface FileUploadServiceClient extends IFileUploadServiceClient {

    public class MultipartSupportConfig {

        @Bean
        public Encoder feignFormEncoder() {
            return new SpringFormEncoder();
        }
    }
}
  1. 添加注解
    // File parameter
    @RequestLine("POST /send_photo")
    @Headers("Content-Type: multipart/form-data")
    void sendPhoto (@Param("is_public") Boolean isPublic, @Param("photo") File photo);

    // byte[] parameter
    @RequestLine("POST /send_photo")
    @Headers("Content-Type: multipart/form-data")
    void sendPhoto (@Param("is_public") Boolean isPublic, @Param("photo") byte[] photo);

    // FormData parameter
    @RequestLine("POST /send_photo")
    @Headers("Content-Type: multipart/form-data")
    void sendPhoto (@Param("is_public") Boolean isPublic, @Param("photo") FormData photo);
posted @ 2020-12-29 17:17  張占嶺  閱讀(5365)  評論(0)    收藏  舉報