Spring cloud分布式系统搭建(一)

写在前面:

​ 这是一个分布式demo,方便今后搭建分布式项目的时候直接使用。

项目从传统项目着手,逐步改造成高可用的分布式,eureka、ribbon、hystrix、zuul、config 等,浅显的涉及到微服务的拆分,负载均衡,服务降级,路由网关等。

源码地址GitHub:https://github.com/Mujio-killer/mall.git

一、传统项目介绍

​ 一直想学习一下Spring Cloud,奈何苦于Spring Cloud全家人口众多,不知道该如何入手;再者相关的demo在网上比较难找,特别是从零搭建而且能正常运行的少之又少。本文是参考多篇博文,在实际搭建验证过后写的,主要配置均能够实现对应功能,在此基础上也会去探究其他相关配置,有验证疏漏之处欢迎指出。

主要参考:简书Felix独箸


前期准备:

开发环境:win10 jdk1.8 IDEA 2019.1
一个传统项目,本文使用spring boot下的商城demo,若已有项目可直接跳到第二节。

工程目录结构:在这里插入图片描述
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 https://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.2.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.mujio</groupId>
    <artifactId>mall</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>mall</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <!-- 添加web服务依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- MySQL数据库依赖 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.41</version>
        </dependency>
        <!-- mybatis依赖 -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.1.1</version>
        </dependency>

        <!-- springboot项目需要的依赖,创建项目自动添加 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

MallApplication启动类:
package com.mujio.mall;


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


@SpringBootApplication
@MapperScan("com.mujio.*.mapper")
public class MallApplication {

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

}

controller包:
package com.mujio.mall.controller;


import com.mujio.mall.entity.Order;
import com.mujio.mall.service.OrderService;
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.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

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

    @Autowired
    private OrderService orderService;

    @RequestMapping("/{id}")
    @ResponseBody
    public Order getOrder(@PathVariable("id") int id){
        return orderService.getOrder(id);
    }
}

package com.mujio.mall.controller;


import com.mujio.mall.entity.Goods;
import com.mujio.mall.service.GoodService;
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.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("/goods")
@RestController
public class GoodsController {

    @Autowired
    private GoodService goodService;

    @RequestMapping("/{id}")
    @ResponseBody
    public Goods getGoods(@PathVariable("id") int id){
        return goodService.getGoods(id);
    }

}

service包:
package com.mujio.mall.service;

import com.mujio.mall.entity.Goods;
import com.mujio.mall.entity.Order;
import com.mujio.mall.mapper.ConnMapper;
import com.mujio.mall.mapper.GoodsMapper;
import com.mujio.mall.mapper.OrderMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class OrderService {

    @Autowired
    private ConnMapper connMapper;

    @Autowired
    private GoodsMapper goodsMapper;

    @Autowired
    private OrderMapper orderMapper;

    public Order getOrder(int id){
        Order order = new Order();
        order.setId(id);
        List<Integer> list = connMapper.getConn(id);
        List<Goods> goodsList = new ArrayList<>();
        for (int goodsid: list ) {
            goodsList.add(goodsMapper.getGoods(goodsid));
        }
        order.setGoodsList(goodsList);
        order.setCreatedate(orderMapper.getOrder(id).getCreatedate());

        return order;
    }

}

package com.mujio.mall.service;

import com.mujio.mall.entity.Goods;
import com.mujio.mall.mapper.GoodsMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class GoodService {

    @Autowired
    private GoodsMapper goodsMapper;

    public Goods getGoods(int id){
        return goodsMapper.getGoods(id);
    }
}

mapper包:
package com.mujio.mall.mapper;


import com.mujio.mall.entity.Order;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

@Mapper
public interface OrderMapper {

    @Select("select * from orders where id = #{id}")
    Order getOrder(int id);
}

package com.mujio.mall.mapper;


import com.mujio.mall.entity.Goods;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

@Mapper
public interface GoodsMapper {

    @Select("select * from goods where id = #{id}")
    Goods getGoods(int id);
}
	
package com.mujio.mall.mapper;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.util.List;

@Mapper
public interface ConnMapper {

    @Select("select goodsid from conn where orderid = #{id}")
    List<Integer> getConn(int id);
}

entity包:
package com.mujio.mall.entity;

import java.util.Date;
import java.util.List;

public class Order {
    private int id;

    private List<Goods> goodsList;

    private Date createdate;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public List<Goods> getGoodsList() {
        return goodsList;
    }

    public void setGoodsList(List<Goods> goodsList) {
        this.goodsList = goodsList;
    }

    public Date getCreatedate() {
        return createdate;
    }

    public void setCreatedate(Date createdate) {
        this.createdate = createdate;
    }


    @Override
    public String toString() {
        return "Order{" +
                "id=" + id +
                ", goodsList=" + goodsList +
                ", createdate=" + createdate +
                '}';
    }
}

package com.mujio.mall.entity;

public class Goods {

    private int id;

    private String name;

    private String price;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPrice() {
        return price;
    }

    public void setPrice(String price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Goods{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", price='" + price + '\'' +
                '}';
    }
}

package com.mujio.mall.entity;

import java.util.List;

public class Conn {
    private int id;

    private int orderid;

    private List goodlist;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getOrderid() {
        return orderid;
    }

    public void setOrderid(int orderid) {
        this.orderid = orderid;
    }

    public List getGoodlist() {
        return goodlist;
    }

    public void setGoodlist(List goodlist) {
        this.goodlist = goodlist;
    }
}

application.properties配置:
#服务开放端口配置
server.port=8080

#数据库连接配置
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mall?characterEncoding=utf8&useUnicode=true&zeroDateTimeBehavior=convertToNull
spring.datasource.username=root
spring.datasource.password=123

数据库:
/*
Navicat MySQL Data Transfer

Source Server         : mujio
Source Server Version : 50045
Source Host           : localhost:3306
Source Database       : mall

Target Server Type    : MYSQL
Target Server Version : 50045
File Encoding         : 65001

Date: 2020-03-23 14:35:14
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for conn
-- ----------------------------
DROP TABLE IF EXISTS `conn`;
CREATE TABLE `conn` (
  `id` int(11) NOT NULL auto_increment,
  `orderid` int(11) default NULL,
  `goodsid` int(11) default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of conn
-- ----------------------------
INSERT INTO `conn` VALUES ('1', '1', '1');
INSERT INTO `conn` VALUES ('2', '1', '2');
INSERT INTO `conn` VALUES ('3', '1', '3');
INSERT INTO `conn` VALUES ('4', '2', '4');
INSERT INTO `conn` VALUES ('5', '2', '5');
INSERT INTO `conn` VALUES ('6', '3', '6');
INSERT INTO `conn` VALUES ('7', '3', '7');
INSERT INTO `conn` VALUES ('8', '4', '8');
INSERT INTO `conn` VALUES ('9', '5', '9');
INSERT INTO `conn` VALUES ('10', '6', '10');
INSERT INTO `conn` VALUES ('11', '6', '1');
INSERT INTO `conn` VALUES ('12', '6', '2');
INSERT INTO `conn` VALUES ('13', '7', '3');
INSERT INTO `conn` VALUES ('14', '7', '4');
INSERT INTO `conn` VALUES ('15', '8', '5');
INSERT INTO `conn` VALUES ('16', '8', '6');
INSERT INTO `conn` VALUES ('17', '8', '7');
INSERT INTO `conn` VALUES ('18', '9', '8');
INSERT INTO `conn` VALUES ('19', '9', '9');
INSERT INTO `conn` VALUES ('20', '10', '10');
INSERT INTO `conn` VALUES ('21', '10', '4');

-- ----------------------------
-- Table structure for goods
-- ----------------------------
DROP TABLE IF EXISTS `goods`;
CREATE TABLE `goods` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(255) default NULL,
  `price` double default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of goods
-- ----------------------------
INSERT INTO `goods` VALUES ('1', '电脑', '7299');
INSERT INTO `goods` VALUES ('2', '鼠标', '49');
INSERT INTO `goods` VALUES ('3', '键盘', '239');
INSERT INTO `goods` VALUES ('4', '鼠标垫', '9');
INSERT INTO `goods` VALUES ('5', '转接口', '39');
INSERT INTO `goods` VALUES ('6', '电脑包', '109');
INSERT INTO `goods` VALUES ('7', '手写板', '319');
INSERT INTO `goods` VALUES ('8', '显示器', '699');
INSERT INTO `goods` VALUES ('9', '固态', '659');
INSERT INTO `goods` VALUES ('10', '内存', '229');

-- ----------------------------
-- Table structure for orders
-- ----------------------------
DROP TABLE IF EXISTS `orders`;
CREATE TABLE `orders` (
  `id` int(11) NOT NULL auto_increment,
  `createdate` datetime default NULL COMMENT '创建时间',
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of orders
-- ----------------------------
INSERT INTO `orders` VALUES ('1', '2020-03-23 11:10:03');
INSERT INTO `orders` VALUES ('2', '2020-03-23 11:10:08');
INSERT INTO `orders` VALUES ('3', '2020-03-23 11:10:10');
INSERT INTO `orders` VALUES ('4', '2020-03-23 11:10:13');
INSERT INTO `orders` VALUES ('5', '2020-03-23 11:10:16');
INSERT INTO `orders` VALUES ('6', '2020-03-23 11:10:19');
INSERT INTO `orders` VALUES ('7', '2020-03-23 11:10:21');
INSERT INTO `orders` VALUES ('8', '2020-03-23 11:10:24');
INSERT INTO `orders` VALUES ('9', '2020-03-23 11:10:28');
INSERT INTO `orders` VALUES ('10', '2020-03-23 11:10:30');

进行简单测试:

访问:http://localhost:8080/order/1
在这里插入图片描述
访问:http://localhost:8080/goods/1
在这里插入图片描述

​ 到这里只是一个普通的单体web项目,当业务量达到一定程度的时候,这样的结构很难满足需求,这时候就需要进行业务的拆分。下一节开始,将实现订单服务商品服务的拆分。

猜你喜欢

转载自blog.csdn.net/weixin_43283363/article/details/105117975