一、SpringCloudAlibaba介绍
1、SpringCloudAlibaba致力于提供微服务开发的一站式解决方案,此项目包含分布式应用微服务的必须组件,方便开发者通过SpringCloud编程模型轻松使用这些组件来开发分布式应用服务。开发者只需要添加一些注解和少量配置,就可以将SpringCloud应用接入阿里微服务解决方案,通过阿里中间件迅速搭建分布式应用系统。
2、主要功能
1、==服务限流降级==:默认支持WebServlet、WebFlux、OpenFeign、RestTemplate、
SpringCloudGateway、Zuul、Dubbo、RocketMQ限流降级功能的接入,可以在运行时通过控制台实时
修改限流降级规则,还支持限流降级Metircs监控。
2、服务注册与发现:适配SpringCloud服务注册与发现,默认集成Ribbon的支持
3、分布式配置管理:支持分布式系统中的外部化配置,配置更改时自动刷新
4、消息驱动能力:基于Spring Cloud Stream为微服务应用构建消息驱动能力
5、分布式事务:使用@GlobalTransactional注解,高效且对业务零侵入的解决分布式事务问题。
6、阿里云对象存储:阿里云提供海量、安全、低成本、高可靠的云存储服务,支持任何应用,任何时间,
任何地点存储和访问任意类型的数据
7、分布式任务调度:提供秒级,精准、高可靠、高可用(cron表达式)任务调度服务,同时提供分布式任务模型,
如网格任务,网格任务支持海量子任务均匀分配到所有的Worker上执行
8、阿里云短信服务
3、主要组件
1、Sentinel:吧流量作为切入点,从流量控制,熔断降级,系统负载保护等多个维度保护服务的稳定性。
2、Nacos:构建云原生态的服务发现,配置管理,和服务管理平台。
3、RocketMQ:开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的,
高可靠的消息发布与订阅服务。
4、Dubbo:Apache Dubbo 高性能RPC框架
5、Seata:高性能微服务分布式事务解决方案
6、Alibaba Cloud ACM:分布式架构环境中对应用配置集中管理和推送的应用配置中心产品(收费)
7、Alibaba Cloud OSS:阿里云对象存储服务(收费)
8、Alibaba Cloud SchedulerX:分布式任务调度服务(收费)
9、Alibaba Cloud SMS:短信服务(收费)
本项目以电商项目中的商品、订单、用户为例,简述各个组件的使用方式。
二、 环境搭建
1、技术选型
maven:3.3.9
数据库:Mysql5.7
持久层:SpringData Jpa
其他:SpringCloudAlibaba
2、模块设计
springcloud-alibaba 父工程
shop-common 公共模块
shop-user 用户微服务【端口807x
shop-product 商品微服务【端口808x
shop-order 订单微服务 【端口809x
3、创建父工程 springcloud-alibaba-chenchen
<?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.chenchen</groupId>
<artifactId>springcloud-alibaba-chenchen</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>shop-common</module>
</modules>
<!--指定父依赖-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
</parent>
<!--依赖版本锁定-->
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
<spring-cloud.alibaba.version>2.1.0.RELEASE</spring-cloud.alibaba.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>
</dependencies>
</dependencyManagement>
</project>
4、创建公共模块 shop-common,添加实体User、Order、Product
<?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">
<parent>
<artifactId>springcloud-alibaba-chenchen</artifactId>
<groupId>com.chenchen</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>shop-common</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.56</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
</dependencies>
</project>
公共模块代码层级
实体Order
package com.chenchen.entity;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity(name = "shop_order")
@Data
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer oid;
private Integer uid;
//商品名称
private String username;
private Integer pid;
//商品名称
private String pname;
//商品价格
private Double pprice;
//购买数量
private Integer number;
}
实体User
package com.chenchen.entity;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity(name = "shop_user")
@Data
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)//数据库自增
private Integer uid;
//用户名
private String username;
//密码
private String password;
//手机号
private String telephone;
}
实体Product
package com.chenchen.entity;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity(name = "shop_product")
@Data
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer pid;
//商品名称
private String pname;
//商品价格
private Double pprice;
//库存
private Integer stock;
}
5、依次创建shop-user、shop-order、shop-product三个子工程
5.1 shop-user
<?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">
<parent>
<artifactId>springcloud-alibaba-chenchen</artifactId>
<groupId>com.chenchen</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>shop-user</artifactId>
<packaging>pom</packaging>
<modules>
<module>../shop-order</module>
</modules>
<dependencies>
<!--springboot-web 表明当前是web工程-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--引入公共模块-->
<dependency>
<groupId>com.chenchen</groupId>
<artifactId>shop-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
启动类创建
package com.chenchen;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class UserApplication {
public static void main(String[] args) {
SpringApplication.run(UserApplication.class, args);
System.out.println("用户微服务启动成功");
}
}
配置文件
server:
port: 8071
spring:
application:
name: service-user
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/shop?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
username: root
password: root
jpa:
properties:
hibernate:
hbm2ddl:
auto: update
dialect: org.hibernate.dialect.MySQL5InnoDBDialect
包层次结构
剩下的shop-order、shop-product工程依次类推。
注意点:服务消费者不应该有service,因为它只需要调用服务提供者
需求:模拟用户下单操作。用户查看商品生成订单
6、编写商品微服务查询方法
6.1 controller
package com.chenchen.controller;
import com.chenchen.entity.Product;
import com.chenchen.service.IProductService;
import lombok.extern.slf4j.Slf4j;
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;
@RestController
@Slf4j
public class ProductController {
@Autowired
private IProductService productService;
/**
* 根据商品id查询商品
*
* @param id
* @return
*/
@RequestMapping("/findProductById/{id}")
public Product findProductById(@PathVariable Integer id) {
log.info("开始查询第:{}号商品",id);
return productService.findProductById(id);
}
}
6.2 service
package com.chenchen.service.impl;
import com.alibaba.fastjson.JSON;
import com.chenchen.entity.Product;
import com.chenchen.mapper.ProductMapper;
import com.chenchen.service.IProductService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
@Slf4j
public class ProductServiceImpl implements IProductService {
@Autowired
private ProductMapper productMapper;
/**
* 根据商品id查询商品信息
*
* @param id
* @return
*/
@Override
public Product findProductById(int id) {
Product product = productMapper.findById(id).get();
log.info("查询到:{}号商品信息:{}", id, JSON.toJSONString(product));
return product;
}
}
6.3 浏览器测试:http://localhost:8081/findProductById/1 7、编写订单微服务,模拟下单操作.
7.1 controller
package com.chenchen.controller;
import com.chenchen.entity.Order;
import com.chenchen.service.IOrderService;
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;
@RestController
public class OrderController {
@Autowired
private IOrderService orderService;
@RequestMapping("/createOrder/{pid}")
public Order createOrder(@PathVariable Integer pid) {
Order order = new Order();
order.setNumber(2);
order.setUid(1);
order.setUsername("chenchen");
order.setPid(pid);
order.setPname("huawei");
order.setPprice(8888.8);
return orderService.createOrder(order);
}
}
7.2 service
package com.chenchen.service.impl;
import com.chenchen.entity.Order;
import com.chenchen.mapper.OrderMapper;
import com.chenchen.service.IOrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.concurrent.Executor;
/**
*
*/
@Service
@Slf4j
public class OrderServiceImpl implements IOrderService {
@Autowired
private OrderMapper orderMapper;
@Transactional
@Override
public Order createOrder(Order order) {
Order entity = null;
try {
entity = orderMapper.save(order);
log.info("下单成功,订单信息{}",entity.toString());
} catch (Exception e) {
e.printStackTrace();
}
return entity;
}
}
浏览器测试:http://localhost:8092/createOrder/1 此时已经可以模拟下单了,但是实际情况是 我们需要调用商品微服务查询商品信息,调用方式很简单,使用模板方法RestTemplate,只需要将它放入bean容器中就好了
此时我们在controller层注入restplate,使用它的内置方法getForObject()即可。
package com.chenchen.controller;
import com.chenchen.entity.Order;
import com.chenchen.entity.Product;
import com.chenchen.service.IOrderService;
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;
import org.springframework.web.client.RestTemplate;
@RestController
public class OrderController {
@Autowired
private IOrderService orderService;
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/createOrder/{pid}")
public Order createOrder(@PathVariable Integer pid) {
String url="http://localhost:8081/findProductById/";
Product product = restTemplate.getForObject(url+pid, Product.class);
Order order = new Order();
order.setOid(1);
order.setNumber(2);
order.setUid(1);
order.setUsername("chenchen");
order.setPid(product.getPid());
order.setPname(product.getPname());
order.setPprice(product.getPprice());
return orderService.createOrder(order);
}
}