Spring Boot如何實現微服務?


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

業務非常簡單:

(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 創建實體 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 { // 准備一些靜態數據

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 創建配置文件

在 src/main/resources 目錄下創建一個 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 創建實體 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; // 創建時間

private Date updateDate; // 修改時間

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

}

 

3.2.3 創建實體 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);

// 創建 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 工具發送請求獲取商品的數據

// 我們也可以使用 spring 給我們提供的另個一個類 RestTemplate,來發送 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創建配置文件

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

server.port=8082

3.2.11啟動測試

Spring-Boot-實現微服務04

3.3 發現問題與解決問題

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,來發送 Http 請求

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

// 返回

return item ;

}

}

 

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

 

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

 

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

 

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

 

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

 

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

 

我們可以使用服務注冊於發現機制來完成


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM