赞
踩
目录
Service中的实现impl所继承的接口IService(各种方法):
2. 新建包com.hmall.xx(业务名),添加和修改启动类,新建mapper包、domain包 - service包 - controller包
3. 拷贝并修改yaml配置文件到resources中,分别修改 端口号、服务名称、datasource(需创建sql datebase)、swagger接口文档说明与controller扫描包
4.domain,mapper,service,controller包代码
5. 刷新maven,添加该业务模块启动项到Services中,并把Active profiles 修改为 local
6. 运行,在访问地址后面添加doc.html访问swagger接口文档,进行调试
2、启动服务,访问http://192.168.150.101:8848/nacos/控制台,可以发现服务注册成功:
-
- @Api(tags = "用户相关接口")
- @RestController
- @RequestMapping("/users")
- @RequiredArgsConstructor
- public class UserController {
-
- private final IUserService userService;
-
- @ApiOperation("用户登录接口")
- @PostMapping("login")
- public UserLoginVO login(@RequestBody @Validated LoginFormDTO loginFormDTO){
- return userService.login(loginFormDTO);
- }
- }
- public interface IUserService extends IService<User> {
-
- UserLoginVO login(LoginFormDTO loginFormDTO);
-
- void deductMoney(String pw, Integer totalFee);
- }
-
- public interface IService<T> {
- int DEFAULT_BATCH_SIZE = 1000;
-
- default boolean save(T entity) {
- return SqlHelper.retBool(this.getBaseMapper().insert(entity));
- }
-
- @Transactional(
- rollbackFor = {Exception.class}
- )
- default boolean saveBatch(Collection<T> entityList) {
- return this.saveBatch(entityList, 1000);
- }
-
- boolean saveBatch(Collection<T> entityList, int batchSize);
-
- @Transactional(
- rollbackFor = {Exception.class}
- )
- default boolean saveOrUpdateBatch(Collection<T> entityList) {
- return this.saveOrUpdateBatch(entityList, 1000);
- }
-
- boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);
- }
- @Data
- public class UserLoginVO {
- private String token;
- private Long userId;
- private String username;
- private Integer balance;
- }
- @Data
- @ApiModel(description = "登录表单实体")
- public class LoginFormDTO {
- @ApiModelProperty(value = "用户名", required = true)
- @NotNull(message = "用户名不能为空")
- private String username;
- @NotNull(message = "密码不能为空")
- @ApiModelProperty(value = "用户名", required = true)
- private String password;
- @ApiModelProperty(value = "是否记住我", required = false)
- private Boolean rememberMe = false;
- }
在首页搜索框输入关键字手机,点击搜索即可进入搜索列表页面:
- @Api(tags = "搜索相关接口")
- @RestController
- @RequestMapping("/search")
- @RequiredArgsConstructor
- public class SearchController {
-
- private final IItemService itemService;
-
- @ApiOperation("搜索商品")
- @GetMapping("/list")
- public PageDTO<ItemDTO> search(ItemPageQuery query) {
- // 分页查询
- Page<Item> result = itemService.lambdaQuery()
- .like(StrUtil.isNotBlank(query.getKey()), Item::getName, query.getKey())
- .eq(StrUtil.isNotBlank(query.getBrand()), Item::getBrand, query.getBrand())
- .eq(StrUtil.isNotBlank(query.getCategory()), Item::getCategory, query.getCategory())
- .eq(Item::getStatus, 1)
- .between(query.getMaxPrice() != null, Item::getPrice, query.getMinPrice(), query.getMaxPrice())
- .page(query.toMpPage("update_time", false));
- // 封装并返回
- return PageDTO.of(result, ItemDTO.class);
- }
- }
在搜索到的商品列表中,点击按钮加入购物车
,即可将商品加入购物车:
加入成功后即可进入购物车列表页,查看自己购物车商品列表:
- @Api(tags = "购物车相关接口")
- @RestController
- @RequestMapping("/carts")
- @RequiredArgsConstructor
- public class CartController {
- private final ICartService cartService;
-
- @ApiOperation("添加商品到购物车")
- @PostMapping
- public void addItem2Cart(@Valid @RequestBody CartFormDTO cartFormDTO){
- cartService.addItem2Cart(cartFormDTO);
- }
-
- @ApiOperation("更新购物车数据")
- @PutMapping
- public void updateCart(@RequestBody Cart cart){
- cartService.updateById(cart);
- }
-
- @ApiOperation("删除购物车中商品")
- @DeleteMapping("{id}")
- public void deleteCartItem(@Param ("购物车条目id")@PathVariable("id") Long id){
- cartService.removeById(id);
- }
-
- @ApiOperation("查询购物车列表")
- @GetMapping
- public List<CartVO> queryMyCarts(){
- return cartService.queryMyCarts();
- }
- @ApiOperation("批量删除购物车中商品")
- @ApiImplicitParam(name = "ids", value = "购物车条目id集合")
- @DeleteMapping
- public void deleteCartItemByIds(@RequestParam("ids") List<Long> ids){
- cartService.removeByItemIds(ids);
- }
- }
其中,查询购物车列表时,由于要判断商品最新的价格和状态,所以还需要查询商品信息,业务流程如下:
创建新模块
选择maven模块,并设定JDK版本为11:
添加依赖
- <?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>
- <parent>
- <groupId>com.heima</groupId>
- <artifactId>hmall</artifactId>
- <version>1.0.0</version>
- </parent>
-
- <groupId>org.qingshui</groupId>
- <artifactId>item-service</artifactId>
-
- <properties>
- <maven.compiler.source>11</maven.compiler.source>
- <maven.compiler.target>11</maven.compiler.target>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- </properties>
-
- <dependencies>
- <!--common-->
- <dependency>
- <groupId>com.heima</groupId>
- <artifactId>hm-common</artifactId>
- <version>1.0.0</version>
- </dependency>
- <!--web-->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
- <!--数据库-->
- <dependency>
- <groupId>mysql</groupId>
- <artifactId>mysql-connector-java</artifactId>
- </dependency>
- <!--mybatis-->
- <dependency>
- <groupId>com.baomidou</groupId>
- <artifactId>mybatis-plus-boot-starter</artifactId>
- </dependency>
- <!--单元测试-->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-test</artifactId>
- <version>3.3.0</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.junit.jupiter</groupId>
- <artifactId>junit-jupiter</artifactId>
- <scope>test</scope>
- </dependency>
- </dependencies>
-
- <build>
- <finalName>${project.artifactId}</finalName>
- <plugins>
- <plugin>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-maven-plugin</artifactId>
- </plugin>
- </plugins>
- </build>
- </project>
新建包com.hmall.item:
编写启动类ItemApplication:
- @MapperScan("com.hmall.item.mapper")
- @SpringBootApplication
- public class ItemApplication {
- public static void main(String[] args) {
- SpringApplication.run(ItemApplication.class, args);
- }
- }
新建mapper包、domain包 - service包 - controller包:
从hm-service中拷贝:
修改application.yaml为:
- server:
- port: 8081
- spring:
- application:
- name: item-service
- profiles:
- active: dev
- datasource:
- url: jdbc:mysql://${hm.db.host}:3306/hm-item?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
- driver-class-name: com.mysql.cj.jdbc.Driver
- username: root
- password: ${hm.db.pw}
- mybatis-plus:
- configuration:
- default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler
- global-config:
- db-config:
- update-strategy: not_null
- id-type: auto
- logging:
- level:
- com.hmall: debug
- pattern:
- dateformat: HH:mm:ss:SSS
- file:
- path: "logs/${spring.application.name}"
- knife4j:
- enable: true
- openapi:
- title: 商品服务接口文档
- description: "信息"
- email: zhanghuyi@itcast.cn
- concat: 虎哥
- url: https://www.itcast.cn
- version: v1.0.0
- group:
- default:
- group-name: default
- api-rule: package
- api-rule-resources:
- - com.hmall.item.controller
创建该模块的数据库:
【1】domain包代码:dto、po、vo、(query)
dto:数据传输对象
OrderDetailDTO:
- @ApiModel(description = "订单明细条目")
- @Data
- @Accessors(chain = true)
- public class OrderDetailDTO {
- @ApiModelProperty("商品id")
- private Long itemId;
- @ApiModelProperty("商品购买数量")
- private Integer num;
- }
ItemDTO:
-
- @Data
- @ApiModel(description = "商品实体")
- public class ItemDTO {
- @ApiModelProperty("商品id")
- private Long id;
- @ApiModelProperty("SKU名称")
- private String name;
- @ApiModelProperty("价格(分)")
- private Integer price;
- @ApiModelProperty("库存数量")
- private Integer stock;
- @ApiModelProperty("商品图片")
- private String image;
- @ApiModelProperty("类目名称")
- private String category;
- @ApiModelProperty("品牌名称")
- private String brand;
- @ApiModelProperty("规格")
- private String spec;
- @ApiModelProperty("销量")
- private Integer sold;
- @ApiModelProperty("评论数")
- private Integer commentCount;
- @ApiModelProperty("是否是推广广告,true/false")
- private Boolean isAD;
- @ApiModelProperty("商品状态 1-正常,2-下架,3-删除")
- private Integer status;
- }
po:实体
-
- @Data
- @EqualsAndHashCode(callSuper = false)
- @Accessors(chain = true)
- @TableName("item")
- public class Item implements Serializable {
-
- private static final long serialVersionUID = 1L;
-
- /**
- * 商品id
- */
- @TableId(value = "id", type = IdType.AUTO)
- private Long id;
-
- /**
- * SKU名称
- */
- private String name;
-
- /**
- * 价格(分)
- */
- private Integer price;
-
- /**
- * 库存数量
- */
- private Integer stock;
-
- /**
- * 商品图片
- */
- private String image;
-
- /**
- * 类目名称
- */
- private String category;
-
- /**
- * 品牌名称
- */
- private String brand;
-
- /**
- * 规格
- */
- private String spec;
-
- /**
- * 销量
- */
- private Integer sold;
-
- /**
- * 评论数
- */
- private Integer commentCount;
-
- /**
- * 是否是推广广告,true/false
- */
- @TableField("isAD")
- private Boolean isAD;
-
- /**
- * 商品状态 1-正常,2-下架,3-删除
- */
- private Integer status;
-
- /**
- * 创建时间
- */
- private LocalDateTime createTime;
-
- /**
- * 更新时间
- */
- private LocalDateTime updateTime;
-
- /**
- * 创建人
- */
- private Long creater;
-
- /**
- * 修改人
- */
- private Long updater;
-
-
- }
vo:视图对象
在hm-service模块中没有与商品有关的代码。
query:分页查询
- @EqualsAndHashCode(callSuper = true)
- @Data
- @ApiModel(description = "商品分页查询条件")
- public class ItemPageQuery extends PageQuery {
- @ApiModelProperty("搜索关键字")
- private String key;
- @ApiModelProperty("商品分类")
- private String category;
- @ApiModelProperty("商品品牌")
- private String brand;
- @ApiModelProperty("价格最小值")
- private Integer minPrice;
- @ApiModelProperty("价格最大值")
- private Integer maxPrice;
- }
【2】mapper包代码 :mapper接口 及mapper.xml文件
- public interface ItemMapper extends BaseMapper<Item> {
-
- @Update("UPDATE item SET stock = stock - #{num} WHERE id = #{itemId}")
- void updateStock(OrderDetailDTO orderDetail);
- }
【3】 service包:service接口及实现类
service接口:
- public interface IItemService extends IService<Item> {
-
- void deductStock(List<OrderDetailDTO> items);
-
- List<ItemDTO> queryItemByIds(Collection<Long> ids);
- }
修改sqlStatement后的实现类:
- @Service
- public class ItemServiceImpl extends ServiceImpl<ItemMapper, Item> implements IItemService {
-
- @Override
- public void deductStock(List<OrderDetailDTO> items) {
- String sqlStatement = "com.hmall.mapper.item.ItemMapper.updateStock";
- boolean r = false;
- try {
- r = executeBatch(items, (sqlSession, entity) -> sqlSession.update(sqlStatement, entity));
- } catch (Exception e) {
- throw new BizIllegalException("更新库存异常,可能是库存不足!", e);
- }
- if (!r) {
- throw new BizIllegalException("库存不足!");
- }
- }
-
- @Override
- public List<ItemDTO> queryItemByIds(Collection<Long> ids) {
- return BeanUtils.copyList(listByIds(ids), ItemDTO.class);
- }
- }
【4】controller包
- @Api(tags = "商品管理相关接口")
- @RestController
- @RequestMapping("/items")
- @RequiredArgsConstructor
- public class ItemController {
-
- private final IItemService itemService;
-
- @ApiOperation("分页查询商品")
- @GetMapping("/page")
- public PageDTO<ItemDTO> queryItemByPage(PageQuery query) {
- // 1.分页查询
- Page<Item> result = itemService.page(query.toMpPage("update_time", false));
- // 2.封装并返回
- return PageDTO.of(result, ItemDTO.class);
- }
-
- @ApiOperation("根据id批量查询商品")
- @GetMapping
- public List<ItemDTO> queryItemByIds(@RequestParam("ids") List<Long> ids){
- return itemService.queryItemByIds(ids);
- }
-
- @ApiOperation("根据id查询商品")
- @GetMapping("{id}")
- public ItemDTO queryItemById(@PathVariable("id") Long id) {
- return BeanUtils.copyBean(itemService.getById(id), ItemDTO.class);
- }
-
- @ApiOperation("新增商品")
- @PostMapping
- public void saveItem(@RequestBody ItemDTO item) {
- // 新增
- itemService.save(BeanUtils.copyBean(item, Item.class));
- }
-
- @ApiOperation("更新商品状态")
- @PutMapping("/status/{id}/{status}")
- public void updateItemStatus(@PathVariable("id") Long id, @PathVariable("status") Integer status){
- Item item = new Item();
- item.setId(id);
- item.setStatus(status);
- itemService.updateById(item);
- }
-
- @ApiOperation("更新商品")
- @PutMapping
- public void updateItem(@RequestBody ItemDTO item) {
- // 不允许修改商品状态,所以强制设置为null,更新时,就会忽略该字段
- item.setStatus(null);
- // 更新
- itemService.updateById(BeanUtils.copyBean(item, Item.class));
- }
-
- @ApiOperation("根据id删除商品")
- @DeleteMapping("{id}")
- public void deleteItemById(@PathVariable("id") Long id) {
- itemService.removeById(id);
- }
-
- @ApiOperation("批量扣减库存")
- @PutMapping("/stock/deduct")
- public void deductStock(@RequestBody List<OrderDetailDTO> items){
- itemService.deductStock(items);
- }
- }
同上
背景:
在拆分的时候,我们发现一个问题:就是购物车业务中需要查询商品信息,但商品信息查询的逻辑全部迁移到了
item-service
服务,导致我们无法查询。(也就是一个模块要进行查询但是查询代码都在另外一个模块)那么问题来了:我们该如何跨服务调用,准确的说,如何在
cart-service
中获取item-service
服务中的提供的商品数据呢?
因此,现在查询购物车列表的流程变成了这样:
假如我们在cart-service中能模拟浏览器,发送http请求到item-service,是不是就实现了跨微服务的远程调用了呢(也就是用Java代码发送Http请求)
Spring给我们提供了一个RestTemplate的API,可以方便的实现Http请求的发送。
其中提供了大量的方法,方便我们发送Http请求,例如:
我们在cart-service
服务中定义一个配置类
先将RestTemplate注册为一个Bean:
- package com.hmall.cart.config;
-
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.web.client.RestTemplate;
-
- @Configuration
- public class RemoteCallConfig {
-
- @Bean
- public RestTemplate restTemplate() {
- return new RestTemplate();
- }
- }
在这个过程中,item-service
提供了查询接口,cart-service
利用Http请求调用该接口。因此item-service
可以称为服务的提供者,而cart-service
则称为服务的消费者或服务调用者。
背景:
RPC通过Http请求实现了跨微服务的远程调用,这种手动发送Http请求的方式存在一些问题。
试想一下,假如商品微服务被调用较多,为了应对更高的并发,我们进行了多实例部署,如图:
此时,每个item-service
的实例其IP或端口不同,问题来了:
item-service这么多实例,cart-service如何知道每一个实例的地址?
http请求要写url地址,cart-service
服务到底该调用哪个实例呢?
如果在运行过程中,某一个item-service
实例宕机,cart-service
依然在调用该怎么办?
如果并发太高,item-service
临时多部署了N台实例,cart-service
如何知道新实例的地址?
这时我们需要注册中心 (其实也是建立一个连接池)
流程如下:
服务启动时就会注册自己的服务信息(服务名、IP、端口)到注册中心
调用者可以从注册中心订阅想要的服务,获取服务对应的实例列表(1个服务可能多实例部署)
调用者自己对实例列表负载均衡,挑选一个实例
调用者向该实例发起远程调用
当服务提供者的实例宕机或者启动新实例时,调用者如何得知呢?
服务提供者会定期向注册中心发送请求,报告自己的健康状态(心跳请求)
当注册中心长时间收不到提供者的心跳时,会认为该实例宕机,将其从服务的实例列表中剔除
当服务有新实例启动时,会发送注册服务请求,其信息会被记录在注册中心的服务实例列表
当注册中心服务列表变更时,会主动通知微服务,更新本地服务列表
将模块(微服务)注册到Nacos
在item-service
的pom.xml
中添加依赖:
- <!--nacos 服务注册发现-->
- <dependency>
- <groupId>com.alibaba.cloud</groupId>
- <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
- </dependency>
在item-service
的application.yml
中添加nacos地址配置:
将nacos地址修改为自己的虚拟机地址
- spring:
- application:
- name: item-service # 服务名称
- cloud:
- nacos:
- server-addr: 192.168.150.101:8848 # nacos地址
服务的消费者要去nacos订阅服务,这个过程就是服务发现 。
服务发现除了要引入nacos依赖以外,由于还需要负载均衡,因此要引入SpringCloud提供的LoadBalancer依赖。
我们在cart-service
中的pom.xml
中添加下面的依赖:
- <!--nacos 服务注册发现-->
- <dependency>
- <groupId>com.alibaba.cloud</groupId>
- <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
- </dependency>
在cart-service
的application.yml
中添加nacos地址配置:
- spring:
- cloud:
- nacos:
- server-addr: 192.168.150.101:8848
接下来,服务调用者cart-service
就可以去订阅item-service
服务了。不过item-service有多个实例,而真正发起调用时只需要知道一个实例的地址。
因此,服务调用者必须利用负载均衡的算法,从多个实例中挑选一个去访问。常见的负载均衡算法有:
随机
轮询
IP的hash
最近最少访问
...
这里我们可以选择最简单的随机负载均衡。
另外,服务发现需要用到一个工具,DiscoveryClient,SpringCloud已经帮我们自动装配,我们可以直接注入使用:
接下来,我们就可以对原来的远程调用做修改了,之前调用时我们需要写死服务提供者的IP和端口:
但现在不需要了,我们通过DiscoveryClient发现服务实例列表,然后通过负载均衡算法,选择一个实例去调用:
OpenFeign其作用就是基于SpringMVC的常见注解,轻松的实现http请求的发送。
- <!--openFeign-->
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-openfeign</artifactId>
- </dependency>
- <!--负载均衡器-->
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-loadbalancer</artifactId>
- </dependency>
接下来,我们在cart-service
的CartApplication
启动类上添加注解,启动OpenFeign功能:
在cart-service
中,定义一个新的接口,编写Feign客户端:
- package com.hmall.cart.client;
-
- import com.hmall.cart.domain.dto.ItemDTO;
- import org.springframework.cloud.openfeign.FeignClient;
- import org.springframework.web.bind.annotation.GetMapping;
- import org.springframework.web.bind.annotation.RequestParam;
-
- import java.util.List;
-
- @FeignClient("item-service") //根据服务名称取注册中心
- public interface ItemClient {
-
- @GetMapping("/items")
- List<ItemDTO> queryItemByIds(@RequestParam("ids") Collection<Long> ids);
- }
这里只需要声明接口,无需实现方法。接口中的几个关键信息:
@FeignClient("item-service")
:声明服务名称
@GetMapping
:声明请求方式
@GetMapping("/items")
:声明请求路径
@RequestParam("ids") Collection<Long> ids
:声明请求参数
List<ItemDTO>
:返回值类型
有了上述信息,OpenFeign就可以利用动态代理帮我们实现这个方法,并且向http://item-service/items
发送一个GET
请求,携带ids为请求参数,并自动将返回值处理为List<ItemDTO>
。
我们只需要直接调用这个方法,即可实现远程调用了。
Feign底层发起http请求,依赖于其它的框架。其底层支持的http客户端实现包括:
HttpURLConnection:默认实现,不支持连接池
Apache HttpClient :支持连接池
OKHttp:支持连接池
因此我们通常会使用带有连接池的客户端来代替默认的HttpURLConnection(效率不好)。比如,我们使用OK Http.
- <!--OK http 的依赖 -->
- <dependency>
- <groupId>io.github.openfeign</groupId>
- <artifactId>feign-okhttp</artifactId>
- </dependency>
在cart-service
的application.yml
配置文件中开启Feign的连接池功能:
- feign:
- okhttp:
- enabled: true # 开启OKHttp功能
Debug方式启动cart-service,请求一次查询我的购物车方法(发起请求),可以发现这里底层的实现已经改为OkHttpClient
OpenFeign只会在FeignClient所在包的日志级别为DEBUG时,才会输出日志。而且其日志级别有4级:
NONE:不记录任何日志信息,这是默认值。
BASIC:仅记录请求的方法,URL以及响应状态码和执行时间
HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息
FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据。
Feign默认的日志级别就是NONE,所以默认我们看不到请求日志。
在hm-api模块下新建一个配置类,定义Feign的日志级别:
接下来,要让日志级别生效,还需要配置这个类。有两种方式:
局部生效:在某个FeignClient
中配置,只对当前FeignClient
生效
@FeignClient(value = "item-service", configuration = DefaultFeignConfig.class)
全局生效:在@EnableFeignClients
中配置,针对所有FeignClient
生效。
@EnableFeignClients(defaultConfiguration = DefaultFeignConfig.class)
日志格式:
- 17:35:32:148 DEBUG 18620 --- [nio-8082-exec-1] com.hmall.api.client.ItemClient : [ItemClient#queryItemByIds] ---> GET http://item-service/items?ids=100000006163 HTTP/1.1
- 17:35:32:148 DEBUG 18620 --- [nio-8082-exec-1] com.hmall.api.client.ItemClient : [ItemClient#queryItemByIds] ---> END HTTP (0-byte body)
- 17:35:32:278 DEBUG 18620 --- [nio-8082-exec-1] com.hmall.api.client.ItemClient : [ItemClient#queryItemByIds] <--- HTTP/1.1 200 (127ms)
- 17:35:32:279 DEBUG 18620 --- [nio-8082-exec-1] com.hmall.api.client.ItemClient : [ItemClient#queryItemByIds] connection: keep-alive
- 17:35:32:279 DEBUG 18620 --- [nio-8082-exec-1] com.hmall.api.client.ItemClient : [ItemClient#queryItemByIds] content-type: application/json
- 17:35:32:279 DEBUG 18620 --- [nio-8082-exec-1] com.hmall.api.client.ItemClient : [ItemClient#queryItemByIds] date: Fri, 26 May 2023 09:35:32 GMT
- 17:35:32:279 DEBUG 18620 --- [nio-8082-exec-1] com.hmall.api.client.ItemClient : [ItemClient#queryItemByIds] keep-alive: timeout=60
- 17:35:32:279 DEBUG 18620 --- [nio-8082-exec-1] com.hmall.api.client.ItemClient : [ItemClient#queryItemByIds] transfer-encoding: chunked
- 17:35:32:279 DEBUG 18620 --- [nio-8082-exec-1] com.hmall.api.client.ItemClient : [ItemClient#queryItemByIds]
- 17:35:32:280 DEBUG 18620 --- [nio-8082-exec-1] com.hmall.api.client.ItemClient : [ItemClient#queryItemByIds] [{"id":100000006163,"name":"巴布豆(BOBDOG)柔薄悦动婴儿拉拉裤XXL码80片(15kg以上)","price":67100,"stock":10000,"image":"https://m.360buyimg.com/mobilecms/s720x720_jfs/t23998/350/2363990466/222391/a6e9581d/5b7cba5bN0c18fb4f.jpg!q70.jpg.webp","category":"拉拉裤","brand":"巴布豆","spec":"{}","sold":11,"commentCount":33343434,"isAD":false,"status":2}]
- 17:35:32:281 DEBUG 18620 --- [nio-8082-exec-1] com.hmall.api.client.ItemClient : [ItemClient#queryItemByIds] <--- END HTTP (369-byte body)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。