Spring Cloud Alibaba study notes (1)---E-commerce project based on microservices


Spring Cloud Alibaba study notes

1 Introduction to microservices

1.1 System architecture evolution

With the development of the Internet, the scale of website applications is also constantly expanding, which in turn leads to continuous changes in the system architecture. From the early days of the Internet to the present, the system architecture has generally gone through the following processes: Single application architecture -> Vertical application architecture -> Distributed architecture -> SOA architecture -> Microservice architecture, and of course the quietly emerging Service Mesh (service gridding). Next, let’s take a look at what each system architecture looks like and what their advantages and disadvantages are.

1.1.1 Single application architecture

In the early days of the Internet, the general website application traffic was small, and only one application was needed, and all functional codes were deployed together. This can reduce the cost of development, deployment and maintenance.
For example, an e-commerce system will contain many modules such as user management, product management, order management, logistics management, etc. We will make them into a web project and then deploy them to a tomcat server.
Insert image description here

Advantages: The project structure is simple. For small projects, the development cost is low. The project is deployed on one node and is easy to maintain.

Disadvantages: All functions are integrated in one project, which is difficult to develop and maintain for large projects. The project modules are tightly coupled, the single point fault tolerance rate is low, and targeted optimization and horizontal expansion cannot be carried out for different modules.

1.1.2 Vertical application architecture

As the number of visits gradually increases, a single application can only rely on adding nodes to cope with it. However, at this time, you will find that not all modules will have a relatively large number of visits.

Still taking the e-commerce example above as an example, the increase in user visits may only affect the users and order modules, but the impact on the message module will be relatively small. So at this time we hope to only add a few more order modules without adding messages. Module. At this time, a single application cannot be achieved, and vertical applications emerge as the times require.

The so-called vertical application architecture is to split the original application into several unrelated applications to improve efficiency. For example, we can split the above single e-commerce application into: e-commerce system (user management,
product management, order management), back-end system (user management, order management, customer management), CMS system (advertising management, marketing management)
. After the split is completed, Once the number of user visits increases, you only need to add nodes to the e-commerce system, without adding nodes to the backend and CMS.

Advantages: System splitting realizes traffic sharing, solves concurrency problems, and can optimize and horizontally expand different modules. Problems in one system will not affect other systems, improving fault tolerance.

Disadvantages: The systems are independent of each other, cannot call each other, and there will be repeated development tasks.

1.1.3 Distributed architecture

As there are more and more vertical applications, there will be more and more duplicate business codes. At this time, we thought about whether we could extract the duplicate code and make it into a unified business layer as an independent service, and then the front-end control layer calls different business layer services? This gives rise to new distributed system architectures. It will split the project into two parts: the presentation layer and the service layer. The service layer contains business logic. The presentation layer only needs to handle the interaction with the page, and the business logic is implemented by calling the services of the service layer.
Insert image description here

Advantages: Extract public functions into service layers to improve code reusability

Disadvantages: The coupling between systems becomes higher, the calling relationships are complicated, and it is difficult to maintain

1.1.4 SOA architecture

In a distributed architecture, when there are more and more services, problems such as capacity evaluation and waste of small service resources gradually emerge. At this time, a dispatch center needs to be added to manage the cluster in real time. At this time, the resource scheduling and management center (SOA Service Oriented
Architecture, service-oriented architecture) is the key.
Insert image description here

Advantages: Using the registration center solves the problem of automatic adjustment of calling relationships between services

Disadvantages: There will be dependencies between services. Once a certain link goes wrong, it will have a greater impact (service avalanche). Service care is complicated, and operation, maintenance, testing and deployment are difficult.

1.1.5 Microservice architecture

To some extent, microservice architecture is the next step in the continued development of service-oriented architecture SOA. It places more emphasis on the "complete split" of services.
Insert image description here

Advantages: Services are atomically split, packaged, deployed and upgraded independently, ensuring clear task division for each microservice, which facilitates the expansion of microservices using lightweight http protocols such as Restful to call each other.

Disadvantages: The technical cost of distributed system development is high (fault tolerance, distributed transactions, etc.)

1.2 Introduction to microservice architecture

Microservice architecture, simply put, is to further split a single application into smaller services. Each service is a project that can be run independently.

1.2.1 Frequently Asked Questions about Microservice Architecture

Once you adopt a microservice system architecture, you will inevitably encounter the following problems:

With so many small services, how to manage them? (Service Governance Registration Center [Service Registration Discovery and Elimination]) With so many small services, how do they communicate with each other? (restful rpc) There are so many small services, how do clients access them? (Gateway) With so many small services, once a problem occurs, how should you handle it yourself? (Fault tolerance) With so many small services, once a problem occurs, how should we troubleshoot it? (Link tracking) No microservice designer can bypass the above problems, so most microservice products are aimed at Each problem is provided with corresponding components to solve them.

Insert image description here

1.2.2 Common concepts of microservice architecture

1.2.2.1 Service Governance

Service governance is the automated management of services, the core of which is the automatic registration and discovery of services.

Service registration: The service instance registers its own service information to the registration center.
Service discovery: The service instance obtains the information of the service instances registered in it through the registration center, and uses this information to request the services they provide.
Service elimination: The service registration center automatically excludes problematic services from the available list so that they will not be called.

Insert image description here

1.2.2.2 Service call

In a microservice architecture, there is usually a need for remote calls between multiple services. The current mainstream remote calling technology is based on

HTTP RESTful interface and TCP-based RPC protocol. REST (Representational State Transfer)
is a format for HTTP calls. It is more standard and universal. No matter which language supports the http protocol

RPC (Remote Promote Call)
is an inter-process communication method. Allows remote services to be called as if they were local services. The main goal of the RPC framework is to make remote service calls simpler and more transparent. The RPC framework is responsible for shielding the underlying transmission method, serialization method and communication details. When using it, developers only need to know who provides what kind of remote service interface at what location, and do not need to care about the underlying communication details and calling process.
Differences and connections

Comparative item RESTfulRPC communication protocol HTTP generally uses TCP, slightly lower performance, higher flexibility, application microservice architecture, SOA architecture
Insert image description here

1.2.2.3 Service Gateway

As the number of microservices continues to increase, different microservices generally have different network addresses, and external clients may need to call the interfaces of multiple services to complete a business requirement. If the client is allowed to communicate directly with each microservice, problems may arise. :
The client needs to call different URL addresses, which increases the difficulty. In certain scenarios, there are problems with cross-domain requests. Each microservice requires separate identity authentication. To address these problems, API gateways were born.

API gateway direct access means that all API calls are uniformly connected to the API gateway layer, and the gateway layer is uniformly accessed and output. The basic functions of a gateway include: unified access, security protection, protocol adaptation, traffic control, long and short link support, and fault tolerance. With the gateway, each API service provider team can focus on its own business logic processing, while the API gateway focuses more on security, traffic, routing and other issues.
Insert image description here

1.2.2.4 Service fault tolerance

In microservices, a request often involves calling several services. If one of the services is unavailable and no service fault tolerance is implemented, it is very likely that a series of services will be unavailable. This is the avalanche effect.
We can't prevent the avalanche effect from happening, we can only make mistakes as much as possible. The three core ideas of service fault tolerance are:

Not affected by the external environment,
not overwhelmed by upstream requests
, not overwhelmed by downstream responses

Insert image description here

1.2.2.5 Link tracking

With the popularity of microservice architecture, services are split according to different dimensions, and one request often involves multiple services. Internet applications are built on different sets of software modules. These software modules may be developed by different teams, may be implemented using different programming languages, and may be distributed on thousands of servers across multiple different data center. Therefore, it is necessary to log multiple service links involved in a request. Performance monitoring is link tracking.
Insert image description here

1.2.3 Common solutions for microservice architecture

1.2.3.1 ServiceComb

Insert image description here

Apache ServiceComb, formerly Huawei Cloud's microservice engine CSE (Cloud Service Engine)
cloud service, is the world's first top-level Apache microservices project. It provides a one-stop microservice open source solution and is committed to helping enterprises, users and developers easily migrate enterprise applications to microservices on the cloud, and achieve efficient operation and maintenance management of microservice applications.

1.2.3.2 SpringCloud

Spring Cloud is a collection of frameworks. It uses the development convenience of Spring Boot to cleverly simplify the development of distributed system infrastructure, such as service discovery registration, configuration center, message bus, load balancing, circuit breakers, data monitoring, etc., all of which can be done using the Spring Boot development style
. to one-click startup and deployment.
Spring Cloud does not reinvent the wheel. It just combines the relatively mature and practical service frameworks developed by various companies, and re-encapsulates them through Spring Boot style to shield the complex configuration and implementation principles, and finally provides Developers have set out a distributed system development toolkit that is easy to understand, deploy, and maintain.
1.2.3.3 SpringCloud Alibaba
Insert image description here

Spring Cloud Alibaba is committed to providing a one-stop solution for microservice development. This project contains the necessary components to develop distributed application microservices, making it easy for developers to
use these components to develop distributed application services through the Spring Cloud programming model.

1.3 Introduction to SpringCloud Alibaba

Spring Cloud Alibaba is committed to providing a one-stop solution for microservice development. This project contains the necessary components to develop distributed application microservices, making it easy for developers to
use these components to develop distributed application services through the Spring Cloud programming model. Relying on Spring Cloud
Alibaba, you only need to add some annotations and a small amount of configuration to
connect Spring Cloud applications to Alibaba microservice solutions and quickly build a distributed application system through Alibaba middleware.

1.3.1 Main functions

Service current limit downgrade: Supports WebServlet, WebFlux, OpenFeign, RestTemplate, Spring Cloud Gateway, Zuul, Dubbo and RocketMQ by default

With access to the current limiting and downgrading function, current limiting and downgrading rules can be modified in real time through the console during runtime, and current limiting and downgrading Metrics monitoring can also be viewed. Service registration and discovery: Nacos adapts to Spring Cloud service registration and discovery standards.

Distributed configuration management: supports externalized configuration in distributed systems and automatically refreshes when configuration changes. Message-driven capabilities: Build message-driven capabilities for microservice applications based on Spring Cloud Stream. Distributed transactions: Use the @GlobalTransactional annotation to solve distributed transaction problems efficiently and with zero intrusion into the business.

Alibaba Cloud Object Storage: Alibaba Cloud provides massive, secure, low-cost, and highly reliable cloud storage services. Supports storage and access of any type of data from any application, anytime, anywhere.

Distributed task scheduling: Provides second-level, accurate, highly reliable, and highly available scheduled (based on Cron expression) task scheduling services. It also provides a distributed task execution model, such as grid tasks. Grid tasks support the even distribution of massive quantum tasks to all Workers (schedulerx-client) for execution.

Alibaba Cloud SMS Service: A global SMS service with friendly, efficient, and intelligent interconnected communication capabilities to help companies quickly build customer reach channels.

1.3.2 Components

Sentinel: Use traffic as the entry point to protect the stability of services from multiple dimensions such as flow control, circuit breaker degradation, and system load protection.
Nacos: A dynamic service discovery, configuration management and service management platform that makes it easier to build cloud-native applications.
RocketMQ: an open source distributed messaging system based on high-availability distributed cluster technology that provides low-latency, highly reliable message publishing and subscription services. Dubbo: Apache
Dubbo™ is a high-performance Java RPC framework. Seata: Alibaba open source product, an easy-to-use, high-performance microservice distributed transaction solution.
Alibaba Cloud ACM: An application configuration center product that centrally manages and pushes application configurations in a distributed architecture environment. Alibaba Cloud
OSS: Alibaba Cloud Object Storage Service (OSS) is a
massive, secure, low-cost, and highly reliable cloud storage service provided by Alibaba Cloud. You can store and access any type of data from any app, anytime, anywhere. Alibaba Cloud
SchedulerX: A distributed task scheduling product developed by the Alibaba middleware team, providing second-level, accurate, highly reliable, and highly available scheduled (based on Cron
expressions) task scheduling services. Alibaba Cloud SMS:
SMS service with global coverage, friendly, efficient and intelligent interconnected communication capabilities, helping enterprises to quickly build customer contact channels.


2 Microservice environment construction

Take the products, orders, and users in the e-commerce project as a case.

2.1 Case preparation


2.1.1 Technology selection

maven: 3.6.3
Database: MySQL 8.0.21
Persistence layer: Mybatis
Others: SpringCloud Alibaba technology stack

2.1.2 Module design

spring-cloud-alibaba-shop parent project
shop-common public module [entity class]
shop-user user microservice [port: 8051]
shop-product product microservice [port: 8061] shop-order order microservice [port: 8071] 】
Insert image description here

2.1.3 Microservice call

In the microservice architecture, the most common scenario is the mutual calls between microservices. We take the common user order in the e-commerce system as an example to demonstrate the invocation of microservices: the customer initiates an order request to the order microservice, and needs to call the product microservice to query product information before saving the order.
We generally call the active caller of a service a service consumer, and the callee of a service a service provider.
Insert image description here

In this scenario, the order microservice is a service consumer, and the product microservice is a service provider.

2.1.4 springcloud-alibaba version description

https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E

Spring-Cloud版本:2021.0.1
Spring-Cloud-Alibaba: 2021.0.1.0
Nacos: 1.4.2
Seata: 1.4.2
Sentinel: 1.8.3
SpringBoot:2.6.3

Insert image description here
Insert image description here

2.2 Database table

-- ----------------------------
-- Table structure for shop_order
-- ----------------------------
DROP TABLE IF EXISTS `shop_order`;
CREATE TABLE `shop_order`  (
  `oid` int(0) NOT NULL AUTO_INCREMENT,
  `uid` int(0) NOT NULL,
  `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `pid` int(0) NOT NULL,
  `pname` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `pprice` decimal(10, 2) NOT NULL,
  `number` int(0) NOT NULL,
  PRIMARY KEY (`oid`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Table structure for shop_product
-- ----------------------------
DROP TABLE IF EXISTS `shop_product`;
CREATE TABLE `shop_product`  (
  `pid` int(0) NOT NULL AUTO_INCREMENT,
  `pname` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `pprice` decimal(10, 2) NOT NULL,
  `stock` int(0) NULL DEFAULT NULL,
  PRIMARY KEY (`pid`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Table structure for shop_user
-- ----------------------------
DROP TABLE IF EXISTS `shop_user`;
CREATE TABLE `shop_user`  (
  `uid` int(0) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `telephone` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`uid`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

2.3 Create parent project

Create a maven project and add the following content to the pom.xml file of the parent module

<?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>

    <!--springBoot的父模块-->
    <parent>
        <artifactId>spring-boot-starter-parent</artifactId>
        <groupId>org.springframework.boot</groupId>
        <version>2.6.3</version>
        <relativePath/>
    </parent>

    <!--父模块版本-->
    <groupId>org.gby</groupId>
    <artifactId>exercise</artifactId>
    <version>${project.version}</version>
    <packaging>pom</packaging>

    <!--子模块-->
    <modules>
        <module>shop-common</module>
        <module>shop-user</module>
        <module>shop-product</module>
    </modules>

    <properties>
        <!--项目同一管理版本号-->
        <project.version>1.0.0.0</project.version>
        <!--第三方依赖统一管理版本号-->
        <spring-cloud-alibaba.version>2021.0.1.0</spring-cloud-alibaba.version>
        <spring-cloud.version>2021.0.1</spring-cloud.version>
        <lombok.version>1.18.24</lombok.version>
        <fastjson.version>1.2.83</fastjson.version>
        <mybatis-spring-boot-starter.version>2.2.0</mybatis-spring-boot-starter.version>
        <pagehelper-spring-boot-starter.version>1.4.3</pagehelper-spring-boot-starter.version>
        <commons-lang3.version>3.12.0</commons-lang3.version>
    </properties>

    <!--管理依赖,可以统一管理版本号-->
    <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>
            <!--com.gby是用户自定义-->
            <dependency>
                <groupId>com.gby</groupId>
                <artifactId>shop-common</artifactId>
                <version>${project.version}</version>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>${fastjson.version}</version>
            </dependency>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>${mybatis-spring-boot-starter.version}</version>
            </dependency>
            <dependency>
                <groupId>com.github.pagehelper</groupId>
                <artifactId>pagehelper-spring-boot-starter</artifactId>
                <version>${pagehelper-spring-boot-starter.version}</version>
            </dependency>
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-lang3</artifactId>
                <version>${commons-lang3.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>

2.3 Create basic modules

2.3.1 Create shop-common module

Add dependencies in 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>
        <artifactId>exercise</artifactId>
        <groupId>org.gby</groupId>
        <version>${project.version}</version>
    </parent>

    <artifactId>shop-common</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
        <!--commons-lang3工具类-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
    </dependencies>

</project>
  1. Files in the src directory
    Insert image description here
package com.gby.common;

/**
 * 作者: Sky
 *
 * @Description:
 */
//返回json的通用格式
public class JsonResult<T> {
    
    
    //状态:0表示成功,1表示失败,-1表示未登录或者登录过期
    private int state;
    //消息
    private String msg;
    //数据
    private T data;

    public JsonResult() {
    
    
    }

    public JsonResult(int state, String msg, T data) {
    
    
        this.state = state;
        this.msg = msg;
        this.data = data;
    }

    public int getState() {
    
    
        return state;
    }

    public String getMsg() {
    
    
        return msg;
    }

    public T getData() {
    
    
        return data;
    }
}
package com.gby.entity;

import lombok.Data;

/**
 * 作者: Sky
 *
 * @Description: 用户
 */
@Data
public class User {
    
    
    /**
     * 用户id
     */
    private Integer uid;
    /**
     * 用户名
     */
    private String username;
    /**
     * 密码
     */
    private String password;
    /**
     * 电话号码
     */
    private String telephone;
}
package com.gby.entity;

import lombok.Data;

import java.math.BigDecimal;

/**
 * 作者: Sky
 *
 * @Description:
 */
@Data
public class Product {
    
    
    /**
     * 商品id
     */
    private Integer pid;
    /**
     * 商品名称
     */
    private String pname;
    /**
     * 商品价格
     */
    private BigDecimal pprice;
    /**
     * 库存数量
     */
    private Integer stock;
}
package com.gby.entity;

/**
 * 作者: Sky
 *
 * @Description:
 */

import lombok.Data;

import java.math.BigDecimal;

/**
 * 订单
 */
@Data
public class Order {
    
    
    /**
     * 订单id
     */
    private Integer oid;
    /**
     * 用户id
     */
    private Integer uid;
    /**
     * 用户名称
     */
    private String username;
    /**
     * 商品id
     */
    private Integer pid;
    /**
     * 商品名称
     */
    private String pname;
    /**
     * 商品价格
     */
    private BigDecimal pprice;
    /**
     * 购买数量
     */
    private Integer number;
}

2.4 Create user microservices

step:

1. Create module import dependencies
2. Create SpringBoot
3. Add configuration files
4. Create necessary interfaces and implementation classes (controller service dao)

2.4.1 Create shop-user module

Project structure:
Insert image description here

pom.xml dependency

<?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>
        <artifactId>exercise</artifactId>
        <groupId>org.gby</groupId>
        <version>${project.version}</version>
    </parent>

    <artifactId>shop-user</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.gby</groupId>
            <artifactId>shop-common</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
        </dependency>
    </dependencies>

    <!--添加maven插件,项目的打包工具,打成jar包,否则在打包运行时报错   -->
    <build>
        <plugins>
            <!--springboot插件,把项目打包jar,通过java -jar的命令运行项目,就可启动web项目-->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
package com.gby;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * 作者: Sky
 *
 * @Description:
 */
@SpringBootApplication
@MapperScan(basePackages = "com.gby.dao")
public class UserApplication {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(UserApplication.class, args);
    }
}

application.yml

server:
  port: 8051
spring:
  application:
    name: service-user
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/db2?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
mybatis:
  mapper-locations: classpath:com/gby/dao/*Mapper.xml
  type-aliases-package: com.gby.entity
logging:
  level:
    com:
      gby:
        dao: debug

UserMapper abstract interface

package com.gby.dao;

import com.gby.entity.User;

import java.util.List;

/**
 * 作者: Sky
 */
public interface UserMapper {
    
    
    int deleteByPrimaryKey(Integer uid);

    int insert(User record);

    User selectByPrimaryKey(Integer uid);

    List<User> selectAll();

    int updateByPrimaryKey(User record);
}

UserMapper.xml file

<?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="com.gby.dao.UserMapper">
    <resultMap id="BaseResultMap" type="com.gby.entity.User">
        <id column="uid" jdbcType="INTEGER" property="uid" />
        <result column="username" jdbcType="VARCHAR" property="username" />
        <result column="password" jdbcType="VARCHAR" property="password" />
        <result column="telephone" jdbcType="VARCHAR" property="telephone" />
    </resultMap>
    <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
        delete from shop_user
        where uid = #{uid,jdbcType=INTEGER}
    </delete>
    <insert id="insert" parameterType="com.gby.entity.User" useGeneratedKeys="true" keyProperty="uid">
        insert into shop_user (uid, username, password,
                               telephone)
        values (#{uid,jdbcType=INTEGER}, #{username,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR},
                #{telephone,jdbcType=VARCHAR})
    </insert>
    <update id="updateByPrimaryKey" parameterType="com.gby.entity.User">
        update shop_user
        set username = #{username,jdbcType=VARCHAR},
            password = #{password,jdbcType=VARCHAR},
            telephone = #{telephone,jdbcType=VARCHAR}
        where uid = #{uid,jdbcType=INTEGER}
    </update>
    <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
        select uid, username, password, telephone
        from shop_user
        where uid = #{uid,jdbcType=INTEGER}
    </select>
    <select id="selectAll" resultMap="BaseResultMap">
        select uid, username, password, telephone
        from shop_user
    </select>
</mapper>

2.4.2 Create shop-product module

Project directory:
Insert image description here

Configuration file application.yml

server:
  port: 8061
spring:
  application:
    name: service-product
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/db2?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
mybatis:
  mapper-locations: classpath:com/gby/dao/*Mapper.xml
  type-aliases-package: com.gby.entity
logging:
  level:
    com:
      gby:
        dao: debug

Declare startup class ProductApplication

package com.gby;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * 作者: Sky
 *
 * @Description:
 */
@SpringBootApplication
@MapperScan(basePackages = "com.gby.dao")
public class ProductApplication {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(ProductApplication.class, args);
    }
}

ProductMapper abstract interface

package com.gby.dao;

import com.gby.entity.Product;

import java.util.List;

/**
 * 作者: Sky
 */
public interface ProductMapper {
    
    
    int deleteByPrimaryKey(Integer pid);

    int insert(Product record);

    Product selectByPrimaryKey(Integer pid);

    List<Product> selectAll();

    int updateByPrimaryKey(Product record);
}

ProductMapper.xml file

<?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="com.gby.dao.ProductMapper">
    <resultMap id="BaseResultMap" type="com.gby.entity.Product">
        <id column="pid" jdbcType="INTEGER" property="pid" />
        <result column="pname" jdbcType="VARCHAR" property="pname" />
        <result column="pprice" jdbcType="DECIMAL" property="pprice" />
        <result column="stock" jdbcType="INTEGER" property="stock" />
    </resultMap>
    <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
        delete from shop_product
        where pid = #{pid,jdbcType=INTEGER}
    </delete>
    <insert id="insert" parameterType="com.gby.entity.Product" useGeneratedKeys="true" keyProperty="pid">
        insert into shop_product (pid, pname, pprice,
                                  stock)
        values (#{pid,jdbcType=INTEGER}, #{pname,jdbcType=VARCHAR}, #{pprice,jdbcType=DECIMAL},
                #{stock,jdbcType=INTEGER})
    </insert>
    <update id="updateByPrimaryKey" parameterType="com.gby.entity.Product">
        update shop_product
        set pname = #{pname,jdbcType=VARCHAR},
            pprice = #{pprice,jdbcType=DECIMAL},
            stock = #{stock,jdbcType=INTEGER}
        where pid = #{pid,jdbcType=INTEGER}
    </update>
    <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
        select pid, pname, pprice, stock
        from shop_product
        where pid = #{pid,jdbcType=INTEGER}
    </select>
    <select id="selectAll" resultMap="BaseResultMap">
        select pid, pname, pprice, stock
        from shop_product
    </select>
</mapper>

service layer

ProductService抽象接口
package com.gby.service;

import com.gby.entity.Product;

/**
 * 作者: Sky
 */
public interface ProductService {
    
    
    Product findById(Integer id);
}

ProductServiceImpl.class

package com.gby.service.Impl;

import com.gby.dao.ProductMapper;
import com.gby.entity.Product;
import com.gby.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 作者: Sky
 *
 * @Description:
 */
@Service
public class PruductServiceImpl implements ProductService {
    
    
    @Autowired
    private ProductMapper productMapper;

    @Override
    public Product findById(Integer id) {
    
    
        return productMapper.selectByPrimaryKey(id);
    }
}

Control layerController

ProductController.class
package com.gby.controller;

import com.gby.common.JsonResult;
import com.gby.entity.Product;
import com.gby.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 作者: Sky
 *
 * @Description:
 */
@RestController
public class ProductController {
    
    
    @Autowired
    private ProductService productService;

    @RequestMapping("product/{pid}")
    public JsonResult<Product> product(@PathVariable("pid") Integer pid){
    
    
        Product product = productService.findById(pid);
        return new JsonResult(0,"",product);
    }
}

Insert data into database

INSERT INTO shop_product value(null,'小米','1000','5000');
INSERT INTO shop_product value(null,'华为','2000','4000');
INSERT INTO shop_product value(null,'苹果','3000','3000');
INSERT INTO shop_product value(null,'OPPO','4000','2000');

Click to start the class test
and enter the URL

localhost:8086/product/1 can test access
Insert image description here

2.6 Create order microservice

Project directory structure:
Insert image description here

Startup class:OrderApplication.class

package com.gby;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

/**
 * 作者: Sky
 *
 * @Description:
 */
@SpringBootApplication
@MapperScan(basePackages = "com.gby.dao")
public class OrderApplication {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(OrderApplication.class,args);
    }
}

Edit the application.ymml configuration file

server:
  port: 8071
spring:
  application:
    name: service-order
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/db2?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
mybatis:
  mapper-locations: classpath:com/gby/dao/*Mapper.xml
  type-aliases-package: com.gby.entity
logging:
  level:
    com:
      gby:
        dao: debug

dao层:OrderMapper.interface

package com.gby.dao;

import com.gby.entity.Order;

import java.util.List;

/**
 * 作者: Sky
 */
public interface OrderMapper {
    
    
    int deleteByPrimaryKey(Integer oid);

    int insert(Order record);

    Order selectByPrimaryKey(Integer oid);

    List<Order> selectAll();

    int updateByPrimaryKey(Order record);
}

OrderMapper.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="com.gby.dao.OrderMapper">
    <resultMap id="BaseResultMap" type="com.gby.entity.Order">
        <id column="oid" jdbcType="INTEGER" property="oid" />
        <result column="uid" jdbcType="INTEGER" property="uid" />
        <result column="username" jdbcType="VARCHAR" property="username" />
        <result column="pid" jdbcType="INTEGER" property="pid" />
        <result column="pname" jdbcType="VARCHAR" property="pname" />
        <result column="pprice" jdbcType="DECIMAL" property="pprice" />
        <result column="number" jdbcType="INTEGER" property="number" />
    </resultMap>
    <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
        delete from shop_order
        where oid = #{oid,jdbcType=INTEGER}
    </delete>
    <insert id="insert" parameterType="com.gby.entity.Order" useGeneratedKeys="true" keyProperty="oid">
        insert into shop_order (oid, uid, username,
                                pid, pname,pprice, number
        )
        values (#{oid,jdbcType=INTEGER}, #{uid,jdbcType=INTEGER}, #{username,jdbcType=VARCHAR},
                #{pid,jdbcType=INTEGER},#{pname,jdbcType=VARCHAR}, #{pprice,jdbcType=DECIMAL}, #{number,jdbcType=INTEGER}
               )
    </insert>
    <update id="updateByPrimaryKey" parameterType="com.gby.entity.Order">
        update shop_order
        set uid = #{uid,jdbcType=INTEGER},
            username = #{username,jdbcType=VARCHAR},
            pid = #{pid,jdbcType=INTEGER},
            pname = #{pname,jdbcType=VARCHAR},
            pprice = #{pprice,jdbcType=DECIMAL},
            number = #{number,jdbcType=INTEGER}
        where oid = #{oid,jdbcType=INTEGER}
    </update>
    <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
        select oid, uid, username, pid, pname, pprice,number
        from shop_order
        where oid = #{oid,jdbcType=INTEGER}
    </select>
    <select id="selectAll" resultMap="BaseResultMap">
        select oid, uid, username, pid,pname, pprice, number
        from shop_order
    </select>
</mapper>

service层:OrderService.interface

package com.gby.service;

import com.gby.entity.Order;

/**
 * 作者: Sky
 */
public interface OrderService {
    
    
    void save(Order order);
}

OrderServiceImpl.class

package com.gby.service.Impl;

import com.gby.dao.OrderMapper;
import com.gby.entity.Order;
import com.gby.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 作者: Sky
 *
 * @Description:
 */
@Service
public class OrderServiceImpl implements OrderService {
    
    
    @Autowired
    private OrderMapper orderMapper;

    @Override
    public void save(Order order) {
    
    
        orderMapper.insert(order);
    }
}

An error will appear here, the bean directory cannot be found (you need to edit a @Bean class in the startup class)

@SpringBootApplication
@MapperScan(basePackages = "com.gby.dao")
public class OrderApplication {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(OrderApplication.class,args);
    }

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

controller层:
OrderController.class

package com.gby.controller;

import com.gby.common.JsonResult;
import com.gby.entity.Order;
import com.gby.entity.Product;
import com.gby.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
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;

/**
 * 作者: Sky
 *
 * @Description:
 */
@RestController
public class OrderController {
    
    
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private OrderService orderService;

    @RequestMapping("order/save/{pid}")
    public JsonResult saveOrderByPid(@PathVariable("pid") Integer pid) {
    
    
        //客户下订单,这个时候要调用商品微服务查询商品信息
        String url = "http://localhost:8061/product/" + pid;
        //返回值类型(因为JsonResult的Data是泛型类型属性)
        ParameterizedTypeReference<JsonResult<Product>> typeReference =
                new ParameterizedTypeReference<JsonResult<Product>>() {
    
    
                };
        //发出请求get请求,请求参数为空
        ResponseEntity<JsonResult<Product>> exchange =
                restTemplate.exchange(url, HttpMethod.GET, null, typeReference);
        //返回值的body属性是请求api的返回数据
        Product product = exchange.getBody().getData();

        //创建Order对象
        Order order = new Order();
        order.setUid(1);
        order.setUsername("测试用户");
        order.setPid(product.getPid());
        order.setPname(product.getPname());
        order.setPprice(product.getPprice());
        order.setNumber(1);
        //保存order对象
        orderService.save(order);

        return new JsonResult(0, "", order);
    }
}
test

Start the OrderApplication class and ProductApplication class before accessing them
Insert image description here

Guess you like

Origin blog.csdn.net/weixin_48434899/article/details/127024377