谷粒商城实战笔记-84-商品服务-API-新增商品-获取分类关联的品牌

文章目录

  • 一,品牌查询接口的后台实现
  • 二,编码经验总结
    • 1,Controller层的作用
      • 1.1 参数处理
      • 1.2 调用Service
      • 1.3 处理Service返回结果
      • 实例
    • 2,VO的封装时机
    • 3,Service中最好注入Service,不要直接依赖Dao
  • 问题记录

本节的主要内容是给发布商品-基本信息模块的品牌查询提供后台实现。

一,品牌查询接口的后台实现

在这里插入图片描述
选择品牌时,查询后台获取所选分类下的品牌,以列表的方式展示。

因为是根据分类查询品牌,所以在CategoryBrandRelationController中开发这个接口。

	@GetMapping("/brands/list")public R relationBrandsList(@RequestParam(value = "catId",required = true)Long catId){List<BrandEntity> vos = categoryBrandRelationService.getBrandsByCatId(catId);List<BrandVo> collect = vos.stream().map(item -> {BrandVo brandVo = new BrandVo();brandVo.setBrandId(item.getBrandId());brandVo.setBrandName(item.getName());return brandVo;}).collect(Collectors.toList());return R.ok().put("data",collect);}

后台的Service实现如下。

	public List<BrandEntity> getBrandsByCatId(Long catId) {List<CategoryBrandRelationEntity> catelogId = relationDao.selectList(new QueryWrapper<CategoryBrandRelationEntity>().eq("catelog_id", catId));List<BrandEntity> collect = catelogId.stream().map(item -> {Long brandId = item.getBrandId();BrandEntity byId = brandService.getById(brandId);return byId;}).collect(Collectors.toList());return collect;}

二,编码经验总结

1,Controller层的作用

Controller层不做具体的业务处理,业务处理放在Service层,Controller的主要逻辑包括三个部分:

  • 参数处理,如各种参数校验
  • 调用Service接口
  • 封装返回结果

1.1 参数处理

  • 获取请求参数
    • 使用@RequestParam注解获取请求参数,例如获取分类ID(categoryId)。
    • 参数设置为必须传递(required=true),并可以指定默认值。
  • 数据校验
    • 在Controller中进行数据校验,确保接收到的数据是合法的。
    • 可以使用HTTP状态码(如403)来返回错误信息,如果参数不符合要求。
  • 处理复杂参数
    • 对于复杂的参数,Controller可以进行额外的校验和处理,确保数据的正确性。

1.2 调用Service

  • 调用Service方法
    • Controller调用Service的方法来处理业务逻辑。例如,调用CategoryBrandRelationServicegetBrandsByCategoryId方法来获取品牌信息。
  • 传递参数
    • 将从请求中获取的参数传递给Service方法。
  • 业务逻辑分离
    • Controller应尽量只处理请求和响应,具体的业务逻辑应由Service处理,避免在Controller中编写复杂的业务逻辑代码。

1.3 处理Service返回结果

  • 封装返回数据
    • Service返回的数据通常是一个完整的实体类或集合。Controller需要将这些数据封装成VO(Value Object),以便前端页面使用。例如,创建BrandVO来封装品牌ID和品牌名称。
    • 使用List<BrandVO>返回品牌的ID和名称,而不是直接返回实体类。
  • 数据转换
    • 将Service返回的实体类转换为VO,使用stream()map()方法进行转换。
  • 处理复杂数据
    • 如果Service返回的数据包含复杂的关联信息,Controller需要进行适当的处理和转换,确保返回给前端的数据是简洁和易于理解的。
  • 错误处理
    • 如果Service处理过程中出现错误,Controller应捕获这些错误,并返回相应的错误信息或状态码,以便前端页面能够正确显示错误信息。

实例

  • 获取分类关联品牌信息
    1. 参数处理:使用@RequestParam获取categoryId,并进行校验。
    2. 调用Service:调用CategoryBrandRelationServicegetBrandsByCategoryId方法,传递categoryId
    3. 处理返回结果:将Service返回的品牌实体类集合转换为List<BrandVO>,并返回给前端页面。

通过这种方式,Controller能够清晰地处理请求、调用Service、并正确地处理和返回数据,确保系统的稳定性和可维护性。

2,VO的封装时机

VO的封装应该在Controller层或者Controller直接调用的Service方法,不宜在DAO或者靠近DAO的方法中过早封装VO,因为VO和前端密切关联,具有一定的特殊性,可复用性不强。

底层方法应该尽量用Entity

先查出Entity,然后封装为VO,尽量在高层接口封装VO,底层接口统一规范,便于复用。

如下方法,getBrandsByCatId方法返回的是Entity,而不是VO,使得这个方法可以被其他方法复用。

	@GetMapping("/brands/list")public R relationBrandsList(@RequestParam(value = "catId",required = true)Long catId){List<BrandEntity> vos = categoryBrandRelationService.getBrandsByCatId(catId);List<BrandVo> collect = vos.stream().map(item -> {BrandVo brandVo = new BrandVo();brandVo.setBrandId(item.getBrandId());brandVo.setBrandName(item.getName());return brandVo;}).collect(Collectors.toList());return R.ok().put("data",collect);}

3,Service中最好注入Service,不要直接依赖Dao

在软件设计中,通常推荐服务层(Service Layer)之间相互依赖而不是直接依赖数据访问层(DAO Layer)。这样做有助于解耦系统各部分,提高可测试性和维护性。

假设有一个简单的应用,该应用包含用户管理和订单管理两个功能。在这个应用中,有以下类:

  1. UserDao - 负责数据库操作,如查询、更新用户信息等。
  2. OrderDao - 负责数据库操作,如查询、更新订单信息等。
  3. UserService - 提供用户相关的业务逻辑。
  4. OrderService - 提供订单相关的业务逻辑。

在这个示例中,OrderService 依赖于 UserService 而不是直接依赖 UserDao。这样的设计有几个好处:

  1. 解耦 - 如果将来需要更换不同的数据库实现或者改变用户数据的存储方式,只需要更改 UserDao 的实现,而不需要更改 OrderService 或者其他任何依赖于 UserService 的地方。
  2. 易于测试 - 可以通过模拟(Mocking)UserService 来测试 OrderService,而不必关心底层的数据访问细节。
  3. 更好的灵活性 - 如果需要增加额外的业务逻辑,比如权限验证、缓存等,可以直接在 UserService 中实现,而不会影响到 OrderService

这种分层的设计模式不仅有助于保持代码的整洁和可维护性,还可以更好地适应未来的需求变化。

问题记录

这一节遇到前端选择分类后,品牌查询未被触发的问题,记录在博客的3/4两个问题中https://blog.csdn.net/epitomizelu/article/details/140569196。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/386685.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue2 vue3 props 的处理机制

在 Vue 2 中&#xff0c;props 是单向数据流&#xff0c;父组件向子组件传递的 props 默认情况下是不具有响应式特性的。这意味着当父组件的数据发生变化时&#xff0c;如果传递给子组件的 props 发生变化&#xff0c;子组件不会自动更新视图。 具体来说&#xff0c;在 Vue 2 …

增量学习中Task incremental、Domain incremental、Class incremental 三种学习模式的概念及代表性数据集?

1 概念 在持续学习领域&#xff0c;Task incremental、Domain incremental、Class incremental 是三种主要的学习模式&#xff0c;它们分别关注不同类型的任务序列和数据分布变化。 1.1 Task Incremental Learning (Task-incremental) 任务增量学习&#xff0c;也称为任务增…

【论文共读】【翻译】【GAN】Generative Adversarial Nets

论文原文地址&#xff1a;https://arxiv.org/pdf/1406.2661 翻译&#xff1a;Generative Adversarial Nets 生成对抗网络 0. 摘要 提出了一种新的对抗过程估计生成模型的框架&#xff0c;其中我们同时训练两个模型&#xff1a;一个是捕获数据分布的生成模型G&#xff0c;另一…

燃气安全无小事,一双专业劳保鞋让你步步安心!

燃气作为我们日常生活中不可或缺的能源之一&#xff0c;为我们的生活提供了极大便利&#xff0c;其安全性往往被忽视在忙碌的日常生活背后。然而&#xff0c;燃气事故一旦发生&#xff0c;后果往往不堪设想&#xff0c;轻则财产损失&#xff0c;重则危及生命。因此&#xff0c;…

dockerfile部署镜像 ->push仓库 ->虚拟机安装建木 ->自动部署化 (详细步骤)

目录 创建私服仓库 vi /etc/docker/daemon.json vim deploy.sh判断脚本内容 创建 建木 后端部署 命名空间 设置密码用户名 创建git仓库 gitignore文件内容 图形项目操作 git maven docker镜像 点击流程日志 vim /etc/docker/daemon.json 执行部署脚本 ip 开发…

Linux网络——深入理解传入层协议TCP

目录 一、前导知识 1.1 TCP协议段格式 1.2 TCP全双工本质 二、三次握手 2.1 标记位 2.2 三次握手 2.3 捎带应答 2.4 标记位 RST 三、四次挥手 3.1 标记位 FIN 四、确认应答(ACK)机制 五、超时重传机制 六 TCP 流量控制 6.1 16位窗口大小 6.2 标记位 PSH 6.3 标记…

Jackson常用注解详解

Hi &#x1f44b;, Im shy 有人见尘埃&#xff0c;有人见星辰 Jackson常用注解详解 文章目录 Jackson常用注解详解0. 引入依赖1. JsonProperty2. JsonIgnore3. JsonFormat4. JsonInclude5. JsonCreator6. JsonValue7. JsonIgnoreProperties结论 Jackson是Java生态系统中广泛…

Redis学习[1] ——基本概念和数据类型

Redis学习[1] ——基本概念和数据类型 一、Redis基础概念 1.1 Redis是什么&#xff0c;有什么特点&#xff1f; Redis是一个基于**内存的数据库&#xff0c;因此读写速度非常快**&#xff0c;常用作缓存、消息队列、分布式锁和键值存储数据库。支持多种数据结构&#xff1a;…

大数据与人工智能:数据隐私与安全的挑战_ai 和 数据隐私

前言 1.背景介绍 随着人工智能(AI)和大数据技术的不断发展&#xff0c;我们的生活、工作和社会都在不断变化。这些技术为我们提供了许多好处&#xff0c;但同时也带来了一系列挑战&#xff0c;其中数据隐私和安全是最为关键的之一。数据隐私和安全问题的出现&#xff0c;主要…

分布式锁的三种实现方式:Redis、基于数据库和Zookeeper

分布式锁的实现 操作共享资源&#xff1a;例如操作数据库中的唯一用户数据、订单系统、优惠券系统、积分系统等&#xff0c;这些系统需要修改用户数据&#xff0c;而多个系统可能同时修改同一份数据&#xff0c;这时就需要使用分布式锁来控制访问&#xff0c;防止数据不一致。…

angular入门基础教程(九)依赖注入(DI)

依赖注入 Angular 中的依赖注入&#xff08;DI&#xff09;是框架最强大的特性之一。可以将依赖注入视为 Angular 在运行时为你的应用 提供所需资源的能力。依赖项可以是服务或其他资源。 使用服务的一种方式是作为与数据和 API 交互的方式。为了使服务可重用&#xff0c;应该…

实战:ZooKeeper 操作命令和集群部署

ZooKeeper 操作命令 ZooKeeper的操作命令主要用于对ZooKeeper服务中的节点进行创建、查看、修改和删除等操作。以下是一些常用的ZooKeeper操作命令及其说明&#xff1a; 一、启动与连接 启动ZooKeeper服务器&#xff1a; ./zkServer.sh start这个命令用于启动ZooKeeper服务器…

SSM学习9:SpringBoot简介、创建项目、配置文件、多环节配置

简介 SpringBoot式用来简化Spring应用的初始搭建以及开发过程的一个框架 项目搭建 File -> New -> Project 选中pom.xml文件&#xff0c;设置为maven项目 项目启动成功 可以访问BasicController中的路径 配置文件 在resources目录下 application.properties 默…

Linux——管理本地用户和组(详细介绍了Linux中用户和组的概念及用法)

目录 一、用户和组概念 &#xff08;一&#xff09;、用户的概念 &#xff08;二&#xff09;、组的概念 补充组 主要组 二、获取超级用户访问权限 &#xff08;一&#xff09;、su 命令和su -命令 &#xff08; 二&#xff09;、sudo命令 三、管理本地用户账户 &…

WPF---Prism视图传参

Prism视图传参方式。 实际应用场景 点击tabitem中的列表数据&#xff0c;同步更新到ListStatic Region对应的界面。目前用两种方式实现了传参数据同步。 第一&#xff0c;事件聚合器&#xff08;EventAggregator&#xff09; 1. 定义事件 创建一个事件类&#xff0c;用于传…

微信小程序配置访问服务器失败所发现的问题及解决方案

目录 事前现象问题1&#xff1a;问题现象&#xff1a;问题分析&#xff1a; 问题2&#xff1a;问题现象&#xff1a;问题分析&#xff1a;解决方案&#xff1a; 事后现象 事前现象 问题1&#xff1a; 问题现象&#xff1a; 在本地调试时&#xff0c;一切顺利&#xff0c;但一…

JAVA开源的html转pdf、png转pdf项目

总览 Open HTML to PDF是一个纯Java库,用于使用CSS 2.1(以及更高版本的标准)对合理子集的格式良好的XML/XHTML(甚至一些HTML5)进行布局和格式化,输出为PDF或图像。 使用该库生成漂亮的PDF文档。但请注意,您不能将现代HTML5+直接应用于该引擎并期望获得出色的结果。您必…

妈吖,看过这个大厂的oracle主键自增,我的信心暴增!信创,国产数据库也能行。

创作不易 只因热爱!! 热衷分享&#xff0c;一起成长! “你的鼓励就是我努力付出的动力” 1.数据库oracle自增主键字段思维导图 在Oracle数据库中&#xff0c;可以通过创建序列&#xff08;SEQUENCE&#xff09;来实现自增功能。但也可以不在数据库中实现&#xff0c;而是通过程…

Docker中使用自定义网络方式实现Redis集群部署与测试流程

场景 Docker中Docker网络-理解Docker0与自定义网络的使用示例&#xff1a; Docker中Docker网络-理解Docker0与自定义网络的使用示例-CSDN博客 参考上面的流程实现自定义网络的实现。 下面记录其应用实例&#xff0c;使用Docker的自定义网络实现redis集群部署。 注&#xf…

vue3数据结构的渲染01

处理数据&#xff1a; //现有原始数据showCertificateUrl “url01;url02” 使用以下代码将两条通过分号";"分割的url进行处理 const parseUrls () > {urls.value [];// 每次重新赋值前一定要清空之前的旧数据&#xff01;if (!showCertificateUrl.value) {retu…