教育行業(yè)A股IPO第一股(股票代碼 003032)

全國咨詢/投訴熱線:400-618-4000

Spring Boot如何實現微服務?

更新時間:2020年04月10日13時59分 來源:黑馬程序員 瀏覽次數:

在正式學習 Spring Cloud 之前我們先使用 Spring Boot 實現一個微服務。

業(yè)務非常簡單:

(1)商品微服務:通過商品 id 查詢商品的服務;

(2)訂單微服務:通過訂單 id 查詢訂單數據,同時需要調用商品微服務查詢出訂單詳情數據對應的商品數據

Spring Boot 實現微服務01


說明:

(1)對于商品微服務而言,商品微服務是服務的提供者,訂單微服務是服務的消費者;

(2)對于訂單微服務而言,訂單微服務是服務的提供者,人是服務的消費者。

3.1 實現商品微服務

3.1.1 pom.xml 文件的配置

<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>

    <groupId>cn.itcast.microservice</groupId>

    <artifactId>itcast-micorservice-item</artifactId>

    <version>0.0.1-SNAPSHOT</version>

    <!-- 定義變量 -->

    <properties>

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

    </properties>

    <parent>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-parent</artifactId>

        <version>1.5.14.RELEASE</version>

    </parent>

    <dependencies>

        <!-- 加入 web 的支持 -->

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-web</artifactId>

        </dependency>

    </dependencies>

</project>

3.1.2 創(chuàng)建實體 Item

package cn.itcast.microservice.pojo;

public class Item {

    private Long id;        // 唯一標識

    private String title;    // 商品標題

    private String pic;     // 圖片的 pic 地址

    private String desc;    // 描述信息

    private Long price;    // 價格

}

3.1.3 編寫 ItemService

package cn.itcast.microservice.service;

import java.util.HashMap;

import java.util.Map;

import org.springframework.stereotype.Service;

import cn.itcast.microservice.pojo.Item;

@Service

public class ItemService {

    private static final Map<Long, Item> MAP = new HashMap<Long, Item>();

        static { // 準備一些靜態(tài)數據

            MAP.put(1L, new Item(1L, "商品標題 1", "http://圖片 1", "商品描述 1", 1000L));

            MAP.put(2L, new Item(1L, "商品標題 2", "http://圖片 2", "商品描述 2", 2000L));

            MAP.put(3L, new Item(1L, "商品標題 3", "http://圖片 3", "商品描述 3", 3000L));

            MAP.put(4L, new Item(1L, "商品標題 4", "http://圖片 4", "商品描述 4", 4000L));

            MAP.put(5L, new Item(1L, "商品標題 5", "http://圖片 5", "商品描述 5", 5000L));

            MAP.put(6L, new Item(1L, "商品標題 6", "http://圖片 6", "商品描述 6", 6000L));

            MAP.put(7L, new Item(1L, "商品標題 7", "http://圖片 7", "商品描述 7", 7000L));

            MAP.put(8L, new Item(1L, "商品標題 8", "http://圖片 8", "商品描述 8", 8000L));

       }

      /**

      * 模擬實現商品查詢

      *

       * @param id

       * @return

       */

    public Item queryItemById(Long id) {

        return MAP.get(id);

    }

}

3.1.4 編寫 ItemController

package cn.itcast.microservice.controller;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.PathVariable;

import org.springframework.web.bind.annotation.GetMapping;

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

import cn.itcast.microservice.pojo.Item;

import cn.itcast.microservice.service.ItemService;

@RestController

public class ItemController {

    @Autowired

    private ItemService itemService;

    /**

    * 對外提供接口服務,查詢商品信息

    *

    * @param id

    * @return

    */

    @GetMapping(value = "/item/{id}")

    public Item queryItemById(@PathVariable("id") Long id) {

        return this.itemService.queryItemById(id);

    }

}

3.1.5 程序入口

package cn.itcast.microservice;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication    //聲明這是一個 Spring Boot 項目

    public class ItemApplication {

    public static void main(String[] args) {

        SpringApplication.run(ItemApplication.class, args);

    }

}


3.1.6 創(chuàng)建配置文件

在 src/main/resources 目錄下創(chuàng)建一個 application.properties 配置文件,在該文件中可以配置如下內容:

server.port=8081

指定服務啟動占用的端口


3.1.7 啟動項目進行訪問

Spring-Boot-實現微服務02

3.2 實現訂單微服務

3.2.1 pom.xml 文件的配置

<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>

<groupId>cn.itcast.microservice</groupId>

<artifactId>itcast-microservice-order</artifactId>

<version>0.0.1-SNAPSHOT</version>

<!-- 定義變量 -->

<properties>

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

</properties>

<parent>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-parent</artifactId>

    <version>1.5.14.RELEASE</version>

</parent>

<dependencies>

    <!-- 加入 web 的支持 -->

    <dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-web</artifactId>

    </dependency>
</dependencies>

</project>

3.2.2 創(chuàng)建實體 Order

package cn.itcast.microservice.pojo;

import java.util.Date;

import java.util.List;

public class Order {

    private String orderId; // 訂單的 id

    private Long userId; // 用戶 id

    private Date createDate; // 創(chuàng)建時間

    private Date updateDate; // 修改時間

    private List<OrderDetail> orderDetails; // 訂單詳情

}

3.2.3 創(chuàng)建實體 OrderDetail

package cn.itcast.microservice.pojo;

public class OrderDetail {

    private String orderId ; // 訂單 id

    private Item item ; // 商品

}

3.2.4 復制 Item 實體

Spring-Boot-實現微服務03

3.2.5 編寫 OrderService

該 Service 實現的根據訂單 Id 查詢訂單的服務,為了方便測試,我們將構造數據實現,不采用查詢數據庫的方式。

package cn.itcast.microservice.service;

import java.util.ArrayList;

import java.util.Date;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import org.springframework.stereotype.Service;

import cn.itcast.microservice.pojo.Item;

import cn.itcast.microservice.pojo.Order;

import cn.itcast.microservice.pojo.OrderDetail;

@Service

public class OrderService {

    private static final Map<String, Order> MAP = new HashMap<String, Order>();

    static {

        // 構造測試數據

        Order order = new Order();

        order.setOrderId("59193738268961441");

        order.setCreateDate(new Date());

        order.setUpdateDate(order.getCreateDate());

        order.setUserId(1L);

       // 創(chuàng)建 OrderDetail 集合對象

        List<OrderDetail> orderDetails = new ArrayList<OrderDetail>();

        Item item = new Item(); // 此處并沒有商品的數據,需要調用商品微服務獲取

        item.setId(1L);

        orderDetails.add(new OrderDetail(order.getOrderId(), item));

        item = new Item(); // 構造第二個商品數據

        item.setId(2L);

        orderDetails.add(new OrderDetail(order.getOrderId(), item));

        // 將 OrderDetail 數據集設置給 Order 對象

        order.setOrderDetails(orderDetails);

        // 將 Order 對象添加到 Map 中

        MAP.put(order.getOrderId(), order);

    }

    /**

   * 根據訂單 id 查詢訂單數據

   *

   * @param orderId

   * @return

   */

    public Order queryOrderById(String orderId) {

        Order order = MAP.get(orderId);

        // 獲取 Order 中的 OrderDetail 列表數據,然后遍歷集合獲取每一個 OrderDetail,然后調用商品微服務根據商品的 id 查詢商品數據

        return order;

    }

}

3.2.6 實現 ItemService

package cn.itcast.microservice.service;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import org.springframework.web.client.RestTemplate;

import cn.itcast.microservice.pojo.Item;

@Service

public class ItemService {

    @Autowired

    private RestTemplate restTemplate ;

    /**

    * 根據商品的 id 進行查詢

    * @param id

    * @return

    */

    public Item queryById(Long id) {

        // 使用 HttpClient 工具發(fā)送請求獲取商品的數據

        // 我們也可以使用 spring 給我們提供的另個一個類 RestTemplate,來發(fā)送 Http 請求

        Item item = restTemplate.getForObject("http://localhost:8081/item/" + id, Item.class) ;

        // 返回

        return item ;

    }

}

3.2.7 完善 OrderService

@Autowired

private ItemService itemService ;

/**

* 根據訂單 id 查詢訂單數據

*

* @param orderId

* @return

*/

public Order queryOrderById(String orderId) {

    Order order = MAP.get(orderId);

    // 獲取 Order 中的 OrderDetail 列表數據,然后遍歷集合獲取每一個 OrderDetail,然后調用商品微服務根據商品的 id 查詢商品數據

    for (OrderDetail orderDetail : order.getOrderDetails()) {

        Item item = itemService.queryById(orderDetail.getItem().getId()) ;

        orderDetail.setItem(item);

}

    return order;

}


3.2.8 編寫 OrderController

package cn.itcast.microservice.controller;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.PathVariable;

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

import cn.itcast.microservice.pojo.Order;

import cn.itcast.microservice.service.OrderService;

@RestController

public class OrderController {

    @Autowired

    private OrderService orderService;

    @GetMapping(value = "/order/{orderId}")

    public Order queryOrderById(@PathVariable("orderId") String orderId) {

        return this.orderService.queryOrderById(orderId);

    }

}

3.2.9 編寫啟動類

package cn.itcast.microservice;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.context.annotation.Bean;

import org.springframework.web.client.RestTemplate;

@SpringBootApplication

public class OrderApplication {

    @Bean

    public RestTemplate restTemplate() {

        return new RestTemplate();

}

// 程序入口

public static void main(String[] args) {

    /**

    * 啟動程序

    */

    SpringApplication.run(OrderApplication.class, args) ;

    }

}

3.2.10創(chuàng)建配置文件

在 src/main/resources 目錄下創(chuàng)建一個 application.properties 配置文件,在該文件中可以配置如下內容:

server.port=8082

3.2.11啟動測試

Spring-Boot-實現微服務04

3.3 發(fā)現問題與解決問題

3.3.1 問題描述

在剛才的服務調用過程中我們的商品服務地址是直接寫死在程序中,存在硬編碼問題

如果商品微服務部署了多個,那么我們訂單微服務如何去調用呢?

3.3.2 問題處理

1. 關于硬編碼的問題我們可以使用配置文件處理,我們可以將地址信息編寫到配置文件中,然后讀取配置文件獲取請求地址信息.

在配置文件中加入如下配置:

itcast.item.url=http://127.0.0.1:8081/item/

修改 ItemService 的實現,通過@Value 注解獲取該值

package cn.itcast.microservice.service;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.stereotype.Service;

import org.springframework.web.client.RestTemplate;

import cn.itcast.microservice.pojo.Item;

@Service

public class ItemService {

    @Autowired

    private RestTemplate restTemplate ;

    @Value("${itcast.item.url}")

    private String itemUrl ;

    /**

    * 根據商品的 id 進行查詢

    * @param id

    * @return

    */

    public Item queryById(Long id) {

        // 我們也可以使用 spring boot 給我們提供的另個一個類 RestTemplate,來發(fā)送 Http 請求

       Item item = restTemplate.getForObject(itemUrl + id, Item.class) ;

        // 返回

        return item ;

    }

}

注: 我們本次的解決方案只是一種臨時的處理方案,如果我們商品微服務的 ip 地址發(fā)送了改變,那么我們對應的訂單微服務的配置文件也需要做響應的改變,因此這種處理方案并沒有本質的解決硬編碼的問題。

2. 如果商品微服務部署了多個,那么我們訂單微服務如何去調用呢? 

關于這個問題,有的開發(fā)人員可能會想。我們可以將多個商品微服務的地址配置到配置文件中,然后在進行讀取配置文件的地址,進行調用。聽起來好像可以,但是我們需要考慮以后問題就是后期維護的問題。

·如果商品微服務的我們又添加或者減少了一個部署,相應的我們需要去更改配置文件的內容。

·如果商品微服務的 ip 地址發(fā)送了改變,那么我們也需要相應的修改配置文件的地址。

所以我們自己這樣實現比較麻煩。

我們可以使用服務注冊于發(fā)現機制來完成


猜你喜歡:

Spring Cloud微服務架構解決方案詳細介紹

0 分享到:
和我們在線交談!