java听书项目
项目的架构

网关:1路由转发 2.认证鉴权(token)3.统一处理(跨域)
Mysql:关系型数据库
ES:搜索数据库
Redis:页面级缓存,会话状态存储
GitLab:私有托管平台
K8S:自动化部署、扩展和管理容器化应用程序的开源系统
Jenkins:自动化部署
1.环境搭建
创建一个父工程:依赖管理 版本锁定
子工程:具体业务实现



Controller编写规则:
1.映射路径
2.请求方式
3.请求参数
4.响应结果-返回值
2.专辑模块
2.1专辑管理添加


1.统一返回结果
package com.atguigu.tingshu.common.result;import lombok.Data;/*** 全局统一返回结果类**/
@Data
public class Result<T> {//返回码private Integer code;//返回消息private String message;//返回数据private T data;public Result(){}// 返回数据protected static <T> Result<T> build(T data) {Result<T> result = new Result<T>();if (data != null)result.setData(data);return result;}public static <T> Result<T> build(T body, Integer code, String message) {Result<T> result = build(body);result.setCode(code);result.setMessage(message);return result;}public static <T> Result<T> build(T body, ResultCodeEnum resultCodeEnum) {Result<T> result = build(body);result.setCode(resultCodeEnum.getCode());result.setMessage(resultCodeEnum.getMessage());return result;}public static<T> Result<T> ok(){return Result.ok(null);}/*** 操作成功* @param data baseCategory1List* @param <T>* @return*/public static<T> Result<T> ok(T data){Result<T> result = build(data);return build(data, ResultCodeEnum.SUCCESS);}public static<T> Result<T> fail(){return Result.fail(null);}/*** 操作失败* @param data* @param <T>* @return*/public static<T> Result<T> fail(T data){Result<T> result = build(data);return build(data, ResultCodeEnum.FAIL);}public Result<T> message(String msg){this.setMessage(msg);return this;}public Result<T> code(Integer code){this.setCode(code);return this;}
}
2. 统一结果状态信息类
package com.atguigu.tingshu.common.result;import lombok.Getter;/*** 统一返回结果状态信息类**/
@Getter
public enum ResultCodeEnum {SUCCESS(200,"成功"),FAIL(201, "失败"),SERVICE_ERROR(2012, "服务异常"),DATA_ERROR(204, "数据异常"),ILLEGAL_REQUEST(205, "非法请求"),REPEAT_SUBMIT(206, "重复提交"),ARGUMENT_VALID_ERROR(210, "参数校验异常"),SIGN_ERROR(300, "签名错误"),SIGN_OVERDUE(301, "签名已过期"),LOGIN_AUTH(208, "未登陆"),PERMISSION(209, "没有权限"),ACCOUNT_ERROR(214, "账号不正确"),PASSWORD_ERROR(215, "密码不正确"),PHONE_CODE_ERROR(215, "手机验证码不正确"),LOGIN_MOBLE_ERROR( 216, "账号不正确"),ACCOUNT_STOP( 216, "账号已停用"),NODE_ERROR( 217, "该节点下有子节点,不可以删除"),VOD_FILE_ID_ERROR( 220, "声音媒体id不正确"),XXL_JOB_ERROR(210, "调度操作失败"),ACCOUNT_LESS(220, "账户余额不足"),ACCOUNT_LOCK_ERROR(221, "账户余额锁定失败"),ACCOUNT_UNLOCK_ERROR(221, "账户余额解锁失败"),ACCOUNT_MINUSLOCK_ERROR(221, "账户余额扣减失败"),ACCOUNT_LOCK_REPEAT(221, "重复锁定"),ACCOUNT_LOCK_RESULT_NULL(221, "锁定账号结果对象为空"),ORDER_SUBMIT_REPEAT(221, "超时或重复提交订单"),NO_BUY_NOT_SEE(230, "未购买不能观看"),EXIST_NO_EXPIRE_LIVE(230, "当前存在未过期直播"),REPEAT_BUY_ERROR(231, "已经购买过该专辑"),;private Integer code;private String message;private ResultCodeEnum(Integer code, String message) {this.code = code;this.message = message;}
}
3.全局异常处理
package com.atguigu.tingshu.common.handler;import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** 全局异常处理类**/
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(Exception.class)@ResponseBodypublic Result error(Exception e){e.printStackTrace();return Result.fail();}/*** 自定义异常处理方法* @param e* @return*/@ExceptionHandler(GuiguException.class)@ResponseBodypublic Result error(GuiguException e){return Result.build(null,e.getCode(), e.getMessage());}@ExceptionHandler({IllegalArgumentException.class})@ResponseBodypublic Result llegalArgumentException(Exception e) {log.error("触发异常拦截: " + e.getMessage(), e);return Result.build(null, ResultCodeEnum.ARGUMENT_VALID_ERROR);}@ExceptionHandler(value = BindException.class)@ResponseBodypublic Result error(BindException exception) {BindingResult result = exception.getBindingResult();Map<String, Object> errorMap = new HashMap<>();List<FieldError> fieldErrors = result.getFieldErrors();fieldErrors.forEach(error -> {log.error("field: " + error.getField() + ", msg:" + error.getDefaultMessage());errorMap.put(error.getField(), error.getDefaultMessage());});return Result.build(errorMap, ResultCodeEnum.ARGUMENT_VALID_ERROR);}@ExceptionHandler(value = MethodArgumentNotValidException.class)@ResponseBodypublic Result error(MethodArgumentNotValidException exception) {BindingResult result = exception.getBindingResult();Map<String, Object> errorMap = new HashMap<>();List<FieldError> fieldErrors = result.getFieldErrors();fieldErrors.forEach(error -> {log.error("field: " + error.getField() + ", msg:" + error.getDefaultMessage());errorMap.put(error.getField(), error.getDefaultMessage());});return Result.build(errorMap, ResultCodeEnum.ARGUMENT_VALID_ERROR);}}
4.自定义全局异常
package com.atguigu.tingshu.common.execption;import com.atguigu.tingshu.common.result.ResultCodeEnum;
import lombok.Data;/*** 自定义全局异常类**/
@Data
public class GuiguException extends RuntimeException {private Integer code;private String message;/*** 通过状态码和错误消息创建异常对象* @param code* @param message*/public GuiguException(Integer code, String message) {super(message);this.code = code;this.message = message;}/*** 接收枚举类型对象* @param resultCodeEnum*/public GuiguException(ResultCodeEnum resultCodeEnum) {super(resultCodeEnum.getMessage());this.code = resultCodeEnum.getCode();this.message = resultCodeEnum.getMessage();}@Overridepublic String toString() {return "GuliException{" +"code=" + code +", message=" + this.getMessage() +'}';}
}
2.1.1 专辑分类列表(三级分类)
1.controller
package com.atguigu.tingshu.album.api;import com.alibaba.fastjson.JSONObject;
import com.atguigu.tingshu.album.service.BaseCategoryService;
import com.atguigu.tingshu.common.result.Result;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.List;
import java.util.Map;
import java.util.Objects;@Tag(name = "分类管理")
@RestController
@RequestMapping(value = "/api/album")
@SuppressWarnings({"all"})
public class BaseCategoryApiController {@Autowiredprivate BaseCategoryService baseCategoryService;/*** @description:* @author: yanhongwei* @date:* @param: * @param null* @return:**//// api/album/category/getBaseCategoryList@GetMapping(value = "/category/getBaseCategoryList")public Result<List<JSONObject>> getBaseCategoryList() {
// public Result<List<Map<String, Object>>> getBaseCategoryList()
// JSONObject jsonObject = new JSONObject();List<JSONObject> categoryList = baseCategoryService.getBaseCategoryList();return Result.ok(categoryList);}}
2.impl
package com.atguigu.tingshu.album.service.impl;import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.tingshu.album.mapper.BaseCategory1Mapper;
import com.atguigu.tingshu.album.mapper.BaseCategory2Mapper;
import com.atguigu.tingshu.album.mapper.BaseCategory3Mapper;
import com.atguigu.tingshu.album.mapper.BaseCategoryViewMapper;
import com.atguigu.tingshu.album.service.BaseCategoryService;
import com.atguigu.tingshu.model.album.BaseCategory1;
import com.atguigu.tingshu.model.album.BaseCategoryView;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.http.client.utils.CloneUtils;
import org.apache.kafka.common.utils.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;@Service
@SuppressWarnings({"all"})
public class BaseCategoryServiceImpl extends ServiceImpl<BaseCategory1Mapper, BaseCategory1> implements BaseCategoryService {@Autowiredprivate BaseCategoryViewMapper baseCategoryViewMapper;@Overridepublic List<JSONObject> getBaseCategoryList() {//创建一级集合,收集数据List<JSONObject> allList = new ArrayList<>();//查询所有分类List<BaseCategoryView> baseCategoryViewsList = baseCategoryViewMapper.selectList(null);//封装if (CollectionUtil.isNotEmpty(baseCategoryViewsList)) {//分组一级分类Map<Long, List<BaseCategoryView>> collect1Map = baseCategoryViewsList.stream().collect(Collectors.groupingBy(BaseCategoryView::getCategory1Id));for (Map.Entry<Long, List<BaseCategoryView>> Entry1 : collect1Map.entrySet()) {//创建一级分类封装对象JSONObject obj1 = new JSONObject();//获取1级id 跟nameLong category1Id = Entry1.getKey();List<BaseCategoryView> category2List = Entry1.getValue();String category1Name = category2List.get(0).getCategory1Name();obj1.put("categoryId", category1Id);obj1.put("categoryName", category1Name);//创建二级分类收集集合List<JSONObject> array2 = new ArrayList<>();//分组二级分类Map<Long, List<BaseCategoryView>> collect2Map = category2List.stream().collect(Collectors.groupingBy(BaseCategoryView::getCategory2Id));for (Map.Entry<Long, List<BaseCategoryView>> Entry2 : collect2Map.entrySet()) {//创建二级分类封装对象JSONObject obj2 = new JSONObject();//获取2级分类id nameLong category2Id = Entry2.getKey();List<BaseCategoryView> category3List = Entry2.getValue();String category2Name = category3List.get(0).getCategory2Name();obj2.put("categoryId", category2Id);obj2.put("categoryName", category2Name);List<JSONObject> array3 = category3List.stream().map(baseCategoryView -> {JSONObject obj3 = new JSONObject();obj3.put("categoryId", baseCategoryView.getCategory3Id());obj3.put("categoryName", baseCategoryView.getCategory3Name());return obj3;}).collect(Collectors.toList());obj2.put("categoryChild", array3);//收集二级分类array2.add(obj2);}//封装2级分类obj1.put("categoryChild", array2);//收集一级分类对象allList.add(obj1);}System.out.println("collect = ");}return allList;}
}
3.mapper
package com.atguigu.tingshu.album.mapper;import com.atguigu.tingshu.model.album.BaseCategoryView;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;@Mapper
public interface BaseCategoryViewMapper extends BaseMapper<BaseCategoryView> {}
4. 视图
创建视图封装一些sql语句,不需要再多表查询了
BaseCategoryView
#创建视图
create view view_category01 as
select c3.id,c1.id category1_id,c1.name category1_name,c2.id category2_id,c2.name category2_name,c3.id category3_id,c3.name category3_name,c3.is_deleted,c3.create_time,c3.update_time
from base_category1 c1inner join base_category2 c2 on c1.id = c2.category1_idinner join base_category3 c3 on c2.id = c3.category2_id

//
//
package com.atguigu.tingshu.model.album;import com.atguigu.tingshu.model.base.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;/*** <p>* BaseCategoryView* </p>** @author atguigu*/
@Data
@Schema(description = "分类视图")
@TableName("base_category_view")
public class BaseCategoryView extends BaseEntity {private static final long serialVersionUID = 1L;@Schema(description = "一级分类编号")@TableField("category1_id")private Long category1Id;@Schema(description = "一级分类名称")@TableField("category1_name")private String category1Name;@Schema(description = "二级分类编号")@TableField("category2_id")private Long category2Id;@Schema(description = "二级分类名称")@TableField("category2_name")private String category2Name;@Schema(description = "三级分类编号")@TableField("category3_id")private Long category3Id;@Schema(description = "三级分类名称")@TableField("category3_name")private String category3Name;}

2.1.2 查询一级分类下面的标签
1.controller
@GetMapping(value = "category/findAttribute/{category1Id}")public Result<List<BaseAttribute>> findAttribute(@PathVariable Long category1Id) {List<BaseAttribute> attributeList = baseCategoryService.findAttribute(category1Id);return Result.ok(attributeList);}
2.impl
package com.atguigu.tingshu.album.service.impl;import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.tingshu.album.mapper.*;
import com.atguigu.tingshu.album.service.BaseCategoryService;
import com.atguigu.tingshu.model.album.BaseAttribute;
相关文章:
java听书项目
项目的架构 网关:1路由转发 2.认证鉴权(token)3.统一处理(跨域) Mysql:关系型数据库 ES:搜索数据库 Redis:页面级缓存,会话状态存储 GitLab:私有托管平台 K8S:自动化部署、扩展和管理容器化应用程序的开源系统 Jenkins:自动化部署 1.环境搭建 创建一个父工程…...
iOS 获取设备占用内存
获取应用占用内存 获取应用进程占用内存 - (NSUInteger)memoryUsage {task_vm_info_data_t vmInfo;mach_msg_type_number_t count TASK_VM_INFO_COUNT;kern_return_t result task_info(mach_task_self(), TASK_VM_INFO, (task_info_t)&vmInfo, &count);if (result …...
C#功能测试
List 内部元素为引用 src[0]为"11" List<Source> src new List<Source>(); src.Add(new Source() { Name "1", Age 1, Description "1" }); src.Add(new Source() { Name "2", Age 2, Description "2"…...
js第八题
题八:滚动弹幕 要求: 1.页面上漂浮字体大小不一、颜色不一,从左向右滚动的弹幕; 2.底部中间有一个发送功能,可以发送新的弹幕; 3.底部的发送部分可以向下收起和弹出。 html <div id"danmu-con…...
第35次CCF计算机软件能力认证 python 参考代码
题目列表1. 密码2. 字符串变换3. 补丁应用4. 通讯延迟5. 木板切割题目列表 第35次CCF计算机软件能力认证 1. 密码 n = int(input()) for _ in range(n):s =...
2025百度快排技术分析:模拟点击与发包算法的背后原理
一晃做SEO已经15年了,2025年还有人问我如何做百度快速排名,我能给出的答案就是:做好内容的前提下,多刷刷吧!百度的SEO排名算法一直是众多SEO从业者研究的重点,模拟算法、点击算法和发包算法是百度快速排名的…...
国产FPGA开发板选择
FPGA开发板是学习和开发FPGA的重要工具,选择合适的开发板对学习效果和开发效率至关重要。随着国产FPGA的发展,淘宝上的许多FPGA开发板店铺也开始进行国产FPGA的设计和销售,本文将对国产FPGA和相关店铺做个简单梳理,帮助有需要使用…...
DeepSeek+即梦 做AI视频
DeepSeek做AI视频 制作流程第一步:DeepSeek 生成视频脚本和分镜 第二步:生成分镜图片绘画提示词第三步:生成分镜图片第四步:使用可灵 AI 工具,将生成的图片转成视频。第五步:剪映成短视频 DeepSeek 真的强&…...
【R语言】聚类分析
聚类分析是一种常用的无监督学习方法,是将所观测的事物或者指标进行分类的一种统计分析方法,其目的是通过辨认在某些特征上相似的事物,并将它们分成各种类别。R语言提供了多种聚类分析的方法和包。 方法优点缺点适用场景K-means计算效率高需…...
LVS相关原理
一、LVS集群的体系结构 1.1 LVS简介 LVS 是 Linux Virtual Server 的简称,也就是 Linux 虚拟服务器 , 是一个由章文嵩博士发起的自由软件项目,它的官方站点是 www.linuxvirtualserver.org 。现在 LVS 已经是 Linux标准内核的一部分,在Linux2…...
linux--关于makefile
makefile文件 可以指定编译顺序,这样方便一个项目的多个文件要编译的挨个操作的麻烦。 makefile文件的命名:makefile 或者 Makefile 必须是这俩,系统才能识别 规则的书写语法如下: 一个makefile内可以有多个规则 目标:依赖a 依…...
从2025年起:数字化建站PHP 8.1应成为建站开发的基准线
在数字化浪潮席卷全球的今天,PHP语言仍然保持着Web开发领域的核心地位。根据W3Techs最新统计,PHP驱动着全球78.9%的已知服务端网站。当时间指向2025年,这个拥有28年历史的编程语言将迎来新的发展里程碑——PHP 8.1版本应成为网站开发的最低基准要求,这不仅是技术迭代的必然…...
根据deepseek模型微调训练自动驾驶模型及数据集的思路
以下是使用DeepSeek模型微调训练自动驾驶模型的详细步骤和代码示例。本流程假设你已有自动驾驶领域的数据集(如驾驶指令、传感器数据等),并基于PyTorch框架实现。 Step 1: 环境准备 # 安装依赖库 pip install torch transformers datasets n…...
蓝桥杯篇---IAP15F2K61S2定时器
文章目录 前言简介定时器的工作模式1.模式02.模式13.模式24.模式3 定时器的寄存器1.TMOD2.TCON3.THO/TL04.TH1/TL1 定时器的使用步骤1.配置TMOD2.设置初值3.启动定时器4.使能中断5.编写中断服务函数 示例代码:定时器的基本使用代码说明示例代码:定时器1用…...
Java发展史
JavaEE的由来 语言的诞生 Java的前身是Oak语言,其目的是搞嵌入式开发开发智能面包机 叮~~~🍞🍞🍞 产品以失败告终 巅峰 网景公司需要网景浏览器打开网页,Oak->Java,进行前端开发(相关技…...
Jenkins 新建配置 Freestyle project 任务 六
Jenkins 新建配置 Freestyle project 任务 六 一、新建任务 在 Jenkins 界面 点击 New Item 点击 Apply 点击 Save 回到任务主界面 二、General 点击左侧 Configure Description:任务描述 勾选 Discard old builds Discard old builds:控制何时…...
Electron视图进程和主进程通讯
快速创建基于vue的electron项目:quick-start/create-electron - npm 视图线程也就index.html是无法直接访问这个api的(如果没有开启视图层访问nodejs的功能,现在几乎没法直接开启,开启了一堆警告提示) 所以需要通过r…...
【湖南-益阳】《益阳市市本级政府投资信息化项目预算编制与财政评审工作指南》益财评〔2024〕346号-省市费用标准解读系列40
《益阳市市本级政府投资信息化项目预算编制与财政评审工作指南(试行)》(益财评〔2024〕346号)由益阳市财政局主编,2024年10月17日起正式执行,本指南主要规定了政府投资信息化项目费用的构成、测量过程和方法…...
springboot+mybatis按条件分页查询多张表
文章目录 背景方案推荐创建 DTO创建 Mapper创建对应 xmlService 代码 背景 假如同 mysql 数据源下有如下几张表: 用户基础信息表用户地址表用户学历信息表 我希望做分页查询用户数据,用户数据为各个表内信息的汇总,并且这个分页查询会根据…...
探索Java中的集合类_特性与使用场景
1. 引言 1.1 Java集合框架概述 Java集合框架(Java Collections Framework, JCF)是Java中用于存储和操作一组对象的类和接口的统称。它提供了多种数据结构来满足不同的需求,如列表、集合、映射等。JCF的核心接口包括Collection、List、Set、Queue和Map,以及它们的各种实现…...
具身智能在智能巡检机器人中的应用——以开关柜带电操作机器人为例
随着机器人技术和人工智能的迅速发展,具身智能在各行业的应用日益广泛,尤其是在电力行业中的智能巡检领域。传统的电力巡检和维护工作通常需要人工操作,存在着高温、高压、强电磁场等危险环境,且效率较低。开关柜带电操作机器人作…...
C#+SqlSugar实现主从库读写分离
在使用 **SqlSugar** 进行分库操作时,可以通过配置多个数据库连接,并根据业务逻辑动态切换数据库。以下是一个完整的分库示例,展示如何实现分库功能。 --- ### **1. 安装 NuGet 包** 安装 SqlSugarCore: bash dotnet add packag…...
Webpack 基础入门
一、Webpack 是什么 Webpack 是一款现代 JavaScript 应用程序的静态模块打包工具。在 Web 开发中,我们的项目会包含各种类型的文件,如 JavaScript、CSS、图片等。Webpack 可以将这些文件打包成一个或多个文件,以便在浏览器中高效加载。它就像…...
nuxt中引入element-ui组件控制台报错问题
在使用element-ui组件的外层加一层 <client-only placeholder"Loading..."><van-button type"primary">主要按钮</van-button> </client-only> 实际使用: <div class"tab"><client-only placehol…...
【机器学习】线性回归 多项式线性回归
【机器学习系列】 KNN算法 KNN算法原理简介及要点 特征归一化的重要性及方式线性回归算法 线性回归与一元线性回归 线性回归模型的损失函数 多元线性回归 多项式线性回归 多项式线性回归 V1.0多项式回归多项式回归的公式 特征代换超越函数作为特征向量维度 V1.0 多项式回归 …...
Java面试第二山!《计算机网络》!
在 Java 面试里,计算机网络知识是高频考点,今天就来盘点那些最容易被问到的计算机网络面试题,帮你轻松应对面试,也方便和朋友们一起探讨学习。 一、HTTP 和 HTTPS 的区别 1. 面试题呈现 HTTP 和 HTTPS 有什么区别?在…...
RocketMQ 5.0安装部署
0.前言 在微服务架构逐渐成为主流的今天,消息队列如同数字世界的快递员,承担着系统间高效通信的重要使命。 Apache RocketMQ 自诞生以来,因其架构简单、业务功能丰富、具备极强可扩展性等特点被众多企业开发者以及云厂商广泛采用。历经十余…...
go语言并发的最佳实践
Go 语言的并发模型是其最强大的特性之一,基于 CSP(Communicating Sequential Processes)理论,通过 goroutine 和 channel 实现轻量级并发. 一、并发核心概念 1. Goroutine 在 Go 语言中,Goroutine 是实现并发编程的…...
俄罗斯方块游戏完整代码示例
以下是一个基于Cocos Creator引擎开发的俄罗斯方块游戏的完整代码示例。该游戏实现了俄罗斯方块的基本功能,并且代码整合在单个文件中,无需任何外部依赖,可以直接在浏览器中运行。 1. 创建Cocos Creator项目 首先,确保你已经安装了…...
Ubuntu22.04配置cuda/cudnn/pytorch
Ubuntu22.04配置cuda/cudnn/pytorch 安装cuda官网下载.run文件并且安装/etc/profile中配置cuda环境变量 cudnn安装官网找cuda版本对应的cudnn版本下载复制相应文件到系统文件中 安装pytorch官网找cuda对应版本的pytorchpython代码测试pytorch-GPU版本安装情况 安装cuda 官网下…...
