在线音乐播放器 --- 分页功能和其他更新

1. 上传功能

由于之前的上传功能, 没有提示功能. 上传成功还是失败都没有提示.

1.1 修改前端代码

这里不使用form直接发送请求.
使用 FormData 将信息返回给服务器.

<body>
<!--enctype="multipart/form-data"-->
<form  enctype="multipart/form-data" id="form1">
    文件上传: <input type="file" name="filename" id="file" />
    歌手名: <label>
    <input type="text" name="singer" placeholder="请输入歌手名" id="singer" /> 
    </label>
    <input type="button" value="上传" id="submit" onclick="login()"/>
</form>

<script src="js/jquery-3.3.1.min.js"></script>
<script>
    function login(){
      
      
        // 获取到这里的文件信息
        let filename = $('#file')[0].files[0];
        if (filename == undefined) {
      
      
            alert("请选择文件!");
            return;
        }
        // 获取到这里的歌手信息
        let singer = document.querySelector('#singer');
        if (singer.value.trim() == ""){
      
      
            alert("请添加歌手");
            return;
        }
        // 使用formData来返回
        let formData = new FormData($("#form1")[0]);
        formData.append("filename",filename);
        formData.append("singer",singer.value.trim());
        $.ajax({
      
      
            type: "POST",
            url: "music/upload",
            data: formData,
            processData: false,
            contentType: false,
            success: function(data) {
      
      
                if(data.status == -1){
      
      
                    alert(data.message);
                    location.assign("upload.html");
                }else{
      
      
                    alert(data.message);
                    location.assign("index.html");
                }
            },
            error:function() {
      
      
                alert("出现异常");
                location.assign("upload.html");
            }
        });
    }
</script>
</body>

1.2 修改后端代码

注意传过来的信息的接收方式
在这里插入图片描述

在这里插入图片描述

2. 分页功能

2.1 主页界面的分页功能

这里分页采用的是四个按钮, 分别是 首页, 上一页, 下一页, 尾页.

2.1.1 按钮的前端代码设计

<div class="paging">
	<button class="btn btn-primary" id="firstButton">首页</button>
    <button class="btn btn-primary" id="preButton">上一页</button>
    <button class="btn btn-primary" id="nextButton">下一页</button>
    <button class="btn btn-primary" id="lastButton">尾页</button>
</div>

在这里插入图片描述

2.1.2 分页模块设计思路

这里让 pageIndex 表示 当前的页码
这里让 pageSize 表示 每个页码展示的最大音乐数
这里让 totalMusic 表示 音乐的总数

在这里插入图片描述
这里如果 pageIndex == 1首页
这里如果pageIndex == Math.ceil(totalMusic*1.0 / pageSize) 就是尾页
这里如果 pageIndex在 (1, Math.ceil(totalMusic*1.0 / pageSize) 之间就是 中间页

2.1.3 前端主要代码


    <script>
      // 页面下标(初始为1)
      let pageIndex = 1;
      // 总音乐数
      let totalMusic = 0;
      // 单个页面最大个数(这里我设置的是3,可根据自己喜欢设置)
      let pageSize = 3;
      
      // 加载页面的时候, 会触发一个不带musicName的load请求
      $(function(){
    
    load()});

      function load(musicName) {
    
    
        $.ajax({
    
    
          url: 'music/findMusic',
          method: 'POST',
          // 传递的时候就需要传递页面下标
          data: {
    
    "name":musicName,"pageIndex":pageIndex},
          dataType: "json",
          success: function(data,status) {
    
    
            if(data.data != null){
    
    
              // 每次加载的时候, 记录音乐总数
              totalMusic = data.data.totalMusic;
              createMusic1(data.data.list);
              let audios = document.querySelectorAll('#player2');
              for(let audio of audios) {
    
    
                new MediaElementPlayer(audio, {
    
    
                              pluginPath: 'https://cdn.jsdelivr.net/npm/[email protected]/build/',
                              shimScriptAccess: 'always',
                              success: function () {
    
    
                                let play = document.querySelector('.player');
                                play.style = "visibility: visible;";
                              }
                });
              }
            }
          }
        })
      </scrpit>

点击首页的情况

    let firstButton = document.querySelector("#firstButton");
    firstButton.onclick = function(){
    
    
      // 首先判定当前页面是否是首页
      if(pageIndex == 1) {
    
    
        alert("当前已经是首页");
        return;
      }
      // 这里不是首页,需要回到首页, 让下标变为1
      pageIndex = 1;
      var name = $("#exampleInputName2").val();
      load(name);
    }

点击尾页的情况

    let lastButton = document.querySelector("#lastButton");
    lastButton.onclick = function() {
    
    
      // 这里判定当前页面是不是尾页, 还需要判断当前totalMusic是否为0, 如果为0, 也应该是尾页
      if(pageIndex == Math.ceil(totalMusic / pageSize) || totalMusic == 0){
    
    
        alert("当前已经是尾页");
        return;
      }
      // 不是尾页, 就设置下标为尾页
      pageIndex = Math.ceil(totalMusic / pageSize);
      var name = $("#exampleInputName2").val();
      load(name);
    }

点击上一页的情况

    let preButton = document.querySelector("#preButton");
    preButton.onclick = function() {
    
    
      // 判定当前是否为首页
      if(pageIndex == 1){
    
    
        alert("当前已经是最前页了");
        return;
      }
      // 不是首页, 就让下标 -1
      pageIndex = pageIndex - 1;
      var name = $("#exampleInputName2").val();
      load(name);
    }

点击下一页的情况

    let nextButton = document.querySelector("#nextButton");
    nextButton.onclick = function() {
    
    
      // 这里判断下标是不是尾页, 还需要判断当前totalMusic是否为0, 如果为0, 也应该是尾页
      if(pageIndex == Math.ceil(totalMusic / pageSize) || totalMusic == 0){
    
    
        alert("当前已经是最后页了");
        return;
      }
      // 设置下标为下一页
      pageIndex = pageIndex + 1;
      var name = $("#exampleInputName2").val();
      load(name);
    }

2.1.4 后端代码

  1. 由于这里首次加载的时候, 要记录当前总total数. 所以需要计算音乐总数.
  2. 由于在加载的时候, 是根据查询来判断的, 所以计算的时候需要带total.
  3. 这里根据下标来计算每页展示的内容
    limit pageSize offset (pageIndex - 1) * pageSize
    例如这里一共有10个音乐. 初始下标为1, pageSize = 3
    第一页: 展示3个 limit 3 offset 0 1~3
    第二页: 展示3个 limit 3 offset 3 4~6
    第三页: 展示3个 limit 3 offset 6 7~9
    第四页: 展示1个 limit 3 offset 9 10~12

2.1.4.1 更改数据库操作

MusicMapper

/**
     * 查找所有的歌曲
     * @return 所有的歌曲
     */
    List<Music> findMusic(int pageRange, int pageSize);

    /**
     * 支持模糊查询的歌曲.
     * @param name 部分歌曲名
     * @return 对应所有的歌曲
     */
    List<Music> findMusicByName(String name,int pageRange, int pageSize);
     
     /**
     * 计算音乐总数
     * @param name 可能为空
     * @return
     */
    int totalMusic(String name);

MusicMapper.xml

    <select id="findMusic" resultType="com.example.onlinemusicserver.model.Music">
        select * from music limit #{pageSize} offset #{pageRange};
    </select>

     <select id="findMusicByName" resultType="com.example.onlinemusicserver.model.Music">
        select * from music where title like concat('%',#{name},'%') limit #{pageSize} offset #{pageRange};
    </select>

	 <select id="totalMusic" resultType="java.lang.Integer">
        select count(musicId) from music
        <where>
            <if test="name != null">
                title like concat('%',#{name},'%');
            </if>
        </where>
    </select>

2.1.4.2 更改Controller代码

注意这里的pageSize, 放在了常量类里, 用final修饰, 这样后期进行更改的时候就更加的方便.

    @RequestMapping("/findMusic")
    public ResponseBodyMessage<HashMap<String,Object>> findMusic(@RequestParam(required = false) String name,
                                                      Integer pageIndex) {
    
    
        if(pageIndex <= 0) {
    
    
            return new ResponseBodyMessage<>(-1,"下标错误",null);
        }
        HashMap<String,Object> hash = new HashMap<>();
        List<Music> list = null;
        // 计算offset的后部分
        int pageRange = (pageIndex - 1) * Constant.PAGE_SIZE;
        // 计算总音乐数
        int totalMusic = musicService.totalMusic(name);
        if(totalMusic != 0 && pageIndex > Math.ceil(totalMusic*1.0/Constant.PAGE_SIZE)){
    
    
            return new ResponseBodyMessage<>(-1,"下标错误",null);
        }
        if(name != null && !"".equals(name)) {
    
    
            list = musicService.findMusicByName(name,pageRange,Constant.PAGE_SIZE);
        }else {
    
    
            list = musicService.findMusic(pageRange,Constant.PAGE_SIZE);
        }
        hash.put("list",list);
        hash.put("totalMusic",totalMusic);
        return new ResponseBodyMessage<>(1,"查询完毕!",hash);
    }

2.2 首次界面的分页功能

  1. 相比于主页界面, 这里分页功能唯一难点就是计算收藏页总数的时候需要多表查询.
  2. 前端没有改变.

2.2.1 后端代码

2.2.1.1 更改数据库操作

collectMapper

 /**
     * 查找用户收藏的所有音乐
     * @param userId 用户Id
     * @return 返回查询到的所有音乐
     */
    List<Music> findLoveMusicByUserId(int userId,int pageRange, int pageSize);

    /**
     * 查找用户收藏音乐中名字带有 name的音乐
     * @param name 部分名字
     * @param userId 用户Id
     * @return 返回查询到的所有音乐
     */
    List<Music> findLoveMusicByNameAndUserId(String name,int userId,int pageRange, int pageSize);
	
	
    int totalMusic(String musicName, int userId);

collectMapper.xml

    <select id="findLoveMusicByUserId" resultType="com.example.onlinemusicserver.model.Music">
        select m.* from collect c,music m where m.musicId = c.musicId and c.userId = #{userId} limit #{pageSize} offset #{pageRange};
    </select>

    <select id="findLoveMusicByNameAndUserId" resultType="com.example.onlinemusicserver.model.Music">
        select m.* from collect c,music m where m.musicId = c.musicId and c.userId = #{userId} and m.title like concat('%',#{name},'%') limit #{pageSize} offset #{pageRange};
    </select>
    
    <select id="totalMusic" resultType="java.lang.Integer">
        select count(c.musicId) from collect c,music m where c.musicId = m.musicId and c.userId=#{userId}
        <if test="musicName != null">
            and m.title like concat('%',#{musicName},'%');
        </if>
    </select>

2.2.1.2 更改 Controller 代码

@RequestMapping("findLoveMusic")
    public ResponseBodyMessage<HashMap<String,Object>> findLoveMusic(@RequestParam(required = false) String musicName,
                                                          HttpServletRequest request,
                                                          Integer pageIndex) {
    
    
        HttpSession session = request.getSession(false);
        HashMap<String,Object> hash = new HashMap<>();
        if(session == null) {
    
    
            return new ResponseBodyMessage<>(-1,"当前未登录",null);
        }
        User user = (User) session.getAttribute(Constant.USER_SESSION_KEY);
        int userId = user.getUserId();
        if(pageIndex <= 0) {
    
    
            return new ResponseBodyMessage<>(-1,"下标错误",null);
        }
        int pageRange = (pageIndex - 1) * Constant.PAGE_SIZE;
        int totalMusic = collectService.totalMusic(musicName,userId);
        if(totalMusic != 0 && pageIndex > Math.ceil(totalMusic*1.0/Constant.PAGE_SIZE)){
    
    
            return new ResponseBodyMessage<>(-1,"下标错误",null);
        }
        List<Music> list = null;
        if(musicName == null && "".equals(musicName)) {
    
    
            list = collectService.findLoveMusicByUserId(userId,pageRange,Constant.PAGE_SIZE);
        }else{
    
    
            list = collectService.findLoveMusicByNameAndUserId(musicName,userId,pageRange,Constant.PAGE_SIZE);
        }
        hash.put("list",list);
        hash.put("totalMusic",totalMusic);
        return new ResponseBodyMessage<>(1,"查询成功!",hash);
    }

3. 配置文件

这里配置文件多创建2个.一个生产环境 一个测试环境

分别起名为
生存环境 application-prod.properties
测试环境 application-dev.properties

这样可以避免在上传服务器和在本地使用的时候频繁的去更改配置文件的信息.

application-dev.properties

spring.datasource.url=jdbc:mysql://localhost:3306/onlinemusicserver?characterEncoding=utf8&useSSL=true
spring.datasource.username=root
spring.datasource.password=0000
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

mybatis.mapper-locations=classpath:mapper/**Mapper.xml

spring.servlet.multipart.max-file-size = 15MB
spring.servlet.multipart.max-request-size=100MB


#debug=true
#
#logging.level.root=INFO
#logging.level.com.example.onlinemusic.mapper=debug
#
#logging.level.druid.sql.Statement=DEBUG
#logging.level.com.example=DEBUG

upload.path=E:/logs/
spring.datasource.url=jdbc:mysql://localhost:3306/onlinemusicserver?characterEncoding=utf8&useSSL=true
spring.datasource.username=root
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

mybatis.mapper-locations=classpath:mapper/**Mapper.xml

spring.servlet.multipart.max-file-size = 15MB
spring.servlet.multipart.max-request-size=100MB

upload.path=/root/musicLogs/

application.properties

spring.profiles.active=dev
#spring.profiles.active=prod

猜你喜欢

转载自blog.csdn.net/wwzzzzzzzzzzzzz/article/details/126541394