這裡開始spring cloud微服務架構搭建,用的maven還是之前自己的本地安裝的,repository倉庫也是本地的。

在搭建專案框架之前先簡單學習一下spring cloud。

Spring Cloud 簡介

       Spring Cloud是一個基於Spring Boot實現的雲應用開發工具,是一系列框架的有序集合。它利用Spring Boot的開發便利性巧妙地簡化了分散式系統基礎設施的開發,如服務發現註冊、配置中心、訊息匯流排、負載均衡、斷路器、資料監控等,都可以用Spring Boot的開發風格做到一鍵啟動和部署。Spring Cloud包含了多個子專案(針對分散式系統中涉及的多個不同開源產品),具體如下spring cloud元件介紹。


Spring Cloud 常用元件

1. Spring Cloud Config 
       服務配置中心,將所有的服務的配置檔案放到本地倉庫或者遠端倉庫,配置中心負責讀取倉庫的配置檔案,其他服務向配置中心讀取配置。Spring Cloud Config使得服務的配置統一管理,並可以在不人為重啟服務的情況下進行配置檔案的重新整理。

2. Spring Cloud Netflix 
      它是通過包裝了Netflix公司的微服務元件實現的,也是Spring Cloud核心元件,包括Eureka,Hystrix,Zuul,Archaius。

3. Eureka 
      服務註冊和發現元件

4. Hystrix 
      熔斷器元件。它通過控制服務的API介面的熔斷來轉移故障,防止微服務系統發生雪崩效應。另外Hystrix能夠起到服務限流和服務降級的作用。使用Hystrix Dashboard元件監控單個服務的熔斷狀態,使用Hystrix Turbine元件可以監控多個服務的熔斷器的狀態。

5. Zuul 
       智慧路由閘道器元件能夠起到智慧路由和請求過濾的作用,內部服務 API 介面通過 Zuul 閘道器統一對外暴露,防止內部服務敏感資訊對外暴露。也可以實現安全驗證,許可權控制。

6. Feign 
       宣告式遠端排程元件。

7. Ribbon 
      負載均衡元件

8. Archaius 
      配置管理API元件,一個基於Java的配置管理庫,主要用於多配置的動態獲取。

9. Spring Cloud Bus 
      訊息匯流排元件,常和Spring Cloud Config配合使用,用於動態重新整理服務的配置。

10. Spring Cloud Sleuth 
      服務鏈路追蹤元件,封裝了Dapper,Zipkin,Kibina等元件,可以實時監控服務鏈路呼叫狀況。

11. Spring Cloud Data Flow 
      大資料操作元件,它是Spring XD的替代品,也是一個混合計算模型,可以通過命令列的方式操作資料流

12. Spring Cloud Consul 
      該元件是Spring Cloud對Consul的封裝,和Eureka類似,它是一個服務註冊和發現元件

13. Spring Cloud Zookeeper 
      該元件是Spring Cloud對Zookeeper的封裝,也是用於服務註冊和發現

14. Spring Cloud Stream 
       資料流操作元件,可以封裝 Redis,RabbitMQ,Kafka等元件,實現訊息的接受和傳送

15. Spring Cloud CLI 
       該元件是對Spring Boot CLI的封裝,可以讓使用者以命令列方式快速搭建和執行容器

16. Spring Cloud Task 
       該元件基於Spring Tsak,提供任務排程和任務管理的功能


Spring Cloud 與 Dubbo 的對比(微服務方面)

從微服務關注點對比Spring Cloud和Dubbo
                    微服務關注點                           Spring Cloud                          Dubbo
管理配置 Config
服務發現 Eureka、Consul、Zookeeper Zookeeper
負載均衡 Ribbon 自帶
網管 Zuul
分散式追蹤 Spring Cloud Sleuth
容錯 Hystrix 不完善
通訊方式 HTTP、Message RPC
安全模組 Spring Cloud Security

        Spring Cloud擁有很多的專案模組,包含微服務的方方面面,Dubbo是個十分優秀的服務治理和服務呼叫框架,但缺少了很多的功能模組,例如閘道器,鏈路追蹤等。 
       開發風格上,Dubbo傾向於xml配置方式,而Spring Cloud基於Spring Boot,它採用基於註解和JavaBean配置方式的敏捷開發。 
       通訊方式上Spring Cloud大多數基於HTTP Restful風格,服務與服務間完全耦合,因此服務無關乎語言和平臺。Dubbo採用遠端呼叫方式,對介面平臺和程式語言有強依賴性。 
       Dubbo和Spring Cloud各有優缺點,Dubbo更易上手,也非常成熟和穩定,Spring Cloud服務框架嚴格遵守 Martin Fowler 提出的微服務規範。


微服務架構

       微服務的概念源於2014年3月Martin Fowler所寫的章“Microservices”http://martinfowler.com/articles/microservices.html

       微服務(Microservices Architecture)是一種架構風格,一個大型複雜軟體應用由一個或多個微服務組成。系統中的各個微服務可被獨立部署,各個微服務之間是鬆耦合的。每個微服務僅關注於完成一件任務並很好地完成該任務。在所有情況下,每個任務代表著一個小的業務能力。

       微服務架構的核心思想是,一個應用是由多個小的、相互獨立的、微服務組成,這些服務執行在自己的程序中,開發和釋出都沒有依賴。不同服務通過一些輕量級互動機制來通訊,例如 RPC、HTTP 等,服務可獨立擴充套件伸縮,每個服務定義了明確的邊界,不同的服務甚至可以採用不同的程式語言來實現,由獨立的團隊來維護。簡單的來說,一個系統的不同模組轉變成不同的服務!而且服務可以使用不同的技術加以實現!

那我們在微服務中應該怎樣設計呢。以下是微服務的設計指南:

  • 職責單一原則(Single Responsibility Principle):把某一個微服務的功能聚焦在特定業務或者有限的範圍內會有助於敏捷開發和服務的釋出。
  • 設計階段就需要把業務範圍進行界定。
  • 需要關心微服務的業務範圍,而不是服務的數量和規模儘量小。數量和規模需要依照業務功能而定。
  • 於SOA不同,某個微服務的功能、操作和訊息協議儘量簡單。
  • 專案初期把服務的範圍制定相對寬泛,隨著深入,進一步重構服務,細分微服務是個很好的做法。

關於為服務的一些取捨:

  • 在合適的專案,合適的團隊,採用微服務架構收益會大於成本。
  • 微服務架構有很多吸引人的地方,但在擁抱微服務之前,也需要認清它所帶來的挑戰。
  • 需要避免為了“微服務”而“微服務”。
  • 微服務架構引入策略 – 對傳統企業而言,開始時可以考慮引入部分合適的微服務架構原則對已有系統進行改造或新建微服務應用,逐步探索及積累微服務架構經驗,而非全盤實施微服務架構。

Spring Cloud Eureka來實現服務治理

  如下我們使用 euraka 體系的spring cloud.
以下工作都在project->springcloud-erueka-project

開啟idea建立project:

選擇maven建立普通的maven管理專案:

填寫工程的組命GroupId和專案名ArtifactId:

確認資訊後點擊finish即可:

選擇自動導包:

建立好的工程:

檢查idea的maven設定file---->settings---->maven:


1. 建立一個module 註冊中心eureka-server(包括監控中心)

    1.1)新建一個module  sc-eureka-server 提供服務註冊和發現

右鍵單擊工程名選擇Module建立模組:

選擇spring boot風格建立spring cloud:

填寫模組組名和模組名稱:

建立註冊中心(包含監控中心),選擇cloud discovery的eureka server,這裡也能看出spring boot的版本是2.1.1:

確認資訊後完成:

建立好的模組目錄以及有以下兩個檔案:

    1.2)增加依賴(其實採用spring boot方式建立的spring cloud已經簡化了很多工作,這裡的依賴也已經完成了,只是我們要知道是什麼依賴:

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>

pom.xml檔案內容如下:

<?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 http://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.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.kgc1803</groupId>
    <artifactId>sc-eureka-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>sc-eureka-server</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.RC2</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>

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

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
        </repository>
    </repositories>

</project>

    1.3)這裡我的所有配置檔案均採用application.yml格式(即將application.properties字尾更改成.yml),當然你可不用更改,根據自己的風格愛好就可以,並在註冊中心模組配置eureka server。在預設設定下,該服務註冊中心也會將自己作為客戶端來嘗試註冊它自己,所以我們需要禁用它的客戶端註冊行為,只需要在application.yml配置檔案中增加如下資訊

    register-with-eureka: false
    fetch-registry: false

application.yml配置檔案內容如下,只是要注意,application.yml風格的配置需要注意各個子級需要對應工整,不然後面啟動服務是不會有效果的,要求更加嚴格:

#服務埠
server:
  port: 8761
#eureka server 的配置
#register-with-eureka: false表示該eureka 節點不能註冊服務
#fetch-registry: false 表示該eureka 節點不能釋出(訂閱)服務
eureka:
  instance:
     hostname: localhost
  client:
     register-with-eureka: false
     fetch-registry: false
     service-url:
        defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ 這裡預設的路徑後面需要加上eureka/才會訪問到。

    1.4)在主服務啟動類上增加eureka server 的註解標籤( @EnableEurekaServer )

package com.kgc1803.sceurekaserver;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer
public class ScEurekaServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ScEurekaServerApplication.class, args);
    }

}

    1.5)啟動測試

訪問服務

啟動工程後,訪問:http://localhost:8761/

可以看到下面的頁面,其中還沒有發現任何服務。


2. 釋出一個服務

    2.1)新建一個module  sc-eureka-service-provider

建立方法跟上面一樣,只是有一點不一樣如下選項:

這裡的取別如下圖:

    2.2)檢查依賴並增加相應的依賴,spring cloud 釋出服務多用 rest 風格,所以需要spring-boot web 包:

	        <!-- eureka-client 既能註冊服務又能訂閱服務-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
	        <!-- spring cloud 釋出服務多用 rest 風格,所以需要spring-boot web 包 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

pom.xml配置檔案內容:

<?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 http://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.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.kgc1803</groupId>
    <artifactId>sc-eureka-service-provider</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>sc-eureka-service-provider</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.RC2</spring-cloud.version>
    </properties>

    <dependencies>
        <!-- eureka-client 既能註冊服務又能訂閱服務-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <!-- spring cloud 釋出服務多用 rest 風格,所以需要spring-boot web 包 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
        </repository>
    </repositories>

</project>

    2.3)在ScEurekaServiceProviderApplication.java服務啟動類同級建立service包並編寫一個服務類;這裡我們使用rest風格的控制器註解:@RestController

DemoService.java服務類:

package com.kgc1803.sceurekaserviceprovider.service;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

//rest 風格控制器註解
@RestController
public class DemoService {
    @RequestMapping("/getInfo")
    public String getDemoInfo(){
        return "this is a provided service !";
    }
}

    2.4)在application.yml中完成eureka client 釋出服務的配置(客戶端(client)向server(伺服器端)註冊服務的配置)

新增配置

需要配置才能找到 Eureka 伺服器。例:

完整配置

server:
  port: 8081
#instance.appname 指明註冊中的名字
#service-url.defultzone:配置註冊中心地址
eureka:
  instance:
    appname: demo_service_provider
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
#應用名字
spring:
  application:
    name: eureka-provider

         其中defaultZone是一個魔術字串後備值,為任何不表示首選項的客戶端提供服務URL(即它是有用的預設值)。 通過spring.application.name屬性,我們可以指定微服務的名稱後續在呼叫的時候只需要使用該名稱就可以進行服務的訪問

    2.5)在主啟動類中增加 釋出服務的註解配置

         開啟服務註冊,在應用主類中通過加上 @EnableEurekaClient,但只有Eureka 可用,你也可以使用@EnableDiscoveryClient。需要配置才能找到Eureka註冊中心伺服器;實驗證明可以不用加。

package com.kgc1803.sceurekaserviceprovider;

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

@SpringBootApplication
@EnableEurekaClient
public class ScEurekaServiceProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(ScEurekaServiceProviderApplication.class, args);
    }

}

        訪問服務

        啟動該工程後,再次訪問啟動工程後:http://localhost:8761/

        可以如下圖內容,我們定義的服務被成功註冊了。

    2.6)啟動與測試:http://localhost:8081/getInfo

出現如下圖所示表名取到了值:


3. 發現(訂閱)一個服務

    3.1)新建一個module  sc-eureka-service-consume(流程跟上面釋出服務模組一樣)

建好的模組目錄:

    3.2)增加依賴

	        <!-- eureka-client 既能註冊服務又能訂閱服務-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
	        <!-- spring cloud 釋出服務多用 rest 風格,所以需要spring-boot web 包 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

    3.3)在 ScEurekaServiceConsumeApplication.java 啟動類的同級目錄編寫一個控制器(主要用來呼叫已註冊的服務,即上面第二個模組註冊的服務);這裡需要注入一個RestTemplate工具類物件才可以呼叫到,但是直接在控制器使用物件是沒辦法得到值的,為了方便其他控制器(同模組)可以呼叫這個工具物件,最好的辦法就是直接在啟動類裡面寫一個方法產生物件,啟動的時候就可以注入了(這裡調值與上面的方法不一樣,也是唯一最大的區別處)。

    //向spring裡注入一個RestTemplate物件
    @Bean
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }

完整的啟動類示例:

package com.kgc1803.sceurekaserviceconsume;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

//在啟動類注入@EnableEurekaClient註解
@SpringBootApplication
@EnableEurekaClient
public class ScEurekaServiceConsumeApplication {

    public static void main(String[] args) {
        SpringApplication.run(ScEurekaServiceConsumeApplication.class, args);
    }

    //向spring裡注入一個RestTemplate物件
    @Bean
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}

         在編寫的控制器中引入RestTemplate物件

 @Autowired
private RestTemplate restTemplate;

        完整的控制器示例:

package com.kgc1803.sceurekaserviceconsume.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class DemoController {
    //映入工具物件RestTemplate
    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping("/test")
    public String getEurekaServiceInfo(){
        /**
         * exchange(url,type,paras,resultType)
         * url:請求地址
         * type:請求型別 get post
         * paras:引數
         * resultType:返回值型別
         */
        //取sc-eureka-service-provider模組服務類getInfo()中的值,這裡獲取url地址和方法名
        String url = "http://localhost:8081/getInfo"; 
        HttpMethod type = HttpMethod.GET; //請求方式
        RequestEntity<String> paras = null;//請求引數,沒有請求引數,所以給null值
        //物件呼叫exchange()帶四個引數的方法,並返回請求
        ResponseEntity<String> responseEntity = restTemplate.exchange(url,type,paras,String.class);
        //返回值,注意,這裡是返回String型別,所以getBody()就是字串,如果方法返回是物件或者list集合,getBody()也就對應返回型別。
        return responseEntity.getBody();
    }
}

    3.4)在application.yml中完成eureka client 釋出服務的配置,方法同上一個模組:

server:
  port: 8082
#客戶端(client)向server(伺服器端)註冊服務的配置
#instance.appname 指明註冊中的名字
#service-url.defultzone:配置註冊中心地址
eureka:
  instance:
    appname: demo_service_consume
  client:
    service-url:
      defaultZone: http://127.0.0.1:8761/eureka/
#應用名字
spring:
  application:
    name: eureka-consume

模組結構圖:

    3.5)啟動測試服務類,重新整理:http://localhost:8761/ 如下圖,兩個服務都發布成功。

      輸入地址:http://localhost:8082/test 測試從控制器根據物件工具取值是否成功:

       取到值,測試成功!

啟動的三個服務類。


拓展總結:

       後端的註冊中和服務類啟動後,註冊中心Eureka大概90秒向服務類做一次通訊,而服務類大概30秒左右跟註冊中心的Erueka回一次通訊;即使後端通訊斷掉了,前端頁面顯示的依然是註冊的服務存在,註冊有效。另外,想要把註冊中報紅色的安全保護機制關掉,只需要在註冊中心模組的配置檔案中加一個配置即可,如下:

#安全保護機制(埠)關閉
instance:
  secure-port-enabled: false

Spring Cloud 與 SSM框架的整合

1.建立公共模組 sc-eureka-service-common(使用普通maven建立即可)

建立好的公共模組如下圖,這個公共模組需要操作的是完成pojo實體類,但是這裡因為和spring cloud並用,所以不用寫service介面了,匯入相應的jar檔案,將公共模組打包釋出到倉庫:

2. 在pomxml檔案增加 json 的依賴:

        <!-- json 外掛 -->
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-mapper-asl</artifactId>
            <version>1.9.12</version>
        </dependency>

打一個jar檔案包:

    <packaging>jar</packaging>
3. 編寫User.java實體類:
package com.kgc1803.demo.pojo;

import org.codehaus.jackson.annotate.JsonProperty;

import java.io.Serializable;
//注意的是pojo實體類一定要實現序列化介面
public class User implements Serializable {
    @JsonProperty
    private Integer id;
    @JsonProperty
    private String userCode;
    @JsonProperty
    private  String userName;
    @JsonProperty
    private String password;

    public User(){}

    public Integer getId() {
        return id;
    }

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

    public String getUserCode() {
        return userCode;
    }

    public void setUserCode(String userCode) {
        this.userCode = userCode;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

   4. 公共模組打成 jar 包釋出到倉庫:

  5. 在sc-eureka-service-consume和sc-eureka-service-provider模組的pom.xml檔案增加公共的 jar 包:

        <!--公共包-->
        <dependency>
            <groupId>com.kgc1803</groupId>
            <artifactId>sc-eureka-service-common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

       更新:對上面的服務類和控制器進行升級改造和拓展,升級是上面用的是無引數的服務類,在控制器用的是 restTemplate 工具物件呼叫 exchange(url,type,paras,resultType)方法實現的,這裡有四個引數,換成以下  getForObject(url,resultType) 或者是 postForObject(url,引數物件,返回值型別)方法會更簡潔(內部做了進一步封裝),這裡直接把三種類型(基礎型別String有參和無參、集合List、物件)示例程式碼全部碼上:

DemoService.java 服務類:
package com.kgc1803.sceurekaserviceprovider.service;

import com.kgc1803.demo.pojo.User;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

//rest 風格控制器註解
@RestController
public class DemoService {

    /**
     * 基本資料型別無引數
     * @return
     */
    @RequestMapping("/getInfo")
    public String getDemoInfo(){
        return "this is a provided service !";
    }

    /**
     * 基本資料型別有引數
     * @param userCode
     * @return
     */
    @RequestMapping("/getInfo_02")
    public String getDemoInfo_02(String userCode){
        return userCode + " , this is a provided cloud 程式 !";
    }

    /**
     * 帶引數的List集合型別
     * @param userCode
     * @return
     */
    @RequestMapping("/getlist")
    public List getList(String userCode){
        List<Map> list = new ArrayList<Map>();
        Map<String,Object> map = new HashMap<String,Object>();
        map.put("userName","張三");
        map.put("userCode",userCode);
        list.add(map);
        return list;
    }

    /**
     * 帶物件引數的物件型別,注意,這裡需要繫結註解:@RequestBody
     * @param user
     * @return
     */
    @RequestMapping(value = "/getuser",method = {RequestMethod.GET,RequestMethod.POST})
    public User getUser(@RequestBody User user){
        return user;
    }

}
DemoController.java 控制器類:
package com.kgc1803.sceurekaserviceconsume.controller;

import com.kgc1803.demo.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.List;

/**
 * 這裡測試,傳值都是從後端傳到前端
 * 測試三種類型:基本資料型別的String、List集合、物件
 */
@RestController
public class DemoController {
    //映入工具物件RestTemplate
    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping("/test")
    public String getEurekaServiceInfo(){
        /**
         * exchange(url,type,paras,resultType) 請求無引數的getDemoInfo()
         * url:請求地址(遠端服務地址)
         * type:請求型別 get post
         * paras:引數
         * resultType:返回值型別  String.class
         */
        //取sc-eureka-service-provider模組服務類getInfo()中的值,這裡獲取url地址和方法名
        String url = "http://localhost:8081/getInfo";
        HttpMethod type = HttpMethod.GET; //請求方式
        RequestEntity<String> paras = null;//請求引數,沒有請求引數,所以給null值
        //物件呼叫exchange()帶四個引數的方法,並返回請求
        ResponseEntity<String> responseEntity = restTemplate.exchange(url,type,paras,String.class);
        //返回值,注意,這裡是返回String型別,所以getBody()就是字串,如果方法返回是物件或者list集合,getBody()也就對應返回型別。
        return responseEntity.getBody();
    }

    @RequestMapping("/test1")
    public String getEurekaServiceInfo_01(){
        /**
         * 對上面的方法進行升級改造,進一步封裝,並呼叫無引數的getDemoInfo()方法達到同樣的效果
         * getForObject(url,resultType) ,可以看出,這個方法的提交方式是GET
         * url:遠端服務地址
         * resultType:返回值型別  String.class
         */
        String url = "http://localhost:8081/getInfo";
        String res = restTemplate.getForObject(url,String.class);
        return res;
    }

    @RequestMapping("/test2")
    public String getEurekaServiceInfo_02(){
        /**
         * 用getForObject(url,resultType)方法呼叫有引數的getDemoInfo_02()方法
         * getForObject(url,resultType) ,可以看出,這個方法的提交方式是GET
         * url:遠端服務地址;我這裡做測試,直接在url將引數固定,利用url傳引數:?userCode=zhangsan
         * resultType:返回值型別  String.class
         */
        String url = "http://localhost:8081/getInfo_02?userCode=zhangsan";
        String res = restTemplate.getForObject(url,String.class);
        return res;
    }

    @RequestMapping("/test3")
    public List getListInfo(){
        /**
         * 用getForObject(url,resultType)方法呼叫有引數的getList()方法
         * getForObject(url,resultType) ,可以看出,這個方法的提交方式是GET
         * url:遠端服務地址;我這裡做測試,直接在url將引數固定,利用url傳引數:?userCode=zhangsan
         * resultType:返回值型別  List.class
         * List mapList = restTemplate.getForObject(url,List.class);
         * 返回到前端所顯示的值:[{"userName":"張三","userCode":"zhangsan"}] 是json 格式的資料
         */
        String url = "http://localhost:8081/getlist?userCode=zhangsan";
        List mapList = restTemplate.getForObject(url,List.class);
        return mapList;
    }

    @RequestMapping("/test4")
    public User getUserInfo(){
        /**
         * 用postForObject(url,引數物件,返回值型別)方法呼叫有引數的getUser()方法
         * postForObject(url,引數物件,返回值型別)可以看出採用的是POST提交方法
         * url:遠端服務地址
         * user:引數物件
         * resultType:返回值型別  User.class
         * User u = restTemplate.postForObject(url,user,User.class);
         */
        User user = new User();
        user.setId(17);
        user.setUserCode("zhangsan");
        user.setUserName("張三");
        user.setPassword("1234");
        String url = "http://localhost:8081/getuser"; //遠端服務地址
        User u = restTemplate.postForObject(url,user,User.class);
        return u;
    }
}

挨個測試以上控制器的輸出結果:

http://localhost:8082/test   String 型別的無引數 呼叫的exchange(url,type,paras,resultType)方法

http://localhost:8082/test1   String 型別的無引數 呼叫的getForObject(url,resultType)方法

http://localhost:8082/test2  String 型別的帶引數 呼叫的getForObject(url,resultType)方法

http://localhost:8082/test3  集合型別的 List 帶引數  呼叫的getForObject(url,resultType)方法 

http://localhost:8082/test4   物件型別 呼叫的是 postForObject(url,引數物件,返回值型別)方法

 

 

 

 

 


至此,IDEA基於Spring Cloud Netflix(2.1.0RC3)等同於(SpringBoot2.1.1正式版)的SpringCloud 微服務架構搭建——實戰教程(一)的Spring Cloud Eureka來實現服務治理就基本結束了!