TypechoJoeTheme

香草物语

统计
登录
用户名
密码
/
注册
用户名
邮箱
输入密码
确认密码

Spring Cloud Alibaba笔记修订版-第二章微服务环境搭建

Laughing博主
2022-11-23
/
0 评论
/
640 阅读
/
1537 个字
/
百度已收录
11/23
本文最后更新于2024年03月15日,已超过41天没有更新。如果文章内容或图片资源失效,请留言反馈,我会及时处理,谢谢!

因为第一章都是一些概念性的东西,包括系统架构的演变、微服务架构的介绍(服务调度、服务治理、服务容错、链路追踪等等),大家感兴趣的可以阅读原文,我们这里直接从第二章微服务环境搭建开始。

本次使用的电商项目中的商品、订单、用户为案例进行讲解。

一、技术选型

JDK :1.8

maven :3.8.6

数据库 :MySQL 8.0.31

持久层 :SpringData Jpa

其他 :Spring Cloud Alibaba 2021.0.4.0,截止到目前最新版本

开发工具 :IntelliJ idea 2022.2

# 二、模块设计

springcloud-alibaba:父工程

shop-common:公共模块【实体类】

shop-user:用户微服务【端口:807x】

shop-product:商品微服务【端口:808x】

`shop-order:订单微服务【端口:809x】

2.1、创建父工程

打开idea,创建maven工程,选择【New Project】,输入NameGroupIdArtifactId,选择存储目录,JDK选择本机安装的1.8版本。点击CREATE完成项目创建。

springcloud-alibaba只是作为父工程,我们不会写任何代码,所以直接把src文件夹整体删掉。

然后在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">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.11</version>
        <relativePath/>
    </parent>

    <groupId>net.xiangcaowuyu</groupId>
    <artifactId>springcloud-alibaba</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <properties>
        <java.version>1.8</java.version>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring-cloud-alibaba.version>2021.0.4.0</spring-cloud-alibaba.version>
        <spring-cloud.version>2021.0.4</spring-cloud.version>
    </properties>

    <dependencyManagement>
        <dependencies>

            <!-- Spring Cloud依赖-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!-- Spring Cloud Alibaba依赖-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>

注意一下是Spring Cloud Alibaba与Spring Cloud及Spring Boot的版本对应关系,一定要选择对应的版本。

Spring Cloud Alibaba VersionSpring Cloud VersionSpring Boot Version
2021.0.4.0*Spring Cloud 2021.0.42.6.11
2021.0.1.0Spring Cloud 2021.0.12.6.3
2021.1Spring Cloud 2020.0.12.4.2

2.2、创建shop-common模块

2.2.1、创建模块

在工程上右键,选择NEW→Module

名称输入shop-common创建模块

2.2.2、添加依赖

因为我们使用JPA,因此需要引入JPA的依赖,为了减少代码量,同时使用了lombokfastjson序列化,所以shop-common添加依赖以下依赖

    <dependencies>
        <!-- jpa依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <!-- lombok依赖-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <!-- fastjson依赖-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>2.0.19</version>
        </dependency>

        <!-- MySQL依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.31</version>
        </dependency>

    </dependencies>

2.2.3、创建包

目前shop-common模块中,src文件夹还是空的,为了规范,我们把shop-common的包定义为net.xiangcaowuyu.shop.common

2.2.4、创建实体

我们统一把实体放到entity下,创建三个实体:用户(User)、商品(Product)、订单(Order)

package net.xiangcaowuyu.shop.common.entity;

import lombok.Data;

import javax.persistence.*;

/**
 * 用户
 */
@Data
@Entity
@Table(name = "shop_user")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer ID;

    /**
     * 用户名
     */
    private String name;

    /**
     * 密码
     */
    private String password;

    /**
     * 手机号码
     */
    private String telephone;

}


package net.xiangcaowuyu.shop.common.entity;

import lombok.Data;

import javax.persistence.*;

/**
 * 商品
 */
@Data
@Entity
@Table(name = "shop_product")
public class Product {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer ID;

    /**
     * 商品名
     */
    private String name;

    /**
     * 价格
     */
    private Double price;

    /**
     * 库存
     */
    private Integer stock;

}


package net.xiangcaowuyu.shop.common.entity;

import lombok.Data;

import javax.persistence.*;

/**
 * 订单
 */
@Data
@Entity
@Table(name = "shop_order")
public class Order {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer ID;

    /**
     * 用户ID
     */
    private Integer uid;

    /**
     * 商品ID
     */
    private Integer pid;

}

2.3、创建用户微服务

2.3.1、创建模块

参考2.2.1创建用户模块shop-user

2.3.2、添加依赖

添加以下依赖即可。

 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>net.xiangcaowuyu</groupId>
            <artifactId>shop-common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

2.3.3、创建包

目前shop-user模块中,src文件夹还是空的,为了规范,我们把shop-user的包定义为net.xiangcaowuyu.shop.user

2.3.4、编写主类

shop-user作为一个微服务,必须是可独立运行的,因此必须创建一个主类UserApplication.java

package net.xiangcaowuyu.shop.product;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EntityScan({"net.xiangcaowuyu.shop.common.entity"})
public class UserApplication {

    public static void main(String[] args) {
        SpringApplication.run(UserApplication.class, args);
    }

}

2.3.5、创建配置文件

resources文件夹添加application.yaml配置文件

server:
  port: 8071
spring:
  application:
    name: service-user
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://192.168.236.2/shop?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=true
    username: root
    password: root
  jpa:
    hibernate:
      #指定为update,每次启动项目检测表结构有变化的时候会新增字段,表不存在时会新建,如果指定create,则每次启动项目都会清空数据并删除表,再新建
      ddl-auto: update
      naming:
        #指定jpa的自动表生成策略,驼峰自动映射为下划线格式
        implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
    # 默认false,在日志里显示执行的sql语句
    show-sql: true
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQL5Dialect
    database: mysql
    database-platform: org.hibernate.dialect.MySQL5Dialect

2.3.6、验证

设置完成后,shop-user整个结构如下

启用UserApplication,此时控制台输入一下内容,说明启动成功

2.4、创建商品微服务

2.4.1、创建模块

参考2.2.1创建商品模块shop-product

2.4.2、添加依赖

添加以下依赖即可。

 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>net.xiangcaowuyu</groupId>
            <artifactId>shop-common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

2.4.3、创建包

目前shop-product模块中,src文件夹还是空的,为了规范,我们把shop-product的包定义为net.xiangcaowuyu.shop.product

2.4.4、编写主类

shop-product作为一个微服务,必须是可独立运行的,因此必须创建一个主类ProductApplication.java

package net.xiangcaowuyu.shop.user;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EntityScan({"net.xiangcaowuyu.shop.common.entity"})
public class ProductApplication {

    public static void main(String[] args) {
        SpringApplication.run(ProductApplication.class, args);
    }

}

2.4.5、创建配置文件

resources文件夹添加application.yaml配置文件

server:
  port: 8081
spring:
  application:
    name: service-product
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://192.168.236.2/shop?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=true
    username: root
    password: root
  jpa:
    hibernate:
      #指定为update,每次启动项目检测表结构有变化的时候会新增字段,表不存在时会新建,如果指定create,则每次启动项目都会清空数据并删除表,再新建
      ddl-auto: update
      naming:
        #指定jpa的自动表生成策略,驼峰自动映射为下划线格式
        implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
    # 默认false,在日志里显示执行的sql语句
    show-sql: true
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQL5Dialect
    database: mysql
    database-platform: org.hibernate.dialect.MySQL5Dialect

2.4.6、验证

设置完成后,shop-product整个结构如下

启用ProductApplication,此时控制台输入一下内容,说明启动成功

2.5、创建订单微服务

2.5.1、创建模块

参考2.2.1创建商品模块shop-order

2.5.2、添加依赖

添加以下依赖即可。

 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>net.xiangcaowuyu</groupId>
            <artifactId>shop-common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

2.5.3、创建包

目前shop-order模块中,src文件夹还是空的,为了规范,我们把shop-product的包定义为net.xiangcaowuyu.shop.order

2.5.4、编写主类

shop-order作为一个微服务,必须是可独立运行的,因此必须创建一个主类OrderApplication.java

package net.xiangcaowuyu.shop.order;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EntityScan({"net.xiangcaowuyu.shop.common.entity"})
public class OrderApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }

}

2.5.5、创建配置文件

resources文件夹添加application.yaml配置文件

server:
  port: 8091
spring:
  application:
    name: service-order
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://192.168.236.2/shop?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=true
    username: root
    password: root
  jpa:
    hibernate:
      #指定为update,每次启动项目检测表结构有变化的时候会新增字段,表不存在时会新建,如果指定create,则每次启动项目都会清空数据并删除表,再新建
      ddl-auto: update
      naming:
        #指定jpa的自动表生成策略,驼峰自动映射为下划线格式
        implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
    # 默认false,在日志里显示执行的sql语句
    show-sql: true
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQL5Dialect
    database: mysql
    database-platform: org.hibernate.dialect.MySQL5Dialect

2.5.6、验证

设置完成后,shop-order整个结构如下

启用OrderApplication,此时控制台输入一下内容,说明启动成功

三、原始服务调用

3.1、创建测试数据

为了方便后续演示,我们现在用户及商品表中创建几条测试数据。

INSERT INTO shop_user (id, name, password, telephone) VALUES (1, '张三', '123456', '13333333333');
INSERT INTO shop_user (id, name, password, telephone) VALUES (2, '李四', '123456', '14444444444');

INSERT INTO shop_product (id, name, price, stock) VALUES (1, '小米', 1000, 5000);
INSERT INTO shop_product (id, name, price, stock) VALUES (2, '华为', 2000, 5000);
INSERT INTO shop_product (id, name, price, stock) VALUES (3, '苹果', 3000, 5000);
INSERT INTO shop_product (id, name, price, stock) VALUES (4, '一加', 4000, 5000);

3.2、商品提供查询服务

3.2.1、数据访问层

创建商品数据访问层一个空的接口,JPA默认会提供查询方法

package net.xiangcaowuyu.shop.product.dao;

import net.xiangcaowuyu.shop.common.entity.Product;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

/**
 * 商品数据访问层
 */
@Repository
public interface ProductDao extends JpaRepository<Product, Integer> {

}

3.2.2、服务层

创建ProductService及接口实现类

package net.xiangcaowuyu.shop.product.service;

import net.xiangcaowuyu.shop.common.entity.Product;

public interface ProductService {

    /**
     * 根据ID查询商品
     *
     * @param ID 商品ID
     * @return 商品
     */
    Product findByID(Integer ID);

}
package net.xiangcaowuyu.shop.product.service.impl;

import net.xiangcaowuyu.shop.common.entity.Product;
import net.xiangcaowuyu.shop.product.dao.ProductDao;
import net.xiangcaowuyu.shop.product.service.ProductService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Service
public class ProductServiceImpl implements ProductService {

    @Resource
    private ProductDao productDao;

    /**
     * 根据ID查询商品
     *
     * @param ID 商品ID
     * @return 商品
     */
    @Override
    public Product findByID(Integer ID) {
        return productDao.findById(ID).get();
    }
}

3.2.3、创建Rest接口

package net.xiangcaowuyu.shop.product.controller;

import lombok.extern.slf4j.Slf4j;
import net.xiangcaowuyu.shop.common.entity.Product;
import net.xiangcaowuyu.shop.product.service.ProductService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
@Slf4j
public class ProductController {

    @Resource
    private ProductService productService;

    @GetMapping("/product/{id}")
    public Product product(@PathVariable("id") Integer ID) {
        return productService.findByID(ID);
    }

}

运行程序,现在浏览器测试一下

3.3、订单查询商品

3.3.1、创建配置文件

我们这里通过RestTemplate访问商品,因此增加一个配置文件。

package net.xiangcaowuyu.shop.order.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class OrderConfiguration {

    @Bean
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }

}

3.3.1、创建Rest接口

这里简单模拟一下订单查询商品信息,只简单创建一个订单的controller

package net.xiangcaowuyu.shop.order.controller;

import lombok.extern.slf4j.Slf4j;
import net.xiangcaowuyu.shop.common.entity.Product;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

@RestController
@RequestMapping("order")
@Slf4j
public class OrderController {

    @Resource
    private RestTemplate restTemplate;

    @GetMapping("product/{id}")
    public Product order(@PathVariable("id") Integer productID){
        return restTemplate.getForObject("http://localhost:8081/product/1", Product.class);
    }

}

简单测试一下订单接口

接口也是能够正常访问的。

四、传统服务调用的一些弊端

通过上面的代码,我们虽然实现了接口的调用,但是我们把服务提供者的网络地址(ip、端口)等硬编码到了代码中,这种做法存在很多问题:

  • 一旦服务提供者地址发生变化,就需要手工修改代码(当然可以做成配置或者放到配置文件中)
  • 一旦是多个服务提供者,无法实现负载均衡功能
  • 一旦服务变得越来越多,人工维护调用关系变得非常困难

为了解决上述问题,我们就引出了微服务架构中的服务治理,也就是通过注册中心等方式,实现服务的自动注册与发现。

JavaSpring CloudSpring BootSpring Cloud Alibaba微服务
朗读
赞(1)
赞赏
感谢您的支持,我会继续努力哒!
版权属于:

香草物语

评论 (0)