基于spring+mysql实现的音乐推荐系统

基于spring+mysql实现的音乐推荐系统 1,项目简介 本音乐网站的开发主要利用 spring 框架开发后台,前端采用 Boostrap+jsp 实现

本文包含相关资料包-----> 点击直达获取<-------

基于spring+mysql实现的音乐推荐系统

1.项目简介

本音乐网站的开发主要利用 spring 框架开发后台,前端采用 Boostrap+jsp 实现,数据库使用的是 MySQL。

1.1 系统功能模块结构

1.2 用户模块功能描述

其中,用户信息管理以及订单是禁止匿名用户访问的内容。

  • 用户信息模块 :注册新用户、登录、用户修改密码、用户个人资料管理

  • 用户留言模块 :用户可以在喜欢的歌曲下留言与其他听众交流

  • 歌曲清单模块 :热门歌曲浏览、新歌浏览(首页显示最新发表的歌曲列表)、歌曲分类浏览、按歌曲名称搜索、商品详细信息

  • 喜欢的歌曲模块 :添加喜欢的歌曲到自己专属的歌单

1.3 管理模块功能描述

  • 用户管理 :登录;查询用户、删除用户

  • 歌曲管理 :添加、修改、删除歌曲信息

2.数据库设计

2.1 表结构

收藏列表表

下载信息表

喜欢表

播放表

个性化表

最近播放表

权限表

用户表

歌曲表

用户权限表

2.2 E-R图

3.项目实现

3.1 加密处理

```java public class MD5Util {

/** 
 * MD5 生成32位md5码 
 * @param inStr
 * 需要加密的字符串
 * @return
 */
public static String string2MD5(String inStr){
    MessageDigest md5 = null;
    try{
        md5 = MessageDigest.getInstance("MD5");
    }catch (Exception e){
        System.out.println(e.toString());
        e.printStackTrace();
        return "";
    }
    char[] charArray = inStr.toCharArray();
    byte[] byteArray = new byte[charArray.length];

    for (int i = 0; i < charArray.length; i++)
        byteArray[i] = (byte) charArray[i];
    byte[] md5Bytes = md5.digest(byteArray);
    StringBuffer hexValue = new StringBuffer();
    for (int i = 0; i < md5Bytes.length; i++){
        int val = ((int) md5Bytes[i]) & 0xff;
        if (val < 16)
            hexValue.append("0");
        hexValue.append(Integer.toHexString(val));
    }
    return hexValue.toString();
}

} ```

3.2 定时任务配置

```java public class Static { /* * 用于记录,两张个性化推荐列表,isFromA为true表示,从表A中读取数据; * 否则从表B中读取. * 每天早上6点,两张表交替更新 / public static volatile boolean isFromA=true;

/**
 * 更新个性化推荐列表的时间间隔(这里每天更新一次)
 */
public static final long PERIOD_DAY = 24 * 60 * 60 * 1000;

/**
 * 更新开始的时间:时
 */
public static final int START_HOUR = 6;

/**
 * 更新开始的时间:分
 */
public static final int START_MINUTE = 0;

/**
 * 更新开始的时间:秒
 */
public static final int START_SECOND = 0;

/**
 * 更新是否从明天开始
 */
public static final boolean IS_START_TOMORROW = false;

/**
 * KNN k值
 * 目前系统用户很少
 */
public static final int K = 2;

/**
 * 基于最近邻用户的协同过滤给用户推荐歌曲的数量 n值
 * 歌曲很少
 */
public static final int N = 10;

/**
 * 排行榜的,每日一词
 */
public static final String [] RANKING_WORD_ARRAY= {"百尺竿头","步步高升","精益求精", "登堂入室","登峰造极","泰山北斗","功成名就","大展鸿图","炉火纯青"};

/**
 * 我的音乐的,每日一词
 */
public static final String [] MY_MUSIC_WORD_ARRAY= {"四面楚歌","余音绕梁","靡靡之音", "扣人心弦","高山流水","四面楚歌","曲高和寡","余音袅袅","一唱三叹","四面楚歌","绕梁三日","游鱼出听"};

/**
 * 搜索结果,每次一词
 */
public static final String [] SEARCH_WORD_ARRAY= {"众里寻他","计获事足","望眼欲穿", "踏破铁鞋","如愿以偿","东寻西觅","摸索门径","寻踪觅迹"};

/**
 * 是否开启混合模式,英文歌词文件较少的情况下建议关闭 
 * 基于最近邻用户的协同过滤 +   基于异构文本网络的嵌入
 * 这里采取简单拼接的混合策略
 */
public static final boolean IS_HYBRID=false;

/**
 * 基于异构文本网络给用户推荐歌曲的数量 n值
 * 歌曲很少很少
 */
public static final int N_HYBRID = 1;

} ```

3.3 编写功能实现代码

```java @Service("songService") public class SongServiceImpl implements SongService{ @Autowired private SongDao songDao; @Autowired private UserDao userDao; @Autowired private TrendingRecDao trendingRecDao;

public List<Integer> getAllSongIdRecords() {
    return songDao.selectAllSongId();
}

public Song getSongById(int songId) {
    return songDao.selectSongById(songId);
}

public Song getSongByIdWithCollectionFlag(HttpServletRequest request, int songId) {
    //获取对应Id的歌曲
    Song song=songDao.selectSongById(songId);
    if(song==null) {
        return null;
    }
    //获取对应Id的歌曲的流行度
    int trendingCoefficient=songDao.selectCoefficientById(songId);
    song.setTrendingCoefficient(trendingCoefficient);
    //获取用户的收藏列表
    List<Collection> collectionList=new ArrayList<Collection>();
    User user=userDao.selectByUser(Request.getUserFromHttpServletRequest(request));
    collectionList=trendingRecDao.getCollection(user);
    if(collectionList!=null) {
        for(Collection c:collectionList) {
            if(c.getSongId()==songId) {
                song.setWhetherCollected(true);
                break;
            }
        }
    }
    return song;
}

public void batchDeleteById(HttpServletRequest request,int[] songIds) {
    if(songIds==null) {
        return;
    }
    for(int id:songIds) {
        Song song=songDao.selectSongById(id);
        if(song!=null) {
            String realSongPath=request.getServletContext().getRealPath(song.getSongAddress());
            File fileSong=new File(realSongPath);
            fileSong.delete();
            if(song.getLyricAddress()!=null) {
                String realLyricPath=request.getServletContext().getRealPath(song.getLyricAddress());
                File fileLyric=new File(realLyricPath);
                fileLyric.delete();
            }
        }
    }
    songDao.deleteByIds(songIds);
}

/**
 * 这里由于在前端文件上传的时候,已经做过验证了,所以后端这里不再次验证了
 * 由于时间关系,这里默认前端的验证是可靠的,虽然有时候这是一种危险的做法
 */
public boolean checkFormat(MultipartFile song, MultipartFile lyric) {
    return true;
}

public boolean addSong(HttpServletRequest request,MultipartFile song, MultipartFile lyric) {
    String name=song.getOriginalFilename();
    //歌曲名称需去掉.mp3的后缀
    String songName=name.substring(0, name.lastIndexOf("."));
    String songAddress="track/song/"+name;
    boolean isInsertSuccessful=false;
    int affectedRows=-1;
    //歌词文件是可选的
    if(lyric.isEmpty()) {
        affectedRows=songDao.insertOnlySong(new Song(songName,songAddress));
        //保存歌曲文件
        saveFile(song,request.getServletContext().getRealPath(songAddress));
    }else {
        //这里的歌曲名称仍旧保留.lrc的后缀
        String lyricName=lyric.getOriginalFilename();
        String lyricAddress="track/lyric/"+lyricName;
        affectedRows=songDao.insertSongWithLyric(new Song(songName,songAddress,lyricName,lyricAddress));
        //保存歌曲文件
        saveFile(song,request.getServletContext().getRealPath(songAddress));
        //保存歌词文件
        saveFile(lyric,request.getServletContext().getRealPath(lyricAddress));
    }
    if(affectedRows>0) {
        isInsertSuccessful=true;
    }
    return isInsertSuccessful;
}

private void saveFile(MultipartFile multipartFile, String realFilePath) {
    try {
        InputStream inputStream=multipartFile.getInputStream();
        FileOutputStream fileOutputStream = new FileOutputStream(realFilePath);  
        try {
            int b = 0;  
            while ((b = inputStream.read()) != -1) {  
                fileOutputStream.write(b);  
            }  
        }finally{
            inputStream.close();  
            fileOutputStream.close(); 
        }
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

public List<Song> getAllSongRecordsWithLyric() {
    return songDao.selectAllSongsWithLyric();
}

} ```

CollaborativeFiltering.java

java public class CollaborativeFiltering { /** * 基于最近邻用户产生协同过滤的推荐结果 * @param userIdList * 用户Id列表 * @param userKNNMatrix * 用户KNN矩阵 * @param user2songRatingMatrix * 用户歌曲“评分”矩阵 * @param songIdList * 歌曲Id列表 * @param n * 推荐的前n首歌曲 * @return * 用户歌曲推荐结果矩阵.userId,[recSongId1,recSongId2...recSongIdn] */ public static Map<Integer, Integer[]> userKNNBasedCF(List<Integer> userIdList, final Map<Integer, Integer[]> userKNNMatrix, final Map<Integer, float[]> user2songRatingMatrix, final List<Integer> songIdList, final int n) { // TODO Auto-generated method stub final Map<Integer,Integer[]> user2songRecMatrix=new HashMap<Integer, Integer[]>(); userIdList.forEach(new Consumer<Integer>() { public void accept(Integer curUserId) { // TODO Auto-generated method stub Integer[] knnIdArray=userKNNMatrix.get(curUserId); /** * 对于每一首当前用户没有听过的歌曲 * 协同得分为: * 其k个最近邻用户对该歌曲的“评分”的聚合 */ float[] curUserRatings=user2songRatingMatrix.get(curUserId); //为用户建立一个最小堆来存放最高的前n首歌曲 MininumHeap mininumHeap=new MininumHeap(n); for(int i=0;i<curUserRatings.length;i++) { //对于没有听过的歌曲 /** * 这里需要注意的是,浮点数不能用==来比较...之前竟然犯了这个低级的错误... * 故这里用 curUserRatings[i]<0.01f 来表示 curUserRatings[i]==0f */ if(curUserRatings[i]<0.01f) { for(int knnIndex=0;knnIndex<knnIdArray.length;knnIndex++) { int knnId=knnIdArray[knnIndex]; float[] knnUserRatings=user2songRatingMatrix.get(knnId); curUserRatings[i]+=knnUserRatings[i]; } //这里的聚合策略取均值 curUserRatings[i]/=knnIdArray.length; int curSongId=songIdList.get(i); //放入堆中 mininumHeap.addElement(new TreeNode(curSongId,curUserRatings[i])); } } /** * 对该用户没有听过的歌曲,协同得分完成,选取n个得分最高的项目作为推荐 */ int trueNumber=n; //如果推荐的歌曲少于计划推荐的n首(处理歌曲很少的情况) if(mininumHeap.getCurHeapSize()<n) { trueNumber=mininumHeap.getCurHeapSize(); } Integer[] curUserRecSongId=new Integer[trueNumber]; for(int i=0;i<trueNumber;i++) { int recSongId=mininumHeap.getArray()[i].id; curUserRecSongId[i]=recSongId; } user2songRecMatrix.put(curUserId, curUserRecSongId); }); return user2songRecMatrix; } }

3.5 功能实现

  • 音乐播放

  • 用户登录注册

  • 用户信息编辑、头像修改

  • 歌曲、歌单搜索

  • 歌单打分

  • 歌单、歌曲评论

  • 歌单列表、歌手列表分页显示

  • 歌词同步显示

  • 音乐收藏、下载、拖动控制、音量控制

  • 后台对用户、歌曲、歌手、歌单信息的管理

4.项目展示

首页

登录与注册

5.安装

5.1 下载数据库中记录的资源

去【链接: https://pan.baidu.com/s/1Qv0ohAIPeTthPK_CDwpfWg 提取码: gwa4 】下载网站依赖的歌曲及图片,将 data 夹里的文件直接放到 music-server 文件夹下。

5.2 修改配置文件

  • 创建数据库
  • 将 music/music-server/sql 文件夹中的 tp_music.sql 文件导入数据库。

  • 修改后端配置文件

  • 在 music/music-server/src/main/resources 这个目录下的文件里修改自己的 spring.datasource.username 和 spring.datasource.password

参考文献

  • 个性化音乐推荐系统的设计与实现(华中科技大学·游聪)
  • 基于用户行为的音乐推荐系统设计与实现(华中科技大学·郝陆风)
  • 移动端音乐Web APP的设计与实现(华中科技大学·金旻)
  • 融合知识图谱的个性化推荐系统设计与实现(天津工业大学·郭峰)
  • 基于潜在因子模型的音乐推荐系统研究(山东科技大学·肖海峰)
  • 基于PHP的在线音乐网站的设计与实现(武汉理工大学·陈君)
  • 基于潜在因子模型的音乐推荐系统研究(山东科技大学·肖海峰)
  • 个性化音乐推荐系统(电子科技大学·曾凡聪)
  • 基于排序学习的音乐推荐系统设计与实现(重庆大学·魏斌)
  • 基于排序学习的音乐推荐系统设计与实现(重庆大学·魏斌)
  • 手机应用推荐程序后台支撑系统设计与实现(北京交通大学·陈昊龙)
  • 基于情感分析的个性化音乐推荐系统的设计与实现(曲阜师范大学·毛庆航)
  • CLARANS改进算法在音乐网站智能推荐系统中的应用(吉林大学·魏佳)
  • 融合HMM及歌曲特征标签的混合推荐算法研究(江西师范大学·李春俊)
  • 基于流式大数据的音乐推荐系统的设计与实现(华中科技大学·何鹏飞)

本文内容包括但不限于文字、数据、图表及超链接等)均来源于该信息及资料的相关主题。发布者:代码助手 ,原文地址:https://m.bishedaima.com/yuanma/35457.html

相关推荐

  • 基于SpringBoot框架的医疗挂号管理系统

    这是一套采用Java编程语言,基于SpringBoot框架构建的医疗预约管理系统源代码,项目中融入了Vue技术,开发工具为Idea或Eclipse,此系统适用于毕业设计或课程实践
    2024年05月23日
    2 1 1
  • 基于Python设计的信息检索系统

    基于Python设计的信息检索系统 【实验目的】: 开发一款针对英文文本的信息检索系统,可以实现建立索引表,布尔查询,通配符查询, 短语查询等功能
    2024年05月14日
    4 1 1
  • 基于Python的信息检索课程设计

    基于Python的信息检索课程设计 sdu视点新闻 全站爬虫爬取+索引构建+搜索引擎查询练习程序 爬虫功能使用Python的scrapy库实现
    2024年05月14日
    3 1 1
  • 学生评奖评优管理系统

    这是一个🔥🔥基于SpringBoot框架的学生评奖评优管理系统设计与实现🔥🔥的项目源码,开发语言Java,框架使用的SpringBoot+vue技术,开发环境Idea/Eclipse
    2024年05月23日
    1 1 1
  • 基于Python实现书店销售管理系统

    书店销售管理管理子系统 一,设 计 总 说 明 现在社会随着计算机技术迅速发展与技术的逐渐成熟,信息技术已经使人们的生活发生深刻的变化,生活中的各种服务系统也使人们在生活中的联系日常销售活动方式发生了很大的变化
    2024年05月14日
    6 1 1
  • 网上摄影工作室

    这是一个🔥🔥基于SpringBoot框架的网上摄影工作室设计与实现🔥🔥的项目源码,开发语言Java,框架使用的SpringBoot+vue技术,开发环境Idea/Eclipse
    2024年05月23日
    2 1 1
  • java+swing实现推箱子小游戏课程设计源码

    在计算机科学领域,游戏设计一直是一个备受关注的话题,随着计算机技术的不断发展,人们对于游戏的需求也越来越高,《java+swing实现推箱子小游戏课程设计源码》是一个旨在使用Java语言和Swing框架实现的推箱子小游戏项目
    2024年05月07日
    5 1 1
  • 基于python + dlib实现人脸识别

    python 进行人脸识别 人脸识别的主要算法 其核心算法是 欧式距离算法使用该算法计算两张脸的面部特征差异,一般在 0,6 以下都可以被认为是同一张脸 人脸识别的主要步骤 获得人脸图片 将人脸图片转为 128D 的矩阵(这个也就是人脸特征的一种数字化表现) 保存人脸 128D 的特征到文件中 获取其他人脸转为 128D 特征通过欧式距离算法与我们保存的特征对比
    2024年05月14日
    2 1 1
  • 网上商城系统

    这是一个🔥🔥基于SpringBoot框架的网上商城系统设计与实现🔥🔥的项目源码,开发语言Java,框架使用的SpringBoot+vue技术,开发环境Idea/Eclipse
    2024年05月23日
    1 1 1
  • 基于python实现的CS通信和P2P通信

    基于python实现的CS通信和P2P通信 一,实验要求 C/S通信实现要求 两台计算机分别模拟服务器,客户端 通过编程实现服务器端
    2024年05月14日
    1 1 1

发表回复

登录后才能评论