精品专题:
01.《C语言从不挂科到高绩点》课程详细笔记
https://blog.csdn.net/yueyehuguang/category_12753294.html?spm=1001.2014.3001.5482
02. 《SpringBoot详细教程》课程详细笔记
https://blog.csdn.net/yueyehuguang/category_12789841.html?spm=1001.2014.3001.5482
03.《SpringBoot电脑商城项目》课程详细笔记
https://blog.csdn.net/yueyehuguang/category_12752883.html?spm=1001.2014.3001.5482
04.《VUE3.0 核心教程》课程详细笔记
https://blog.csdn.net/yueyehuguang/category_12769996.html?spm=1001.2014.3001.5482
05. 《SSM详细教程》课程详细笔记
https://blog.csdn.net/yueyehuguang/category_12806942.html?spm=1001.2014.3001.5482
================================
|| 持续分享系列教程,关注一下不迷路 ||
|| 视频教程:墨轩大楼 ||
================================
在上一章节中我们已经大体了解了微服务以及微服务的实现技术,本教程主要讲解SpringCloud Alibaba的技术栈。
🌲 2.1 案例准备
🌿 2.1.1 技术选型
maven:3.6.3
数据库:mysql 8.0
持久层框架:mybatis 2.3.1、mybatisPlus
SpringBoot版本:2.7.17
cloud:SpringCloud Alibaba 技术栈 3.4.1
🌿 2.1.2 模块设计
父工程:spring-cloud
公共模块:shop-common 【工具类、实体类】
用户微服务:shop-user 【端口:801x】
商品微服务:shop-product 【端口:802x】
订单微服务:shop-order 【端口:803x】
🌿 2.1.3 微服务调用
在微服务架构中,最常见的场景就是微服务之间的相互调用。我们以电商系统中常见的用户下单 为例来演示微服务的调用:客户向订单微服务 发起一个下单的请求,在进行保存订单之前需要调用商品微服务查询商品的信息。
我们一般把服务的主动调用方 称为服务消费者 ,把服务的被调用方 称为服务提供者。
在这种场景下,订单微服务就是一个服务消费者, 商品微服务就是一个服务提供者。
🌲 2.2 创建父工程
创建一个SpringBoot2.7.17版本项目,添加相关依赖
<?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.7.17</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<packaging>pom</packaging>
<groupId>com.moxuan</groupId>
<artifactId>spring_cloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring_cloud</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
<spring-cloud.version>2021.0.3</spring-cloud.version>
<spring-cloud-alibaba.version>2021.0.4.0</spring-cloud-alibaba.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<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>
<type>pom</type>
<version>${spring-cloud-alibaba.version}</version>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</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>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter-test</artifactId>
<version>2.3.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.16</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.56</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
🌲 2.3 创建公共模块
创建公共模块shop-common,在pom.xml中将父模块设置为前面创建的spring-cloud模块。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>com.moxuan</groupId>
<artifactId>spring_cloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.moxuan</groupId>
<artifactId>shop-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>shop-common</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
创建实体类,将项目中所需要的实体类都创建到这个模块里面
package com.moxuan.shopcommon.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@Data
@TableName("t_user")
public class User {
private Integer uid;
private String email;
private String password;
private String nickname;
}
package com.moxuan.shopcommon.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@TableName("t_product")
public class Product {
@TableId(type= IdType.AUTO)
private Integer pid;
private String pname;// 商品名称
private Double pprice; // 商品价格
private Integer stock; // 库存
public Product(String pname, Double pprice, Integer stock) {
this.pname = pname;
this.pprice = pprice;
this.stock = stock;
}
}
package com.moxuan.shopcommon.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@Data
@TableName("t_order")
public class Order {
// 订单id
@TableId(type = IdType.AUTO)
private Long oid;
private Integer uid; // 用户id
private String username;// 用户名
private Integer pid;// 商品id
private String pname; // 商品名称
private Double pprice; // 商品价格
private Integer num;// 购买数量
}
创建向前端统一返回数据的工具类
package com.moxuan.shopcommon.util;
import java.util.HashMap;
import java.util.Map;
/**
*
* 返回码
*/
public enum ReturnCode {
/*********************************************全局ReturnCode(请勿改动)*********************************************/
SUCCESS("0000", "成功完成操作"),
BUSSINESS_EXCEPTION("10000", "业务系统异常"),
NO_RESULT("10001", "查询无结果"),
MULTI_RESULT("10002", "查询结果不唯一"),
EXPORT_EXCEL_ERROR("10004", "导出Excel异常"),
USER_NOT_LOGIN("90000", "用户未登录"),
ACCESS_FORBIDDEN("90001","无访问权限"),
AUTHENTICATION_FAILURE("90002","认证失败"),
TOKEN_FORBIDDEN("90003","无访问口令,请先登陆后获取"),
TOKEN_EXPIRE("90004","Token失效,需要重新登陆"),
TOKEN_ERROR("90005","Token创建出错,请联系管理员"),
USER_LOGIN_ERROR("90006","账号或者密码错误"),
SYSTEM_ERROR("99999", "系统繁忙,请稍后再试.");
/**
* 返回码
*/
private String code;
/**
* 返回信息
*/
private String msg;
ReturnCode(String code, String msg) {
this.code = code;
this.msg = msg;
}
public String code() {
return this.code;
}
public String msg() {
return this.msg;
}
public Map<String, String> toMap() {
Map<String, String> map = new HashMap<>();
map.put("msg", this.msg);
map.put("code", this.code);
return map;
}
}
package com.moxuan.shopcommon.util;
import com.alibaba.fastjson.JSON;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 封装结果的工具类
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result {
private String Code;
private Object data;// 数据源
private String msg;
public static Result sendResult(ReturnCode returnCode) {
Result result = new Result();
result.setCode(returnCode.code());
result.setMsg(returnCode.msg());
return result;
}
public static Result sendResult(ReturnCode returnCode,Object data){
Result result = sendResult(returnCode);
String jsonData = JSON.toJSONString(data);
result.setData(jsonData);
return result;
}
}
🌲 2.4 创建用户微服务
新建一个 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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.moxuan</groupId>
<artifactId>spring_cloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/>
</parent>
<groupId>com.moxuan</groupId>
<artifactId>shop-user</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>shop-user</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
</project><dependency> <groupId>com.moxuan</groupId> <artifactId>shop-common</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
-
添加配置文件
server.port=8011
spring.application.name=service-user
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/cloud
spring.datasource.username=root
spring.datasource.password=123456
🌲 2.5 创建商品微服务
创建一个名为 shop_product 的模块,并添加springboot依赖、父模块、公共模块
<?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>com.moxuan</groupId>
<artifactId>spring_cloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.moxuan</groupId>
<artifactId>shop-product</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>shop-product</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.moxuan</groupId>
<artifactId>shop-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
添加配置文件
server.port=8021
spring.application.name=service-product
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/cloud
spring.datasource.username=root
spring.datasource.password=123456
创建ProductMapper
package com.moxuan.shopproduct.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.moxuan.shopcommon.entity.Product;
public interface ProductMapper extends BaseMapper<Product> {
}
在启动类中开启MP接口扫描
package com.moxuan.shopproduct;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.moxuan.shopproduct.dao")
public class ShopProductApplication {
public static void main(String[] args) {
SpringApplication.run(ShopProductApplication.class, args);
}
}
创建ProductService以及实现类
package com.moxuan.shopproduct.service;
import com.moxuan.shopcommon.util.Result;
public interface ProductService {
Result getProductById(int pid);
Result saveProductBeach();
}
package com.moxuan.shopproduct.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.moxuan.shopcommon.entity.Product;
import com.moxuan.shopcommon.util.Result;
import com.moxuan.shopcommon.util.ReturnCode;
import com.moxuan.shopproduct.dao.ProductMapper;
import com.moxuan.shopproduct.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service
public class ProductServiceImpl extends ServiceImpl<ProductMapper,Product> implements ProductService {
@Autowired
private ProductMapper productMapper;
public Result getProductById(int pid) {
QueryWrapper<Product> qw = new QueryWrapper<>();
qw.lambda().eq(Product::getPid,pid);
Product product = productMapper.selectOne(qw);
if(product==null){
return Result.sendResult(ReturnCode.NO_RESULT);
}
return Result.sendResult(ReturnCode.SUCCESS,product);
}
/**
* 批量插入数据
* @return
*/
public Result saveProductBeach() {
List<Product> productList = new ArrayList<>();
productList.add(new Product("小米",1000.0,5000));
productList.add(new Product("华为",2000.0,5000));
productList.add(new Product("苹果",3000.0,5000));
productList.add(new Product("OPPO",2000.0,5000));
boolean flag = saveBatch(productList);
if(!flag){
return Result.sendResult(ReturnCode.BUSSINESS_EXCEPTION);
}
return Result.sendResult(ReturnCode.SUCCESS);
}
}
创建控制器类Controller
package com.moxuan.shopproduct.controller;
import com.moxuan.shopcommon.entity.Product;
import com.moxuan.shopcommon.util.Result;
import com.moxuan.shopproduct.service.ProductService;
import com.moxuan.shopproduct.service.impl.ProductServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
@RestController
@Slf4j
public class ProductController {
@Autowired
private ProductService productService;
@GetMapping("/product/{pid}")
public Result product(@PathVariable("pid") int pid){
Result result = productService.getProductById(pid);
log.info("查询到商品:"+result);
return result;
}
@PostMapping("/product/sa")
public Result saveProductBeach(){
Result result = productService.saveProductBeach();
return result;
}
}
启动项目,先访问http://localhost:8021/product/sa 批量添加数据
然后再访问: http://localhost:8021/product/1 看能否查询到数据
🌲 2.6 创建订单微服务
创建一个名为 shop-order 的模块,并添加springboot依赖、父模块、公共模块
<?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>com.moxuan</groupId>
<artifactId>spring_cloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.moxuan</groupId>
<artifactId>shop-order</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>shop-order</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.moxuan</groupId>
<artifactId>shop-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
添加配置文件
server.port=8031
spring.application.name=service-product
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/cloud
spring.datasource.username=root
spring.datasource.password=123456
创建OrderMapper接口
package com.moxuan.shoporder.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.moxuan.shopcommon.entity.Order;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface OrderMapper extends BaseMapper<Order> {
}
在启动类中开启mp注解扫描,并添加RestTemplateBean,方便后续微服务之间的数据通信
package com.moxuan.shoporder;
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;
@SpringBootApplication
@MapperScan("com.moxuan.shoporder.dao")
public class ShopOrderApplication {
public static void main(String[] args) {
SpringApplication.run(ShopOrderApplication.class, args);
}
/**
* org.springframework.web.client.RestTemplate;
* 可以用来调用其他微服务
* @return
*/
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
创建OrderService以及实现类
package com.moxuan.shoporder.service;
import com.moxuan.shopcommon.entity.Order;
import com.moxuan.shopcommon.util.Result;
public interface OrderService {
Result saveOrder(Order order);
}
package com.moxuan.shoporder.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.moxuan.shopcommon.entity.Order;
import com.moxuan.shopcommon.util.Result;
import com.moxuan.shopcommon.util.ReturnCode;
import com.moxuan.shoporder.dao.OrderMapper;
import com.moxuan.shoporder.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {
@Autowired
private OrderMapper orderMapper;
@Override
public Result saveOrder(Order order) {
int num = orderMapper.insert(order);
if(num==0){
return Result.sendResult(ReturnCode.BUSSINESS_EXCEPTION);
}
return Result.sendResult(ReturnCode.SUCCESS);
}
}
创建OrderController
package com.moxuan.shoporder.controller;
import com.alibaba.fastjson.JSON;
import com.moxuan.shopcommon.entity.Order;
import com.moxuan.shopcommon.entity.Product;
import com.moxuan.shopcommon.util.Result;
import com.moxuan.shoporder.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.Map;
@RestController
@Slf4j
public class OrderController {
@Autowired
private OrderService orderService;
@Autowired
private RestTemplate restTemplate;
@GetMapping("/order/prod/{pid}")
public Result order(@PathVariable("pid")Integer pid){
log.info(">> 客户下单,这时候要调用商品微服务查询商品信息");
// 通过restTemplate调用商品微服务
Result result = restTemplate.getForObject(
"http://localhost:8021/product/"+pid,
Result.class
);
log.info("商品信息>> 查询结果"+result.getData());
// Map<String,Object> pro =
// (HashMap<String, Object>) result.getData();
//
// Order order = new Order();
// order.setUid(1);
// order.setUsername("墨轩");
// order.setPid((Integer)pro.get("pid"));
// order.setPname((String)pro.get("pname"));
// order.setPprice((Double)pro.get("pprice"));
// order.setNumber(1);
Product pro = JSON.parseObject(result.getData().toString(),Product.class);
System.out.println(pro);
Order order = new Order();
order.setUid(1);
order.setUsername("墨轩");
order.setPid(pro.getPid());
order.setPname(pro.getPname());
order.setPprice(pro.getPprice());
order.setNum(1);
result = orderService.saveOrder(order);
return result;
}
}
启动项目,测试生成订单