当前位置: 首页 > news >正文

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)
    @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;

相关文章:

  • 【复现DeepSeek-R1之Open R1实战】系列4:跑通GRPO!
  • 【Vue3源码解析】应用实例创建及页面渲染
  • 后端生成二维码,前端请求接口生成二维码并展示,且多个参数后边的参数没有正常传输问题处理
  • 【MySQL】我在广州学Mysql 系列——Mysql 日志管理详解
  • 0079.基于springboot+vue的学科竞赛管理系统+论文
  • Linux探秘坊-------8.进程详解
  • 【性能测试】如何理解“10个线程且10次循环“的请求和“100线程且1次循环“的请求
  • 基于TCP与UDP协议的性能测试研究
  • 【SpringBoot苍穹外卖】debugDay04
  • 计算机专业知识【 轻松理解数据库四大运算:笛卡尔积、选择、投影与连接】
  • HDFS是如何存储和管理大数据
  • JavaScript 开发秘籍:日常总结与实战技巧-1
  • JS宏进阶:递归练习
  • Ubuntu 下 nginx-1.24.0 源码分析 - NGX_MAX_ALLOC_FROM_POOL
  • 游戏引擎学习第107天
  • ELK8.17部署(Ubantu24x64)
  • Go 语言编译的原理
  • 【R语言】聚类分析
  • 共享经济视角下的2+1链动模式开源AI智能名片S2B2C商城小程序应用探究
  • 基于SpringBoot的“高校创新创业课程体系”的设计与实现(源码+数据库+文档+PPT)
  • 舞者王佳俊谈“与AI共舞”:像多了一个舞伴,要考虑它的“感受”
  • 金融月评|尽早增强政策力度、调整施策点
  • 混乱的5天:俄乌和谈如何从充满希望走向“卡壳”
  • 四川内江警方通报一起持刀伤人致死案:因车辆停放引起,嫌犯被抓获
  • 《上海市建筑信息模型技术应用指南(2025版)》发布
  • 腾讯一季度净利增14%:AI直接拉动广告收入增长,王者荣耀流水创新高