【Java项目实战】在线音乐播放器(从需求到产品完整解析)

2023-05-16

准备工作必看:【Java项目实战】在线音乐播放器(前期准备)

核心功能

  1. 登录、注册
  2. 上传音乐
  3. 删除某一个音乐信息
  4. 删除选中的音乐信息
  5. 查询音乐(包含查找指定/模糊匹配的音乐)
  6. 添加音乐到“喜欢列表”。
  7. 查询喜欢的音乐(包含查找指定/模糊匹配的音乐)

重要知识点

  1. 简单的Web服务器设计能力
  2. Java 操作 MySQL 数据库(联表查询等操作)
  3. 数据库设计
  4. json 的使用
  5. 强化 HTTP 协议的理解
  6. Servlet 的使用
  7. Java集合的使用
  8. 前端知识的简单使用如:HTML+CSS+JS

最终效果

在这里插入图片描述

整体架构(BS架构)

项目整体基于HTTP协议,前端使用HTML+CSS+JS构建页面整体布局,后端采用分层结构,分为Servlet层,Service层,Dao层的设计,以达到在设计上的高内聚低耦合
在这里插入图片描述

数据库设计

我们需要设计三张表:

music表
在这里插入图片描述
user表
在这里插入图片描述
lovemusic表
在这里插入图片描述

创建表

-- 数据库
drop database if exists `musicserver`;
create database if not exists `musicserver` character set utf8;
-- 使用数据库
use `musicserver`;
DROP TABLE IF EXISTS `music`;
CREATE TABLE `music` (
`id` int PRIMARY KEY AUTO_INCREMENT,
`title` varchar(50) NOT NULL,
`singer` varchar(30) NOT NULL,
`time` varchar(13) NOT NULL,
`url` varchar(100) NOT NULL,
`userid` int(11) NOT NULL
);
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` INT PRIMARY KEY AUTO_INCREMENT,
`username` varchar(20) NOT NULL,
`password` varchar(32) NOT NULL,
`age` INT NOT NULL,
`gender` varchar(2) NOT NULL,
`email` varchar(50) NOT NULL
);
DROP TABLE IF EXISTS `lovemusic`;
CREATE TABLE `lovemusic` (
`id` int PRIMARY KEY AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`music_id` int(11) NOT NULL
);
INSERT INTO user(username,password,age,gender,email)
VALUES("bit","123","10","男","1262913815@qq.com");

在这里插入图片描述

从idea的database面板连接数据库

在这里插入图片描述
在这里插入图片描述
下载成功:
在这里插入图片描述
在这里插入图片描述
连接成功:
在这里插入图片描述
这样就可以通过idea查看数据库了,比较方便。当然也不是必须的,不连接自己从过cmd查看也是可以的。(自己根据情况)

lib下添加jar包

首先下载好需要的jar包,如下:
在这里插入图片描述
然后将下载的jar包复制到之前创建的lib目录里边。(上篇博客有写到,见文章开头链接)

在这里插入图片描述
idea中也就可以看到了:
在这里插入图片描述
这里没有解压,还得继续解压,操作如下:
在这里插入图片描述
在这里插入图片描述
选择之后点击Apply和OK。这时看到还未显示,继续:
在这里插入图片描述
之后再换回第一个下拉选项,这样就解压好了。
在这里插入图片描述
(5.7.27版本jar包)

用户+音乐模块设计

创建entity包

在这里插入图片描述

1、创建User类

package entity;
public class User {
private int id;
private String username;
private String password;
private String gender;
private int age;
private String email;
}

2、创建Music类

package entity;
public class Music {
private int id;
private String title;
private String singer;
private Date time;
private String url;
private int userid;
}

并生成对应的get set toString方法:

关于 Json

Json 是一种常见是数据格式组织方式. 源于 JavaScript, 是一种键值对风格的数据格式. 在Java中 我们可以采用Jackson库中的ObjectMapper类来完成 Json 的解析和构造。
学习示例:

package test;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * @ClassName Person
 * @Description :   json(对象-》字符串)
 * @Author Josvin
 * @Date 2021/02/18/22:41
 */
public class Person {
    private int id;
    private String name;
    private String password;
    public Person() {
        super();
    }
    public Person(int id, String name, String password) {
        this.id = id;
        this.name = name;
        this.password = password;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }

    public static void main(String[] args) throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        Person person = new Person(1, "tom", "123");
        String jsonString = objectMapper.writeValueAsString(person);
        System.out.println("JsonString: " + jsonString);
    }
}

在这里插入图片描述

API设计

交互的流程:
在这里插入图片描述

  1. 登录
    在这里插入图片描述

  2. 上传音乐
    在这里插入图片描述

  3. 删除某个音乐
    在这里插入图片描述

  4. 删除选中音乐(批量删除)
    在这里插入图片描述

  5. 查询音乐(支持模糊查询)
    在这里插入图片描述

  6. 添加喜欢音乐到喜欢列表
    在这里插入图片描述

  7. 查询喜欢的音乐
    在这里插入图片描述

  8. 移除喜欢的音乐
    在这里插入图片描述

封装数据库操作

1 创建一个util包

创建JDBCUtils类。

package util;

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.*;
/**
 * @ClassName DBUtils
 * @Description :工具类,连接数据库
 * @Author Josvin
 * @Date 2021/02/19/12:34
 */
    public class DBUtils {
        private static String url = "jdbc:mysql://127.0.0.1:3306/musicserver?useSSL=false";
        private static String password = "admin";
        private static String username = "root";
        private static volatile DataSource DATASOURCE;
        private static DataSource getDataSource(){
// 双重校验锁
            if(DATASOURCE == null){
                synchronized (DBUtils.class){
                    if(DATASOURCE == null){
                        DATASOURCE = new MysqlDataSource();
                        ((MysqlDataSource) DATASOURCE).setUrl(url);
                        ((MysqlDataSource) DATASOURCE).setUser(username);
                        ((MysqlDataSource) DATASOURCE).setPassword(password);
                    }
                }
            }
            return DATASOURCE;
        }
        public static Connection getConnection(){
            try {
//从池子里获取连接
                Connection connection = getDataSource().getConnection();
                return connection;
            } catch (SQLException e) {
                e.printStackTrace();
                throw new RuntimeException("获取数据库连接失败");
            }
        }
        public static void getClose(Connection connection, PreparedStatement statement, ResultSet resultSet) {
            if(resultSet!=null) {
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(statement!=null) {
                try {
                    statement.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(connection!=null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
}

2 创建dao包和UserDao类

2.1 实现UserDao.login

package dao;

import entity.User;
import util.DBUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * @ClassName UserDao
 * @Description :有关用户的数据库操作
 * @Author Josvin
 * @Date 2021/02/19/12:43
 */
public class UserDao {

    // 登录
    public static User login(User loginUser) {
        User user = null;
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            String sql = "select*from user where username=? and password=?";
            connection = DBUtils.getConnection();
            preparedStatement = connection.prepareStatement(sql);// 对 sql 语句进行预编译
            preparedStatement.setString(1, loginUser.getUsername());
            preparedStatement.setString(2, loginUser.getPassword());
            resultSet = preparedStatement.executeQuery();
         ///  在这里神魔时候用if 什么时候用while 根据查询的结果决定,在这里根据用户名和密码查询只有一条用if即可
            if(resultSet.next()) {
                user = new User();
                user.setId(resultSet.getInt("id"));
                user.setUsername(resultSet.getString("username"));
                user.setPassword(resultSet.getString("password"));
                user.setAge(resultSet.getInt("age"));
                user.setGender(resultSet.getString("gender"));
                user.setEmail(resultSet.getString("email"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtils.getClose(connection, preparedStatement, resultSet);
        }
        return user;
    }

    public static void main(String[] args) {
        User user = new User();
        user.setUsername("bit");
        user.setPassword("123");
        User loginUser = login(user);
        System.out.println(loginUser);
    }

}

测试:
在这里插入图片描述

2.2 实现UserDao.register

   // 注册
    public void register(User user) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        try {
            connection = DBUtils.getConnection();
            preparedStatement = connection.prepareStatement("insert into user values(null,?,?,?,?,?)");
            preparedStatement.setString(1, user.getUsername());
            preparedStatement.setString(2, user.getPassword());
            preparedStatement.setString(3, user.getGender());
            preparedStatement.setInt(4, user.getAge());
            preparedStatement.setString(5, user.getEmail());
            preparedStatement.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }finally {
            DBUtils.getClose(connection, preparedStatement, null);
        }
    }

3 创建MusicDao类

3.1 实现MusicDao.findMusic

package dao;

import entity.Music;
import util.DBUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName MusicDao
 * @Description :有关于音乐的数据库操作
 * @Author Josvin
 * @Date 2021/02/19/12:44
 */
public class MusicDao {
    /**
     * 查询全部歌单
     */
    public List<Music> findMusic(){
        List<Music> musics = new ArrayList<>();
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            conn = DBUtils.getConnection();
            ps = conn.prepareStatement("select*from music");
            rs = ps.executeQuery();
            // 查询结果不止一条
            while(rs.next()) {
                Music music = new Music();
                music.setId(rs.getInt("id"));
                music.setTitle(rs.getString("title"));
                music.setSinger(rs.getString("singer"));
                music.setTime(rs.getDate("time"));
                music.setUrl(rs.getString("url"));
                music.setUserid(rs.getInt("userid"));
                musics.add(music);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }finally {
            DBUtils.getClose(conn, ps, rs);
        }
        return musics;
    }
}

3.2 实现MusicDao.findMusicById

/**
     * 根据id查找音乐
     * @param id
     * @return
     */
    public Music findMusicById(int id){
        Music music = null;
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            conn = DBUtils.getConnection();
            ps = conn.prepareStatement("select * from music where id=?");
            ps.setInt(1,id);
            rs = ps.executeQuery();
            if(rs.next()) {
                music = new Music();
                music.setId(rs.getInt("id"));
                music.setTitle(rs.getString("title"));
                music.setSinger(rs.getString("singer"));
                music.setTime(rs.getDate("time"));
                music.setUrl(rs.getString("url"));
                music.setUserid(rs.getInt("userid"));
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }finally {
            DBUtils.getClose(conn, ps, rs);
        }
        return music;
    }

3.3 实现MusicDao.ifMusic

/**
     * 根据关键字查询歌单
     */
    public List<Music> ifMusic(String str){
        List<Music> musics = new ArrayList<>();
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            conn = DBUtils.getConnection();
            ps = conn.prepareStatement("select*from music where title like '%"+str+"%'");
            rs = ps.executeQuery();
            while(rs.next()) {
                Music music = new Music();
                music.setId(rs.getInt("id"));
                music.setTitle(rs.getString("title"));
                music.setSinger(rs.getString("singer"));
                music.setTime(rs.getDate("time"));
                music.setUrl(rs.getString("url"));
                music.setUserid(rs.getInt("userid"));
                musics.add(music);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } finally {
            DBUtils.getClose(conn, ps, rs);
        }
        return musics;
    }

3.4 实现MusicDao.Insert

/**
     * 也可以直接传一个Music 对象
     * 上传音乐
     * 1、上传到服务器
     * 2、上传到数据库
     */
    public int Insert(String title, String singer, String time, String url, int userid) {
        Connection conn = DBUtils.getConnection();
        PreparedStatement pst=null;
        int number = 0;
        try {
            pst=conn.prepareStatement("insert into music(title,singer,time,url,userid) values(?,?,?,?,?)");
            pst.setString(1,title);
            pst.setString(2,singer);
            pst.setString(3,time);
            pst.setString(4,url);
            pst.setInt(5,userid);
            number = pst.executeUpdate();/// 更新数据库
            return number;
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DBUtils.getClose(conn, pst, null);
        }
        return 0;
    }

3.5 实现MusicDao.deleteMusicById

 /**
    *   删除歌曲:
    *
    */
    public int deleteMusicById(int id) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        try {
            String sql = "delete from music where id=?";
            connection = DBUtils.getConnection();
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1,id);
            int ret = preparedStatement.executeUpdate();
            if(ret == 1) {
//同时删除中间表中的数据
//1、看中间表是否有数据,如果有删除
                if(findLoveMusicOnDel(id)) {
                    int ret2 = removeLoveMusicOnDelete(id);
                    if(ret2 == 1){
                        return 1;
                    }
                } else {
//如果没有找到,说明这首歌,没有被添加到喜欢的列表
                    return 1;
                }
            }
        }catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DBUtils.getClose(connection,preparedStatement,null);
        }
        return 0;
    }

    /**
     * 看中间表是否有该id的音乐数据
     */
    public boolean findLoveMusicOnDel(int id) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            String sql = "select * from lovemusic where music_id=?";
            connection = DBUtils.getConnection();
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1,id);
            resultSet = preparedStatement.executeQuery();
            if(resultSet.next()) {
                return true;
            }
        }catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DBUtils.getClose(connection,preparedStatement,null);
        }
        return false;
    }
    /**
     * 当删除服务器上的音乐时,同时在我喜欢的列表的数据库中进行删除。
     * @param musicId
     * @return
     */
    public int removeLoveMusicOnDelete(int musicId) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        try {
            String sql = "delete from lovemusic where music_id=?";
            connection = DBUtils.getConnection();
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1,musicId);
            int ret = preparedStatement.executeUpdate();
            if(ret == 1) {
                return ret;
            }
        }catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DBUtils.getClose(connection,preparedStatement,null);
        }
        return 0;
    }

3.6 实现MusicDao.insertLoveMusic

/**
     * 添加音乐到“喜欢”列表中
     * 用户-》音乐
     * 多对多
     * 需要中间表
     */
    public boolean insertLoveMusic(int userId,int musicId) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        try {
            String sql = "insert into lovemusic(user_id, music_id) VALUES (?,?)";
            connection = DBUtils.getConnection();
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1,userId);
            preparedStatement.setInt(2,musicId);
            int ret = preparedStatement.executeUpdate();
            if (ret == 1) {
                return true;
            }
        }catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DBUtils.getClose(connection,preparedStatement,null);
        }
        return false;
    }

3.7 实现MusicDao.removeLoveMusic

/**
     * @param userId 用户id
     * @param musicId 歌曲id
     * @return 返回受影响的行数
     * 移除当前用户喜欢的这首音乐,因为同一首音乐可能多个用户喜欢
     */
    public int removeLoveMusic(int userId,int musicId) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        try {
            String sql = "delete from lovemusic where user_id=? and music_id=?";
            connection = DBUtils.getConnection();
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1,userId);
            preparedStatement.setInt(2,musicId);
            int ret = preparedStatement.executeUpdate();
            if(ret == 1) {
                return ret;
            }
        }catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DBUtils.getClose(connection,preparedStatement,null);
        }
        return 0;
    }

3.8 实现MusicDao.findMusicByMusicId

/**
     * 添加喜欢的音乐的时候,需要先判断该音乐是否存在
     * @param musicID
     * @return
     */
    public boolean findMusicByMusicId(int user_id,int musicID) {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            conn = DBUtils.getConnection();
            ps = conn.prepareStatement("select * from lovemusic where music_id=? and user_id=?");
            ps.setInt(1,musicID);
            ps.setInt(2,user_id);
            rs = ps.executeQuery();
            if(rs.next()) {
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }finally {
            DBUtils.getClose(conn, ps, rs);
        }
        return false;

    }

3.9 实现MusicDao.findLoveMusic

/**
     * 查询用户喜欢的全部歌单
     * @param user_id
     * @return
     */
    public List<Music> findLoveMusic(int user_id){
        List<Music> musics = new ArrayList<>();
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            conn = DBUtils.getConnection();
            ps = conn.prepareStatement("select m.id as music_id,title,singer,time,url,userid from lovemusic lm,music m where lm.music_id=m.id and user_id=?");
            ps.setInt(1,user_id);
            rs = ps.executeQuery();
            while(rs.next()) {
                Music music = new Music();
                music.setId(rs.getInt("music_id"));
                music.setTitle(rs.getString("title"));
                music.setSinger(rs.getString("singer"));
                music.setTime(rs.getDate("time"));
                music.setUrl(rs.getString("url"));
                music.setUserid(rs.getInt("userid"));
                musics.add(music);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }finally {
            DBUtils.getClose(conn, ps, rs);
        }
        return musics;
    }

3.10 实现MusicDao.ifMusicLove

/**
     * 根据关键字查询喜欢的歌单
     * @param str
     * @return
     */
    public List<Music> ifMusicLove(String str,int user_id){
        List<Music> musics = new ArrayList<>();
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            conn = DBUtils.getConnection();
//ps = conn.prepareStatement("select*from music where title like '%"+str+"%'");
            ps = conn.prepareStatement("select m.id as music_id,title,singer,time,url,userid from lovemusic lm,music m where lm.music_id=m.id and user_id=? and title like '%"+str+"%'");
            ps.setInt(1,user_id);
            rs = ps.executeQuery();
            while(rs.next()) {
                Music music = new Music();
                music.setId(rs.getInt("music_id"));
                music.setTitle(rs.getString("title"));
                music.setSinger(rs.getString("singer"));
                music.setTime(rs.getDate("time"));
                music.setUrl(rs.getString("url"));
                music.setUserid(rs.getInt("userid"));
                musics.add(music);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } finally {
            DBUtils.getClose(conn, ps, rs);
        }
        return musics;
    }

Service层设计实现

1.实现UserService

package service;

import dao.UserDao;
import entity.User;

/**
 * @ClassName UserService
 * @Description :TODO
 * @Author Josvin
 * @Date 2021/02/20/17:10
 */
public class UserService {
    //登录方法
    public User login(User loginUser) {
        UserDao userDao = new UserDao();
        User user = userDao.login(loginUser);
//System.out.println("UserService "+ user);
        return user;
    }
    // 注册方法
    public void register(User user) {
        UserDao userDao = new UserDao();
        userDao.register(user);
    }
}

2.实现MusicService

package service;

/**
 * @ClassName MusicService
 * @Description :TODO
 * Service 层是一个中间层,可以整合Dao层的功能。也就是将Dao层的各个模块嵌套起来,实现逻辑关系
 * @Author Josvin
 * @Date 2021/02/20/17:10
 */
public class MusicService {
    //TODO

}

Servlet设计与实现

1.LoginServlet实现

package servlet;

import com.fasterxml.jackson.databind.ObjectMapper;
import dao.UserDao;
import entity.User;
import service.UserService;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName LoginServlet
 * @Description :TODO
 * @Author Josvin
 * @Date 2021/02/20/19:22
 */
@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("application/json;charset=utf-8");
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println("username:"+username);
        System.out.println("password:"+password);
        //UserDao dao = new UserDao();
        Map<String ,Object> return_map = new HashMap<>();
        User loginUser =new User(); //创建一个数据库实体类对象
        loginUser.setUsername(username);
        loginUser.setPassword(password);
        try {
            //User user = dao.login(loginUser);
            UserService userService = new UserService();
            User user = userService.login(loginUser);
            if(user != null) {
                req.getSession().setAttribute("user", user);//绑定数据
                return_map.put("msg",true);
                System.out.println("登陆成功!");
            }else {
                System.out.println("登陆失败!");
                return_map.put("msg",false);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        ObjectMapper mapper = new ObjectMapper(); //利用Jackson将map转化为json对象
        mapper.writeValue(resp.getWriter(),return_map);// return_map 返回给前端
    }

}

测试:
在这里插入图片描述
测试出现错误,不见跳转检查发现前端代码没写url:
在这里插入图片描述

修改之后,点击登录则会跳转页面:
在这里插入图片描述

2.FindMusicServlet实现

package servlet;

import com.fasterxml.jackson.databind.ObjectMapper;
import dao.MusicDao;
import entity.Music;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

/**
 * @ClassName FindMusicServlet
 * @Description :TODO
 * @Author Josvin
 * @Date 2021/02/20/20:27
 */
@WebServlet("/findMusic")
public class FindMusicServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html; charset=utf-8");
        System.out.println("测试查找函数");
        String str = req.getParameter("musicName");
        MusicDao dao = new MusicDao();
        List<Music> musics = null;
        if(str!=null) {
            musics = dao.ifMusic(str);//关键字查询
        }else {
            musics = dao.findMusic();
        }
        for (Music music : musics) {
            System.out.println(music.getUrl());
        }
        ObjectMapper mapper = new ObjectMapper();
        mapper.writeValue(resp.getWriter(),musics);
    }
}

测试出现错误不见页面显示歌曲:
在这里插入图片描述
下来开始解决错误:
在这里插入图片描述
在这里插入图片描述
应该是我在数据库插入的时间那个字段出现了问题,注意中文和英文:
在这里插入图片描述
这样就可以播放了:
在这里插入图片描述

3.删除音乐信息实现

3.1 删除某个音乐(DeleteMusicServlet)

**
 * @ClassName DeleteMusicServlet
 * @Description :TODO
 * @Author Josvin
 * @Date 2021/02/21/20:44
 */
@WebServlet("/deleteServlet")
public class DeleteMusicServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("删除指定音乐!");
        req.setCharacterEncoding("utf-8");
        resp.setContentType("application/json;charset=utf-8");
        Map<String,Object> map=new HashMap<>();
        String strId = req.getParameter("id");
        int id = Integer.parseInt(strId);
        System.out.println("id:"+ id);
        try {
            MusicDao musicDao = new MusicDao();
//1.查找有没有当前id
            Music music = musicDao.findMusicById(id);
//没有这个id的音乐 直接返回
            if(music == null) return;
//2、如果有就开始删除库中的音乐
            int delete = musicDao.deleteMusicById(id);
            System.out.println("delete:"+delete);
            if(delete == 1){
//3、数据库删除完成后,检查还是否存在。如果不存在,那么删除掉磁盘上的文件
                File file = new File("E:\\Java_code\\JavaCode\\OnlineMusic\\web\\"+music.getUrl()+".mp3");
                System.out.println("文件是否存在:"+file.exists());
                System.out.println("file: "+file);
                if(file.delete()){
//证明删除成功
                    map.put("msg",true);
                    System.out.println("删除文件成功!");

                }else {
                    map.put("msg",false);
                    System.out.println("文件名:"+file.getName());
                    System.out.println("删除文件失败!");
                }
            }else {
                map.put("msg",false);
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
//将map转化为json
        ObjectMapper mapper=new ObjectMapper();
        mapper.writeValue(resp.getWriter(),map);
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

数据库和服务器都删掉了。

3.2 删除选中音乐


/**
 * @ClassName DeleteSelMusicServlet
 * @Description :TODO
 * @Author Josvin
 * @Date 2021/02/21/21:04
 */
@WebServlet("/deleteSelMusicServlet")
public class DeleteSelMusicServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("application/json;charset=utf-8");
        String[] values = req.getParameterValues("id[]");
        System.out.println("deleteSelectedServlet:"+Arrays.toString(values));
//删除
        int sum=0;
        Map<String,Object> map=new HashMap<>();
        MusicDao musicDao = new MusicDao();
        for (int i = 0; i < values.length; i++) {
            int j = Integer.parseInt(values[i]);
            System.out.println("j :" + j);
//调用Service层方法删除
            Music music = musicDao.findMusicById(j);
            int delete = musicDao.deleteMusicById(j);
//sum=sum+delete;
            if (delete == 1) {
//3、数据库删除完成后,检查还是否存在。如果不存在,那么删除掉磁盘上的文件
                File file = new File("E:\\Java_code\\JavaCode\\OnlineMusic\\web\\" + music.getUrl() + ".mp3");
                System.out.println("文件是否存在:" + file.exists());
                System.out.println("file: " + file);
                if (file.delete()) {
//证明删除成功
//map.put("msg", true);
                    sum = sum + delete;
                } else {
//map.put("msg", false);
                    System.out.println("文件名:" + file.getName());
                    System.out.println("删除文件失败!");
                }
            }
        }
        System.out.println("sum: "+sum);
//sum==values.length 说明选中的所有元素已经全部删除了
        if(sum==values.length){
//证明删除成功
            map.put("msg",true);
        }else {
            map.put("msg",false);
        }
//将map转化为json
        ObjectMapper mapper=new ObjectMapper();
        mapper.writeValue(resp.getWriter(),map);
    }
}

在这里插入图片描述

4. 上传音乐

上传音乐分为2步:

  • 第一步将音乐上传到服务器
  • 第二步将音乐信息存放到数据库

4.1 第一步:将音乐上传到服务器

/**
 * @ClassName UploadMusicServlet
 * @Description :TODO
 * @Author Josvin
 * @Date 2021/02/21/19:45
 */

@WebServlet("/upload")
//@MultipartConfig
public class UploadMusicServlet extends HttpServlet {
    private final String SAVEPATH="E:\\Java_code\\JavaCode\\OnlineMusic\\web\\music\\";
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html; charset=utf-8");
        User user = (User) request.getSession().getAttribute("user");
        if (user == null) {
            request.setAttribute("Msg", "请登录后再进行上传");
            response.getWriter().write("<h2> 请登录后再进行上传 "+"</h2>");
        } else {
            // 上传
            FileItemFactory factory = new DiskFileItemFactory();//
            ServletFileUpload upload = new ServletFileUpload(factory);//
            List<FileItem> items = null;
            try {
                items = upload.parseRequest(request);
            } catch (FileUploadException e) {
                e.printStackTrace();
                return;
            }
            System.out.println("items:"+items );
            FileItem item = items.get(0);
            System.out.println("item: "+item);
            String fileName = item.getName();
            System.out.println("fileName"+fileName);
            request.getSession().setAttribute("fileName", fileName);
            try {
                item.write(new File(SAVEPATH, fileName));
            } catch (Exception e) {
                e.printStackTrace();
            }
            // 上传到数据库
            response.sendRedirect("uploadsucess.html");
        }
    }
}

在这里插入图片描述
在这里插入图片描述
通过之前登录会把用户信息写在Session之中,我们在往数据库中添加信息就可以获取用户信息。

4.2 第二步:将音乐信息存放到数据库


/**
 * @ClassName UploadInsertServlet
 * @Description :TODO
 * @Author Josvin
 * @Date 2021/02/21/20:11
 */
@WebServlet("/uploadsucess")
public class UploadInsertServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html; charset=utf-8");
        String strings = (String)req.getSession().getAttribute("fileName");
        String[] titles = strings.split("\\.");// 去掉.mp3
        String title = titles[0];
        System.out.println("title:" + title);
        String url = "music\\"+title;
        System.out.println("url:"+url);
        String singer = req.getParameter("singer");
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
        String time=sdf.format(new Date());
        MusicDao dao = new MusicDao();
        User user = (User) req.getSession().getAttribute("user");
        int user_id = user.getId();
        int num = dao.insert(title,singer,time,url,user_id);
        if(num!=0){
            resp.sendRedirect("list.html");
        }
    }
}

5.添加喜欢的音乐到喜欢列表

/**
 * @ClassName LoveMusicServlet
 * @Description :TODO
 * @Author Josvin
 * @Date 2021/02/21/21:25
 */
@WebServlet("/loveMusicServlet")
public class LoveMusicServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("application/json;charset=utf-8");
        String strId = req.getParameter("id");
        int musicId = Integer.parseInt(strId);
        System.out.println("musicID: "+musicId);
        User user = (User) req.getSession().getAttribute("user");
        int user_id = user.getId();
        MusicDao musicDao = new MusicDao();
        Map<String,Object> map=new HashMap<>();
//插入之前需要先查看是否该音乐已经被添加到喜欢列表
        boolean effect = musicDao.findMusicByMusicId(user_id,musicId);
        if(effect) {
            map.put("msg",false);
        }else {
            boolean flg = musicDao.insertLoveMusic(user_id,musicId);
            if(flg) {
                map.put("msg",true);
            }else {
                map.put("msg",false);
            }
        }
        ObjectMapper mapper=new ObjectMapper();
        mapper.writeValue(resp.getWriter(),map);
    }
}

6.查找我喜欢的音乐列表

/**
 * @ClassName FindLoveMusicServlet
 * @Description :TODO
 * @Author Josvin
 * @Date 2021/02/21/21:38
 */
@WebServlet("/findLoveMusic")
public class FindLoveMusicServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("application/json;charset=utf-8");
        String str = req.getParameter("loveMusicName");
        System.out.println("loveMusicName:"+str);
        User user = (User) req.getSession().getAttribute("user");
        int user_id = user.getId();
        MusicDao musicDao = new MusicDao();
        List<Music> musics = null;
        if(str!=null) {
            musics = musicDao.ifMusicLove(str,user_id);//关键字查询
        }else {
            musics = musicDao.findLoveMusic(user_id);
        }
        for (Music music : musics) {
            System.out.println(music.getUrl());
        }
        ObjectMapper mapper = new ObjectMapper();
        mapper.writeValue(resp.getWriter(),musics);
    }
}

在这里插入图片描述

7.移除我喜欢的音乐


/**
 * @ClassName RemoveLoveServlet
 * @Description :TODO
 * @Author Josvin
 * @Date 2021/02/21/21:51
 */
@WebServlet("/removeLoveServlet")
public class RemoveLoveServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("application/json;charset=utf-8");
        User user = (User) req.getSession().getAttribute("user");
        int user_id = user.getId();
        Map<String,Object> map=new HashMap<>();
        String strId = req.getParameter("id");
        int music_id = Integer.parseInt(strId);
        MusicDao musicDao = new MusicDao();
        int delete = musicDao.removeLoveMusic(user_id,music_id);
        if(delete == 1) {
            map.put("msg",true);
        }else {
            map.put("msg",false);
        }
        ObjectMapper mapper=new ObjectMapper();
        mapper.writeValue(resp.getWriter(),map);
    }
}

前端页面的设计

前端采用HTML+CSS+JS设计。
直接在百度上搜索 “免费网页模板”, 能找到很多免费模板网站. 可以直接基于现成的漂亮的页面进行修改.
tips: 做减法比做加法更容易.
将网页模板解压缩, 拷贝到项目的webapp 或者 web 目录中.
网址分享:
http://tpl.amazeui.org/
https://ajz.fkw.com/pro11.html?_ta=150&kw=145

部署(后续。。。)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【Java项目实战】在线音乐播放器(从需求到产品完整解析) 的相关文章

  • stm32之蓝牙模块HC-05使用

    参考资料 xff1a 常用模块 HC 05蓝牙串口通信模块使用详解 xff08 实例 xff1a 手机蓝牙控制STM32单片机 xff09 HC 05蓝牙模块使用教程 HC 05蓝牙模块使用记录 补充与理解 xff1a 套餐有两个板子 一个
  • 2021-09-28->HttpClientUtil 工具包

    span class token keyword package span span class token namespace com span class token punctuation span ruoyi span class
  • 微信通知方法

    span class token comment 微信通知 span span class token function wxMessage span span class token punctuation span userId spa
  • 2021-09-29->微信支付

    接下来看微信支付jsapi接口是怎么调用的 步骤一 xff1a 获取微信支付四大参数 首先要想支持微信支付 必须拥有两个账号 微信公众平台 xff1a 账户 公众APPID xff0c APPSECEPT xff0c 微信商户平台商户ID
  • 20以为加减法

    span class token keyword for span span class token punctuation span span class token keyword int span i span class token
  • coturn服务配置

    COTURN服务配置 准备工作 一台带有公网ip的服务器 xff08 coturn服务部署在具有公网ip的服务器上 xff09 下载coturn wget https span class token operator span span
  • BigDecimal 精确算法 工具类

    BigDecimal a 61 new BigDecimal 101 BigDecimal b 61 new BigDecimal 111 使用compareTo方法比较 注意 xff1a a b均不能为null xff0c 否则会报空指针
  • wsappx_什么是“ wsappx”,为什么在我的PC上运行它?

    wsappx The wsappx process is part of Windows 8 and 10 and you may see it running in the background or even using a signi
  • python获取文件路径、文件夹内所有文件

    python获取文件路径 文件夹内所有文件名字 项目内相对路径 在test12 py内 想获取其所在文件夹的所有的表格文件 windows 第一种方案 34 34 34 获取路径 34 34 34 def list dir file dir
  • MySQL-常用内置函数(字符串、数值、日期、流程)

    字符串函数 xff1a 函数作用CONCAT str1 str2 拼接字符串 xff0c 返回拼接后的字符串LENGTH str 返回字符串字节长度 xff0c 注意是字节 xff0c 中文占3个LEFT str len 返回从最左边截取到
  • MySQL-基础语法DDL、DML、DQL、DCL

    DDL xff1a DDL Data Definition Language 数据库定义语言用来定义数据库对象 xff1a 数据库 xff0c 表 xff0c 列等 关键字 xff1a create drop alter 等 语法 DML语
  • VMware安装虚拟机Mac版

    VMware xff1a 1 不需要分区或重开机就能再同一台PC上使用多种操作系统 2 完全隔离并且保护不同操作系统的环境以及所有软件 资料 3 不同的操作系统之间还能互动操作 4 有复原功能 5 能够设置并且随时修改操作系统的操作环境 下
  • JSON转换工具

    JSON的处理 xff1a JSON JavaScript Object Notation xff1a 是一种轻量级的数据交换格式 它是基于 ECMAScript 规范的一个子集 xff0c 采用完全独立于编程语言的文本格式来存储和表示数据
  • MacOS Apple M1 安装ARM架构的JDK及动态切换版本

    JDK下载安装 xff1a 咱就是说 xff0c ARM版本的JDK就是一个字 xff0c 真特么快 xff0c 想变快吗 xff0c 赶紧下载叭 xff01 xff01 1 下载地址 xff1a https www azul com do
  • Go_详解TCP协议三次握手四次挥手

    三次握手 xff1a 三次握手表示建立通信阶段 xff0c 在TCP协议中 xff0c 在发送数据的准备阶段 xff0c 客户端与服务器之间的三次交互 xff0c 以保证连接的可靠 xff0c 由于这种面向连接的特性 xff0c TCP协议
  • Go_常量、iota(枚举)的使用

    常量 常量是在程序运行过程中 xff0c 其值不可以发生改变的数据 xff0c 常量无法被获取地址 常量中的数据类型能是布尔型 数字型 xff08 整型 浮点型和复数型 xff09 字符串 常量的定义是通过const关键字完成的 xff0c
  • Go_反射的使用

    反射可以在运行时动态地检查变量和类型 xff0c 并且可以调用变量和类型的方法 获取和修改变量的值和类型等 使用反射可以使程序更加灵活 xff0c 但也需要谨慎使用 基于反射的代码是极其脆弱的 xff0c 反射中的类型错误会在真正运行的时候
  • 登录注册页怎么做

    app常见页面 xff1a 引导页 xff1a 概念 xff1a 第一次安装App或者更新App后第一次打开App时所展示的可以滑动的页面 作用 xff1a 主要是用于展示产品本身的一些核心功能点或者特色 启动页 xff1a 概念 xff1
  • win10安装appx工具_如何在Windows 10上安装.Appx或.AppxBundle软件

    win10安装appx工具 Microsoft s new Universal Windows Platform applications use the Appx or AppxBundle file format They re nor
  • 本地mysql数据库开启远程访问

    本地mysql数据库开启远程访问 1 开启远程访问端口 3306端口 依次点击控制面板 系统和安全 windows防火墙 高级设置 入站规则 xff1b 设置端口为3306 一直点下一步 xff1b PS xff1a 入站 xff1a 别人

随机推荐

  • Go_String常用操作

    字符串操作 xff1a len xff1a 统计字符串的长度 span class token keyword func span span class token function main span span class token p
  • Arrarys常用的方法

    int newArrary 61 Arrays copyOf int original int newarrary length 拷贝数组 xff0c 可定义要拷贝的长度 Array copyOf 有进行复制的功能 xff0c 而且底层是调
  • Unity2019 打包Android报错 Android NDK not found

    打包报错 xff1a UnityException Android NDK not found Android NDK not found or invalid NDK配置报错 xff1a Edit gt Preferences gt Ex
  • 安装zabbix proxy

    Centos7搭建zabbix proxy5 0 概述安装创建数据库导入数据下载包安装 编译过程中的报错 概述 Zabbix 代理可以代表 Zabbix 服务器收集性能和可用性数据 这样 xff0c 代理可以自己承担一些收集数据的负载并卸载
  • Mac localhost无法访问

    Mac localhost无法访问 localhost 8080和127 0 0 1 8080可以访问nginx的文件 xff0c 但输入localhost和127 0 0 1都打不开了
  • 生产者与消费者问题(线程同步经典案例)

    生产者 xff08 producer xff09 和消费者 xff08 consumer xff09 问题是并发处理中最常见的一类问题 xff0c 是一个多线程同步问题的经典案例 可以这样描述这个问题 xff0c 有一个或者多个生产者产生某
  • Git忽略提交规则 & .gitignore配置总结

    Git忽略提交规则 xff06 gitignore配置总结 在使用Git的过程中 xff0c 我们喜欢有的文件比如日志 xff0c 临时文件 xff0c 编译的中间文件等不要提交到代码仓库 xff0c 这时就要设置相应的忽略规则 xff0c
  • Spring之配置文件

    Spring简介 Spring是什么 Spring 自带 IoC xff08 Inverse of Control 控制反转 xff09 和 AOP Aspect Oriented Programming 面向切面编程 可以很方便地对数据库
  • Ubuntu开启SSH服务远程登录

    Ubuntu开启SSH服务远程登录 Ubuntu下开启ssh服务并能通过MobaXterm或者 Xshell进行远程登录 本人使用的是window10系统安装的MobaXterm window10系统安装MobaXterm可以参考 http
  • MongoDB

    一 MongoDB简介 1 集成简介 spring data mongodb提供了MongoTemplate与MongoRepository两种方式访问mongodb xff0c MongoRepository操作简单 xff0c Mong
  • 更改桌面壁纸_使用DeskSlide轻松更改桌面墙纸

    更改桌面壁纸 Looking to add some variety to your desktop instead of looking at the same wallpaper day in and day out Have fun
  • 科学素养题(2022年2月-2022年10月)

    二月科学素养 在我国山东省和山西省中间的 山 34 是 C A泰山 B吕梁山 C太行山 D沂蒙山 在一些寻宝游戏中 每个线索都会指向下一个线索的位置 玩家可以顺着这些线索一个一个找到所有的元素 这样的寻宝游戏的设计与 数据结构有着异曲同工之
  • Servlet综合练习:个人博客系统

    功能简介 1 注册新用户 2 xff09 登录已有用户 3 xff09 展示博客列表 xff08 包含文章标题以及作者信息 xff09 xff0c 点击标题就会跳转到文章详情页 4 xff09 文章详情页中 xff0c 显示文章标题 xff
  • Linux 环境搭建(如何获得一个免费云服务器)以及Linux基本指令

    搭建 Linux 环境 Linux 环境的搭建方式 主要有三种 直接安装在物理机上 但是由于 Linux 桌面使用起来非常不友好 不推荐 使用虚拟机软件 将 Linux 搭建在虚拟机上 但是由于当前的虚拟机软件 如 VMWare 之类的 存
  • 深入理解HTTP协议

    目标 xff1a 掌握 http 原理 xff0c 重点掌握 http Request amp Response 格式掌握 http 中相关重点知识 xff0c 如请求方法 xff0c 属性 xff0c 状态码等使用 java socket
  • 异常声音检测MFCC/HMM...相关

    有无研究这个方向的同学 xff0c 自己准备做这个方向 xff0c 可以相互讨论讨论 xff0c 留言我加你 xff0c 一起啊 x1f60f xff01
  • C语言goto语句简单使用

    简单介绍 C语言中提供了可以随意滥用的 goto语句和标记跳转的标号 从理论上 goto语句是没有必要的 xff0c 实践中没有goto语句也可以很容易的写出代码 但是某些场合下goto语句还是用得着的 xff0c 最常见的用法就是终止程序
  • 【网络原理】一个数据包从发送到接收在网络中经历了那些过程(详细分析)

    一个数据包从发送到接收在网络中经历了那些过程 假设学生给老师发送电子邮件 xff0c 内容为 xff1a 老师您好 xff01 从计算机A向另一台计算机B发送电子邮件 xff0c 站在网络原理的角度来分析整个过程 启动应用程序新建邮件 xf
  • 【贪心算法】leetcode402.移掉K位数字

    题目描述 xff08 传送门 xff09 给定一个以字符串表示的非负整数 num xff0c 移除这个数中的 k 位数字 xff0c 使得剩下的数字最小 注意 num 的长度小于 10002 且 k num 不会包含任何前导零 示例 1 输
  • 【Java项目实战】在线音乐播放器(从需求到产品完整解析)

    准备工作必看 xff1a Java项目实战 在线音乐播放器 xff08 前期准备 xff09 核心功能 登录 注册上传音乐删除某一个音乐信息删除选中的音乐信息查询音乐 包含查找指定 模糊匹配的音乐 添加音乐到 喜欢列表 查询喜欢的音乐 包含