更新時(shí)間:2020年04月10日13時(shí)59分 來(lái)源:黑馬程序員 瀏覽次數(shù):
在正式學(xué)習(xí) Spring Cloud 之前我們先使用 Spring Boot 實(shí)現(xiàn)一個(gè)微服務(wù)。
業(yè)務(wù)非常簡(jiǎn)單:
(1)商品微服務(wù):通過(guò)商品 id 查詢商品的服務(wù);
(2)訂單微服務(wù):通過(guò)訂單 id 查詢訂單數(shù)據(jù),同時(shí)需要調(diào)用商品微服務(wù)查詢出訂單詳情數(shù)據(jù)對(duì)應(yīng)的商品數(shù)據(jù)
說(shuō)明:
(1)對(duì)于商品微服務(wù)而言,商品微服務(wù)是服務(wù)的提供者,訂單微服務(wù)是服務(wù)的消費(fèi)者;
(2)對(duì)于訂單微服務(wù)而言,訂單微服務(wù)是服務(wù)的提供者,人是服務(wù)的消費(fèi)者。
3.1 實(shí)現(xiàn)商品微服務(wù)
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)建實(shí)體 Item
package cn.itcast.microservice.pojo;
public class Item {
private Long id; // 唯一標(biāo)識(shí)
private String title; // 商品標(biāo)題
private String pic; // 圖片的 pic 地址
private String desc; // 描述信息
private Long price; // 價(jià)格
}
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 { // 準(zhǔn)備一些靜態(tài)數(shù)據(jù)
MAP.put(1L, new Item(1L, "商品標(biāo)題 1", "http://圖片 1", "商品描述 1", 1000L));
MAP.put(2L, new Item(1L, "商品標(biāo)題 2", "http://圖片 2", "商品描述 2", 2000L));
MAP.put(3L, new Item(1L, "商品標(biāo)題 3", "http://圖片 3", "商品描述 3", 3000L));
MAP.put(4L, new Item(1L, "商品標(biāo)題 4", "http://圖片 4", "商品描述 4", 4000L));
MAP.put(5L, new Item(1L, "商品標(biāo)題 5", "http://圖片 5", "商品描述 5", 5000L));
MAP.put(6L, new Item(1L, "商品標(biāo)題 6", "http://圖片 6", "商品描述 6", 6000L));
MAP.put(7L, new Item(1L, "商品標(biāo)題 7", "http://圖片 7", "商品描述 7", 7000L));
MAP.put(8L, new Item(1L, "商品標(biāo)題 8", "http://圖片 8", "商品描述 8", 8000L));
}
/**
* 模擬實(shí)現(xiàn)商品查詢
*
* @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;
/**
* 對(duì)外提供接口服務(wù),查詢商品信息
*
* @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 //聲明這是一個(gè) Spring Boot 項(xiàng)目
public class ItemApplication {
public static void main(String[] args) {
SpringApplication.run(ItemApplication.class, args);
}
}
3.1.6 創(chuàng)建配置文件
在 src/main/resources 目錄下創(chuàng)建一個(gè) application.properties 配置文件,在該文件中可以配置如下內(nèi)容:
server.port=8081
指定服務(wù)啟動(dòng)占用的端口
3.1.7 啟動(dòng)項(xiàng)目進(jìn)行訪問(wèn)
3.2 實(shí)現(xiàn)訂單微服務(wù)
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)建實(shí)體 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)建時(shí)間
private Date updateDate; // 修改時(shí)間
private List<OrderDetail> orderDetails; // 訂單詳情
}
3.2.3 創(chuàng)建實(shí)體 OrderDetail
package cn.itcast.microservice.pojo;
public class OrderDetail {
private String orderId ; // 訂單 id
private Item item ; // 商品
}
3.2.4 復(fù)制 Item 實(shí)體
3.2.5 編寫 OrderService
該 Service 實(shí)現(xiàn)的根據(jù)訂單 Id 查詢訂單的服務(wù),為了方便測(cè)試,我們將構(gòu)造數(shù)據(jù)實(shí)現(xiàn),不采用查詢數(shù)據(jù)庫(kù)的方式。
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 {
// 構(gòu)造測(cè)試數(shù)據(jù)
Order order = new Order();
order.setOrderId("59193738268961441");
order.setCreateDate(new Date());
order.setUpdateDate(order.getCreateDate());
order.setUserId(1L);
// 創(chuàng)建 OrderDetail 集合對(duì)象
List<OrderDetail> orderDetails = new ArrayList<OrderDetail>();
Item item = new Item(); // 此處并沒(méi)有商品的數(shù)據(jù),需要調(diào)用商品微服務(wù)獲取
item.setId(1L);
orderDetails.add(new OrderDetail(order.getOrderId(), item));
item = new Item(); // 構(gòu)造第二個(gè)商品數(shù)據(jù)
item.setId(2L);
orderDetails.add(new OrderDetail(order.getOrderId(), item));
// 將 OrderDetail 數(shù)據(jù)集設(shè)置給 Order 對(duì)象
order.setOrderDetails(orderDetails);
// 將 Order 對(duì)象添加到 Map 中
MAP.put(order.getOrderId(), order);
}
/**
* 根據(jù)訂單 id 查詢訂單數(shù)據(jù)
*
* @param orderId
* @return
*/
public Order queryOrderById(String orderId) {
Order order = MAP.get(orderId);
// 獲取 Order 中的 OrderDetail 列表數(shù)據(jù),然后遍歷集合獲取每一個(gè) OrderDetail,然后調(diào)用商品微服務(wù)根據(jù)商品的 id 查詢商品數(shù)據(jù)
return order;
}
}
3.2.6 實(shí)現(xiàn) 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 ;
/**
* 根據(jù)商品的 id 進(jìn)行查詢
* @param id
* @return
*/
public Item queryById(Long id) {
// 使用 HttpClient 工具發(fā)送請(qǐng)求獲取商品的數(shù)據(jù)
// 我們也可以使用 spring 給我們提供的另個(gè)一個(gè)類 RestTemplate,來(lái)發(fā)送 Http 請(qǐng)求
Item item = restTemplate.getForObject("http://localhost:8081/item/" + id, Item.class) ;
// 返回
return item ;
}
}
3.2.7 完善 OrderService
@Autowired
private ItemService itemService ;
/**
* 根據(jù)訂單 id 查詢訂單數(shù)據(jù)
*
* @param orderId
* @return
*/
public Order queryOrderById(String orderId) {
Order order = MAP.get(orderId);
// 獲取 Order 中的 OrderDetail 列表數(shù)據(jù),然后遍歷集合獲取每一個(gè) OrderDetail,然后調(diào)用商品微服務(wù)根據(jù)商品的 id 查詢商品數(shù)據(jù)
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 編寫啟動(dòng)類
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) {
/**
* 啟動(dòng)程序
*/
SpringApplication.run(OrderApplication.class, args) ;
}
}
3.2.10創(chuàng)建配置文件
在 src/main/resources 目錄下創(chuàng)建一個(gè) application.properties 配置文件,在該文件中可以配置如下內(nèi)容:
server.port=8082
3.2.11啟動(dòng)測(cè)試
3.3 發(fā)現(xiàn)問(wèn)題與解決問(wèn)題
3.3.1 問(wèn)題描述
在剛才的服務(wù)調(diào)用過(guò)程中我們的商品服務(wù)地址是直接寫死在程序中,存在硬編碼問(wèn)題
如果商品微服務(wù)部署了多個(gè),那么我們訂單微服務(wù)如何去調(diào)用呢?
3.3.2 問(wèn)題處理
1. 關(guān)于硬編碼的問(wèn)題我們可以使用配置文件處理,我們可以將地址信息編寫到配置文件中,然后讀取配置文件獲取請(qǐng)求地址信息.
在配置文件中加入如下配置:
itcast.item.url=http://127.0.0.1:8081/item/
修改 ItemService 的實(shí)現(xiàn),通過(guò)@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 ;
/**
* 根據(jù)商品的 id 進(jìn)行查詢
* @param id
* @return
*/
public Item queryById(Long id) {
// 我們也可以使用 spring boot 給我們提供的另個(gè)一個(gè)類 RestTemplate,來(lái)發(fā)送 Http 請(qǐng)求
Item item = restTemplate.getForObject(itemUrl + id, Item.class) ;
// 返回
return item ;
}
}
注: 我們本次的解決方案只是一種臨時(shí)的處理方案,如果我們商品微服務(wù)的 ip 地址發(fā)送了改變,那么我們對(duì)應(yīng)的訂單微服務(wù)的配置文件也需要做響應(yīng)的改變,因此這種處理方案并沒(méi)有本質(zhì)的解決硬編碼的問(wèn)題。
2. 如果商品微服務(wù)部署了多個(gè),那么我們訂單微服務(wù)如何去調(diào)用呢?
關(guān)于這個(gè)問(wèn)題,有的開(kāi)發(fā)人員可能會(huì)想。我們可以將多個(gè)商品微服務(wù)的地址配置到配置文件中,然后在進(jìn)行讀取配置文件的地址,進(jìn)行調(diào)用。聽(tīng)起來(lái)好像可以,但是我們需要考慮以后問(wèn)題就是后期維護(hù)的問(wèn)題。
·如果商品微服務(wù)的我們又添加或者減少了一個(gè)部署,相應(yīng)的我們需要去更改配置文件的內(nèi)容。
·如果商品微服務(wù)的 ip 地址發(fā)送了改變,那么我們也需要相應(yīng)的修改配置文件的地址。
所以我們自己這樣實(shí)現(xiàn)比較麻煩。
我們可以使用服務(wù)注冊(cè)于發(fā)現(xiàn)機(jī)制來(lái)完成
猜你喜歡:
什么是Neo4j?如何通過(guò)Neo4j構(gòu)建《人民的名義》的關(guān)系圖譜?
2020-04-03傳智播客Java實(shí)戰(zhàn)項(xiàng)目紀(jì)實(shí):java實(shí)戰(zhàn)項(xiàng)目過(guò)程再現(xiàn)
2020-04-03黑馬AI機(jī)器人實(shí)戰(zhàn)教程[Java培訓(xùn)]
2020-03-26上海哪個(gè)Java培訓(xùn)好?推薦這兩家
2020-03-22北京Java培訓(xùn)學(xué)校哪好?[java培訓(xùn)推薦]
2020-03-22Spring Cloud微服務(wù)架構(gòu)解決方案詳細(xì)介紹[java培訓(xùn)]
2020-03-18北京校區(qū)