前言
博主介绍:优快云特邀作者、985高校计算机专业毕业、现任某互联网大厂高级全栈开发工程师、Gitee/掘金/华为云/阿里云/GitHub等平台持续输出高质量技术内容、深耕Java、小程序、前端、python等技术领域和毕业项目实战,以及程序定制化开发、全栈讲解。
💯文末获取源码+数据库💯
感兴趣的可以先收藏起来,还有大家在毕设选题,项目以及论文编写等相关问题都可以找我咨询,希望帮助更多的人。
详细视频演示
具体实现截图
后端框架SpringBoot
Spring Boot允许开发者快速构建出既可以独立运行又满足生产级别标准的Spring基础应用程序。此框架通过提供一系列便捷的工具和服务,极大地促进了基于Spring的应用开发工作的效率和质量。通过提供一系列大型项目中常用的默认配置,Spring Boot最大化减少配置文件的使用,开发者能够迅速启动和运行Spring应用程序。
Spring Boot通过约定优于配置的原则,避免了许多传统Spring应用开发时繁琐的配置,该框架支持对内嵌服务器的自动配置,如Tomcat、Jetty或Undertow,从而简化了Web应用的部署过程。
前端框架Vue
Vue.js是一种流行的JavaScript框架,它具有许多优势。其中,Vue.js的核心优势之一是虚拟DOM技术。虚拟DOM是一个内存中的数据结构,它在实现高效的DOM操作方面发挥了重要作用。
Vue.js采用了响应式数据绑定、虚拟DOM、组件化等现代化技术,为开发者提供了一种灵活、高效、易于维护的开发模式。当数据发生变化时,Vue.js能够自动更新UI,开发者无需手动更新UI,从而能够更加专注于数据处理。
持久层框架MyBaits
MyBatis是一个开源的持久层框架,它可以帮助开发者简化数据库操作的编写和管理。MyBatis的核心思想是将SQL语句和Java代码分离,通过XML或注解的方式来描述数据库操作,从而实现了数据访问层的解耦和灵活性。
MyBatis的优势主要包括以下几点:
简化数据库操作:MyBatis通过提供强大的SQL映射功能,可以将Java对象与数据库表进行映射,开发者无需手动编写繁琐的SQL语句,大大简化了数据库操作的编写和维护。
灵活的SQL控制:MyBatis支持动态SQL,可以根据不同的条件和逻辑来动态生成SQL语句,使得查询、更新等操作更加灵活和可控。
缓存支持:MyBatis提供了一级缓存和二级缓存的支持,可以有效减少数据库的访问次数,提高系统性能。
可扩展性强:MyBatis采用插件机制,可以方便地扩展和定制自己的功能,满足各种不同的业务需求。
所有项目均为博主亲自收集、开发并严格测试,确保源码完整、可运行,无缺失依赖或兼容性问题!同学们拿到后就能使用!博主具备多年高级开发经验,能深入讲解代码架构、核心逻辑及技术难点,助你高效掌握项目精髓。
成功系统案例:
参考代码
package com.shanzhu.music.controller;
import cn.hutool.core.util.BooleanUtil;
import com.shanzhu.music.common.R;
import com.shanzhu.music.entity.po.SongList;
import com.shanzhu.music.entity.vo.UploadPicVo;
import com.shanzhu.music.service.RecommendSongListService;
import com.shanzhu.music.service.SongListService;
import com.shanzhu.music.utils.PathUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.util.List;
/**
* 歌单 控制层
*
* @author: CodeUp
* @date: 2025-07-01
*/
@RestController
@RequestMapping("/songList")
@RequiredArgsConstructor
public class SongListController {
@Value("${useRecommend}")
private Boolean userRecommend;
private final SongListService songListService;
private final RecommendSongListService recommendSongListService;
/**
* 添加歌单
*
* @param title 标题
* @param pic 歌单图片
* @param introduction 简介
* @param style 风格
* @return 添加结果
*/
@PostMapping(value = "/add")
public R addSongList(
String title,
String pic,
String introduction,
String style
) {
//保存到歌单的对象中
SongList songList = new SongList();
songList.setTitle(title);
songList.setPic(pic);
songList.setIntroduction(introduction);
songList.setStyle(style);
//添加成功
if (songListService.insert(songList)) {
return R.ok("添加成功");
}
return R.error("添加失败");
}
/**
* 修改歌单
*
* @param id 主键
* @param title 标题
* @param introduction 简介
* @param style 风格
* @return 修改结果
*/
@PostMapping(value = "/update")
public R updateSongList(
String id,
String title,
String introduction,
String style
) {
//保存到歌单的对象中
SongList songList = new SongList();
songList.setId(Integer.parseInt(id));
songList.setTitle(title);
songList.setIntroduction(introduction);
songList.setStyle(style);
//修改成功
if (songListService.update(songList)) {
return R.ok("修改成功");
}
return R.error("修改失败");
}
/**
* 删除歌单
*
* @param id 歌单id
* @return 删除结果
*/
@GetMapping(value = "/delete")
public Boolean deleteSongList(Integer id) {
return songListService.delete(id);
}
/**
* 查询歌单
*
* @param id 歌单id
* @return 歌单
*/
@GetMapping(value = "/selectByPrimaryKey")
public SongList selectByPrimaryKey(Integer id) {
return songListService.selectByPrimaryKey(id);
}
/**
* 查询所有歌单
*
* @param userId 用户id
* @return 歌单列表
*/
@GetMapping(value = "/allSongList")
public List<SongList> allSongList(@RequestParam(value = "userId", required = false) String userId) {
if (userId == null || "0".equals(userId) || "null".equals(userId) || BooleanUtil.isFalse(userRecommend)) {
return songListService.allSongList();
} else {
//通过用户收藏来推荐
return recommendSongListService.recommendSongListByCollect(Integer.valueOf(userId));
}
}
/**
* 根据标题精确查询歌单列表
*
* @param title 标题
* @return 歌单列表
*/
@GetMapping(value = "/songListOfTitle")
public List<SongList> songListOfName(String title) {
return songListService.songListOfTitle(title);
}
/**
* 根据标题模糊查询歌单列表
*
* @param title 标题
* @return 歌单列表
*/
@GetMapping(value = "/likeTitle")
public List<SongList> likeTitle(String title) {
return songListService.likeTitle("%" + title + "%");
}
/**
* 根据风格模糊查询歌单列表
*
* @param style 歌单风格
* @return 歌单列表
*/
@RequestMapping(value = "/likeStyle", method = RequestMethod.GET)
public Object likeStyle(String style) {
return songListService.likeStyle("%" + style + "%");
}
/**
* 更新歌单图片
*
* @param avatorFile 头像文件
* @param id 歌单id
* @return 更新结果
*/
@PostMapping(value = "/updateSongListPic")
public R<UploadPicVo> updateSongListPic(
@RequestParam("file") MultipartFile avatorFile,
@RequestParam("id") Integer id
) throws IOException {
if (avatorFile.isEmpty()) {
return R.error("文件上传失败");
}
//文件名=当前时间到毫秒+原来的文件名
String fileName = System.currentTimeMillis() + avatorFile.getOriginalFilename();
//文件路径
String filePath = PathUtils.getClassLoadRootPath() + "/img/songListPic/";
//如果文件路径不存在,新增该路径
File file1 = new File(filePath);
if (!file1.exists()) {
file1.mkdir();
}
//实际的文件地址
File dest = new File(filePath + fileName);
//存储到数据库里的相对文件地址
String storeAvatorPath = "/img/songListPic/" + fileName;
avatorFile.transferTo(dest);
SongList songList = new SongList();
songList.setId(id);
songList.setPic(storeAvatorPath);
//更新歌单
if (songListService.update(songList)) {
UploadPicVo uploadPicVo = new UploadPicVo();
uploadPicVo.setPic(storeAvatorPath);
return R.ok("上传成功", uploadPicVo);
}
return R.error("上传失败");
}
}
数据库
-- ----------------------------
-- Table structure for collect
-- ----------------------------
DROP TABLE IF EXISTS `collect`;
CREATE TABLE `collect` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键',
`user_id` int DEFAULT NULL COMMENT '用户id',
`type` tinyint(1) DEFAULT NULL COMMENT '收藏类型(0歌曲1歌单)',
`song_id` int DEFAULT NULL COMMENT '歌曲id',
`song_list_id` int DEFAULT NULL COMMENT '歌单id',
`create_time` datetime DEFAULT NULL COMMENT '收藏时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=80 DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC COMMENT='收藏';
-- ----------------------------
-- Records of collect
-- ----------------------------
BEGIN;
INSERT INTO `collect` (`id`, `user_id`, `type`, `song_id`, `song_list_id`, `create_time`) VALUES (70, 35, 0, 27, NULL, '2024-07-25 10:38:07');
INSERT INTO `collect` (`id`, `user_id`, `type`, `song_id`, `song_list_id`, `create_time`) VALUES (79, 36, 0, 116, NULL, '2024-07-25 10:58:37');
COMMIT;
-- ----------------------------
-- Table structure for comment
-- ----------------------------
DROP TABLE IF EXISTS `comment`;
CREATE TABLE `comment` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键',
`user_id` int DEFAULT NULL COMMENT '用户id',
`type` tinyint(1) DEFAULT NULL COMMENT '评论类型(0歌曲1歌单)',
`song_id` int DEFAULT NULL COMMENT '歌曲id',
`song_list_id` int DEFAULT NULL COMMENT '歌单id',
`content` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8_general_ci DEFAULT NULL COMMENT '评论内容',
`create_time` datetime DEFAULT NULL COMMENT '收藏时间',
`up` int DEFAULT '0' COMMENT '评论点赞数',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=66 DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC COMMENT='评论';
-- ----------------------------
-- Records of comment
-- ----------------------------
BEGIN;
INSERT INTO `comment` (`id`, `user_id`, `type`, `song_id`, `song_list_id`, `content`, `create_time`, `up`) VALUES (63, 33, 1, NULL, 87, '很好听的歌曲', '2023-11-26 10:36:51', 0);
INSERT INTO `comment` (`id`, `user_id`, `type`, `song_id`, `song_list_id`, `content`, `create_time`, `up`) VALUES (64, 33, 1, NULL, 91, '11', '2023-11-26 15:32:36', 0);
INSERT INTO `comment` (`id`, `user_id`, `type`, `song_id`, `song_list_id`, `content`, `create_time`, `up`) VALUES (65, 35, 1, NULL, 86, '非常不错', '2023-11-28 21:34:41', 0);
源码获取
如需交流/获取资料,请先【关注+私信】我,评论源码,发送源码获取方式~