微服务架构概述 
微服务架构是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调,互相配合,为用户提供最终价值。每个服务运行在其独立的进程中,服务与服务间采用轻量级的通信机制互相协作(通常是基于HTTP协议的RESTful API)。每个服务都围绕着具本业务进行构建,并且能够独立的部署到生产环境,类生产环境等。另外,应当尽量避免统一的,集中式的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言,工具对其进行构建。
微服务架构是一堆小服务的集合
每一个服务都可以作为一个单独的进程来运行
微服务的建模是围绕业务逻辑进行的
服务是独立部署的
微服务是去中心化的,也就是说是分布式的
 
SpringCloud 
SpringCloud是分布式微服务架构的一站式解决方案,是多种微服务架构落地技术的集合体,俗称微服务全家桶。SpringCloud已成为微服务开发的主流技术栈。 
SpringCloud版本目前最新为H版
SpringCloud和SpringBoot的版本选择
此次项目的技术版本
SpringCloud各种组件的停更升级替换 
项目环境搭建 父工程项目搭建 搭建一个Maven项目,作为Maven的父工程项目。删除src目录
添加项目依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 <packaging > pom</packaging > <properties >     <project.build.sourceEncoding > UTF-8</project.build.sourceEncoding >      <maven.compiler.source > 1.8</maven.compiler.source >      <maven.compiler.target > 1.8</maven.compiler.target >      <junit.version > 4.12</junit.version >      <log4j.version > 1.2.17</log4j.version >      <lombok.version > 1.16.18</lombok.version >      <mysql.version > 5.1.47</mysql.version >      <druid.version > 1.1.16</druid.version >      <mybatis.spring.boot.version > 1.3.0</mybatis.spring.boot.version >  </properties > <dependencyManagement >     <dependencies >                   <dependency >              <groupId > org.springframework.boot</groupId >              <artifactId > spring-boot-dependencies</artifactId >              <version > 2.2.2.RELEASE</version >              <type > pom</type >              <scope > import</scope >          </dependency >                   <dependency >              <groupId > org.springframework.cloud</groupId >              <artifactId > spring-cloud-dependencies</artifactId >              <version > Hoxton.SR1</version >              <type > pom</type >              <scope > import</scope >          </dependency >                   <dependency >              <groupId > com.alibaba.cloud</groupId >              <artifactId > spring-cloud-alibaba-dependencies</artifactId >              <version > 2.1.0.RELEASE</version >              <type > pom</type >              <scope > import</scope >          </dependency >          <dependency >              <groupId > mysql</groupId >              <artifactId > mysql-connector-java</artifactId >              <version > ${mysql.version}</version >          </dependency >          <dependency >              <groupId > com.alibaba</groupId >              <artifactId > druid</artifactId >              <version > ${druid.version}</version >          </dependency >          <dependency >              <groupId > org.mybatis.spring.boot</groupId >              <artifactId > mybatis-spring-boot-starter</artifactId >              <version > ${mybatis.spring.boot.version}</version >          </dependency >          <dependency >              <groupId > junit</groupId >              <artifactId > junit</artifactId >              <version > ${junit.version}</version >          </dependency >          <dependency >              <groupId > log4j</groupId >              <artifactId > log4j</artifactId >              <version > ${log4j.version}</version >          </dependency >          <dependency >              <groupId > org.projectlombok</groupId >              <artifactId > lombok</artifactId >              <version > ${lombok.version}</version >              <optional > true</optional >          </dependency >      </dependencies >  </dependencyManagement > <build >     <plugins >          <plugin >              <groupId > org.springframework.boot</groupId >              <artifactId > spring-boot-maven-plugin</artifactId >              <configuration >                  <fork > true</fork >                  <addResources > true</addResources >              </configuration >          </plugin >      </plugins >  </build > 
支付模块构建 在父工程中新建支付Modulecloud-provider-payment8001,同样是Maven项目
pom 添加依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 <dependencies >     <dependency >          <groupId > org.springframework.boot</groupId >          <artifactId > spring-boot-starter-web</artifactId >      </dependency >           <dependency >          <groupId > org.springframework.boot</groupId >          <artifactId > spring-boot-starter-actuator</artifactId >      </dependency >      <dependency >          <groupId > org.mybatis.spring.boot</groupId >          <artifactId > mybatis-spring-boot-starter</artifactId >      </dependency >      <dependency >          <groupId > com.alibaba</groupId >          <artifactId > druid</artifactId >               </dependency >           <dependency >          <groupId > mysql</groupId >          <artifactId > mysql-connector-java</artifactId >      </dependency >           <dependency >          <groupId > org.springframework.boot</groupId >          <artifactId > spring-boot-starter-jdbc</artifactId >      </dependency >      <dependency >          <groupId > org.projectlombok</groupId >          <artifactId > lombok</artifactId >          <optional > true</optional >      </dependency >      <dependency >          <groupId > org.springframework.boot</groupId >          <artifactId > spring-boot-starter-test</artifactId >          <scope > test</scope >      </dependency >  </dependencies > 
配置文件 新建编写配置文件application.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 server:   port:  8001  spring:   application:      name:  cloud-payment-service     datasource:      type:  com.alibaba.druid.pool.DruidDataSource        driver-class-name:  org.gjt.mm.mysql.Driver          url:  jdbc:mysql://localhost:3306/springcloud?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=false      username:  root      password:  kylin  mybatis:   mapper-locations:  classpath:mapper/*.xml     type-aliases-package:  com.kylin.entities   
主启动类 创建com.kylin包在包下创建SpringBoot启动类PaymentMain8001
1 2 3 4 5 6 @SpringBootApplication public  class  PaymentMain8001      public  static  void  main (String[] args)           SpringApplication.run(PaymentMain8001.class, args);     } } 
数据库 1 2 3 4 5 CREATE  TABLE  payment ( id BIGINT (20 ) NOT  NULL  AUTO_INCREMENT COMMENT ID,  'serial'  VARCHAR (200 ) DEFAULT ,  PRIMARY  KEY(id) ) ENGINE= INNODB AUTO_INCREMENT= 1  DEFAULT  CHARSET= utf8 
自己插入数据
entities Payment
1 2 3 4 5 6 7 @Data @AllArgsConstructor @NoArgsConstructor public  class  Payment  implements  Serializable      private  Long id;     private  String serial; } 
CommonResult
1 2 3 4 5 6 7 8 9 10 11 12 13 @Data @AllArgsConstructor @NoArgsConstructor public  class  CommonResult <T >     private  Integer code;     private  String message;     private  T data;     public  CommonResult (Integer code,String message)          this (code,message,null );     } } 
Dao PaymentDao
1 2 3 4 5 6 7 8 @Mapper public  interface  PaymentDao      int  create (Payment payment)      Payment getPaymentId (@Param("id")  Long id)  ; } 
PaymentMapper 分别按id查询和插入数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <?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.kylin.dao.PaymentDao" >     <insert  id ="create"  parameterType ="payment"  useGeneratedKeys ="true"  keyColumn ="id" >          insert into payment(serial) values (#{serial})     </insert >      <resultMap  id ="BaseResultMap"  type ="payment" >          <id  column ="id"  property ="id"  jdbcType ="BIGINT" />          <id  column ="serial"  property ="serial"  jdbcType ="VARCHAR" />      </resultMap >      <select  id ="getPaymentId"  resultMap ="BaseResultMap"  parameterType ="Long" >          select * from payment where id = #{id}     </select >  </mapper > 
Service PaymentService
1 2 3 4 5 6 public  interface  PaymentService      int  create (Payment payment)      Payment getPaymentId (Long id)  ; } 
PaymentService实现类PaymentServiceImpl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Service public  class  PaymentServiceImpl  implements  PaymentService      @Resource      PaymentDao paymentDao;     @Override      public  int  create (Payment payment)           return  paymentDao.create(payment);     }     @Override      public  Payment getPaymentId (Long id)           return  paymentDao.getPaymentId(id);     } } 
Controller PaymentController
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 @RestController @Slf4j public  class  PaymentController      @Resource      private  PaymentService paymentService;     @PostMapping(value = "/payment/create")      public  CommonResult create (Payment payment)          int  result = paymentService.create(payment);         log.info("*****插入结果:" +result);         if  (result>0 ){               return  new  CommonResult(200 ,"插入数据库成功" ,result);         }else  {             return  new  CommonResult(444 ,"插入数据库失败" ,null );         }     }     @GetMapping(value = "/payment/get/{id}")      public  CommonResult getPaymentById (@PathVariable("id")  Long id)          Payment payment = paymentService.getPaymentById(id);         log.info("*****查询结果:" +payment);         if  (payment!=null ){               return  new  CommonResult(200 ,"查询成功" ,payment);         }else  {             return  new  CommonResult(444 ,"没有对应记录,查询ID:" +id,null );         }     } } 
测试 在主启动类中启动项目进行测试查询操作http://localhost:8001/payment/get/31
由于插入操作是发送的post请求,浏览器默认不支持地址栏发送post请求所以使用Postman发送post请求
发生post请求成功
查看数据库
全部测试成功,代码无误~
消费者订单模块构建 创建cloud-consumer-order80模块
pom 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 <dependencies >          <dependency >          <groupId > org.springframework.boot</groupId >          <artifactId > spring-boot-starter-web</artifactId >      </dependency >           <dependency >          <groupId > org.springframework.boot</groupId >          <artifactId > spring-boot-starter-actuator</artifactId >      </dependency >           <dependency >          <groupId > org.springframework.boot</groupId >          <artifactId > spring-boot-devtools</artifactId >          <scope > runtime</scope >          <optional > true</optional >      </dependency >           <dependency >          <groupId > org.projectlombok</groupId >          <artifactId > lombok</artifactId >          <optional > true</optional >      </dependency >           <dependency >          <groupId > org.springframework.boot</groupId >          <artifactId > spring-boot-starter-test</artifactId >          <scope > test</scope >      </dependency >  </dependencies > 
配置文件
主启动类
创建com.kylin包在包下创建主启动类OrderMain80
1 2 3 4 5 6 7 @SpringBootApplication public  class  OrderMain80      public  static  void  main (String[] args)           SpringApplication.run(OrderMain80.class,args);     } } 
entities 将支付模块cloud-provider-payment8001中的entities包拷贝
Controller 编写OrderController,由于要使用消费者模块调用支付模块。我们这里使用Resttemplate发送请求调用。
传统情况下在java代码里访问restful服务,一般使用Apache的HttpClient。不过此种方法使用起来太过繁琐。spring提供了一种简单便捷的模板类来进行操作,这就是RestTemplate。RestTemplate提供了多种便捷访问远程Http服务的方法,是一种简单便捷的访问restful服务模板类,是Spring提供的用于访问Rest服务的客户端模板工具集 
使用前将其注入到Spring容器中,使用RestTemplate访问restful接口非常的简单,(url,requestMap,ResponseBean.class)这三个参数分别代表REST请求地址,请求参数,HTTP响应转换被转换的对象类型。
创建config包,编写ApplicationContextConfig在下面注入RestTemplate
1 2 3 4 5 6 7 8 @Configuration public  class  ApplicationContextConfig      @Bean      public  RestTemplate getRestTemplate ()           return  new  RestTemplate();     } } 
此时在继续编写OrderController
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @RestController @Slf4j public  class  OrderController      public  static  final  String PAYMENT_URL = "http://localhost:8001" ;     @Resource      RestTemplate restTemplate;     @GetMapping("/consumer/payment/create")      public  CommonResult<Payment> create (Payment payment)           return  restTemplate.postForObject(PAYMENT_URL + "/payment/create" , payment, CommonResult.class);     }     @GetMapping("/consumer/payment/get/{id}")      public  CommonResult<Payment> getPayment (@PathVariable("id")  Long id)           return  restTemplate.getForObject(PAYMENT_URL + "/payment/get/"  + id, CommonResult.class);     } } 
测试 再启动OrderMain80和PaymentMain80此时idea会弹出一个提示是否启用Services选择启用,方便管理多个服务之间的启动关闭。启动成功后发送请求查看效果
发现插入数据为空!
由于RestTemplate.postForObject发送的是Json格式的字符,所以需要@RequestBody注解接收。
重启项目查看效果,成功!
工程重构 通过构建项目的基础环境,我们发现我们的项目中存在重复的部分。也就是我们的的entities
我们将他抽取成一个模块cloud-api-commons,新建一个模块
pom 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <dependencies >          <dependency >          <groupId > org.springframework.boot</groupId >          <artifactId > spring-boot-devtools</artifactId >          <scope > runtime</scope >          <optional > true</optional >      </dependency >      <dependency >          <groupId > org.projectlombok</groupId >          <artifactId > lombok</artifactId >          <optional > true</optional >      </dependency >           <dependency >          <groupId > cn.hutool</groupId >          <artifactId > hutool-all</artifactId >          <version > 5.1.0</version >      </dependency >  </dependencies > 
将entities下的类复制过来
接着将这个模块clean,install
接着分别将我们之前的两个项目中的entities包删除
分别修改项目的pom.xml引入cloud-api-commons,坐标修改为自己的,记得导入依赖。
1 2 3 4 5 <dependency >     <groupId > com.kylin</groupId >      <artifactId > cloud-api-commons</artifactId >      <version > 1.0-SNAPSHOT</version >  </dependency > 
测试一下功能是否正常,一切正常!
SpringCloud学习的基础环境搭建完成!