商品微服务编码

承接前文,本节继续讲解微服务架构下商品微服务的编码改造,把原来单体项目中的功能模块一点一点整合到这个工程里。本节的源代码是在 newbee-mall-cloud-dev-step06 工程的基础上改造的,将工程命名为 newbee-mall-cloud-dev-step07

商品微服务代码改造

打开商品微服务 newbee-mall-cloud-goods-web 的工程目录,在 ltd.goods.cloud.newbee 包下依次创建 config 包、dao 包、entity 包、service 包。在 resources 目录下新增 mapper 文件夹用于存放 Mapper 文件,直接将原单体 API 项目中与商品管理和商品分类管理相关的业务代码及 Mapper 文件(如图 4-11 所示)依次复制过来。

image 2025 04 23 14 01 41 770
Figure 1. 图4-11 单体 API 项目中与商品管理和商品分类管理相关的业务代码及 Mapper 文件

由于代码量较大,这里就不一一讲解了,按照对应的文件目录复制过来即可。上述步骤完成后,最终的代码目录如图 4-12 所示。

image 2025 04 23 14 02 10 044
Figure 2. 图4-12 代码目录

修改 newbee-mall-cloud-goods-web 工程的 application.properties 配置文件,主要是数据库连接参数及 MyBatis 扫描配置,代码如下:

# datasource config (MySQL)
spring.datasource.name=newbee-mall-cloud-goods-datasource
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/newbee_mall_cloud_goods_db?useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=utf8&autoReconnect=true&useSSL=false&allowMultiQueries=true
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.maximum-pool-size=15
spring.datasource.hikari.auto-commit=true
spring.datasource.hikari.idle-timeout=60000
spring.datasource.hikari.pool-name=hikariCP
spring.datasource.hikari.max-lifetime=600000
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.connection-test-query=SELECT 1

# mybatis config
mybatis.mapper-locations=classpath:mapper/*Mapper.xml

这部分源代码涉及的数据库为 newbee_mall_cloud_goods_db,数据库表为 tb_newbee_mall_goods_categorytb_newbee_mall_goods_info

在商品微服务的代码调整前,有些工具类已经被移到公用模块 newbee-mall-cloud-common 中,所以在 pom.xml 文件中需要引入公用模块。同时,代码中使用这些工具类的地方也需要处理一下引用路径。

除此之外,商品微服务中还有一些公用类,都放到了公用模块 newbee-mall-cloud-common 中。

Controller 类中的接口地址都做了微调,与之前单体项目中定义的 URL 不同。调整的原因主要是在网关配置时方便一些。

打开 newbee-mall-cloud-gateway-admin 项目中的 application.properties 文件,新增关于商品微服务的路由信息,配置项为 spring.cloud.gateway.routes.*,新增代码如下:

# 商品微服务的路由配置-1
spring.cloud.gateway.routes[1].id=categories-admin-service-route
spring.cloud.gateway.routes[1].uri=lb://newbee-mall-cloud-goods-service
spring.cloud.gateway.routes[1].order=1
spring.cloud.gateway.routes[1].predicates[0]=Path=/categories/admin/**

# 商品微服务的路由配置-2
spring.cloud.gateway.routes[2].id=goods-admin-service-route
spring.cloud.gateway.routes[2].uri=lb://newbee-mall-cloud-goods-service
spring.cloud.gateway.routes[2].order=1
spring.cloud.gateway.routes[2].predicates[0]=Path=/goods/admin/**

这里主要配置 newbee-mall-cloud-gateway-admin 到商品微服务的路由信息。如果访问网关项目的路径是以 /goods/admin/categories/admin 开头的,就路由到商品微服务实例。

OpenFeign 编码暴露远程接口

newbee-mall-cloud-goods-api 模块中新增需要暴露的接口 FeignClient。如果其他微服务实例需要获取商品微服务中的资源,就可以通过调用商品微服务下暴露的接口来实现。

笔者在 NewBeeAdminGoodsInfoController 类中新建了一个商品详情接口,并将其暴露,代码如下:

@GetMapping("/goodsDetail")
@ApiOperation(value = "获取单条商品信息", notes = "根据 id 查询")
public Result goodsDetail(@RequestParam("goodsId") Long goodsId) {
    NewBeeMallGoods goods = newBeeMallGoodsService.getNewBeeMallGoodsById(goodsId);
    return ResultGenerator.genSuccessResult(goods);
}

newbee-mall-cloud-goods-api 目录下新建 ltd.goods.cloud.newbee.openfeign 包,之后在该包下新增 NewBeeCloudGoodsServiceFeign 类,用于创建对商品模块中相关接口的 OpenFeign 调用。

NewBeeCloudGoodsServiceFeign 类的代码如下:

package ltd.goods.cloud.newbee.openfeign;

import ltd.common.cloud.newbee.dto.Result;
import ltd.goods.cloud.newbee.dto.NewBeeMallGoodsDTO;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

@FeignClient(value = "newbee-mall-cloud-goods-service", path = "/goods")
public interface NewBeeCloudGoodsServiceFeign {

    @GetMapping(value = "/admin/goodsDetail")
    Result<NewBeeMallGoodsDTO> getGoodsDetail(@RequestParam(value = "goodsId") Long goodsId);
}

这个方法的作用是根据商品 id 获取一条商品数据。调用的接口是 newbee-mall-cloud-goods-web 模块下 NewBeeAdminGoodsInfoController 类中的 goodsDetail() 方法。如果其他服务需要与商品微服务进行远程通信获取相关数据,就可以引入 newbee-mall-cloud-goods-api 模块作为依赖,并且直接调用 NewBeeCloudGoodsServiceFeign 类中的 getGoodsDetail() 方法。

在后续的开发过程中,如果商品微服务中有其他接口需要暴露以供其他微服务调用,就可以继续在 NewBeeCloudGoodsServiceFeign 类中编码。

功能测试

代码修改完成后,测试步骤是不能漏掉的,一定要验证项目是否能正常启动,接口是否能正常调用,防止在代码移动过程中出现一些小问题,导致项目无法启动或代码报错。在项目启动前需要分别启动 Nacos ServerRedis Server,之后依次启动 newbee-mall-cloud-user-web 工程、newbee-mall-cloud-goods-web 工程和 newbee-mall-cloud-gateway-admin 工程下的主类。启动成功后,就可以进行本节的功能测试了。

先打开用户微服务的 Swagger 页面,在浏览器中输入如下网址: http://localhost:29000/swagger-ui/index.html。

然后在该页面中使用登录接口获取一个 token 值,用于后续的功能测试。比如,笔者在测试时获取了一个值为 “95eb476a4ac9677488278b8a7e3b2834” 的 token 字段。

接着打开商品微服务的 Swagger 页面,在浏览器中输入如下网址: http://localhost:29010/swagger-ui/index.html。

最后就可以在 Swagger 页面提供的UI页面中进行商品微服务的接口测试了,商品微服务接口文档显示的内容如图 4-13 所示。

image 2025 04 23 14 11 56 836
Figure 3. 图4-13 商品微服务接口文档显示的内容

这里演示一下商品分类相关接口。单击 “新增分类”→“Try it out” 按钮,在参数栏中输入分类名称、分类等级等字段,在登录认证 token 的输入框中输入管理员用户登录接口返回的 token 值,如图 4-14 所示。

image 2025 04 23 14 12 10 662
Figure 4. 图4-14 新增商品分类接口的测试过程

单击 “Execute” 按钮,接口的响应结果如图 4-15 所示。

image 2025 04 23 14 12 43 706
Figure 5. 图4-15 新增商品分类接口的响应结果

若后端接口的测试结果中有 “SUCCESS”,则表示数据添加成功,查看商品微服务的数据库,分类表中已经新增了一条数据。笔者在测试时,输入的参数都是符合规范的。如果输入的参数没有通过基本的验证判断,就会报出对应的错误提示,读者在测试时需要注意这一点。

该接口对应到实际的项目页面中,是新蜂商城后台管理系统中的商品分类管理页面,添加商品分类的示例页面如图 4-16 所示。

image 2025 04 23 14 13 15 295
Figure 6. 图4-16 添加商品分类的示例页面

这里只演示了一个接口的测试过程,读者在测试时可以看看其他接口。商品管理模块和商品分类管理模块下的接口对应到实际的页面中,分别是新蜂商城后台管理系统中的商品管理页面和商品分类管理页面。