三、Spring Cloud入門案例
使用微服務架構的分布式系統,微服務之間通過網絡通信。我們通過服務提供者與服務消費者來描述微服務之間的調用關系:
服務提供者:服務的被調用方,提供調用接口的一方;
服務消費者:服務的調用方,依賴于其他服務的一方。
案例描述:使用者在購買商品時發起一個購買的請求,在進行儲存訂單之前需要調用商品微服務查詢目前商品的相關資訊。也就是說訂單微服務是一個服務消費者,商品微服務是一個服務提供者。
資料庫表的設計
商品表
訂單表
環境搭建
- 建立新項目:SpringCloud-ebuy
- 建立父工程:ebuy-parent 父工程中引入相關依賴:
<?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> <!-- gav:項目的坐标 --> <groupId>cn.ebuy</groupId> <artifactId>ebuy-parent</artifactId> <packaging>pom</packaging> <version>1.0-SNAPSHOT</version> <modules> <module>../ebuy-product</module> <module>../ebuy-order</module> </modules> <!-- spring cloud依賴于springboot,導入spring boot的jar包 --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.6.RELEASE</version> </parent> <!-- 設定字元集編碼和運作版本号 --> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>9</java.version> </properties> <dependencies> <!-- spring boot的web子產品--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- spring boot的日志--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </dependency> <!-- spring boot的單元測試 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- lombok可以自動生成getter/setter方法,隻需要标記@Data注解即可--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.4</version> <scope>provided</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <!-- spring cloud依賴包--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Greenwich.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> </project>
- 建立微服務工程:ebuy-product
- 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"> <!-- 依賴父子產品 --> <parent> <artifactId>ebuy-parent</artifactId> <groupId>cn.ebuy</groupId> <version>1.0-SNAPSHOT</version> <relativePath>../ebuy-parent/pom.xml</relativePath> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>ebuy-product</artifactId> <dependencies> <!-- spring boot啟動--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.2</version> </dependency> <!-- 分頁插件 --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>1.3.0</version> </dependency> <!-- mysql驅動 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.49</version> </dependency> <!-- spring cloud相關 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-commons</artifactId> </dependency> </dependencies> </project>
- 實體類
package cn.ebuy.product.pojo; import lombok.Data; import java.io.Serializable; import java.math.BigDecimal; /** * 實體類 * 使用了lombok簡化實體類的開發 * Lombok能以簡單的注解形式來簡化java代碼,提高開發人員的開發效率 */ @Data @SuppressWarnings("all") public class EasybuyProduct implements Serializable { private Long epId; private String epName; private String epDescription; private BigDecimal epPrice; private Long epStock; private Long epcId; private Long epcChildId; private String epFileName; private static final long serialVersionUID = 1L; }
-
mapper資料通路層
資料通路層接口
mappr.xml檔案package cn.ebuy.product.mapper; import cn.ebuy.product.pojo.EasybuyProduct; import java.util.List; @SuppressWarnings("all") public interface EasybuyProductMapper { /** * 根據主鍵id查詢商品資訊 * @param epId * @return */ EasybuyProduct selectByPrimaryKey(Long epId); }
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace="cn.ebuy.product.mapper.EasybuyProductMapper" > <resultMap id="BaseResultMap" type="cn.ebuy.product.pojo.EasybuyProduct" > <id column="ep_id" property="epId" jdbcType="DECIMAL" /> <result column="ep_name" property="epName" jdbcType="VARCHAR" /> <result column="ep_description" property="epDescription" jdbcType="VARCHAR" /> <result column="ep_price" property="epPrice" jdbcType="DECIMAL" /> <result column="ep_stock" property="epStock" jdbcType="DECIMAL" /> <result column="epc_id" property="epcId" jdbcType="DECIMAL" /> <result column="epc_child_id" property="epcChildId" jdbcType="DECIMAL" /> <result column="ep_file_name" property="epFileName" jdbcType="VARCHAR" /> <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Long" > select ep_id, ep_name, ep_description, ep_price, ep_stock, epc_id, epc_child_id, ep_file_name from EASYBUY_PRODUCT where ep_id = #{epId,jdbcType=DECIMAL} </select> </mapper>
- 業務邏輯層接口及實作類
package cn.ebuy.product.service; import cn.ebuy.product.pojo.EasybuyProduct; import com.github.pagehelper.PageInfo; import java.util.List; /** * 業務邏輯層接口 */ @SuppressWarnings("all") public interface EasybuyProductService { /** * 根據主鍵id查詢商品資訊 * @param epId * @return */ EasybuyProduct selectByPrimaryKey(Long epId); } package cn.ebuy.product.service.impl; import cn.ebuy.product.pojo.EasybuyProduct; import cn.ebuy.product.mapper.EasybuyProductMapper; import cn.ebuy.product.service.EasybuyProductService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; /** * 業務邏輯層接口實作類 */ @Service @SuppressWarnings("all") public class EasybuyProductServiceImpl implements EasybuyProductService { @Autowired EasybuyProductMapper easybuyProductMapper; @Override public EasybuyProduct selectByPrimaryKey(Long epId) { return easybuyProductMapper.selectByPrimaryKey(epId); } }
- web層controller
package cn.ebuy.product.controller; import cn.ebuy.product.pojo.EasybuyProduct; import cn.ebuy.product.service.EasybuyProductService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/product") @SuppressWarnings("all") public class ProductController { @Autowired private EasybuyProductService easybuyProductService; /** * 根據主鍵id查詢商品資訊 * @param id * @return */ @RequestMapping(value = "/{id}",method = RequestMethod.GET) public EasybuyProduct findById(@PathVariable Long id) { EasybuyProduct product = easybuyProductService.selectByPrimaryKey(id); return product; } }
- 配置啟動類
package cn.ebuy.product; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication(scanBasePackages = "cn.ebuy.product") @MapperScan(basePackages = "cn.ebuy.product.mapper") @SuppressWarnings("all") public class ProductApplication { public static void main(String[] args) { SpringApplication.run(ProductApplication.class,args); } }
- 配置yml檔案
server: port: 9011 #端口号 spring: application: name: ebuy-product #服務名稱 datasource: driver-class-name: com.mysql.jdbc.Driver #mysql驅動 url: jdbc:mysql://127.0.0.1:3306/ebuy?useUnicode=true&characterEncoding=utf8 username: root #連接配接資料庫使用者名 password: root #連接配接資料庫密碼 mybatis: type-aliases-package: cn.ebuy.product.pojo #實體類映射 mapper-locations: cn/ebuy/product/mapper/*.xml #mybatis掃描xml檔案位址 logging: level: cn.ebuy: DEBUG
- 建立微服務工程ebuy-order order需要調用商品product的服務,它本身作為一個消費者去調用。這裡隻是來實作對ebuy-product微服務的調用,是以其實沒有訂單業務的相關實作。
- 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"> <!-- 依賴于父子產品 --> <parent> <artifactId>ebuy-parent</artifactId> <groupId>cn.ebuy</groupId> <version>1.0-SNAPSHOT</version> <relativePath>../ebuy-parent/pom.xml</relativePath> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>ebuy-order</artifactId> <dependencies> <!-- spring cloud相關 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-commons</artifactId> </dependency> </dependencies> </project>
- product實體類(友善傳回結果)
package cn.ebuy.order.pojo; import lombok.Data; import java.io.Serializable; import java.math.BigDecimal; @Data @SuppressWarnings("all") public class EasybuyProduct implements Serializable { private Long epId; private String epName; private String epDescription; private BigDecimal epPrice; private Long epStock; private Long epcId; private Long epcChildId; private String epFileName; private static final long serialVersionUID = 1L; }
- web層controller
package cn.ebuy.order.controller; import cn.ebuy.order.pojo.EasybuyProduct; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import java.util.List; @RestController @RequestMapping("/order") @SuppressWarnings("all") public class OrderController { @Autowired RestTemplate restTemplate; @Autowired private DiscoveryClient discoveryClient; /** * 這裡的位址是沒有做叢集時的寫法,隻有一個位址 * @param id * @return */ @RequestMapping(value = "/{id}",method = RequestMethod.GET) public EasybuyProduct findById(@PathVariable Long id) { EasybuyProduct easybuyProduct=new EasybuyProduct(); // 這裡是調用product裡的服務,端口号是:9011 easybuyProduct=restTemplate.getForObject("http://127.0.0.1:9011/product/"+id,EasybuyProduct.class); return easybuyProduct; } }
- 配置啟動類
package cn.ebuy.order; 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 { /** * 配置RestTemplate交給spring管理 * @return */ @Bean public RestTemplate restTemplate() { return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(OrderApplication.class,args); } }
- 配置yml檔案
server: port: 9012 #端口 spring: application: name: ebuy-order #服務名稱 logging: level: cn.ebuy: DEBUG
至此,兩個微服務之間的調用就實作了,如有不妥之處,歡迎大家指正!