微服务概念
[引用]
Microservice architectures are the ‘new normal’. Building small, self-contained, ready to run applications can bring great flexibility and added resilience to your code. Spring Boot’s many purpose-built features make it easy to build and run your microservices in production at scale. And don’t forget, no microservice architecture is complete without Spring Cloud ‒ easing administration and boosting your fault-tolerance.
[说明]
微服务是一种架构模式,提倡将单一应用程序划分成一组小的服务,服务之间互相协调、互相配合,为用户提供最终价值。
每个服务运行在其独立的进程中,服务之间采用轻量级的通信机制互相协作。
每个服务都围绕具体业务构建,并且能够独立的部署到生产环境、类生产环境等。
SpringCloud
分布式微服务架构的一站式解决方案 ,是多种微服务架构落地技术的集合体
Spring Cloud can help with service discovery, load-balancing, circuit-breaking, distributed tracing, and monitoring. It can even act as an API gateway.
QuickStart
请记住 :
约定 > 配置 > 编码
微服务基础环境搭建 1.新建maven工程
2.检查字符编码是否正确
3.注解生效激活
4.检查jdk配置
5.配置依赖
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 89 90 91 92 93 <?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 > <groupId > com.cyan</groupId > <artifactId > cloud</artifactId > <version > 1.0-SNAPSHOT</version > <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 > <scope > runtime</scope > </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 > </project >
dependencyManagement
maven使用dependencyManagement来提供一种管理依赖版本号的方式,通常在一个组织或项目的最顶层的父POM看到dependencyManagement元素
使用pom.xml中的dependencyManagement元素能让所有在子项目中引用一个依赖而不用显示列出版本号,maven会沿着父子层次向上走,直到找到一个拥有dependencyManagement元素的项目,然后它就会使用dependencyManagement元素指定的版本号
多个子项目引用同样依赖,可以避免在每个子项目中声明一个版本号,若升级或切换其他版本号,仅需要在顶层父容器更新,不需要一个一个子项目的修改;另外若某子项目需要另外版本,仅需要声明version
dependencyManagement只是声明依赖,并不实现引入 ,因此项目需要显示声明需要的依赖若不在子项目中声明依赖,是不会从父项目中继承下来的;
只有在子项目中写了该依赖,并且没有指定具体版本,才会从父项目中继承该项,并且version和scope都读取父pom
如果子项目中指定了版本号,那么会使用子项目中指定的jar版本
注意
父工程创建完成执行mvn:install
将父工程发布到仓库方便子工程继承
支付模块搭建
微服务模块构建五部曲
新建module
引入POM
配置YML
添加主启动
处理业务类
cloud-provider-payment-8001
1.新建cloud-provider-payment-8001
2.引入pom文件
spring-cloud-starter-zipkin
spring-boot-starter-web
spring-boot-starter-actuator
mybatis-spring-boot-starter
druid-spring-boot-starter
mysql-connector-java
spring-boot-starter-jdbc
lombok
spring-boot-starter-test
spring-cloud-starter-netflix-eureka-client
3.配置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/db2019?useUnicode=true&characterEncoding=utf-8&useSSL=false username: root password: root mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.cyan.springcloud.entities
4.添加主启动
1 2 3 4 5 6 @SpringBootApplication public class PaymentMain8001 { public static void main (String[] args) { SpringApplication.run(PaymentMain8001.class, args); } }
5.创建数据库
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
6.处理业务逻辑
实体类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 @Data @AllArgsConstructor @NoArgsConstructor public class Payment implements Serializable { private Long id; private String serial; } @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 ); } }
数据访问层
1 2 3 4 5 6 7 @Mapper public interface PaymentDao { int create (Payment payment) ; Payment getPaymentById (@Param("id") Long id) ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <?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.cyan.springcloud.dao.PaymentDao" > <insert id ="create" parameterType ="Payment" useGeneratedKeys ="true" keyProperty ="id" > INSERT INTO payment(serial) VALUES(#{serial}); </insert > <resultMap id ="BaseResultMap" type ="com.cyan.springcloud.entities.Payment" > <id column ="id" property ="id" jdbcType ="BIGINT" /> <id column ="serial" property ="serial" jdbcType ="VARCHAR" /> </resultMap > <select id ="getPaymentById" parameterType ="Long" resultMap ="BaseResultMap" > SELECT * FROM payment WHERE id = #{id}; </select > </mapper >
业务逻辑层
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public interface PaymentService { int create (Payment payment) ; Payment getPaymentById (Long id) ; } @Service public class PaymentServiceImpl implements PaymentService { @Resource private PaymentDao paymentDao; @Override public int create (Payment payment) { return paymentDao.create(payment); } @Override public Payment getPaymentById (Long id) { return paymentDao.getPaymentById(id); } }
控制器层
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 @Slf4j @RestController @RequestMapping(value = "/payment") public class PaymentController { @Resource private PaymentService paymentService; @PostMapping(value = "/create") public CommonResult create (Payment payment) { int result = paymentService.create(payment); log.info("插入结果:{}" , result); if (result > 0 ) { return new CommonResult (200 , "Insert Success" , result); } else { return new CommonResult (500 , "Insert Failed" , null ); } } @GetMapping(value = "/get/{id}") public CommonResult getPaymentById (@PathVariable("id") Long id) { Payment payment = paymentService.getPaymentById(id); log.info("查询结果:{}" , payment); if (payment != null ) { return new CommonResult (200 , "Query Success" , payment); } else { return new CommonResult (404 , "Query Failed" + id, null ); } } }
消费者订单模块构建
cloud-consumer-order-80
1.新建cloud-consumer-order-80
2.引入pom文件
lombok
spring-boot-starter-web
spring-boot-starter-actuator
spring-boot-starter-test
3.配置YML
4.添加主启动
1 2 3 4 5 6 @SpringBootApplication public class OrderMain80 { public static void main (String[] args) { SpringApplication.run(OrderMain80.class, args); } }
5.处理业务逻辑
实体类
RestTemplate
RestTemplate提供多种便捷访问远程Http服务 的方法,是一种简单便捷的访问restful服务模板类,是Spring提供的用于访问Rest服务的客户端模板工具集
使用RestTemplate访问restful接口比较简单
url
表示REST请求地址
requestMap
表示请求参数
ResponseBean.class
表示HTTP响应转换成的对象类型
配置类
1 2 3 4 5 6 7 8 @Configuration public class ApplicationContextConfig { @Bean public RestTemplate getRestTemplate () { return new RestTemplate (); } }
接口层
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @Slf4j @RestController @RequestMapping("/consumer") public class OrderController { public static final String PAYMENT_URL = "http://localhost:8001" ; @Resource private RestTemplate restTemplate; @GetMapping("/payment/create") public CommonResult<Payment> create (Payment payment) { return restTemplate.postForObject(PAYMENT_URL + "/payment/create" , payment, CommonResult.class); } @GetMapping("/payment/get/{id}") public CommonResult<Payment> getPayment (@PathVariable("id") Long id) { return restTemplate.getForObject(PAYMENT_URL + "/payment/get/" + id, CommonResult.class); } }
抽取公共模块 发现问题:系统存在重复部分,需要进行重构
1.新建模块:cloud-api-commons
2.添加依赖
3.将公共部分封装进该模块
4.maven命令clean install
5.订单模块80和支付模块8001分别改造
删除各自原先的entities
文件夹
添加依赖
1 2 3 4 5 <dependency > <groupId > com.cyan</groupId > <artifactId > cloud-api-commons</artifactId > <version > ${project.version}</version > </dependency >
附录 项目源码