SpringCloud架構:8-構建獨立的Feign工程及遇到的坑

一、背景

在實際開發過程中,一般會構建一個工程,來存放整個Spring Cloud項目中的所有的Feign接口,同時也會存放Feign調用過程中的複雜類型的實體類。

這裏原有一個郵件服務、一個活動申請服務,場景就是訪問活動申請服務的接口,然後活動申請服務通過feign調用郵件服務。重點是獨立的Feign工程,所以活動申請和郵件並無具體業務邏輯。

二、版本確認

在我自己構建工程的過程中,遇到了各種各樣的坑,其中一類是由於springboot版本與SpringCloud版本的對應關係導致的,所以這裏先確定下版本。

SpringBoot的版本
<parent>
	<groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.7.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

SpringCloud的版本
<dependencyManagement>
	<dependencies>
    	<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-dependencies</artifactId>
			<version>Greenwich.SR3</version>
			<type>pom</type>
			<scope>import</scope>
		</dependency>
	</dependencies>
</dependencyManagement>

三、建立Feign工程

  • 新建一個springboot項目,這裏就叫scloud-feign,也有些人喜歡把這個工程命名爲xxxx-client,不過這個不重要。
  • 因爲後期這個項目是以jar包的形式引入到其他項目(服務)中的,所以刪掉resource、test這些沒用的文件夾。
    最終的項目結構
    在這裏插入圖片描述

四、Feign工程的pom

  • 另外引入openfeign依賴和lombok依賴。
  • 注意這裏引入的是spring-cloud-starter-openfeign依賴而不是spring-cloud-starter-feign這裏是一個坑,在一些書上,未標明springboot和springcloud的版本就直接寫引入spring-cloud-starter-feign是會導致掉坑的。
  • 基於以上確定的springboot和SpringCloud的版本的情況下,請引入spring-cloud-starter-openfeign
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.7.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.scloud</groupId>
    <artifactId>feign</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>feign</name>
    <description>feign Client</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--Feign依賴-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>2.1.3.RELEASE</version>
        </dependency>

        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

五、在郵件服務寫三個接口

  • 爲了涵蓋實際開發中常用的接口方式,寫三個簡單的發送郵件的接口。
  • 新建一個郵件實體:
@Data
public class Email {
    /** 收件人 */
    private String to;

    /** 郵件內容 */
    private String content;
	
	/** 發送結果 */
    private String rs;
}
  • 新建三個接口:
// 郵件服務
@RestController
@RequestMapping("/api/email")
public class EmailSendController {

    // GET發送郵件:參數爲[信息字符串] 返回郵件實體
    @PostMapping(value = "/send/dto/re/dto")
    public Email emailPostDtoReDto(@RequestParam("to") String to, @RequestParam("content") String content){
        Email email = new Email();
        email.setTo(to);
        email.setContent(content);
        email.setRs("send ok!");
        return email;
    }

    // POST發送郵件:參數爲[郵件信息實體] 返回郵件實體
    @PostMapping(value = "/send/dto/re/dto")
    public Email emailPostDtoReDto(@RequestBody Email email){
		email.setRs("send ok!");
        return email;
    }

    // POST發送郵件:參數爲[郵件信息實體] 返回字符串
    @PostMapping(value = "/send/dto/re/str")
    public String emailPostDtoReStr(@RequestBody Email email){
        return "send ok";
    }
}

六、在Feign工程寫Feign接口

  • 新建email包,所有指向郵件服務的feign接口都寫在這個包下,這樣各個服務的feign接口更清晰一些。
  • 新建一個郵件實體:
@Data
public class Email {
    /** 收件人 */
    private String to;

    /** 郵件內容 */
    private String content;
	
	/** 發送結果 */
    private String rs;
}
  • 新建一個Feign接口指向郵件服務:
    使用@FeignClient()註解標識這個feign接口指向郵件服務
    注意@FeignClient是org.springframework.cloud.openfeign.FeignClient包下的
package com.scloud.feign.email.feign;

import com.scloud.feign.email.dto.Email;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;

@FeignClient(name = "SCLOUD-EMAIL-SERVICE")
public interface EmailFeignInterface {

    // GET發送郵件:參數爲[郵件信息字符串] 返回郵件實體
    @PostMapping(value = "/api/email/send/str/re/dto")
    Email emailPostStrReDto(@RequestParam("to") String to, @RequestParam("content") String content);

    // POST發送郵件:參數爲[郵件信息實體] 返回郵件實體
    @PostMapping(value = "/api/email/send/dto/re/dto")
    Email emailPostDtoReDto(@RequestBody Email email);

    // POST發送郵件:參數爲[郵件信息實體] 返回字符串
    @PostMapping(value = "/api/email/send/dto/re/str")
    String emailPostDtoReStr(@RequestBody Email email);
}

在這裏插入圖片描述

  • 構建一下Feign工程,這樣其他項目就能以jar包的形式引入Feign工程了
    在這裏插入圖片描述

七、在活動申請服務引入Feign工程

  • 在活動申請服務的pom中引入Feign工程
<!--feign工程-->
<dependency>
	<groupId>com.scloud</groupId>
	<artifactId>feign</artifactId>
	<version>0.0.1-SNAPSHOT</version>
</dependency>
  • 同時也要引入open-feign依賴,:
<!--Feign依賴-->
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
  • 在活動申請服務的啓動類中啓用feign
    需要注意@EnableFeignClients()註解是來自包org.springframework.cloud.openfeign.EnableFeignClients
package com.scloud.activimanage;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@EnableEurekaClient
// 有些書上是這種格式:basePackages="",有坑!記得加{}
@EnableFeignClients(basePackages = {"com.scloud.feign.*"})	// 啓用Feign
@SpringBootApplication
public class ActivimanageApplication {
    public static void main(String[] args) {
        SpringApplication.run(ActivimanageApplication.class, args);
    }
}

八、在活動申請服務中使用Feign訪問郵件服務

引入Feign工程中的指向郵件服務的feign接口,即可使用。當然如果有其他服務也需要調用郵件服務,那就同樣引入Feign工程中的接口就能用了。

@RestController
@RequestMapping("/api/activity")
public class ActivityApplyController {

    @Autowired
    private EmailFeignInterface emailFeignInterface;

    // 申請活動
    @GetMapping(value = "/apply")
    public String applyActivity(){
        System.out.println("申請活動");

        // email服務feign接口1
        Email email1 = emailFeignInterface.emailPostStrReDto("[email protected]", "apply activi");
        System.out.println("feign接口1:"+email1.getRs());

        // email服務feign接口2
        Email email2 = new Email();
        email2.setTo("[email protected]");
        email2.setContent("apply activi");
        String rs = emailFeignInterface.emailPostDtoReStr(email2);
        System.out.println("feign接口2:"+rs);

        // email服務feign接口3
        Email email3 = emailFeignInterface.emailPostDtoReDto(email2);
        System.out.println("feign接口3:"+email1.getRs());

       return "ok";
    }
}

九、結果

訪問一下活動申請服務的接口,測試一下,發現能夠成功通過feign接口訪問到郵件服務。
在這裏插入圖片描述

十、避免掉坑

  • 先確認好springboot和SpringCloud的版本號
  • 在springboot 2.1.7.RELEASE版本、SpringCloud Greenwich.SR3版本的前提下,Feign工程和需要使用feign調用的工程請引入spring-cloud-starter-openfeign依賴。
  • 早些版本是引入的spring-cloud-starter-feign依賴,可能有些書上未注意到版本的差異,比如用以上的2.1.7.RELEASE和Greenwich.SR3版本,再引入spring-cloud-starter-feign就會出現訪問不到活動申請接口的詭異的坑。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章