java听书项目

news2025/3/12 17:59:10

项目的架构

网关: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)
    @ResponseBody
    public Result error(Exception e){
        e.printStackTrace();
        return Result.fail();
    }

    /**
     * 自定义异常处理方法
     * @param e
     * @return
     */
    @ExceptionHandler(GuiguException.class)
    @ResponseBody
    public Result error(GuiguException e){
        return Result.build(null,e.getCode(), e.getMessage());
    }

    @ExceptionHandler({IllegalArgumentException.class})
    @ResponseBody
    public Result llegalArgumentException(Exception e) {
        log.error("触发异常拦截: " + e.getMessage(), e);
        return Result.build(null, ResultCodeEnum.ARGUMENT_VALID_ERROR);
    }


    @ExceptionHandler(value = BindException.class)
    @ResponseBody
    public 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)
    @ResponseBody
    public 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();
    }

    @Override
    public 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 {

    @Autowired
    private 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 {

    @Autowired
    private BaseCategoryViewMapper baseCategoryViewMapper;

    @Override
    public 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 跟name
                Long 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 name
                    Long 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 c1
         inner join base_category2 c2 on c1.id = c2.category1_id
         inner 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;

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

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

相关文章

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"…

2025百度快排技术分析:模拟点击与发包算法的背后原理

一晃做SEO已经15年了&#xff0c;2025年还有人问我如何做百度快速排名&#xff0c;我能给出的答案就是&#xff1a;做好内容的前提下&#xff0c;多刷刷吧&#xff01;百度的SEO排名算法一直是众多SEO从业者研究的重点&#xff0c;模拟算法、点击算法和发包算法是百度快速排名的…

DeepSeek+即梦 做AI视频

DeepSeek做AI视频 制作流程第一步&#xff1a;DeepSeek 生成视频脚本和分镜 第二步&#xff1a;生成分镜图片绘画提示词第三步&#xff1a;生成分镜图片第四步&#xff1a;使用可灵 AI 工具&#xff0c;将生成的图片转成视频。第五步&#xff1a;剪映成短视频 DeepSeek 真的强&…

【R语言】聚类分析

聚类分析是一种常用的无监督学习方法&#xff0c;是将所观测的事物或者指标进行分类的一种统计分析方法&#xff0c;其目的是通过辨认在某些特征上相似的事物&#xff0c;并将它们分成各种类别。R语言提供了多种聚类分析的方法和包。 方法优点缺点适用场景K-means计算效率高需…

LVS相关原理

一、LVS集群的体系结构 1.1 LVS简介 LVS 是 Linux Virtual Server 的简称&#xff0c;也就是 Linux 虚拟服务器 , 是一个由章文嵩博士发起的自由软件项目&#xff0c;它的官方站点是 www.linuxvirtualserver.org 。现在 LVS 已经是 Linux标准内核的一部分&#xff0c;在Linux2…

linux--关于makefile

makefile文件 可以指定编译顺序&#xff0c;这样方便一个项目的多个文件要编译的挨个操作的麻烦。 makefile文件的命名&#xff1a;makefile 或者 Makefile 必须是这俩&#xff0c;系统才能识别 规则的书写语法如下&#xff1a; 一个makefile内可以有多个规则 目标:依赖a 依…

Java发展史

JavaEE的由来 语言的诞生 Java的前身是Oak语言&#xff0c;其目的是搞嵌入式开发开发智能面包机 叮~~~&#x1f35e;&#x1f35e;&#x1f35e; 产品以失败告终 巅峰 网景公司需要网景浏览器打开网页&#xff0c;Oak->Java&#xff0c;进行前端开发&#xff08;相关技…

Jenkins 新建配置 Freestyle project 任务 六

Jenkins 新建配置 Freestyle project 任务 六 一、新建任务 在 Jenkins 界面 点击 New Item 点击 Apply 点击 Save 回到任务主界面 二、General 点击左侧 Configure Description&#xff1a;任务描述 勾选 Discard old builds Discard old builds&#xff1a;控制何时…

Electron视图进程和主进程通讯

快速创建基于vue的electron项目&#xff1a;quick-start/create-electron - npm 视图线程也就index.html是无法直接访问这个api的&#xff08;如果没有开启视图层访问nodejs的功能&#xff0c;现在几乎没法直接开启&#xff0c;开启了一堆警告提示&#xff09; 所以需要通过r…

【湖南-益阳】《益阳市市本级政府投资信息化项目预算编制与财政评审工作指南》益财评〔2024〕346号-省市费用标准解读系列40

《益阳市市本级政府投资信息化项目预算编制与财政评审工作指南&#xff08;试行&#xff09;》&#xff08;益财评〔2024〕346号&#xff09;由益阳市财政局主编&#xff0c;2024年10月17日起正式执行&#xff0c;本指南主要规定了政府投资信息化项目费用的构成、测量过程和方法…

具身智能在智能巡检机器人中的应用——以开关柜带电操作机器人为例

随着机器人技术和人工智能的迅速发展&#xff0c;具身智能在各行业的应用日益广泛&#xff0c;尤其是在电力行业中的智能巡检领域。传统的电力巡检和维护工作通常需要人工操作&#xff0c;存在着高温、高压、强电磁场等危险环境&#xff0c;且效率较低。开关柜带电操作机器人作…

nuxt中引入element-ui组件控制台报错问题

在使用element-ui组件的外层加一层 <client-only placeholder"Loading..."><van-button type"primary">主要按钮</van-button> </client-only> 实际使用&#xff1a; <div class"tab"><client-only placehol…

Java面试第二山!《计算机网络》!

在 Java 面试里&#xff0c;计算机网络知识是高频考点&#xff0c;今天就来盘点那些最容易被问到的计算机网络面试题&#xff0c;帮你轻松应对面试&#xff0c;也方便和朋友们一起探讨学习。 一、HTTP 和 HTTPS 的区别 1. 面试题呈现 HTTP 和 HTTPS 有什么区别&#xff1f;在…

RocketMQ 5.0安装部署

0.前言 在微服务架构逐渐成为主流的今天&#xff0c;消息队列如同数字世界的快递员&#xff0c;承担着系统间高效通信的重要使命。 Apache RocketMQ 自诞生以来&#xff0c;因其架构简单、业务功能丰富、具备极强可扩展性等特点被众多企业开发者以及云厂商广泛采用。历经十余…

俄罗斯方块游戏完整代码示例

以下是一个基于Cocos Creator引擎开发的俄罗斯方块游戏的完整代码示例。该游戏实现了俄罗斯方块的基本功能&#xff0c;并且代码整合在单个文件中&#xff0c;无需任何外部依赖&#xff0c;可以直接在浏览器中运行。 1. 创建Cocos Creator项目 首先&#xff0c;确保你已经安装了…

Ubuntu22.04配置cuda/cudnn/pytorch

Ubuntu22.04配置cuda/cudnn/pytorch 安装cuda官网下载.run文件并且安装/etc/profile中配置cuda环境变量 cudnn安装官网找cuda版本对应的cudnn版本下载复制相应文件到系统文件中 安装pytorch官网找cuda对应版本的pytorchpython代码测试pytorch-GPU版本安装情况 安装cuda 官网下…

【九】Golang 数组

&#x1f4a2;欢迎来到张胤尘的技术站 &#x1f4a5;技术如江河&#xff0c;汇聚众志成。代码似星辰&#xff0c;照亮行征程。开源精神长&#xff0c;传承永不忘。携手共前行&#xff0c;未来更辉煌&#x1f4a5; 文章目录 数组数组初始化默认初始化显式初始化省略长度初始化索…

百达翡丽(Patek Philippe):瑞士制表的巅峰之作(中英双语)

百达翡丽&#xff08;Patek Philippe&#xff09;&#xff1a;瑞士制表的巅峰之作 在钟表界&#xff0c;百达翡丽&#xff08;Patek Philippe&#xff09; 一直被誉为“世界三大名表”之一&#xff0c;并且常被认为是其中的至高存在。一句“没人能真正拥有一枚百达翡丽&#x…

【学习】软件测试中的分类树法介绍

分类树法是一种软件测试设计技术&#xff0c;它通过构建一个树状结构来组织和展示输入数据的多种组合。这种方法有助于系统地识别和分析可能的测试情况&#xff0c;从而确保对软件进行全面而详尽的测试。分类树法特别适用于具有多个选择或条件的复杂系统&#xff0c;它可以有效…

打造智能语料库:通过Coco AI Server 实现 Notion 笔记 RAG 检索功能

本文将详细介绍如何将 Notion 作为语料库&#xff0c;部署 Coco Server 的 RAG&#xff08;Retrieval-Augmented Generation&#xff09;功能。我们将使用 Easysearch 作为语料库存储 Notion 素材&#xff0c;并通过 ollama 进行 LLM 推理。 1. 环境准备 1.1 启动 Easysearch…