三、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数据访问层
数据访问层接口
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); }
mappr.xml文件
<?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
至此,两个微服务之间的调用就实现了,如有不妥之处,欢迎大家指正!