赞
踩
4、选择项目存放路径,就可以创建出一个 SpringBoot 项目
1、创建 config 包,在 config 包中创建 LoginInterceptor 类
4、在 UserMapper 接口中新增 selectByName 方法
4、在 UserController 类中添加 register 方法
2、在 MusicController 类中添加 playMusic 方法
4. 在 MusicController 类中添加 deleteByMusicId 方法
2. 在 MusicController 类中添加 deleteSelMusic 方法
4、在 MusicController 类中添加 findMusic 方法
4、在 LoveMusicController 类中添加 findLoveMusic 方法
4、在 LoveMusicController 类中添加 removeLoveMusic 方法
3、调整 MusicController 类中的 deleteMusicByMusicId 和 deleteSelMusic 方法
- #配置数据库
- spring.datasource.url=jdbc:mysql://127.0.0.1:3306/onlinemusic?characterEncoding=utf8&serverTimezone=UTC
- spring.datasource.username=你的用户名
- spring.datasource.password=你的密码
- spring.datasource.driver-class-name=com.mysql.jdbc.Driver
-
- #配置xml
- mybatis.mapper-locations=classpath:mybatis/**Mapper.xml
-
- # 音乐上传后的路径
- music.local.path=E:/SaveMusic/(填写存放歌曲的路径)
-
- #配置springboot上传文件的大小,默认每个文件的配置最大为15Mb,单次请求的文件的总数不能大于100Mb
- spring.servlet.multipart.max-file-size = 15MB
- spring.servlet.multipart.max-request-size=100MB
-
- # 配置springboot日志调试模式是否开启
- debug=true
-
- # 设置打印日志的级别,及打印sql语句
- #日志级别:trace,debug,info,warn,error
- #基本日志
- logging.level.root=INFO
- logging.level.com.example.onlinemusic.mapper=debug
- #扫描的包:druid.sql.Statement类和frank包
- logging.level.druid.sql.Statement=DEBUG
- logging.level.com.example=DEBUG
- -- 创建数据库
- drop database if exists `onlinemusic`;
- create database if not exists `onlinemusic` character set utf8;
- -- 使用数据库
- use `onlinemusic`;
-
- -- 用户表
- DROP TABLE IF EXISTS `user`;
- CREATE TABLE `user` (
- `userid` INT PRIMARY KEY AUTO_INCREMENT comment '用户id',
- `username` varchar(20) NOT NULL comment '用户名',
- `password` varchar(255) NOT NULL comment '密码'
- );
-
- -- 歌曲表
- DROP TABLE IF EXISTS `music`;
- CREATE TABLE `music` (
- `musicid` int PRIMARY KEY AUTO_INCREMENT comment '歌曲id',
- `title` varchar(50) NOT NULL comment '歌曲名称',
- `singer` varchar(30) NOT NULL comment '歌手',
- `time` varchar(13) NOT NULL comment '上传歌曲时间',
- `url` varchar(1000) NOT NULL comment '存放歌曲的路径',
- `userid` int(11) NOT NULL comment '上传歌曲的用户'
- );
-
- -- 歌曲收藏表
- DROP TABLE IF EXISTS `lovemusic`;
- CREATE TABLE `lovemusic` (
- `loveid` int PRIMARY KEY AUTO_INCREMENT comment '收藏歌曲的id',
- `user_id` int(11) NOT NULL comment '收藏歌曲的用户id',
- `music_id` int(11) NOT NULL comment '歌曲id'
- );
在 package com.example.musicserver 目录下创建一个 tools 包(工具包),在这个包中存放整个项目要使用的工具类。
- 设计统一的响应体工具类,因为做任何操作时都需要响应,所以封装一个通用的响应工具类,这个工具类设计成一个泛型类。
- package com.example.onlinemusic.tools;
-
- import lombok.Data;
-
- @Data
- public class ResponseBodyMessage <T>{
- private int status; //状态码
-
- private String message; // 返回的信息(出错的原因等)
-
- private T data; // 返回给前端的数据(因为返回的数据类型不确定,可能是 String,boolea,int ...,因此使用泛型)
-
- public ResponseBodyMessage(int status, String message, T data) {
- this.status = status;
- this.message = message;
- this.data = data;
- }
- }
- 这个类用来存储不变的常量。 例如:设置 session 对象中的 key 值,key 是一个不变的字符串。
- 如果在其他地方获取对应的 session 就可以通过这个类中的字符串进行获取。
- package com.example.onlinemusic.tools;
-
- public class Constant {
- public static final String USER_SESSION_KEY= "USERINFO_SESSION_KEY"; // 设置 session 中的 key 值
- }
MD5是一个安全的散列算法,输入两个不同的明文不会得到相同的输出值,根据输出值,不能得到原始的明文,即其过程不可逆; 但是虽然不可逆,但是不是说就是安全的。因为自从出现彩虹表后,这样的密码也"不安全"。
- 彩虹表:彩虹表就是一个庞大的、针对各种可能的字母组合预先计算好的哈希值的集合,不一定是针对MD5算法的,各种算法的都有,有了它可以快速的破解各类密码。越是复杂的密码,需要的彩虹表就越大,现在主流的彩虹表都是100G以上。
更安全的做法是加盐或者长密码等做法,让整个加密的字符串变的更长,破解时间变慢。密码学的应用安全,是建立在破解所要付出的成本远超出能得到的利益上的。
- 加盐的做法:盐是在每个密码中加入一些单词来变成一个新的密码,存入数据库当中。
(1)在 pom.xml 文件中添加依赖(添加到 <dependencies> </dependencies> 标签内)
- <!-- md5 依赖 -->
- <dependency>
- <groupId>commons-codec</groupId>
- <artifactId>commons-codec</artifactId>
- </dependency>
- <dependency>
- <groupId>org.apache.commons</groupId>
- <artifactId>commons-lang3</artifactId>
- <version>3.9</version>
- </dependency>
(2)在 tools 包中创建 MD5Util 类
- package com.example.onlinemusic.tools;
-
- import org.apache.commons.codec.digest.DigestUtils;
-
- public class MD5Util {
- // 定义一个固定的盐值
- private static final String salt = "1j2a3v4a5"; // 盐值可以自定义
-
- public static String md5(String src) {
- return DigestUtils.md5Hex(src);
- }
-
- /**
- * 第一次加密 :模拟前端自己加密,然后传到后端
- *
- * @param inputPass
- * @return
- */
- public static String inputPassToFormPass(String inputPass) {
- String str = "" + salt.charAt(1) + salt.charAt(3) + inputPass
- + salt.charAt(5) + salt.charAt(6);
- return md5(str);
- }
-
- /**
- * 第2次MD5加密
- *
- * @param formPass 前端加密过的密码,传给后端进行第2次加密
- * @param salt 用户数据库当中的盐值
- * @return
- */
- public static String formPassToDBPass(String formPass, String salt) {
- String str = "" + salt.charAt(0) + salt.charAt(2) + formPass + salt.charAt(5)
- + salt.charAt(4);
- return md5(str);
- }
-
- /**
- * 上面两个函数合到一起进行调用
- *
- * @param saltDB
- * @return
- * @paraminputPass
- */
- public static String inputPassToDbPass(String inputPass, String saltDB) {
- String formPass = inputPassToFormPass(inputPass);
- String dbPass = formPassToDBPass(formPass, saltDB);
- return dbPass;
- }
-
- public static void main(String[] args) {
- System.out.println("对用户输入密码进行第1次加密:" + inputPassToFormPass("123456"));
- System.out.println("对用户输入密码进行第2次加密:" + formPassToDBPass(inputPassToFormPass("123456"), salt));
- System.out.println("对用户输入密码进行第2次加密:" + inputPassToDbPass("123456", salt));
- }
- }
运行结果
不管运行多少次,这个密码是规定的。因为这里没有用随机盐值。当密码长度很大,盐值也是随机的情况下,密码的强度也加大了。破解成本也增加了。
- Bcrypt 就是一款加密工具,可以比较方便地实现数据的加密工作。也可以简单理解为它内部自己实现了随机加盐处理 。
- 使用MD5加密,每次加密后的密文其实都是一样的,这样就方便了MD5通过大数据的方式进行破解。
- Bcrypt生成的密文是60位的,而MD5的是32位的,因此 Bcrypt 破解难度更大。
(1)在 pom.xml 文件中添加依赖(添加到 <dependencies> </dependencies> 标签内)
- <!-- security依赖包 (加密)-->
- <dependency>
- <groupId>org.springframework.security</groupId>
- <artifactId>spring-security-web</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.security</groupId>
- <artifactId>spring-security-config</artifactId>
- </dependency>
(2)在springboot启动类添加下面的内容
- @SpringBootApplication(exclude =
- {org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.class})
(3)在 tools 包中创建 BCryptTest 测试类
- package com.example.onlinemusic.tools;
-
- import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
-
- public class BCryptTest {
- public static void main(String[] args) {
- //模拟从前端获得的密码
- String password = "123456";
- BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
- String newPassword = bCryptPasswordEncoder.encode(password);
- System.out.println("加密的密码为: "+newPassword);
-
- //使用matches方法进行密码的校验
- boolean same_password_result = bCryptPasswordEncoder.matches(password,newPassword);
-
- //返回true
- System.out.println("加密的密码和正确密码对比结果: "+same_password_result);
- boolean other_password_result = bCryptPasswordEncoder.matches("987654",newPassword);
-
- //返回false
- System.out.println("加密的密码和错误的密码对比结果: " + other_password_result);
- }
- }
运行结果(每次运行的生成的密码都不一样)
- encode方法:对用户密码进行加密。
- matches方法:参数一,待检验的未加密的密码 。参数二:从数据库中查询出的加密后密码 。
- BCrypt加密: 一种加盐的单向Hash,不可逆的加密算法,同一种明文(plaintext),每次加密后的密文都不一样,而且不可反向破解生成明文,破解难度很大。
- MD5加密: 是不加盐的单向Hash,不可逆的加密算法,同一个密码经过hash的时候生成的是同一个hash值,在大多数的情况下,有些经过md5加密的方法将会被破解。
- Bcrypt生成的密文是60位的。而MD5的是32位的。
- 目前,MD5和BCrypt比较流行。相对来说,BCrypt比MD5更安全,但加密更慢。
- 虽然BCrpyt也是输入的字符串+盐,但是与MD5+盐的主要区别是:每次加的盐不同(BCrpyt 中的盐值是随即生成的),导致每次生成的结果也不相同。无法比对!
- package com.example.onlinemusic.config;
-
- import com.example.onlinemusic.tools.Constant;
- import com.example.onlinemusic.tools.ResponseBodyMessage;
- import org.springframework.web.servlet.HandlerInterceptor;
-
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import javax.servlet.http.HttpSession;
-
- public class LoginInterceptor implements HandlerInterceptor {
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- HttpSession session = request.getSession(false);
- if(session == null || session.getAttribute(Constant.USER_SESSION_KEY)==null){
- return false;
- }
- return true;
- }
- }
- package com.example.onlinemusic.config;
-
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
- import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
- import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-
- @Configuration
- public class AppConfig implements WebMvcConfigurer {
-
- @Bean
- public BCryptPasswordEncoder getBCryptPasswordEncoder(){
- return new BCryptPasswordEncoder();
- }
-
- /**
- * 添加拦截器
- * @param registry
- */
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
- // 登录之后才可以访问其他页面
- LoginInterceptor loginInterceptor = new LoginInterceptor();
- registry.addInterceptor(loginInterceptor).
- // 拦截所有的
- addPathPatterns("/**")
- //排除所有的JS
- .excludePathPatterns("/js/**.js")
- //排除images下所有的元素
- .excludePathPatterns("/images/**")
- .excludePathPatterns("/css/**.css")
- .excludePathPatterns("/fronts/**")
- .excludePathPatterns("/player/**")
- .excludePathPatterns("/login.html")
- .excludePathPatterns("/register.html")
- //排除登录和注册接口
- .excludePathPatterns("/user/login")
- .excludePathPatterns("/user/register");
- }
- }
- 请求:
- {
- post, // 使用 post 请求
- /user/login // 请求路径
- data:{ username, password } // 传入的数据
- }
-
- 响应:
- {
- "status": 200,
- "message": "登录成功",
- "data": {
- "id": xxxxx,
- "username": xxxxxx,
- "password": xxxxxxxx
- }
-
- }
-
- 响应设计字段解释:
- {
- 状态码为 200 表示成功,-200表示失败
- 状态描述信息,描述此次请求成功或者失败的原因
- 返回的数据,请求成功后,需要给前端的数据信息(返回用户id,用户名)
- }
- package com.example.onlinemusic.model;
-
- import lombok.Data;
-
- @Data
- public class User {
- private int userId; // 用户id
- private String username; // 用户名
- private String password; // 密码
- }
在 package com.example.musicserver.mapper 包中创建 UserMapper 接口
- package com.example.onlinemusic.mapper;
-
- import com.example.onlinemusic.model.User;
- import org.apache.ibatis.annotations.Mapper;
-
- @Mapper
- public interface UserMapper {
- User login(User loginUser);
- }
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="com.example.onlinemusic.mapper.UserMapper">
- <select id="login" resultType="com.example.onlinemusic.model.User">
- select * from user where username=#{username} and password=#{password}
- </select>
-
- <select id="selectByName" resultType="com.example.onlinemusic.model.User">
- select * from user where username=#{username};
- </select>
-
- </mapper>
- // 通过用户名查询用户是否存在(用户名是唯一的)
- User selectByName(String username);
- package com.example.onlinemusic.controller;
-
- import com.example.onlinemusic.mapper.UserMapper;
- import com.example.onlinemusic.model.User;
- import com.example.onlinemusic.tools.Constant;
- import com.example.onlinemusic.tools.ResponseBodyMessage;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestParam;
- import org.springframework.web.bind.annotation.RestController;
-
- import javax.servlet.http.HttpServletRequest;
-
- @RestController
- @RequestMapping("/user")
- public class UserController {
- @Autowired
- private UserMapper userMapper;
-
- // 使用 BCrypt 对密码进行加密
- @Autowired
- private BCryptPasswordEncoder bCryptPasswordEncoder;
-
- @RequestMapping("/login")
- // 传入用户名和密码
- public ResponseBodyMessage<User> login(@RequestParam String username, @RequestParam String password, HttpServletRequest request){
-
- // 调用 UserMapper 接口
- User user = userMapper.selectByName(username);
-
- // 判断是否登录成功
- if(user != null){
- System.out.println("登录成功"); // 可以在控制台中打印登录信息
-
- // 判断当前用户输入的密码(password) 与 数据库中查询到的密码(加密的密码,getPassword())是否匹配
- boolean flag = bCryptPasswordEncoder.matches(password,user.getPassword());
-
- if(!flag){
- // 密码不匹配,登录失败
- return new ResponseBodyMessage<>(-200,"用户名或密码错误",user);
- }
-
- // 如果登录成功就将信息写入到 session 中(在 session 中存储了一个用户信息对象,此后可以随时从 session 中将这个对象取出来进行一些操作)
- request.getSession().setAttribute(Constant.USER_SESSION_KEY,user);
- // 状态码为200,表示登录成功,并返回用户信息
- return new ResponseBodyMessage<>(200,"登录成功",user);
- }else{
- System.out.println("登录失败");
- // 状态码为500,表示登录失败,并返回用户信息
- return new ResponseBodyMessage<>(-200,"用户名或密码错误",user);
-
- }
- }
- }
在数据库中插入一条数据,启动项目,使用 postman 进行测试。
- <script>
- $(function(){
- $("#submit").click(function(){
- // 点击登录按钮,获取用户名和密码
- var username = $("#username").val();
- var password = $("#password").val();
-
- // 判断用户名和密码是否为空(使用 trim 方法,防止输入空格)
- if(username.trim() == "" || password.trim() == ""){
- alert("账号或密码不能为空");
- return;
- }
- // 如果用户名和密码不为空,使用 Ajax 传入请求
- $.ajax({
- type:"POST",
- url:"/user/login",
- data:{
- "username":username,
- "password":password
- },
- // 服务器返回的数据类型
- dataType:"json",
- // 请求成功,服务器返回数据
- success:function(data){
- console.log(data);
- // 如果状态码为 200,表示登录成功
- if(data.status == 200){
- alert("登录成功");
- // 跳转到指定页面
- window.location.href="list.html";
- }else{
- alert("登录失败,账号或密码错误");
- // 登录失败,将用户名或密码置空
- $("#username").val("");
- $("#password").val("");
- }
- }
- });
- });
- });
-
- $(function () {
- $("#register").click(function () {
- window.location.href="register.html";
- });
- });
-
- </script>
- 请求:
- {
- post, // 使用 post 请求
- /user/register // 请求路径
- data:{ username, password } // 传入的数据
- }
-
- 响应:
- {
- "status": 200,
- "message": "注册成功",
- "data": {
- "id": xxxxx,
- "username": xxxxxx,
- "password": xxxxxxxx
- }
-
- }
-
- 响应设计字段解释:
- {
- 状态码为 200 表示成功,-200表示失败
- 状态描述信息,描述此次请求成功或者失败的原因
- 返回的数据,请求成功后,需要给前端的数据信息(返回用户id,用户名)
- }
- // 输入用户名和密码,注册账号
- boolean insertInToValues(String username,String password);
- <insert id="insertInToValues" >
- insert into user(username,password)
- values(#{username},#{password});
- </insert>
- /**
- * 用户注册
- * @param username
- * @param password
- * @return
- */
- @RequestMapping("/register")
- public ResponseBodyMessage<Boolean> register(@RequestParam String username,@RequestParam String password) {
- User user1 = userMapper.selectByName(username);
- if(user1 != null) {
- return new ResponseBodyMessage<>(-1,"当前用户已经存在",false);
- }else {
- String newPassword = bCryptPasswordEncoder.encode(password);
- boolean flag = userMapper.insertInToValues(username,newPassword);
- if(flag == true){
- return new ResponseBodyMessage<>(200,"注册成功",true);
- }else{
- return new ResponseBodyMessage<>(-200,"注册失败",false);
- }
- }
- }
- <script>
- $(function(){
- $("#register").click(function(){
- var username = $("#username").val();
- var password = $("#password").val();
- $.ajax({
- url: "/user/register",
- type: "POST",
- data:{
- "username":username,
- "password":password
- },
- dataType:"json",
- success: function(data){
- console.log(data);
- if(data.status == 200) {
- alert("注册成功");
- window.location.href="login.html";
- }else{
- alert("注册失败");
- $("#username").val("");
- $("#password").val("");
- $("#repassword").val("");
- }
- }
- })
- })
- });
- </script>
- 请求:
- {
- post, // 使用 post 请求
- /music/upload // 请求路径
- {singer,MultipartFile file},//上传歌手,歌曲文件
- }
-
- 响应:
- {
- "status": 200,
- "message": "上传成功!",
- "data": true
- }
-
- 响应设计字段解释:
- {
- 状态码为 200 表示成功,-200 表示失败
- 状态描述信息,描述此次请求成功或者失败的原因
- 返回的数据,请求成功后,需要给前端的数据信息,true 表示上传成功,false 表示上传失败
- }
- package com.example.onlinemusic.model;
-
- import lombok.Data;
-
- @Data
- public class Music {
- private int musicId; // 歌曲id
- private String title; // 歌曲名称
- private String singer; //歌手
- private String time; // 上传歌曲的时间
- private String url; // 上传歌曲的路径
- private int userId; // 上传歌曲的用户
- }
- package com.example.onlinemusic.mapper;
-
- import org.apache.ibatis.annotations.Mapper;
-
- @Mapper
- public interface MusicMapper {
- /**
- * 插入音乐
- * @param title
- * @param singer
- * @param time
- * @param url
- * @param userId
- * @return
- */
- int insert(String title,String singer,String time,String url,int userId);
-
- /**
- * 查询歌曲名
- * @param title
- * @return
- */
- List<Music> selectBytitle(String title);
- }
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="com.example.onlinemusic.mapper.UserMapper">
-
- <insert id="insert">
- insert into music(title,singer,time,url,userId)
- values(#(title),#(singer),#(time),#(url),#(userId));
- </insert>
-
- <select id="selectBytitle" resultType="com.example.onlinemusic.model.Music">
- select * from music where title = #{title};
- </select>
-
- </mapper>
- package com.example.onlinemusic.controller;
-
- import com.example.onlinemusic.mapper.LoveMusicMapper;
- import com.example.onlinemusic.mapper.MusicMapper;
- import com.example.onlinemusic.model.Music;
- import com.example.onlinemusic.model.User;
- import com.example.onlinemusic.tools.Constant;
- import com.example.onlinemusic.tools.ResponseBodyMessage;
- import org.apache.ibatis.binding.BindingException;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.http.ResponseEntity;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestParam;
- import org.springframework.web.bind.annotation.RestController;
- import org.springframework.web.multipart.MultipartFile;
-
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import javax.servlet.http.HttpSession;
- import java.io.File;
- import java.io.IOException;
- import java.nio.file.Files;
- import java.text.SimpleDateFormat;
- import java.util.Date;
- import java.util.List;
-
-
- @RestController
- @RequestMapping("/music")
- public class MusicController {
-
- // 在配置文件中添加歌曲路径
- @Value("${music.local.path}")
- private String SAVE_PATH;
-
- @Autowired
- private MusicMapper musicMapper;
-
- @Autowired
- private LoveMusicMapper loveMusicMapper;
-
- /**
- * 上传音乐
- * 请求路径:/music/upload
- * @param singer 上传歌手
- * @param file 上传歌曲
- * @param request 请求,验证是否登录
- * @return 返回true表示上传成功,返回false表示上传失败
- */
- @RequestMapping("/upload")
- public ResponseBodyMessage<Boolean> insertMusic(@RequestParam String singer, @RequestParam ("filename")MultipartFile file, HttpServletRequest request, HttpServletResponse response){
-
- // 1. 检查是否登录
- HttpSession session = request.getSession(false);
- if(session == null || session.getAttribute(Constant.USER_SESSION_KEY)==null){
- System.out.println("没有登录");
- return new ResponseBodyMessage<>(-200,"请登录后再进行上传",false);
- }
-
- // 2. 获取的是文件的完整名称,包括文件名称+文件拓展名
- String fileNameAndType = file.getOriginalFilename();
-
- // 3. 查询数据库中是否存在当前要上传的音乐(歌曲名+歌手)
- /**
- * 获取标题(标题不包含后缀.mp3)
- * 使用 lastIndexOf 从后向前找第一个 .
- */
- int index = fileNameAndType.lastIndexOf(".");
- String title = fileNameAndType.substring(0,index);
-
- // 使用 list 存放歌曲,获取歌曲名
- List<Music> list = musicMapper.selectBytitle(title);
- if(list != null){
- for(Music music : list){
- // 判断当前上传的歌曲+歌手在数据库中是否存在,如果存在则上传失败(歌曲名+歌手 不能重复)
- if(music.getSinger().equals(singer)){
- return new ResponseBodyMessage<>(-200,"上传失败,数据库中存在此歌曲,不能重复上传",false);
- }
- }
- }
-
- // 2. 数据上传到服务器
-
- // 上传文件路径
- String path = SAVE_PATH+fileNameAndType;
-
- // 上传文件
- File dest = new File(path);
- if(!dest.exists()){
- //如果路径不存在就创建目录
- dest.mkdir();
- }
- try {
- // 将接收到的文件传输到给定目标路径
- file.transferTo(dest);
- } catch (IOException e) {
- e.printStackTrace();
- return new ResponseBodyMessage<>(-200,"上传失败,服务器出现问题",false);
- }
-
- // 3. 判断上传的文件是否为mp3文件(判断是否存在 TAG 字符)
- File file1 = new File(path);
- byte[] bytes = null;
- try {
- bytes = Files.readAllBytes(file1.toPath());
- if(bytes == null){
- return new ResponseBodyMessage<>(-200,"上传失败,文件不存在",false);
- }
- String str = new String(bytes);
- if(!str.contains("TAG")){
- file1.delete();
- return new ResponseBodyMessage<>(-200,"上传的文件不是mp3文件",false);
- }
- } catch (IOException e) {
- e.printStackTrace();
- return new ResponseBodyMessage<>(-200,"上传失败,服务器出现问题",false);
- }
-
- // 4. 将数据上传到数据库中(1. 准备数据 2. 调用 insert)
-
-
- /**
- * 获取 userId
- * 登录成功后将用户信息写到 session 中,通过 session 中key值(Constant.USERINFO) 就可以获取到对应的 value 值(用户信息)
- */
- User user = (User)session.getAttribute(Constant.USER_SESSION_KEY);
- // 获取用户Id
- int userId = user.getUserId();
-
- /**
- * url 的作用: 播放音乐->发送 http 请求
- */
- String url = "/music/get?path="+title; // 将 url 存入数据库时不用加后缀 .mp3,在取数据的时候加一个后缀就可以了
-
- /**
- * 获取上传的时间
- * 将获取的时间格式化为:年-月-日 的形式
- */
- SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
- String time = simpleDateFormat.format(new Date());
-
- // 插入数据
- try {
- int ret = musicMapper.insert(title,singer,time,url,userId);
- if(ret == 1){
- // 数据插入成功
- // 这里应该跳转到音乐列表页面
- response.sendRedirect("/list.html");
- return new ResponseBodyMessage<>(200,"数据库上传成功",true);
- }else{
- // 数据插入失败
- return new ResponseBodyMessage<>(-200,"数据库上传失败",false);
- }
- }catch (BindingException | IOException e){
- // 数据库上传失败,将上传到文件夹中的数据删除
- dest.delete();
- e.printStackTrace();
- return new ResponseBodyMessage<>(-200,"数据库上传失败",false);
- }
- }
-
- /**
- * 播放音乐
- * 请求路径:/music/get?get=xxx.mp3
- * @param path
- * @return
- */
- @RequestMapping("/get")
- public ResponseEntity<byte[]> playMusic(@RequestParam String path) {
- File file = new File(SAVE_PATH+path);
- byte[] bytes = null;
- try {
- bytes = Files.readAllBytes(file.toPath()); // 将文件路径中的文件以字节的形式读取,放到 bytes 数组中
- if(bytes == null){
- // 如果没有读取的文件,则返回状态码 400
- return ResponseEntity.badRequest().build();
- }
- // 成功读取到文件
- return ResponseEntity.ok(bytes);
- } catch (IOException e) {
- e.printStackTrace();
- }
- // 如果没有读取的文件,则返回状态码 400
- return ResponseEntity.badRequest().build();
- }
-
- /**
- * 删除单个音乐
- * 请求路径:/music/delete?musicId=x
- * @param musicId
- * @return
- */
- @RequestMapping("/delete")
- public ResponseBodyMessage<Boolean> deleteMusicByMusicId(@RequestParam String musicId){
- /**
- * 1. 检查待删除的音乐是否存在
- * 2. 如果存在要删除的音乐
- * 1. 删除数据库中的数据
- * 2. 删除服务器上的数据
- */
- // 检查待删除的音乐是否存在
- Music music = musicMapper.findMusicById(Integer.parseInt(musicId));
- if(music == null){
- System.out.println("在控制台打印日志:没有要删除的音乐id");
- return new ResponseBodyMessage<>(-200,"要删除的音乐不存在",false);
- }else{
- // 调用 musicMapper 接口中的 deleteMusicById 方法删除数据库中的数据
- int ret = musicMapper.deleteMusicById(Integer.parseInt(musicId));
-
- if(ret == 1){
- // 成功删除数据库中的数据
- /*int index = music.getUrl().lastIndexOf("=");
- String fileName = music.getUrl().substring(index+1);*/
-
- String fileName = music.getTitle();
- // 根据存放音乐的路径删除服务器中的数据
- File file = new File(SAVE_PATH+fileName+".mp3");
- System.out.println("在控制台打印日志:当前音乐的路径:"+file.getPath());
- //对删除服务器中的数据进行判断
- if(file.delete()){
- // 删除成功
- return new ResponseBodyMessage<>(200,"音乐删除成功",true);
- }else{
- return new ResponseBodyMessage<>(-200,"服务器中的音乐删除失败",false);
- }
- }else{
- return new ResponseBodyMessage<>(-200,"数据库中的音乐删除失败",false);
- }
- }
- }
-
- /**
- * 批量删除选中的音乐
- * 请求路径:/music/deleteSel
- * @param musicId
- * @return
- */
- @RequestMapping("/deleteSel")
- public ResponseBodyMessage<Boolean> deleteSelMusic(@RequestParam("musicId[]") List<Integer> musicId) {
- System.out.println("在控制台打印日志:所有音乐的 Id:"+musicId);
- int sum = 0; // 统计删除的音乐
- for (int i = 0; i < musicId.size(); i++) {
- Music music = musicMapper.findMusicById(musicId.get(i));
- if (music == null) {
- System.out.println("没有要删除的音乐id");
- return new ResponseBodyMessage<>(-200, "要删除的音乐不存在", false);
- }
- int ret = musicMapper.deleteMusicById(musicId.get(i));
- if (ret == 1) {
- // 成功删除数据库中的数据
- String fileName = music.getTitle();
- // 根据存放音乐的路径删除服务器中的数据
- File file = new File(SAVE_PATH + fileName + ".mp3");
- System.out.println("当前音乐的路径:" + file.getPath());
- //对删除服务器中的数据进行判断
- if (file.delete()) {
- // 成功删除一条数据,sum 就加上 ret(数据库中成功删除)
- sum += ret;
- } else {
- return new ResponseBodyMessage<>(-200, "服务器中的音乐删除失败", false);
- }
- }else{
- return new ResponseBodyMessage<>(-200,"数据库中的音乐删除失败",false);
- }
- }
- if(sum == musicId.size()){
- // 选中的数据全部删除成功
- System.out.println("在控制台打印日志:选择中的歌曲删除成功");
- return new ResponseBodyMessage<>(200,"音乐删除成功",true);
- }else{
- System.out.println("在控制台打印日志:选择中的歌曲删除失败");
- return new ResponseBodyMessage<>(-200,"音乐删除失败",false);
- }
- }
-
- /**
- * 查询音乐
- * @param musicName
- * @return
- */
- @RequestMapping("/findmusic")
- public ResponseBodyMessage<List<Music>> findMusic(@RequestParam(required = false) String musicName){
- List<Music> musicList = null;
- if(musicName != null){
- // 模糊查询,根据歌曲名查询指定的歌曲
- musicList = musicMapper.findMusicByName(musicName);
- }else{
- // 查询所有的音乐
- musicList = musicMapper.findMusic();
- }
- // 查询成功,返回查询到的音乐信息
- return new ResponseBodyMessage<>(200,"查询成功",musicList);
- }
- }
- <div class="upload-container">
- <form method="post" enctype="multipart/form-data" action="/music/upload">
- <div class="upload-dialog">
- <strong>上传本地音乐</strong>
- <em>XiaoXiangYeYu's music upload_music</em>
- <div class="row">
- <span>音乐</span>
- <input type="file" id="file" name="filename" placeholder="上传歌曲" class="upload_txtbx"/>
- </div>
- <div class="row">
- <span>歌手</span>
- <input type="text" id="singer" name="singer" placeholder="请输入歌手名" class="upload_txtbx"/>
- </div>
- <div class="row">
- <input type="submit" id="submit" value="上传歌曲" class="submit_btn"/>
- </div>
- </div>
- </form>
- </div>
- 请求:
- {
- get, // 使用 get 请求
- /music/get?path=xxx.mp3 // 请求路径(数据库中存储的 url)
- }
-
- 响应:
- {
- 音乐数据本身的字节信息 // 服务器将数据以字节的形式返回给客户端,客户端获取到信息后就可以进行解析,然后播放音乐
- }
- /**
- * 播放音乐
- * 请求路径:/music/get?paht=xxx.mp3
- * @param path
- * @return
- */
- @RequestMapping("/get")
- public ResponseEntity<byte[]> playMusic(@RequestParam String path) {
- File file = new File(SAVE_PATH+path);
- byte[] bytes = null;
- try {
- bytes = Files.readAllBytes(file.toPath()); // 将文件路径中的文件以字节的形式读取,放到 bytes 数组中
- if(bytes == null){
- // 如果没有读取的文件,则返回状态码 400
- return ResponseEntity.badRequest().build();
- }
- // 成功读取到文件
- return ResponseEntity.ok(bytes);
- } catch (IOException e) {
- e.printStackTrace();
- }
- // 如果没有读取的文件,则返回状态码 400
- return ResponseEntity.badRequest().build();
- }
- <script>
- var audios = document.getElementsByTagName("audio");
- // 暂停函数
- function pauseAll() {
- var self = this;
- [].forEach.call(audios, function (i) {
- // 将audios中其他的audio全部暂停
- i !== self && i.pause();
- })
- }
- // 给play事件绑定暂停函数
- [].forEach.call(audios, function (i) {
- i.addEventListener("play", pauseAll.bind(i));
- });
- </script>
- 请求:
- {
- post, // 使用 post 请求
- /music/delete, // 请求路径
- musicId // 要删除歌曲的 id
- }
-
- 响应:
- {
- "status": 200,
- "message": "删除成功!",
- "data": true
- }
-
- 响应设计字段解释:
- {
- 状态码为 200 表示成功,-200 表示失败
- 状态描述信息,描述此次请求成功或者失败的原因
- 返回的数据,请求成功后,需要给前端的数据信息,true 表示删除成功,false 表示删除失败
- }
- /**
- * 通过音乐 Id 查询当前音乐是否存在
- * @param musicId
- * @return
- */
- Music findMusicById(int musicId);
-
- /**
- * 通过当前音乐 Id 删除音乐
- * @param musicId
- * @return
- */
- int deleteMusicById(int musicId);
- <select id="findMusicById" resultType="com.example.onlinemusic.model.Music">
- select * from music where musicid = #{musicid};
- </select>
-
- <delete id="deleteMusicById" parameterType="java.lang.Integer">
- delete from music where musicid = #{musicid};
- </delete>
- /**
- * 删除单个音乐
- * 请求路径:/music/delete?musicId=x
- * @param musicId
- * @return
- */
- @RequestMapping("/delete")
- public ResponseBodyMessage<Boolean> deleteByMusicId(@RequestParam String musicId){
- /**
- * 1. 检查待删除的音乐是否存在
- * 2. 如果存在要删除的音乐
- * 1. 删除数据库中的数据
- * 2. 删除服务器上的数据
- */
- // 检查待删除的音乐是否存在
- Music music = musicMapper.findMusicById(Integer.parseInt(musicId));
- if(music == null){
- System.out.println("在控制台打印日志:没有要删除的音乐id");
- return new ResponseBodyMessage<>(-200,"要删除的音乐不存在",false);
- }else{
- // 调用 musicMapper 接口中的 deleteMusicById 方法删除数据库中的数据
- int ret = musicMapper.deleteMusicById(Integer.parseInt(musicId));
-
- if(ret == 1){
- // 成功删除数据库中的数据
- String fileName = music.getTitle();
-
- // 根据存放音乐的路径删除服务器中的数据
- File file = new File(SAVE_PATH+fileName+".mp3");
- System.out.println("在控制台打印日志:当前音乐的路径:"+file.getPath());
-
- //对删除服务器中的数据进行判断
- if(file.delete()){
- // 删除成功
- return new ResponseBodyMessage<>(200,"音乐删除成功",true);
- }else{
- return new ResponseBodyMessage<>(-200,"服务器中的音乐删除失败",false);
- }
- }else{
- return new ResponseBodyMessage<>(-200,"数据库中的音乐删除失败",false);
- }
- }
- }
- function deleteInfo(obj){
- console.log(obj);
- $.ajax({
- url:"/music/delete",
- type:"POST",
- data:{
- "musicId":obj
- },
- dataType:"json",
-
- success:function(data){
- console.log(data);
- if(data.data == true){
- alert("删除成功,重新加载当前页面");
- window.location.href = "list.html";
- }else{
- alert("删除失败");
- }
- }
-
- });
- }
- 请求:
- {
- post, // 使用 post 请求
- /music/deleteSel, // 请求路径
- data:{
- "id":musicId // 要删除的歌曲 id 的数组
- }
- }
-
- 响应:
- {
- "status": 200,
- "message": "批量删除成功!",
- "data": true
- }
-
- 响应设计字段解释:
- {
- 状态码为 200 表示成功,-200 表示失败
- 状态描述信息,描述此次请求成功或者失败的原因
- 返回的数据,请求成功后,需要给前端的数据信息,true 表示删除成功,false 表示删除失败
- }
- /**
- * 批量删除选中的音乐
- * 请求路径:/music/deleteSel
- * @param musicId
- * @return
- */
- @RequestMapping("/deleteSel")
- public ResponseBodyMessage<Boolean> deleteSelMusic(@RequestParam("musicId[]") List<Integer> musicId) {
- System.out.println("在控制台打印日志:所有音乐的 Id:"+musicId);
- int sum = 0; // 统计删除的音乐
- for (int i = 0; i < musicId.size(); i++) {
- Music music = musicMapper.findMusicById(musicId.get(i));
- if (music == null) {
- System.out.println("没有要删除的音乐id");
- return new ResponseBodyMessage<>(-200, "要删除的音乐不存在", false);
- }
- int ret = musicMapper.deleteMusicById(musicId.get(i));
- if (ret == 1) {
- // 成功删除数据库中的数据
- String fileName = music.getTitle();
- // 根据存放音乐的路径删除服务器中的数据
- File file = new File(SAVE_PATH + fileName + ".mp3");
- System.out.println("当前音乐的路径:" + file.getPath());
- //对删除服务器中的数据进行判断
- if (file.delete()) {
- // 成功删除一条数据,sum 就加上 ret(数据库中成功删除)
- sum += ret;
- } else {
- return new ResponseBodyMessage<>(-200, "服务器中的音乐删除失败", false);
- }
- }else{
- return new ResponseBodyMessage<>(-200,"数据库中的音乐删除失败",false);
- }
- }
- if(sum == musicId.size()){
- // 选中的数据全部删除成功
- System.out.println("在控制台打印日志:整体删除成功");
- return new ResponseBodyMessage<>(200,"音乐删除成功",true);
- }else{
- System.out.println("在控制台打印日志:整体删除失败");
- return new ResponseBodyMessage<>(-200,"音乐删除失败",false);
- }
- }
- }
- $(function(){
- $("#submit1").click(function(){
- var name = $("#exampleInputName2").val();
- load(name);
- // window.location.href = "findMusic?musicName="+name;
- });
-
- $.when(load).done(function(){
- $("#delete").click(function(){
- var id = new Array(); // 音乐Id
- var i = 0; // 数组下标
- // 遍历checkbox
- $("input:checkbox").each(function(){
- // 如果被选中,this代表发生事件的dom元素,<input>
- if($(this).is(":checked")){
- id[i] = $(this).attr("id");
- i++;
- }
- });
- console.log(id);
-
- $.ajax({
- url:"/music/deleteSel",
- data:{
- "musicId":id
- },
- dataType:"json",
- type:"POST",
-
- success:function(obj){
- if(obj.data == true){
- alert("删除成功");
- window.location.href = "list.html";
- }else{
- alert("删除失败");
- }
- }
- });
- });
- });
-
- });
此处查询需要满足两个功能:
- 支持模糊查询
- 支持传入参数为空,当参数为空时默认查询到所有的音乐
- 请求:
- {
- get, // 使用 get 请求
- /music/findmusic, // 请求路径
- data:{musicName:musicName}, // 根据歌曲名进行查询
- }
-
- 响应:【不给musicName传参】// 如果不传参时默认查询到所有的音乐
- {
- "status": 200,
- "message": "查询到了歌曲的信息",
- "data": [
- {
- "id": 19,
- "title": "张靓颖 - 我的梦",
- "singer": "张靓颖",
- "url": "/music/get?path=张靓颖 - 我的梦",
- "time": "2022-08-20",
- "userid": 1
- },
- {
- "id": 20,
- "title": "纯音乐 - Victory",
- "singer": "张三",
- "url": "/music/get?path=纯音乐 - Victory",
- "time": "2022-03-20",
- "userid": 1
- }]
- }
-
- 响应:【给musicName传参】// 如果传入参数返回指定查询的歌曲
- {
- "status": 200,
- "message": "查询到了歌曲的信息",
- "data": [
- {
- "id": 19,
- "title": "张靓颖 - 我的梦",
- "singer": "张靓颖",
- "url": "/music/get?path=张靓颖 - 我的梦",
- "time": "2022-08-20",
- "userid": 1
- }]
- }
-
- 响应设计字段解释:
- {
- 状态码为 200 表示成功
- 状态描述信息,描述此次请求成功
- 返回的数据,请求成功后给前端的数据信息,返回查询到的音乐信息(歌曲id、歌曲名、歌手、存放歌曲的路径、上传时间、上传用户的id)
- }
- /**
- * 查询所有的音乐
- * @return
- */
- List<Music> findMusic();
-
- /**
- * 模糊查询,根据歌曲名查询指定的歌曲
- * @param musicName
- * @return
- */
- List<Music> findMusicByName(String musicName);
- <select id="findMusic" resultType="com.example.onlinemusic.model.Music">
- select * from music ;
- </select>
-
- <select id="findMusicByName" resultType="com.example.onlinemusic.model.Music">
- select * from music where title like concat('%', #{musicName}, '%');
- </select>
- /**
- * 查询音乐
- * @param musicName
- * @return
- */
- @RequestMapping("/findmusic")
- public ResponseBodyMessage<List<Music>> findMusic(@RequestParam(required = false) String musicName){
- List<Music> musicList = null;
- if(musicName != null){
- // 模糊查询,根据歌曲名查询指定的歌曲
- musicList = musicMapper.findMusicByName(musicName);
- }else{
- // 查询所有的音乐
- musicList = musicMapper.findMusic();
- }
- // 查询成功,返回查询到的音乐信息
- return new ResponseBodyMessage<>(200,"查询成功",musicList);
- }
- <script type="text/javascript">
- // 查询
- $(function(){
- load();
- });
-
- // musicName 可以传参(模糊匹配),也可以不传参(不传参默认传入的是所有的音乐)
- function load(musicName){
-
- $.ajax({
- type:"GET",
- url:"/music/findmusic",
- data:{
- "musicName":musicName
- },
- // 服务器返回的数据类型
- dataType:"json",
-
- // obj 查找存储的所有信息
- success:function(obj){
- console.log(obj);
- // data数组,存放歌曲信息
- var data = obj.data;
-
- var s = '';
- for(var i=0;i<data.length;i++){
-
- var musicUrl = data[i].url+".mp3";
- console.log(musicUrl);
- s += '<tr>';
- s += '<th> <input id="'+data[i].musicId+'"type="checkbox"> </th>';
- s += '<td>'+ data[i].title +'</td>';
- s += '<td>'+ data[i].singer +'</td>';
- s += "<td <a href=\"\"> <audio src= \""+ musicUrl+"\" + controls=\"controls\" preload=\"auto\" loop=\"loop\" class=\"audio_btn\"> >" + "</audio> </a> </td>";
- s += '<td> <button class = "btn btn-primary" onclick="loveInfo('+data[i].musicId+')"> 收藏歌曲 </button>' + '</td>';
- s += '<td> <button class="btn btn-primary" onclick="deleteInfo('+ data[i].musicId +')" >删除歌曲</button>'+'</td>';
- s += '</tr>';
- }
-
- $("#info").html(s);
- }
- });
- }
- 请求:
- {
- post, // 使用 post 请求
- /lovemusic/likeMusic // 请求路径
- data: music_id //音乐id
- }
-
- 响应:
- {
- "status": 0,
- "message": "点赞音乐成功",
- "data": true
- }
-
- 响应设计字段解释:
- {
- 状态码为 200 表示成功,-200 表示失败
- 状态描述信息,描述此次请求成功或者失败的原因
- 返回的数据,请求成功后,需要给前端的数据信息,true 表示收藏成功,false 表示收藏失败
- }
- package com.example.onlinemusic.model;
-
- import lombok.Data;
-
- @Data
- public class LoveMusic {
- private int loveId;
- private int userId;
- private int musicId;
- }
- package com.example.onlinemusic.mapper;
-
- import com.example.onlinemusic.model.LoveMusic;
- import org.apache.ibatis.annotations.Mapper;
-
- @Mapper
- public interface LoveMusicMapper {
-
- /**
- * 查询是否已经收藏过该音乐
- * @param userId
- * @param musicId
- * @return
- */
- LoveMusic findLoveMusic(int userId, int musicId);
-
- /**
- * 收藏音乐
- * @param userId
- * @param musicId
- * @return
- */
- boolean insertLoveMusic(int userId,int musicId);
-
- }
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="com.example.onlinemusic.mapper.LoveMusicMapper">
-
- <select id="findLoveMusic" resultType="com.example.onlinemusic.model.LoveMusic">
- select * from lovemusic where user_id = #{userId} and music_id = #{musicId};
- </select>
-
- <insert id="insertLoveMusic">
- insert into lovemusic(user_id,music_id) values(#{userId}, #{musicId});
- </insert>
-
- </mapper>
- package com.example.onlinemusic.controller;
-
- import com.example.onlinemusic.mapper.LoveMusicMapper;
- import com.example.onlinemusic.model.LoveMusic;
- import com.example.onlinemusic.model.Music;
- import com.example.onlinemusic.model.User;
- import com.example.onlinemusic.tools.Constant;
- import com.example.onlinemusic.tools.ResponseBodyMessage;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestParam;
- import org.springframework.web.bind.annotation.RestController;
-
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpSession;
- import java.util.List;
-
- @RestController
- @RequestMapping("/lovemusic")
- public class LoveMusicController {
-
- @Autowired
- private LoveMusicMapper loveMusicMapper;
-
- /**
- * 收藏音乐
- * 请求路径:/lovemusic/likeMusic?music_id=x
- * @param music_id 传入的音乐 id
- * @param request
- * @return
- */
- @RequestMapping("/likeMusic")
- public ResponseBodyMessage<Boolean> likeMusic(@RequestParam String music_id, HttpServletRequest request){
-
- // 1. 检查是否登录
- HttpSession session = request.getSession(false);
- if(session == null || session.getAttribute(Constant.USER_SESSION_KEY)==null){
- System.out.println("登录失败");
- return new ResponseBodyMessage<>(-200,"请登录后再进行收藏",false);
- }
-
- // 2. 获取 usrId
- User user = (User)session.getAttribute(Constant.USER_SESSION_KEY);
- int userId = user.getUserId();
- System.out.println("在控制台打印日志:user_id:"+userId);
-
- // 3. 将传入的 music_id 转换成整型(获取 musicId)
- int musicId = Integer.parseInt(music_id);
- System.out.println("在控制台打印日志:music_id:"+musicId);
-
- // 4. 判断当前歌曲是否被收藏过
- LoveMusic loveMusic = loveMusicMapper.findLoveMusic(userId,musicId);
- if(loveMusic != null){
- // 之前收藏过这首歌曲
- return new ResponseBodyMessage<>(-200,"该歌曲已被收藏,请勿重复收藏",false);
- }else{
- boolean ret = loveMusicMapper.insertLoveMusic(userId,musicId);
- if(ret){
- return new ResponseBodyMessage<>(200,"收藏成功",true);
- }else{
- return new ResponseBodyMessage<>(-200,"收藏失败",false);
- }
- }
- }
- }
- function loveInfo(obj){
- $.ajax({
- type:"POST",
- url:"/lovemusic/likeMusic",
- data:{
- "music_id":obj
- },
- dataType:"json",
-
- success:function(data){
- if(data.data == true){
- alert("收藏成功");
- window.location.href = "loveMusic.html";
- }else{
- alert("收藏失败");
- }
- }
- });
- }
此处查询需要满足两个功能:
- 支持模糊查询
- 支持传入参数为空,当参数为空时默认查询到所有的音乐
- 请求:
- {
- get, // 使用 get 请求
- /lovemusic/findlovemusic, // 请求路径
- data:{musicName:musicName}, // 根据歌曲名进行查询
- }
-
- 响应:【不传入musicName参数】// 如果不传参时默认查询到所有的音乐
- {
- "status": 200,
- "message": "查询到了所有的收藏的音乐",
- "data": [
- {
- "id": 19,
- "title": "张靓颖 - 我的梦",
- "singer": "张靓颖",
- "url": "/music/get?path=张靓颖 - 我的梦",
- "time": "2022-08-20",
- "userid": 1
- },
- {
- "id": 20,
- "title": "纯音乐 - Victory",
- "singer": "张三",
- "url": "/music/get?path=纯音乐 - Victory",
- "time": "2022-03-20",
- "userid": 1
- }]
- }
-
- 响应:【传入musicName参数】// 如果传入参数返回指定查询的歌曲
- {
- "status": 200,
- "message": "查询到了收藏歌曲的信息",
- "data": [
- {
- "id": 19,
- "title": "张靓颖 - 我的梦",
- "singer": "张靓颖",
- "url": "/music/get?path=张靓颖 - 我的梦",
- "time": "2022-08-20",
- "userid": 1
- }]
- }
-
- 响应设计字段解释:
- {
- 状态码为 200 表示成功
- 状态描述信息,描述此次请求成功
- 返回的数据,请求成功后给前端的数据信息,返回查询到的音乐信息(歌曲id、歌曲名、歌手、存放歌曲的路径、上传时间、上传用户的id)
- }
- /**
- * 查询当前用户收藏的所有音乐
- * @param userId
- * @return
- */
- List<Music> findLoveMusicByUserId(int userId);
-
- /**
- * 模糊查询,根据歌曲名查询当前用户指定的收藏歌曲
- * @param musicName
- * @param userId
- * @return
- */
- List<Music> findLoveMusicByMusicNameAndUserId(String musicName,int userId);
- <select id="findLoveMusicByUserId" resultType="com.example.onlinemusic.model.Music">
- select music.*
- from music,lovemusic
- where music.musicid = lovemusic.music_id and user_id = #{userId};
- </select>
-
- <select id="findLoveMusicByMusicNameAndUserId" resultType="com.example.onlinemusic.model.Music">
- select music.*
- from music,lovemusic
- where music.musicid = lovemusic.music_id and user_id = #{userId} and title like concat('%', #{musicName}, '%');
- </select>
- @RequestMapping("findlovemusic")
- public ResponseBodyMessage<List<Music>> findLoveMusic(@RequestParam(required = false) String musicName,HttpServletRequest request){
- // 1. 检查是否登录
- HttpSession session = request.getSession(false);
- if(session == null || session.getAttribute(Constant.USER_SESSION_KEY)==null){
- System.out.println("登录失败");
- return new ResponseBodyMessage<>(-200,"请登录后再查找",null);
- }
-
- // 2. 获取 usrId
- User user = (User)session.getAttribute(Constant.USER_SESSION_KEY);
- int user_id = user.getUserId();
- System.out.println("在控制台打印日志:user_id:"+user_id);
-
- List<Music> musicList = null;
- if(musicName == null){
- //查询当前用户收藏的所有音乐
- musicList = loveMusicMapper.findLoveMusicByUserId(user_id);
- }else{
- //模糊查询,根据歌曲名查询当前用户指定的收藏歌曲
- musicList = loveMusicMapper.findLoveMusicByMusicNameAndUserId(musicName,user_id);
- }
- return new ResponseBodyMessage<>(200,"查询成功",musicList);
- }
- $(function(){
- load();
- });
-
- // musicName 可以传参(模糊匹配),也可以不传参(不传参默认传入的是所有的音乐)
- function load(musicName){
-
- $.ajax({
- type:"GET",
- url:"/lovemusic/findlovemusic",
- data:{
- "musicName":musicName
- },
- // 服务器返回的数据类型
- dataType:"json",
-
- // obj 查找存储的所有信息
- success:function(obj){
- console.log(obj);
- // data数组,存放歌曲信息
- var data = obj.data;
-
- var s = '';
- for(var i=0;i<data.length;i++){
- var musicUrl = data[i].url+".mp3";
- s += '<tr>';
- s += '<td>'+ data[i].title +'</td>';
- s += '<td>'+ data[i].singer +'</td>';
- s += "<td <a href=\"\"> <audio src= \""+ musicUrl+"\" + controls=\"controls\" preload=\"auto\" loop=\"loop\" class=\"audio_btn\"> >" + "</audio> </a> </td>";
- s += '<td> <button class="btn btn-primary" onclick="deleteInfo('+ data[i].musicId +')">取消收藏</button>'+'</td>';
- s += '</tr>';
- }
-
- $("#info").html(s);
- }
- });
- }
- 请求:
- {
- post, // 使用 post 请求
- /lovemusic/removelovemusic, // 请求路径
- data:{id:music_id} // 根据收藏列表中音乐的 id 进行移除
- }
-
- 响应:
- {
- "status": 200,
- "message": "取消收藏成功!",
- "data": true
- }
-
-
- 响应设计字段解释:
- {
- 状态码为 200 表示成功,-200 表示失败
- 状态描述信息,描述此次请求成功或者失败的原因
- 返回的数据,请求成功后,需要给前端的数据信息,true 表示移除收藏成功,false 表示移除收藏失败
- }
- /**
- * 移除某个用户收藏的引用
- * @param userId 用户的 ID
- * @param musicId 待移除音乐的 ID
- * @return 受影响的行数
- */
- int removeLoveMusic(int userId,int musicId);
- <delete id="removeLoveMusic" parameterType="java.lang.Integer">
- delete from lovemusic where user_id = #{userId} and music_id = #{musicId};
- </delete>
- /**
- * 移除收藏的音乐
- * @param music_id
- * @param request
- * @return
- */
- @RequestMapping("/removelovemusic")
- public ResponseBodyMessage<Boolean> removeLoveMusic(@RequestParam String music_id,HttpServletRequest request){
-
- // 1. 检查是否登录
- HttpSession session = request.getSession(false);
- if(session == null || session.getAttribute(Constant.USER_SESSION_KEY)==null){
- System.out.println("登录失败");
- return new ResponseBodyMessage<>(-200,"请登录后再移除",false);
- }
-
- // 2. 获取 usrId
- User user = (User)session.getAttribute(Constant.USER_SESSION_KEY);
- int userId = user.getUserId();
- System.out.println("在控制台打印日志:user_id:"+userId);
-
- // 3. 将传入的 music_id 转换成整型(获取 musicId)
- int musicId = Integer.parseInt(music_id);
- System.out.println("在控制台打印日志:music_id:"+musicId);
-
- int ret = loveMusicMapper.removeLoveMusic(userId,musicId);
- if(ret == 1){
- return new ResponseBodyMessage<>(200,"取消收藏成功",true);
- }else{
- return new ResponseBodyMessage<>(-200,"取消收藏失败",false);
- }
- }
- function deleteInfo(obj){
- console.log(obj);
- $.ajax({
- url:"/lovemusic/removelovemusic",
- type:"POST",
- data:{
- "music_id":obj
- },
- dataType:"json",
-
- success:function(data){
- console.log(data);
- if(data.data == true){
- alert("取消收藏成功,重新加载当前页面");
- window.location.href = "loveMusic.html";
- }else{
- alert("取消收藏失败");
- }
- }
-
- });
- }
前面所完成的功能中存在一个BUG,当成功删除音乐表(music)中的音乐后,收藏表(lovemusic)中的音乐不会被删除。
- /**
- * 根据音乐的ID进行删除
- * @param musicId
- * @return
- */
- int deleteLoveMusicByMusicId(int musicId);
- <delete id="deleteLoveMusicByMusicId" parameterType="java.lang.Integer">
- delete from lovemusic where music_id = #{musicId};
- </delete>
- // 在 MusicController 注入 LoveMusicMapper
- @Autowired
- private LoveMusicMapper loveMusicMapper;
-
- // 调整后的 deleteMusicByMusicId 方法 和 deleteSelMusic 方法
- /**
- * 删除单个音乐
- * 请求路径:/music/delete?musicId=x
- * @param musicId
- * @return
- */
- @RequestMapping("/delete")
- public ResponseBodyMessage<Boolean> deleteMusicByMusicId(@RequestParam String musicId){
- /**
- * 1. 检查待删除的音乐是否存在
- * 2. 如果存在要删除的音乐
- * 1. 删除数据库中的数据
- * 2. 删除服务器上的数据
- */
- // 检查待删除的音乐是否存在
- Music music = musicMapper.findMusicById(Integer.parseInt(musicId));
- if(music == null){
- System.out.println("在控制台打印日志:没有要删除的音乐id");
- return new ResponseBodyMessage<>(-200,"要删除的音乐不存在",false);
- }else{
- // 调用 musicMapper 接口中的 deleteMusicById 方法删除数据库中的数据
- int ret = musicMapper.deleteMusicById(Integer.parseInt(musicId));
-
- if(ret == 1){
- // 成功删除数据库中的数据
- String fileName = music.getTitle();
-
- // 根据存放音乐的路径删除服务器中的数据
- File file = new File(SAVE_PATH+fileName+".mp3");
- System.out.println("在控制台打印日志:当前音乐的路径:"+file.getPath());
- //对删除服务器中的数据进行判断
- if(file.delete()){
- // 同步删除 lovemusic 表中的音乐
- loveMusicMapper.deleteLoveMusicByMusicId(Integer.parseInt(musicId));
- // 删除成功
- return new ResponseBodyMessage<>(200,"音乐删除成功",true);
- }else{
- return new ResponseBodyMessage<>(-200,"服务器中的音乐删除失败",false);
- }
- }else{
- return new ResponseBodyMessage<>(-200,"数据库中的音乐删除失败",false);
- }
- }
- }
-
- /**
- * 批量删除选中的音乐
- * 请求路径:/music/deleteSel
- * @param musicId
- * @return
- */
- @RequestMapping("/deleteSel")
- public ResponseBodyMessage<Boolean> deleteSelMusic(@RequestParam("musicId[]") List<Integer> musicId) {
- System.out.println("在控制台打印日志:所有音乐的 Id:"+musicId);
- int sum = 0; // 统计删除的音乐
- for (int i = 0; i < musicId.size(); i++) {
- Music music = musicMapper.findMusicById(musicId.get(i));
- if (music == null) {
- System.out.println("没有要删除的音乐id");
- return new ResponseBodyMessage<>(-200, "要删除的音乐不存在", false);
- }
- int ret = musicMapper.deleteMusicById(musicId.get(i));
- if (ret == 1) {
- // 成功删除数据库中的数据
- String fileName = music.getTitle();
- // 根据存放音乐的路径删除服务器中的数据
- File file = new File(SAVE_PATH + fileName + ".mp3");
- System.out.println("当前音乐的路径:" + file.getPath());
- //对删除服务器中的数据进行判断
- if (file.delete()) {
- // 同步删除 lovemusic 表中的音乐
- loveMusicMapper.deleteLoveMusicByMusicId(musicId.get(i));
- // 成功删除一条数据,sum 就加上 ret(数据库中成功删除)
- sum += ret;
- } else {
- return new ResponseBodyMessage<>(-200, "服务器中的音乐删除失败", false);
- }
- }else{
- return new ResponseBodyMessage<>(-200,"数据库中的音乐删除失败",false);
- }
- }
- if(sum == musicId.size()){
- // 选中的数据全部删除成功
- System.out.println("在控制台打印日志:选择中的歌曲删除成功");
- return new ResponseBodyMessage<>(200,"音乐删除成功",true);
- }else{
- System.out.println("在控制台打印日志:选择中的歌曲删除失败");
- return new ResponseBodyMessage<>(-200,"音乐删除失败",false);
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。