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

news2025/1/12 18:07:12

文章目录

  • 一,品牌查询接口的后台实现
  • 二,编码经验总结
    • 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.coloradmin.cn/o/1959472.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

BUGKU-CTF-WEB 源代码

URL解码平台&#xff1a;https://www.iamwawa.cn/urldecode.html 看看源码 存在script&#xff1a; <script> var p1 %66%75%6e%63%74%69%6f%6e%20%63%68%65%63%6b%53%75%62%6d%69%74%28%29%7b%76%61%72%20%61%3d%64%6f%63%75%6d%65%6e%74%2e%67%65%74%45%6c%65%6d%65…

基于Gunicorn、Flask和Docker的高并发应用部署指南

一、简介 随着互联网的发展&#xff0c;现代应用程序需要处理越来越多的并发请求&#xff0c;高并发应用程序的需求促使开发者寻找可靠且高效的解决方案来管理和优化服务器负载。在这种背景下&#xff0c;Gunicorn、Flask和Docker成为构建和部署高并发应用的理想组合。 首先&…

一分钟了解VMware虚拟机三种网络模式区别

VMware虚拟机提供了三种主要的网络模式&#xff0c;分别是桥接模式&#xff08;Bridged Mode&#xff09;、网络地址转换模式&#xff08;NAT Mode&#xff09;和仅主机模式&#xff08;Host-Only Mode&#xff09;。这三种模式各有其特点和适用场景&#xff0c;以下是对它们之…

mysql的回表查询

大家好&#xff0c;我是程序媛雪儿&#xff0c;今天咱们聊mysql的回表查询&#xff0c;在mysql慢查询那篇文章中我们知道&#xff0c;当extra那一列显示&#xff0c;Using index condition&#xff0c;表示直接使用了索引&#xff0c;但是需要回表查询数据&#xff0c;这种情况…

GaussDB关键技术原理|高可用:逻辑复制

GaussDB关键技术原理|高可用&#xff1a;DCF&双集群容灾从DCF与双集群容灾技术两方面对GaussDB的高可用能力进行了介绍&#xff0c;本篇将从逻辑复制方面继续解读GaussDB高可用能力。 目录 3 逻辑复制 3.1 基本概念 3.2 逻辑解码 3.3 备机解码 3.4 并行解码 3.5 一致…

docker中使用nginx配置https访问

1.申请ssl证书: https://www.joyssl.com/certificate/select/free.html 免费的ssl证书&#xff08;一般有效期是90天&#xff09;到期后&#xff0c;则需要重新申请 申请完之后下载证书 然后到验证信息中 然后到自己的域名控制台 添加解析记录(这是ssl相关的,后面还要添加自…

电测量数据交换DLMSCOSEM组件第53部分:DLMSCOSEM应用层(上)

1.范围 本部分规定了DLMS/COSEM客户机和服务器的DLMS/COSEM应用层的结构、服务和协议。同时,定义规则规定DLMS/COSEM通信配置。 它定义了用于建立和释放应用程序连接的服务,以及用于访问GB/T17215.662中使用逻辑名称(LN)或短名称(SN)引用定义的COSEM接口对象的方法和属性…

Django实战:开启数字化任务管理的新纪元

&#x1f680; Django实战&#xff1a;开启数字化任务管理的新纪元 &#x1f310; &#x1f4d6; 引言 在数字化转型的浪潮中&#xff0c;任务管理的智能化成为提升组织效能的关键。今天&#xff0c;我将带领大家深入了解我们最新开发的OFTS系统——一款创新的组织任务管理软…

【算法刷题日志】信封嵌套问题

俄罗斯套娃信封问题 信封嵌套问题可以转换为最长递增子序列的问题。每次合法的嵌套都是大的套小的&#xff0c;就相当于找一个最长递增子序列&#xff0c;长度就是能嵌套的最多个数&#xff0c;所以我们可以先对宽度进行升序排序&#xff0c;如果宽度相同就按高度降序排序&…

动态SLAM:如何判断一个特征是动态特征(对极几何)

文章目录 1.什么是极线、极点和极面2.如何判断其为动态点特征3.如何判断其为动态线特征 1.什么是极线、极点和极面 由图可知&#xff0c;C1,C2,X(X1,X2)组成了一个三角平面&#xff0c;这个三角所在的平面就是极面 在这个极平面中&#xff0c;和成像平面相交的线是极线&#xf…

“2024青岛软博会”助力打造“世界工业互联网之都”

在数字经济浪潮的推动下&#xff0c;青岛国际软件融合创新展&#xff08;简称青岛软博会&#xff09;作为年度科技盛宴&#xff0c;不仅全面展示了青岛软件产业发展的辉煌成果&#xff0c;更聚焦于工业软件这一核心领域&#xff0c;为青岛乃至全国的软件产业转型升级注入了强劲…

【gmid】设计一个CS放大器

1.电路原理图 & 电路指标 设计指标&#xff1a; 负载电容CL2 pF增益带宽积GBW100 MHz增益 Av10gm/Id10 2. 根据电路指标进行 手算 2.1 确定 gm 2.2 确定负载电阻 RD 2.3 确定 Id Vov > 150mVgm/id < 10MOS管处于 强反型区Vov < 0gm/id 较大MOS管处于 亚阈值区0…

深入解析 Go 语言 GMP 模型:并发编程的核心机制

前言 本章是Go并发编程的起始篇章&#xff0c;在未来几篇文章中我们会围绕Go并发编程进行理论和实战的学习&#xff0c;欢迎关注我哦&#xff01; 本章主要以介绍GMP模型为主&#xff0c;偏向于面试和八股&#xff0c;目的是让小伙伴们注重于知识本身&#xff0c;面向面试&am…

昇思25天学习打卡营第20天|CV-ResNet50图像分类

打卡 目录 打卡 图像分类 ResNet网络介绍 数据集准备与加载 可视化部分数据集 残差网络构建 Building Block 结构 代码实现 Bottleneck结构 代码实现 构建ResNet50网络 代码定义 模型训练与评估 可视化模型预测 重点&#xff1a;通过网络层数加深&#xff0c;感知…

Windows系统使用Docker搭建Focalboard项目管理工具详细教程

目录 前言 1. 使用Docker本地部署Focalboard 1.1 在Windows中安装 Docker 1.2 使用Docker部署Focalboard 2. 安装Cpolar内网穿透工具 3. 实现公网访问Focalboard 4. 固定Focalboard公网地址 前言 作者简介&#xff1a; 懒大王敲代码&#xff0c;计算机专业应届生 今天给…

TCP为什么需要四次挥手?

tcp为什么需要四次挥手&#xff1f; 答案有两个&#xff1a; 1.将发送fin包的权限交给被动断开发的应用层去处理&#xff0c;也就是让程序员处理 2.接第一个答案&#xff0c;应用层有了发送fin的权限&#xff0c;可以在发送fin前继续向对端发送消息 为了搞清楚这个问题&…

【java】力扣 反转字符串中的单词

目录 题目描述题目描述思路代码 题目描述 151.反转字符串中的单词 题目描述 思路 主要是利用快慢指针和字符串的截取 还要了解去掉首尾空格的函数是trim 那s"the sky is blue"举例 这个例子是没有首尾空格的&#xff0c;以防万一&#xff0c;我们不管有没有&#…

第06课 Scratch入门篇:侏罗纪公园

侏罗纪公园 入门篇适合新手&#xff0c;如您已经学过&#xff0c;可以忽略本节课&#xff01; 一、故事背景&#xff1a; 在遥远的过去&#xff0c;有一个充满神秘与惊奇的时代——侏罗纪。那是一个恐龙称霸的时代&#xff0c;各种巨大的生物在这片古老的土地上留下了它们的足…

APT 安装软件详细教程

文章目录 APT 安装软件详细教程APT 概述APT 的基本命令APT 命令详解安装软件包更新和升级软件包删除软件包搜索和查找软件包管理软件包依赖清理软件包缓存APT 配置软件源配置自定义软件源常见问题及解决方案解决软件包依赖问题处理软件源错误其他常见问题使用 APT 的最佳实践总…

【设计模式】工厂模式详解

1.简介 工厂模式是一种创建型设计模式&#xff0c;通过提供一个接口或抽象类来创建对象&#xff0c;而不是直接实例化对象。工厂模式的主要思想是将对象的创建与使用分离&#xff0c;使得创建对象的过程更加灵活和可扩展。 工厂模式主要包括以下角色&#xff1a; 抽象工厂&a…