1. 程式人生 > >第8章 Dubbo入門到重構服務

第8章 Dubbo入門到重構服務

Dubbo入門到重構服務

8-1 架構演變過程

在這裡插入圖片描述


在這裡插入圖片描述


在這裡插入圖片描述


在這裡插入圖片描述

8-2 dubbo 入門簡介

在這裡插入圖片描述


在這裡插入圖片描述


Dubbo官方網站


8-3 單體到分層模式程式碼演示

這種單體的方式,如果我們需要哪一個服務,那麼我們就把這個服務的依賴匯入即可引用:
在這裡插入圖片描述
IMoocJSONResult類:統一返回給前端的類

/**
 * 
 * @Description: 自定義響應資料結構
 * 				這個類是提供給門戶,ios,安卓,微信商城用的
 * 				門戶接受此類資料後需要使用本類的方法轉換成對於的資料型別格式(類,或者list)
 * 				其他自行處理
 * 				200:表示成功
 * 				500:表示錯誤,錯誤資訊在msg欄位中
 * 				501:bean驗證錯誤,不管多少個錯誤都以map形式返回
 * 				502:攔截器攔截到使用者token出錯
 * 				555:異常丟擲資訊
 */
public class IMoocJSONResult { // 響應業務狀態 private Integer status; // 響應訊息 private String msg; // 響應中的資料 private Object data; private String ok; // 不使用 public static IMoocJSONResult build(Integer status, String msg, Object data) { return new IMoocJSONResult(status,
msg, data); } public static IMoocJSONResult ok(Object data) { return new IMoocJSONResult(data); } public static IMoocJSONResult ok() { return new IMoocJSONResult(null); } public static IMoocJSONResult errorMsg(String msg) { return new IMoocJSONResult(500, msg, null); } public static IMoocJSONResult errorMap(Object data) { return new IMoocJSONResult(501, "error", data); } public static IMoocJSONResult errorTokenMsg(String msg) { return new IMoocJSONResult(502, msg, null); } public static IMoocJSONResult errorException(String msg) { return new IMoocJSONResult(555, msg, null); } public IMoocJSONResult() { } // public static LeeJSONResult build(Integer status, String msg) { // return new LeeJSONResult(status, msg, null); // } public IMoocJSONResult(Integer status, String msg, Object data) { this.status = status; this.msg = msg; this.data = data; } public IMoocJSONResult(Object data) { this.status = 200; this.msg = "OK"; this.data = data; } public Boolean isOK() { return this.status == 200; } public Integer getStatus() { return status; } public void setStatus(Integer status) { this.status = status; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public Object getData() { return data; } public void setData(Object data) { this.data = data; } public String getOk() { return ok; } public void setOk(String ok) { this.ok = ok; } }

這個就是Mybatis逆向工程的配置檔案:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
  PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
  "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
	<context id="testTables" targetRuntime="MyBatis3">
		<commentGenerator>
			<!-- 是否去除自動生成的註釋 true:是 : false:否 -->
			<property name="suppressAllComments" value="true" />
		</commentGenerator>
		<!--資料庫連線的資訊:驅動類、連線地址、使用者名稱、密碼 -->
		<jdbcConnection 
			driverClass="com.mysql.jdbc.Driver"
			connectionURL="jdbc:mysql://localhost:3306/imooc-services" userId="root"
			password="root">
		</jdbcConnection>
		<!-- 預設false,把JDBC DECIMAL 和 NUMERIC 型別解析為 Integer,為 true時把JDBC DECIMAL 和 
			NUMERIC 型別解析為java.math.BigDecimal -->
		<javaTypeResolver>
			<property name="forceBigDecimals" value="false" />
		</javaTypeResolver>

		<!-- targetProject:生成PO類的位置 -->
		<javaModelGenerator 
			targetPackage="com.imooc.pojo"
			targetProject=".\src">
			<!-- enableSubPackages:是否讓schema作為包的字尾 -->
			<property name="enableSubPackages" value="false" />
			<!-- 從資料庫返回的值被清理前後的空格 -->
			<property name="trimStrings" value="true" />
		</javaModelGenerator>
        <!-- targetProject:mapper對映檔案生成的位置 -->
		<sqlMapGenerator 
			targetPackage="com.imooc.mapper" 
			targetProject=".\src">
			<!-- enableSubPackages:是否讓schema作為包的字尾 -->
			<property name="enableSubPackages" value="false" />
		</sqlMapGenerator>
		<!-- targetPackage:mapper介面生成的位置 -->
		<javaClientGenerator 
			type="XMLMAPPER"
			targetPackage="com.imooc.mapper" 
			targetProject=".\src">
			<!-- enableSubPackages:是否讓schema作為包的字尾 -->
			<property name="enableSubPackages" value="false" />
		</javaClientGenerator>
		<!-- 指定資料庫表 -->
		<table schema="" tableName="orders"></table>
		<table schema="" tableName="items"></table>

	</context>
</generatorConfiguration>

當我們配置好了之後,我們啟動這個類裡面的主方法就可以了:

public class GeneratorSqlmap {

	public void generator() throws Exception{

		List<String> warnings = new ArrayList<String>();
		boolean overwrite = true;
		//指定 逆向工程配置檔案
		File configFile = new File("generatorConfig.xml"); 
		ConfigurationParser cp = new ConfigurationParser(warnings);
		Configuration config = cp.parseConfiguration(configFile);
		DefaultShellCallback callback = new DefaultShellCallback(overwrite);
		MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config,
				callback, warnings);
		myBatisGenerator.generate(null);

	} 
	public static void main(String[] args) throws Exception {
		try {
			GeneratorSqlmap generatorSqlmap = new GeneratorSqlmap();
			generatorSqlmap.generator();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}

}

當我們生成好了實體類、Mapper介面類,Mapper對映檔案了之後,我們把這些檔案拷貝到我們要用的地方就可以了!


這個就是訂單模組裡面的訂單服務:

@Service("ordersService")
public class OrdersServiceImpl implements OrdersService {
	
	final static Logger log = LoggerFactory.getLogger(OrdersServiceImpl.class);
	
	@Autowired
	private OrdersMapper ordersMapper;
	
	@Override
	public Orders getOrder(String orderId) {
		return ordersMapper.selectByPrimaryKey(orderId);
	}

	@Override
	public boolean createOrder(String itemId) {
		
		// 建立訂單
		String oid = UUID.randomUUID().toString().replaceAll("-", "");
		Orders o = new Orders();
		o.setId(oid);
		o.setOrderNum(oid);
		o.setItemId(itemId);
		ordersMapper.insert(o);
		
		log.info("訂單建立成功");
		
		return true;
	}

}

而這個就是商品服務裡面的server介面:

public interface ItemsService {

	/**
	 * @Description: 根據商品id獲取商品
	 */
	public Items getItem(String itemId);
	
	/**
	 * @Description: 查詢商品庫存
	 */
	public int getItemCounts(String itemId);
	
	/**
	 * @Description: 購買商品成功後減少庫存
	 */
	public void displayReduceCounts(String itemId, int buyCounts);

}

而這個就是實現類:

@Service("itemsService")
public class ItemsServiceImpl implements ItemsService {
	
	@Autowired
	private ItemsMapper itemsMapper;

	@Override
	public Items getItem(String itemId) {	
		return itemsMapper.selectByPrimaryKey(itemId);
	}
	
	@Override
	public int getItemCounts(String itemId) {
		Items item = itemsMapper.selectByPrimaryKey(itemId);
		return item.getCounts();
	}

	@Override
	public void displayReduceCounts(String itemId, int buyCounts) {
		
		//		int a  = 1 / 0;
		
		Items reduceItem = new Items();
		reduceItem.setId(itemId);
		reduceItem.setBuyCounts(buyCounts);
		itemsMapper.reduceCounts(reduceItem);
	}

}

這個就是購買商品的service:有兩個過程,一個是從商品服務裡面去減少庫存,另外一個就從訂單服務裡面去建立訂單;

@Service("buyService")
public class BuyServiceImpl implements BuyService {
	
	final static Logger log = LoggerFactory.getLogger(BuyServiceImpl.class);
	
	@Autowired
	private ItemsService itemService;

	@Autowired
	private OrdersService ordersService;
	
	@Override
	public void doBuyItem(String itemId) {
		// 減少庫存
		itemService.displayReduceCounts(itemId, 1);
		
		// 建立訂單
		ordersService.createOrder(itemId);
	}
	
	@Override
	public boolean displayBuy(String itemId) {
		
		int buyCounts = 5;
		
		// 1. 判斷庫存
		int stockCounts = itemService.getItemCounts(itemId);
		if (stockCounts < buyCounts) {
			log.info("庫存剩餘{}件,使用者需求量{}件,庫存不足,訂單建立失敗...", 
					stockCounts, buyCounts);
			return false;
		}
		
		// 2. 建立訂單
		boolean isOrderCreated = ordersService.createOrder(itemId);
		
		// 3. 建立訂單成功後,扣除庫存
		if (isOrderCreated) {
			log.info("訂單建立成功...");
			itemService.displayReduceCounts(itemId, buyCounts);
		} else {
			log.info("訂單建立失敗...");
			return false;
		}
		
		return true;
	}
	
}

8-4 重構商品服務,抽取抽象工程

建立一個API工程:
在這裡插入圖片描述

8-5 暴露商品服務

上面所寫的就是API層就是介面層;而下面我們寫的service層就是實現層:
這個就是生產者的xml配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
	http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
		
	<!-- 為當前服務提供者取個名字,並且提供給註冊中心 -->
	<dubbo:application name="imooc-dubbo-item-service"></dubbo:application>
	
	<!-- 註冊中心的配置,使用zk暴露服務 -->
	<dubbo:registry protocol="zookeeper" address="192.168.1.110:2181"></dubbo:registry>
	
	<!-- 定義暴露服務的埠號 -->
	<dubbo:protocol name="dubbo" port="20880"></dubbo:protocol>
	
	<!-- 暴露具體的服務介面 -->
	<dubbo:service retries="3" interface="com.imooc.item.service.ItemsService" 
		ref="itemsService"></dubbo:service>
	
</beans>

在這裡插入圖片描述


這個就是暴露生產者的xml配置:我們暴露出去的實際上一個介面

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
	http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
		
	<!-- 為當前服務提供者取個名字,並且提供給註冊中心 -->
	<dubbo:application name="imooc-dubbo-item-service"></dubbo:application>
	
	<!-- 註冊中心的配置,使用zk暴露服務 -->
	<dubbo:registry protocol="zookeeper" address="192.168.1.110:2181"></dubbo:registry>
	
	<!-- 定義暴露服務的埠號 -->
	<dubbo:protocol name="dubbo" port="20880"></dubbo:protocol>
	
	<!-- 暴露具體的服務介面,retries表示的就是一個重連機制 -->
	<dubbo:service retries="3" interface="com.imooc.item.service.ItemsService" 
		ref="itemsService"></dubbo:service>
	
</beans>

8-6 使用tomcat啟動dubbo服務

在這裡插入圖片描述
我們在聚合工程裡面引入jar包:

		<!-- 引入dubbo -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>dubbo</artifactId>
			<exclusions>
				<exclusion>
					<groupId>org.springframework</groupId>
					<artifactId>spring</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.apache.zookeeper</groupId>
			<artifactId>zookeeper</artifactId>
		</dependency>
		<dependency>
			<groupId>com.github.sgroschupf</groupId>