JavaWeb项目--【在线音乐播放器】onlineMusicPlayer

项目简介

基于Java Servlet 构建的在线音乐服务器。

项目功能

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

项目技术

  1. 前端知识:HTML+CSS+JavaScript
  2. 后端:Servlet 的使用
  3. 数据库:mysql
  4. tomcat、Maven的使用
  5. json 的使用

项目结构

项目整体基于HTTP协议。
前端使用HTML+CSS+JS构建页面整体布局。
后端采用分层结构,分为Servlet层,Dao层。
采用分层设计,降低了整个代码的耦合度。

MySQL由Dao层操作再返回给Dao层。
Dao层由Servlet操作,再返回。
前端页面和Servlet进行交互。

项目内容

1.数据库设计

当前需要三张表。

• 创建数据库

drop database if exists musicplayer;
create database if not exists musicplayer character set utf8;
--使用数据库
use musicplayer;

• 创建表

user表

drop table if exists user;
create table user (
id int primary key auto_increment,
username varchar(20) not null,
password varchar(30) not null,
age int not null,
sex varchar(2) not null,
email varchar(50) not null
);

music表

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

lovemusic表

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,sex,email)
values("lala","2233","12","女","965543061@qq.com");

2.项目及idea的配置

1)使用maven打包。
在 pom.xml 指定当前打包打成 war 包。
在这里插入图片描述
2)创建结构,生成 web.xml。
main文件夹下,NewFile --> webapp/ WEB-INF/ web.xml
在这里插入图片描述
3)设置编码格式,防止出现中文乱码。
在这里插入图片描述
4)设置自动编译。
在这里插入图片描述
5)配置 pom.xml
向 maven 中引入相关依赖。
pom.xml 文件 中放Jackson、servlet、 mysql相关的依赖。
再指定当前 war包的名字:

<finalName>OnlineMusic</finalName>
<!-- 注意:指定的war包的名称是之后项目运行时的 根目录 -->

再指定一些插件的版本,以免受到 maven 版本的影响。

3.创建entity包(实体包)

根据数据库创建实体类:User、Music。其中的属性与数据库中的对应。

User类

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

Music类

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

4.根据功能介绍,确定请求和响应

使用Json
Json 是一种键值对风格的数据格式, 把前端输入的对象转换成字符串(序列化)。
在这里插入图片描述
Java中 我们采用Jackson库中的 ObjectMapper类来完成Json的构造。

向 maven 中引入依赖:

<!-- Jackson相关-->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.11.4</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.11.4</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.11.4</version>
</dependency>

1)登录:

请求:

POST:/loginServlet
data:{username,password}

响应:{msg:true}

2)注册:

请求:

POST:/register
data:{username,password,age,sex,email}

响应:{msg:true}

3)上传音乐:

请求:

POST:/upload
data:filename

4)删除某一个音乐:

请求:

POST:/deleteServlet
data:{“id”:id}

响应:{msg:true}

5)删除选中:

请求:(id 数组)

POST:/deleteSelMusic
data:{“id”:id}

响应:{msg:true}

6)模糊查询音乐:

请求:

Get:/findMusic
data:{musicName:musicName}

响应:{msg:true}

7)添加喜欢音乐到喜欢列表:

请求:

POST:/loveMusic
data:{“id”:obj}

响应:{msg:true}

8)模糊查询喜欢的音乐:

请求:

Get:/findLoveMusic
data:{musicName:musicName}

响应:{msg:true}

9)移除喜欢的音乐:

请求:

POST:/removeLoveMusic
data:{‘id’:obj}

响应:{msg:true}

5.封装数据库的相关操作

1)创建 util 包(工具相关的),其中再创建 DBUtils 类,和数据库建立连接。


public class DBUtils {                                        // 数据库名字对应
    private static String url = "jdbc:mysql://127.0.0.1:3306/数据库名称?useSSL=false";
    private static String password ="2222";//数据库密码
    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 getConn(){
        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 包(数据库持久层),主要来操作MySQL,实现各功能。

创建UserDao类:
login;
register
创建MusicDao类:
insert;
findMusic;
findMusicById;
findMusicByKey;
deleteMusicById;
findLoveMusicById;
deleteLoveMusicById
创建LoveMusicDao类:
findLoveMusic;
findLoveMusicByMusicIdAndUserId;
findLoveMusicBykeyAndUID;
removeLoveMusic

注意:
1.查询当前用户喜欢的音乐,数据库中需要两张表联合查询 music、musicLove。

   public List<Music> findLoveMusic(int user_id) {
        List<Music> musicList = new ArrayList<>();
        Connection con = null;
        PreparedStatement prs = null;
        ResultSet resultSet = null;

        try {
            con = DBUtils.getConn();
            //  String sql ="select * from lovemusic where user_id =?";

            // 查询 user_id ,数据在 music表里,需要两张表联合查询
            // music: id title singer time url userid
            // lovemusic: id user_id music_id
            String sql = "select m.id as m_id,title,singer,time,url,userid from" +
                    " music m,lovemusic lm where m.id = lm.music_id and lm.user_id =?";

            prs = con.prepareStatement(sql); // 执行完 不需要插入
            prs.setInt(1,user_id);  // 给个指定的值

            resultSet = prs.executeQuery(); // 然后 判断结果集 显示
            while (resultSet.next()){
                Music music = new Music();
                music.setId(resultSet.getInt("m_id"));
                music.setTitle(resultSet.getString("title"));
                music.setSinger(resultSet.getString("singer"));
                music.setTime(resultSet.getString("time"));
                music.setUrl(resultSet.getString("url"));
                music.setUserId(resultSet.getInt("userid"));
                musicList.add(music);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DBUtils.getClose(con,prs,resultSet);
        }
        return musicList;
    }

6.实现Servlet

实现各个Servlet,处理请求。
Servlet与前端页面交互,生成动态Web页面。
在这里插入图片描述
例:登录loginServlet:

@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");  // 设置编码,设置响应数据格式,拿到数据,通过dao层,操作数据库,最后返回响应的数据,再返回给前端

        String username = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println("username:"+username);
        System.out.println("password:"+password);

        Map<String ,Object> return_map = new HashMap<>();
        // service层和dao层联系,又需要 dao层操作数据库
        UserDao userDao = new UserDao();
        // 登录需要登录用户 loginUser
        User loginUser = new User(); //创建一个数据库实体类对象
        loginUser.setUsername(username);
        loginUser.setPassword(password);

        LoginService loginService = new LoginService();
        User user = loginService.login(loginUser);
      //  User user = userDao.login(loginUser);  // 接受下登录的返回值

        if (user == null){
            // 登录失败
            return_map.put("msg",false);
        }else {
            req.getSession().setAttribute("user", user);//绑定数据
            return_map.put("msg",true);
        }

        ObjectMapper mapper = new ObjectMapper();
        //利用Jackson将map转化为json对象,
        // writer 将转换后的json字符串保存到字符输出流中,最后给客户端
        mapper.writeValue(resp.getWriter(),return_map);  // 写到前端
    }
}

注意:
上传音乐的流程:
1)将音乐上传到服务器
2)再将音乐信息存入数据库


@WebServlet("/upload")
@MultipartConfig
public class UploadMusicServlet extends HttpServlet {
    // 定义文件存储位置,上传到 music 文件夹
    private static final String SAVEPATH = "D:\\IDEA\\IdeaProjects\\OnlineMusic\\src\\main\\webapp\\music\\";
    private static final String SAVEPATH = "/home/liu/install/apache-tomcat-8.5.69/webapps/OnlineMusic/music/";  // 部署到云服务器 对应路径


    @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");  // 需要从请求中拿到刚刚登录后的session;
                                                                  // 此处attribute()中取的要和登录时的key--》user对应
        if (user == null){
            System.out.println("没有登录,不能上传!");
        }else {
            //1、先上传服务器
            Part part = req.getPart("filename");    // fiddler 抓包获取到的内容 Content-Disposition:
         // form-data; name="filename"; filename="毛不易 - 若有缘由.mp3";                     
            //从content-disposition头中获取源文件名称,获取到一个字符串
            String header = part.getHeader("Content-Disposition");
            // 字符串处理
            int start = header.lastIndexOf("=");   // 最后一个 = 的后面 ,就是需要的内容
            String fileName = header.substring(start + 1) .replace("\"", "");  // 把 " 替换掉
            // 最后获取到的应该是:毛不易 - 若有缘由.mp3
            System.out.println("fileName2:" + fileName); 
            // 现在已经拿到音乐文件.mp3  --- 写到服务器指定路径下
            part.write(SAVEPATH + fileName);  // 调用 write方法,在SAVEPATH路径下,把文件存进去
            String singer = req.getParameter("singer");
            System.out.println("歌手:"+singer);
            // 此时可以查看到 music文件夹里包含了 音乐
            // 2、插入数据库
            // 看数据库中的信息 title、singer、time、url
            String[] titles = fileName.split("\\."); // 毛不易 - 若有缘由.mp3, 用.分割,title=毛不易 - 若有缘由 0下标
            String title = titles[0];
            System.out.println("title:" + title);

            String url = "music\\"+title;
            System.out.println("url:"+url);

            // 格式化时间
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            String time=sdf.format(new Date());

            int userId = user.getId();

            MusicDao musicDao = new MusicDao();
            int ret = musicDao.insert(title,singer,time,url,userId); // 数据库里存
            if (ret == 1){
                // 上传成功
                resp.sendRedirect("list.html"); // 重定向
            }else {
                System.out.println("上传失败!");
                part.delete();  // 数据库上传失败了,就要把前面服务器上传成功的给删掉
            }
        }
    }
}

7.前端页面设计

采用HTML+CSS+JS设计
不做重点,可寻找模板,稍作改动。

8.最终实现效果

登录:
在这里插入图片描述
注册:
在这里插入图片描述
列表页:
在这里插入图片描述
添加音乐到喜欢列表:
在这里插入图片描述
喜欢音乐列表:
在这里插入图片描述

音乐播放器在线链接:
http://106.54.183.128:8080/OnlineMusic/login.html

  • 12
    点赞
  • 96
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值