控制台 退出登录

四、微服务项目搭建


4.1、技术选型

  • 持久层:SpingData Jpa
  • 数据库: MySQL5.7
  • 技术栈:SpringCloud Alibaba 技术栈

4.2、模块设计

我们搭建一个微服务的项目,但是只有简单的代码,没有任何业务逻辑。

  • shop-parent 父工程
  • shop-product-api:商品微服务api ,用于存放商品实体。
  • shop-product-server:商品微服务,他的1端口是808x。
  • shop-order-api 订单微服务api,用于存放订单实体。
  • shop-order-server 订单微服务,他的端口是808x。

4.3、微服务的调用

在微服务架构中,最常见的场景就是微服务之间的相互调用。我们以电商系统中常见的用户下单为例来演示微服务的调用:客户向订单微服务发起一个下单的请求,在进行保存订单之前需要调用商品微服务查询商品的信息。

我们一般把服务的主动调用方称为服务消费者,把服务的被调用方称为服务提供者

![[00_System/Attachments/6d362b19c3de99f86752efbc7163de75_MD5.png]]

4.4、创建父工程

创建一个maven工程,然后在pom.xml文件中添加下面内容

<?xml version="1.0" encoding="UTF-8"?>

  <modelVersion>4.0.0</modelVersion>
  
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.3.RELEASE</version>
    <relativePath/>
  
  <groupId>cn.linstudy</groupId>
  <artifactId>Shop-parent</artifactId>
  pom
  <version>1.0.0</version>
  <modules>
    <module>Shop-order-api</module>
    <module>Shop-order-server</module>
    <module>Shop-product-api</module>
    <module>Shop-product-server</module>
  </modules>
  
    <java.version>11</java.version>
    UTF-8
    UTF-8
    <spring-cloud.version>Hoxton.SR8</spring-cloud.version>
    <spring-cloud-alibaba.version>2.2.3.RELEASE</spring-cloud-alibaba.version>
  
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>${spring-cloud.version}</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
      <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-alibaba-dependencies</artifactId>
        <version>${spring-cloud-alibaba.version}</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
      <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.47</version>
      </dependency>
    </dependencies>
  </dependencyManagement>

复制代码

4.5、创建商品服务

4.5.1、书写Shop-product-api的依赖

创建Shop-product-api项目,然后在pom.xml文件中添加下面内容

<?xml version="1.0" encoding="UTF-8"?>

  
    <artifactId>Shop-parent</artifactId>
    <groupId>cn.linstudy</groupId>
    <version>1.0.0</version>
  
  <modelVersion>4.0.0</modelVersion>
  <artifactId>Shop-product-api</artifactId>

  
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
  

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
    </dependency>
  </dependencies>

复制代码

4.5.2、创建实体

//商品
@Entity(name = "t_shop_product")
@Data
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long pid;//主键
    private String pname;//商品名称
    private Double pprice;//商品价格
    private Integer stock;//库存
}
复制代码

4.5.3、书写Shop-product-server的依赖

<?xml version="1.0" encoding="UTF-8"?>

  
    <artifactId>Shop-parent</artifactId>
    <groupId>cn.linstudy</groupId>
    <version>1.0.0</version>
  
  <modelVersion>4.0.0</modelVersion>

  <artifactId>Shop-order-server</artifactId>

  
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
  

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>fastjson</artifactId>
      <version>1.2.56</version>
    </dependency>
    <dependency>
      <groupId>cn.linstudy</groupId>
      <artifactId>Shop-order-api</artifactId>
      <version>1.0.0</version>
    </dependency>
    <dependency>
      <groupId>cn.linstudy</groupId>
      <artifactId>Shop-product-api</artifactId>
      <version>1.0.0</version>
    </dependency>
      
   </dependencies>

复制代码

4.5.4、编写application.yml

server:
  port: 8081
spring:
  application:
    name: product-service
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql:///shop-product?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
    username: root
    password: admin
  jpa:
    properties:
      hibernate:
        hbm2ddl:
          auto: update
        dialect: org.hibernate.dialect.MySQL5InnoDBDialect
复制代码

4.5.5、创建数据库

由于我们使用的是JPA,所以我们需要创建数据库,但是不需要创建表,因为JPA会在对应的数据库中自动创建表。

4.5.6、创建DAO接口

// 第一个参数是实体类,第二个参数是实体类对象的主键的类型
public interface ProductDao extends JpaRepository<Product,Long> {

}
复制代码

4.5.7、创建Service接口及其实现类

public interface ProductService {
  Product findById(Long productId);
}
复制代码
@Service
public class ProductServiceImpl implements ProductService {
  @Autowired
  ProductDao productDao;
    
  @Override
  public Product findById(Long productId) {
    return productDao.findById(productId).get();
  }
}
复制代码

4.5.8、书写Controller

@RestController
@Slf4j
public class ProductController {
    @Autowired
    private ProductService productService;
    
    //商品信息查询
    @RequestMapping("/product")
    public Product findByPid(@RequestParam("pid") Long pid) {
             Product product = productService.findByPid(pid);
             return product;
    }
}
复制代码

4.5.9、加入测试数据

我们在启动项目的时候,可以发现表已经默认帮我们自动创建好了,我们需要导入测试数据。

INSERT INTO t_shop_product VALUE(NULL,'小米','1000','5000'); 
INSERT INTO t_shop_product VALUE(NULL,'华为','2000','5000'); 
INSERT INTO t_shop_product VALUE(NULL,'苹果','3000','5000'); 
INSERT INTO t_shop_product VALUE(NULL,'OPPO','4000','5000');
复制代码

4.5.10、测试

![[00_System/Attachments/3fea6979b43dd61074bcbad4f01800f7_MD5.png]]

4.6、创建订单微服务

4.6.1、书写Shop-order-api的依赖

<?xml version="1.0" encoding="UTF-8"?>

  
    <artifactId>Shop-parent</artifactId>
    <groupId>cn.linstudy</groupId>
    <version>1.0.0</version>
  
  <modelVersion>4.0.0</modelVersion>

  <artifactId>Shop-order-api</artifactId>

  
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
  

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
    </dependency>
  </dependencies>

复制代码

4.6.2、创建订单实体

//订单
@Entity(name = "t_shop_order")
@Data
@JsonIgnoreProperties(value = { "hibernateLazyInitializer"})
public class Order implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long oid;//订单id

    //用户
    private Long uid;//用户id
    private String username;//用户名
    //商品
    private Long pid;//商品id
    private String pname;//商品名称
    private Double pprice;//商品单价
    //数量
    private Integer number;//购买数量
}
复制代码

4.6.3、创建shop-order-server项目

在pom.xml中添加依赖。

<?xml version="1.0" encoding="UTF-8"?>

  
    <artifactId>Shop-parent</artifactId>
    <groupId>cn.linstudy</groupId>
    <version>1.0.0</version>
  
  <modelVersion>4.0.0</modelVersion>

  <artifactId>Shop-order-server</artifactId>

  
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
  

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>fastjson</artifactId>
      <version>1.2.56</version>
    </dependency>
    <dependency>
      <groupId>cn.linstudy</groupId>
      <artifactId>Shop-order-api</artifactId>
      <version>1.0.0</version>
    </dependency>
    <dependency>
      <groupId>cn.linstudy</groupId>
      <artifactId>Shop-product-api</artifactId>
      <version>1.0.0</version>
    </dependency>

复制代码

4.6.4、编写application.yml

server:
  port: 8082
spring:
  application:
    name: order-service
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql:///shop-product?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
    username: root
    password: 1101121833
  jpa:
    properties:
      hibernate:
        hbm2ddl:
          auto: update
        dialect: org.hibernate.dialect.MySQL5InnoDBDialect
复制代码

4.6.5、编写Service及其实现类

我们写的Service接口及其实现类不具备任何的业务逻辑,仅仅只是为了测试而用。

public interface OrderService {
  Order getById(Long oid,Long pid);
}

复制代码
@Service
public class OrderServiceImpl implements OrderService {

  @Autowired
  OrderDao orderDao;

  @Override
  public Order getById(Long oid, Long pid) {
    return orderDao.getOne(oid);
  }
}

复制代码

4.6.6、创建Controller

@RestController
@Slf4j
public class OrderController {
    @Autowired
    private OrderService orderService;
  	@RequestMapping("getById")
  	public Order getById(Long oid,Long pid){
        return orderService.getById(oid, pid);
}
复制代码

4.7、服务之间如何进行调用

假设我们在订单的服务里面需要调用到商品服务,先查询出id为1的商品,然后再查询出他的订单,这个1时候就涉及到服务之间的调用问题了。 服务之间的1调用本质上是通过Java代码去发起一个Http请求,我们可以使用RestTemplate来进行调用。

4.7.1、在shop-order-server的启动类中添加注解

我们既然需要RestTemplate类,就需要将RestTemplate类注入到容器中。

@SpringBootApplication
public class OrderServer {
    public static void main(String[] args) {
        SpringApplication.run(OrderServer.class,args);
    }
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}
复制代码

4.7.2、修改Controller代码

@RestController
public class OrderController {

  @Autowired
  RestTemplate restTemplate;

  @Autowired
  OrderService orderService;
  @RequestMapping("getById")
  public Order getById(Long oid,Long pid){
    Product product = restTemplate.getForObject(
        "http://localhost:8083/product?productId="+pid,Product.class); // 这里通过restTemplate去发起http请求,请求地址是http://localhost:8083/product,携带的参数是productId
    Order order = orderService.getById(oid, product.getPid());
    order.setUsername(product.getPname());
    return order;
  }
}

这样我们就完成了服务之间的互相调用。

4.8、存在的问题

虽然我们已经可以实现微服务之间的调用。但是我们把服务提供者的网络地址(ip,端口)等硬编码到了代码中,这种做法存在许多问题:

  • 一旦服务提供者地址变化,就需要手工修改代码。

  • 一旦是多个服务提供者,无法实现负载均衡功能。

  • 一旦服务变得越来越多,人工维护调用关系困难。

    那么应该怎么解决呢?这时候就需要通过注册中心动态的实现服务治理

本文采用 CC BY-NC-SA 4.0 协议发布

相关文章

None

None

None

None

SpringCloud(9)

SpringCloud(9)

SpringCloud(8)