之前我们启动Nacos都是使用dos命令行
启动过程比较复杂,命令比较长
Idea实际上支持我们更加方便的启动Nacos
步骤1:

步骤2:

步骤3:

配置成功之后
Nacos就会出现在idea的启动选项中了
这种方法实际上只是为了简便大家启动nacos的操作,还是需要掌握命令行的启动方式的!
创建csmall-cart子项目
父子相认
子项目pom文件为:
- "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.0modelVersion>
- <parent>
- <groupId>cn.tedugroupId>
- <artifactId>csmallartifactId>
- <version>0.0.1-SNAPSHOTversion>
- <relativePath/>
- parent>
- <groupId>cn.tedugroupId>
- <artifactId>csmall-cartartifactId>
- <version>0.0.1-SNAPSHOTversion>
- <name>csmall-cartname>
- <description>Demo project for Spring Bootdescription>
-
- <dependencies>
-
- <dependency>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-starter-webartifactId>
- dependency>
-
- <dependency>
- <groupId>org.mybatis.spring.bootgroupId>
- <artifactId>mybatis-spring-boot-starterartifactId>
- dependency>
-
- <dependency>
- <groupId>com.alibabagroupId>
- <artifactId>druidartifactId>
- dependency>
-
- <dependency>
- <groupId>mysqlgroupId>
- <artifactId>mysql-connector-javaartifactId>
- dependency>
-
- <dependency>
- <groupId>cn.tedugroupId>
- <artifactId>csmall-commonsartifactId>
- <version>0.0.1-SNAPSHOTversion>
- dependency>
-
- <dependency>
- <groupId>com.github.xiaoymingroupId>
- <artifactId>knife4j-spring-boot-starterartifactId>
- dependency>
-
- <dependency>
- <groupId>com.alibaba.cloudgroupId>
- <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
- dependency>
- dependencies>
-
- project>
删除test文件夹
删除application.properties配置文件
创建application.yml文件,内容如下
- server:
- port: 20001
- #公共配置
- mybatis:
- configuration:
- # 禁用缓存
- cache-enabled: false
- # 配置映射驼峰命名法,数据库中user_name的字段,会映射在java的userName属性上
- map-underscore-to-camel-case: true
- # 将运行的sql语句输出到控制台
- log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
- knife4j:
- # 开启增强配置
- enable: true
- # 生产环境屏蔽,开启将禁止访问在线API文档
- production: false
- # Basic认证功能,即是否需要通过用户名、密码验证后才可以访问在线API文档
- basic:
- # 是否开启Basic认证
- enable: false
- # 用户名,如果开启Basic认证却未配置用户名与密码,默认是:admin/123321
- username: root
- # 密码
- password: root
- spring:
- profiles:
- active: dev
推荐大家学习使用数据库的专用可视化工具来操作数据库
heidiSQL(安装MariaDB自带的)免费的
SqlYog Navicat是收费的
我们cart模块要操作数据库,首先保证要有数据
所以我们要创建需要的表和添加表中的数据
sql代码已经发送在csmall-finish项目的node文件夹中:csmall_db.sql
运行其中的sql代码即可
- CREATE DATABASE IF NOT EXISTS `csmall_db` DEFAULT CHARACTER SET utf8mb4;
- USE `csmall_db`;
-
- DROP TABLE IF EXISTS `cart_tbl`;
-
- CREATE TABLE `cart_tbl` (
- `id` int NOT NULL AUTO_INCREMENT COMMENT '购物车id',
- `commodity_code` varchar(255) DEFAULT NULL COMMENT '商品编码',
- `price` int DEFAULT '0' COMMENT '商品单价',
- `count` int DEFAULT '0' COMMENT '购买数量',
- `user_id` varchar(255) DEFAULT NULL COMMENT '用户id',
- PRIMARY KEY (`id`),
- UNIQUE KEY `commodity_code` (`commodity_code`)
- ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb3;
-
-
- insert into `cart_tbl`(`id`,`commodity_code`,`price`,`count`,`user_id`) values
- (1,'PU201',500,10,'UU100');
-
-
- DROP TABLE IF EXISTS `order_tbl`;
-
- CREATE TABLE `order_tbl` (
- `id` int NOT NULL AUTO_INCREMENT COMMENT '订单id',
- `user_id` varchar(255) DEFAULT NULL COMMENT '用户id',
- `commodity_code` varchar(255) DEFAULT NULL COMMENT '商品编码,也可以是商品id',
- `count` int DEFAULT '0' COMMENT '购买这个商品的数量',
- `money` int DEFAULT '0' COMMENT '订单金额',
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8mb3;
-
- insert into `order_tbl`(`id`,`user_id`,`commodity_code`,`count`,`money`) values
- (22,'UU100','PU201',10,200),
- (23,'UU100','PU201',10,200),
- (24,'UU100','PU201',10,200),
- (25,'UU100','PU201',10,200);
-
-
- DROP TABLE IF EXISTS `stock_tbl`;
-
- CREATE TABLE `stock_tbl` (
- `id` int NOT NULL AUTO_INCREMENT COMMENT '商品id',
- `commodity_code` varchar(255) DEFAULT NULL COMMENT '商品编码',
- `count` int DEFAULT '0' COMMENT '商品库存',
- PRIMARY KEY (`id`),
- UNIQUE KEY `commodity_code` (`commodity_code`)
- ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb3;
-
- insert into `stock_tbl`(`id`,`commodity_code`,`count`) values
- (1,'PU201',990);
-
- DROP TABLE IF EXISTS `undo_log`;
-
- CREATE TABLE `undo_log` (
- `id` bigint NOT NULL AUTO_INCREMENT,
- `branch_id` bigint NOT NULL,
- `xid` varchar(100) NOT NULL,
- `context` varchar(128) NOT NULL,
- `rollback_info` longblob NOT NULL,
- `log_status` int NOT NULL,
- `log_created` datetime NOT NULL,
- `log_modified` datetime NOT NULL,
- PRIMARY KEY (`id`),
- UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
- ) ENGINE=InnoDB AUTO_INCREMENT=68 DEFAULT CHARSET=utf8mb3;
-
application-dev.yml
- spring:
- datasource:
- url: jdbc:mysql://localhost:3306/csmall_db?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&allowMultiQueries=true
- username: root
- password: root
- application:
- # 为当前项目起名,这个名字会被Nacos记录并使用
- name: nacos-cart
- cloud:
- nacos:
- discovery:
- # 配置Nacos所在的位置,用于注册时提交信息
- server-addr: localhost:8848
- ephemeral: false
和business项目一样
我们需要创建config包,包中创建相关配置类
- @Configuration // 所有配置Spring的配置类必须添加这个注解
- @ComponentScan(basePackages = "cn.tedu.csmall.commons.exception")
- public class CommonsConfiguration {
- }
knife4j配置
- @Configuration
- @EnableSwagger2WebMvc
- public class Knife4jConfiguration {
-
- /**
- * 【重要】指定Controller包路径
- */
- private String basePackage = "cn.tedu.csmall.cart.controller";
- /**
- * 分组名称
- */
- private String groupName = "base-cart";
- /**
- * 主机名
- */
- private String host = "http://java.tedu.cn";
- /**
- * 标题
- */
- private String title = "酷鲨商城项目案例在线API文档--基础cart-web实例";
- /**
- * 简介
- */
- private String description = "构建基础cart-web项目,实现购物车管理";
- // 略....
- }
当前cart模块除了上述配置之外,还需要添加Mybatis扫描mapper包的配置
config包中再创建一个MyBatisConfiguration类,代码如下
- @Configuration
- // Mybatis框架扫描mapper包接口的注解
- @MapperScan("cn.tedu.csmall.cart.mapper")
- public class MybatisConfiguration {
- }
我们尝试启动Nacos后
启动cart模块
观察nacos服务列表中是否包含当前服务名称
cart模块能够正常启动,但是还没有任何业务
结合我们最终生成订单的业务
当前cart模块需要开发如下两个功能
1.新增购物车中商品
2.删除购物车中商品
创建mapper包
创建CartMapper接口,中编写两个方法
一个新增购物车,一个删除购物车
- @Repository
- public interface CartMapper {
- // 新增购物车中商品的方法
- @Insert("insert into cart_tbl(commodity_code,price,count,user_id) " +
- "values(#{commodityCode},#{price},#{count},#{userId})")
- void insertCart(Cart cart);
-
- // 删除购物车
- @Delete("delete from cart_tbl where user_id=#{userId} and " +
- " commodity_code=#{commodityCode}")
- void deleteCartByUserIdAndCommodityCode(@Param("userId") String userId,
- @Param("commodityCode") String commodityCode);
-
-
- }
创建service包
包中创建ICartService
接口中编写新增和删除购物车的两个业务逻辑层方法声明
- public interface ICartService {
-
- // 新增购物车商品的业务逻辑层方法
- void cartAdd(CartAddDTO cartAddDTO);
-
- // 删除购物车商品的业务逻辑层方法
- void deleteUserCart(String userId,String commodityCode);
-
-
- }
创建impl包
编写业务实现类
- @Service
- @Slf4j
- public class CartServiceImpl implements ICartService {
-
- @Autowired
- private CartMapper cartMapper;
-
- @Override
- public void cartAdd(CartAddDTO cartAddDTO) {
- // 当前方法参数是CartAddDTO类型,而mapper执行新增需要的类型是Cart
- // 所以需要将现在cartAddDTO中,所有同名属性赋值给Cart类型对象才能实现mapper调用
- // 先实例化一个Cart对象
- Cart cart=new Cart();
- // 利用BeanUtils工具类,将cartAddDTO同名属性赋值到cart
- BeanUtils.copyProperties(cartAddDTO,cart);
- // 调用mapper新增购物车商品的方法
- cartMapper.insertCart(cart);
- // 如果新增顺利,将新增的对象输出到日志
- log.info("新增购物车商品成功:{}",cart);
- }
-
- @Override
- public void deleteUserCart(String userId, String commodityCode) {
- // 删除功能需要userId和commodityCode,直接使用参数调用即可
- cartMapper.deleteCartByUserIdAndCommodityCode(userId,commodityCode);
- // 一切正常,日志提示
- log.info("购物车删除完成");
- }
- }
如果需要设置日志输出级别
dev的yml文件中添加
logging: level: cn.tedu.csmall.cart: debug
创建controller包
包中创建CartController类
代码如下
- @RestController
- @RequestMapping("/base/cart")
- @Api(tags = "购物车管理")
- public class CartController {
- @Autowired
- private ICartService cartService;
-
- @PostMapping("/add")
- @ApiOperation("新增购物车商品")
- public JsonResult cartAdd(CartAddDTO cartAddDTO){
- cartService.cartAdd(cartAddDTO);
- return JsonResult.ok("新增购物车商品完成!");
- }
-
- @PostMapping("/delete")
- @ApiOperation("删除购物车商品")
- @ApiImplicitParams({
- @ApiImplicitParam(value = "用户ID",name="userId",example = "UU100"),
- @ApiImplicitParam(value = "商品编号",name="commodityCode",example = "PC100")
- })
- public JsonResult deleteUserCart(String userId,String commodityCode){
- cartService.deleteUserCart(userId,commodityCode);
- return JsonResult.ok("删除购物车商品完成!");
- }
-
- }
重启Cart模块
测试localhost:20001/doc.html
发送新增购物车的请求测试
然后测试删除购物车的功能
- "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.0modelVersion>
- <parent>
- <groupId>cn.tedugroupId>
- <artifactId>csmallartifactId>
- <version>0.0.1-SNAPSHOTversion>
- <relativePath/>
- parent>
- <groupId>cn.tedugroupId>
- <artifactId>csmall-orderartifactId>
- <version>0.0.1-SNAPSHOTversion>
- <name>csmall-ordername>
- <description>Demo project for Spring Bootdescription>
-
- <dependencies>
-
- <dependency>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-starter-webartifactId>
- dependency>
-
- <dependency>
- <groupId>org.mybatis.spring.bootgroupId>
- <artifactId>mybatis-spring-boot-starterartifactId>
- dependency>
-
- <dependency>
- <groupId>com.alibabagroupId>
- <artifactId>druidartifactId>
- dependency>
-
- <dependency>
- <groupId>mysqlgroupId>
- <artifactId>mysql-connector-javaartifactId>
- dependency>
-
- <dependency>
- <groupId>cn.tedugroupId>
- <artifactId>csmall-commonsartifactId>
- <version>0.0.1-SNAPSHOTversion>
- dependency>
-
- <dependency>
- <groupId>com.github.xiaoymingroupId>
- <artifactId>knife4j-spring-boot-starterartifactId>
- dependency>
-
- <dependency>
- <groupId>com.alibaba.cloudgroupId>
- <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
- dependency>
- dependencies>
-
- project>
删除test文件夹
删除application.properties文件
可以将cart模块的application.yml文件和application-dev.yml复制过来
但是要修改需要变化的属性
application.yml端口号修改
- server:
- port: 20002
application-dev.yml修改项目名称
- application:
- name: nacos-order
直接复制cart模块的config包到当前order模块即可
修改内容如下
knife4j配置主要修改:
- /**
- * 【重要】指定Controller包路径
- */
- private String basePackage = "cn.tedu.csmall.order.controller";
- /**
- * 分组名称
- */
- private String groupName = "base-order";
- /**
- * 主机名
- */
- private String host = "http://java.tedu.cn";
- /**
- * 标题
- */
- private String title = "酷鲨商城项目案例在线API文档--基础order-web实例";
- /**
- * 简介
- */
- private String description = "构建基础order-web项目,实现订单管理";
Mybatis配置修改如下
- @Configuration
- // Mybatis框架扫描mapper包接口的注解
- @MapperScan("cn.tedu.csmall.order.mapper")
- public class MybatisConfiguration {
- }
创建mapper包
创建OrderMapper接口
添加新增订单方法
- @Repository
- public interface OrderMapper {
- // 新增订单的方法
- @Insert("insert into order_tbl(user_id,commodity_code,count,money) " +
- "values(#{userId},#{commodityCode},#{count},#{money})")
- void insertOrder(Order order);
- }
创建service包
包中创建IOrderService
- public interface IOrderService {
-
- // 声明新增订单的方法
- void orderAdd(OrderAddDTO orderAddDTO);
- }
创建service.impl包
包中创建OrderServiceImpl
- @Service
- @Slf4j
- public class OrderServiceImpl implements IOrderService {
-
- @Autowired
- private OrderMapper orderMapper;
-
- @Override
- public void orderAdd(OrderAddDTO orderAddDTO) {
- // 1.减少订单中商品的库存数(要调用stock模块的方法)
- // 2.删除订单中选中的购物车的商品(要调用cart模块的方法)
- // 3.执行将orderAddDTO中的信息新增到订单表中的功能
- // 实例化一个Order对象
- Order order=new Order();
- BeanUtils.copyProperties(orderAddDTO,order);
- // 执行新增
- orderMapper.insertOrder(order);
- log.info("新增的订单信息为{}",order);
- }
- }
创建controller包
创建OrderController类
- @RestController
- @RequestMapping("/base/order")
- @Api(tags = "订单管理")
- public class OrderController {
- @Autowired
- private IOrderService orderService;
-
- @ApiOperation("新增订单")
- @PostMapping("/add")
- public JsonResult orderAdd(OrderAddDTO orderAddDTO){
- // 调用业务逻辑层
- orderService.orderAdd(orderAddDTO);
- return JsonResult.ok("新增订单完成!");
- }
-
- }
启动order项目
检查nacos注册状态和knife4j测试新增订单效果
先启动nacos再启动order
创建csmall-stock
修改父项目pom文件,父子相认
子项目pom文件
- "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.0modelVersion>
- <parent>
- <groupId>cn.tedugroupId>
- <artifactId>csmallartifactId>
- <version>0.0.1-SNAPSHOTversion>
- <relativePath/>
- parent>
- <groupId>cn.tedugroupId>
- <artifactId>csmall-stockartifactId>
- <version>0.0.1-SNAPSHOTversion>
- <name>csmall-stockname>
- <description>Demo project for Spring Bootdescription>
-
- <dependencies>
-
- <dependency>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-starter-webartifactId>
- dependency>
-
- <dependency>
- <groupId>org.mybatis.spring.bootgroupId>
- <artifactId>mybatis-spring-boot-starterartifactId>
- dependency>
-
- <dependency>
- <groupId>com.alibabagroupId>
- <artifactId>druidartifactId>
- dependency>
-
- <dependency>
- <groupId>mysqlgroupId>
- <artifactId>mysql-connector-javaartifactId>
- dependency>
-
- <dependency>
- <groupId>cn.tedugroupId>
- <artifactId>csmall-commonsartifactId>
- <version>0.0.1-SNAPSHOTversion>
- dependency>
-
- <dependency>
- <groupId>com.github.xiaoymingroupId>
- <artifactId>knife4j-spring-boot-starterartifactId>
- dependency>
-
- <dependency>
- <groupId>com.alibaba.cloudgroupId>
- <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
- dependency>
- dependencies>
-
- project>
删除test测试文件夹
删除application.properties文件
复制order\cart模块的application.yml和application-dev.yml文件
修改端口号和项目名称
从order\cart模块复制config包
修改MybatisConfiguration\Knife4jConfiguration对应的包名
- UPDATE stock_tbl SET COUNT=COUNT-10
- WHERE commodity_code='PC100' AND COUNT>=10
mapper包下StockMapper
- @Repository
- public interface StockMapper {
-
- // 修改(减少)指定商品库存数的方法
- @Update("UPDATE stock_tbl SET COUNT=COUNT-#{reduceCount} " +
- " WHERE commodity_code=#{commodityCode} AND COUNT>=#{reduceCount}")
- void updateStockByCommodityCode(@Param("commodityCode") String commodityCode,
- @Param("reduceCount") Integer reduceCount);
-
-
- }
在service包下创建IStockService
- public interface IStockService {
- // 减少库存数的业务逻辑层方法
- void reduceCommodityCount(StockReduceCountDTO stockReduceCountDTO);
- }
service.impl包下创建StockServiceImpl
- @Service
- @Slf4j
- public class StockServiceImpl implements IStockService {
- @Autowired
- private StockMapper stockMapper;
- @Override
- public void reduceCommodityCount(StockReduceCountDTO stockReduceCountDTO) {
- // 调用stockMapper减少库存数的方法
- // 参数1:商品编号
- // 参数2:减少的库存数
- stockMapper.updateStockByCommodityCode(
- stockReduceCountDTO.getCommodityCode(),
- stockReduceCountDTO.getReduceCount());
- log.info("库存减少已执行");
- }
- }
controller包
StockController类
- @RestController
- @RequestMapping("/base/stock")
- @Api(tags = "库存管理")
- public class StockController {
- @Autowired
- private IStockService stockService;
-
- @PostMapping("/reduce/count")
- @ApiOperation("减少商品库存数")
- public JsonResult reduceCommodityCount(StockReduceCountDTO stockReduceCountDTO){
- // 调用业务逻辑层
- stockService.reduceCommodityCount(stockReduceCountDTO);
- return JsonResult.ok("库存减少已执行!");
- }
-
- }
启动服务测试成功即可
RPC是Remote Procedure Call的缩写 翻译为:远程过程调用
目标是为了实现两台(多台)计算机\服务器,相互调用方法\通信的解决方案
RPC只是实现远程调用的一套标准
该标准主要规定了两部分内容
1.通信协议
2.序列化协议
为了方便大家理解RPC,下面的图片帮助理解

上面图是老婆和老公在家的时,老婆让老公洗碗的调用流程
这个流程可以理解为项目内的功能的调用,类似面向对象编程实例化对象,调用方法的过程
但是这个调用关系如果是远程的,意思是老婆和老公现在是两个不同的项目

我们看到上图中,远程调用必须借助一个通信设备,图片中是手机
3.1.1通信协议
通信协议指的就是远程调用的通信方式
实际上这个通知的方式可以有多种
例如:写信,飞鸽传书,闪送等等
在程序中,通信方式也有多种
3.1.2序列化协议
序列化协议指通信内容的格式,双方都要理解这个格式
上面的图片中,老婆给老公发信息,一定是双方都能理解的信息
发送信息是序列化过程,接收信息需要反序列化
程序中,序列化的方式也是多种的
上面对RPC有基本认识之后,再学习Dubbo就简单了
Dubbo是一套RPC框架。既然是框架,我们可以在框架结构高度,定义Dubbo中使用的通信协议,使用的序列化框架技术,而数据格式由Dubbo定义,我们负责配置之后直接通过客户端调用服务端代码。
可以说Dubbo就是RPC概念的实现
Dubbo是SpringCloudAlibaba提供的框架
能够实现微服务相互调用的功能!

我们学习的Dubbo指的都是2.7之后的版本
是能够和SpringCloudAlibaba配合使用的
Dubbo历程
2012年底dubbo停止更新后到2017年dubbo继续更新之前
2015SpringCloud开始兴起,当时没有阿里的框架
国内公司要从SpringCloud和Dubbo中抉择使用哪个微服务方案
在2012年dubbo停止更新后国内的当当网在dubbo的基础上开发了dubboX框架,并进行维护
2019年后,SpringCloud和Dubbo才能共同使用
RPC框架分通信协议和序列化协议
Dubbo框架支持多种通信协议和序列化协议,可以通过配置文件进行修改
Dubbo支持的通信协议
支持的序列化协议
Dubbo默认情况下,支持的协议有如下特征
Dubbo方便支持高并发和高性能
在Dubbo的调用过程中,必须包含注册中心的支持
注册中心推荐阿里自己的Nacos,兼容性好,能够发挥最大性能
但是Dubbo也支持其它软件作为注册中心(例如Redis,zookeeper等)
服务发现,即消费端自动发现服务地址列表的能力,是微服务框架需要具备的关键能力,借助于自动化的服务发现,微服务之间可以在无需感知对端部署位置与 IP 地址的情况下实现通信。
上面RPC的示例中,老婆就是服务的消费端,她能发现老公具备的服务
如果老婆调用了老公的服务,就是完成了Dubbo调用

consumer服务的消费者,指服务的调用者(使用者)也就是老婆的位置
provider服务的提供者,指服务的拥有者(生产者)也就是老公的位置
在Dubbo中,远程调用依据是服务的提供者在Nacos中注册的服务名称
一个服务名称,可能有多个运行的实例,任何一个空闲的实例都可以提供服务
常见面试题:Dubbo的注册发现流程
1.首先服务的提供者启动服务时,将自己的具备的服务注册到注册中心,其中包括当前提供者的ip地址和端口号等信息,Dubbo会同时注册该项目提供的远程调用的方法
2.消费者(使用者)启动项目,也注册到注册中心,同时从注册中心中获得当前项目具备的所有服务列表
3.当注册中心中有新的服务出现时,会通知已经订阅发现的消费者,消费者会更新所有服务列表
4.RPC调用,消费者需要调用远程方法时,根据注册中心服务列表的信息,只需服务名称,不需要ip地址和端口号等信息,就可以利用Dubbo调用远程方法了
我们当前csmall项目的远程调用关系如下
