赞
踩
前端 : HTML+CSS+JavaScript+JQuery
后端 : Spring MVC+Spring Boot+MyBatis
配置数据库
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
mybatis.mapper-locations=classpath:mapper/**Mapper.xml
配置文件上传大小
spring.servlet.multipart.max-file-size = 15MB
spring.servlet.multipart.max-request-size=100MB
配置上传的路径
upload.path=E:/logs/
mapper下添加 目录 **.xml 并添加代码
<?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.onlinemusicserver.mapper."对应的Mapper"">
</mapper>
这里设计数据库.
用户表
- 用户Id
- 用户账号
- 用户密码
音乐表
- 音乐Id
- 音乐名
- 音乐歌手
- 上传时间
- 存储地址
- 用户Id
收藏表
- 收藏Id
- 用户Id
- 音乐Id
drop database if exists `onlinemusicserver`; create database `onlinemusicserver`; use `onlinemusicserver`; drop table if exists `user`; create table `user`( `userId` int primary key auto_increment, `username` varchar(20) unique, `password` varchar(255) not null ); drop table if exists `music`; create table `music`( `musicId` int primary key auto_increment, `title` varchar(100) not null, `author` varchar(20) not null, `uploadtime` timestamp default CURRENT_TIMESTAMP, `path` varchar(1000) not null, `userId` int not null ); drop table if exists `collect`; create table `collect`( `collectId` int primary key auto_increment, `userId` int not null, `musicId` int not null );
上传音乐
请求
POST /music/upload HTTP/1.1
{singer, MultipartFile file}
响应
{
status: 1/-1 (1 为成功, -1 为失败),
message: "对应信息",
data: "内容"
}
收藏功能
请求
POST /collect/loveMusic HTTP/1.1
{musicId: 1}
响应
{
status: 1/-1,
message: "",
data: ""
}
取消收藏功能
请求
POST /collect/deleteLoveMusic HTTP/1.1
{musicId: 1}
响应
{
status: 1/-1,
message: "",
data: ""
}
收集页面 — 空查询 模糊查询
请求 POST /collect/findLoveMusic HTTP/1.1 {musicName: "可以为空可以不为空, 为空的时候,查询所有, 不为空的时候, 模糊查询"} 响应 { status: 1/-1, message: "", data: { { musicId: "", title: "", author: "", uploadtime: "", path: "", userId: "", } ... } }
主页页面 — 空查询 模糊查询
请求 POST /music/findMusic HTTP/1.1 {musicName: "可以为空可以不为空, 为空的时候,查询所有, 不为空的时候, 模糊查询"} 响应 { status: 1/-1, message: "", data: { { musicId: "", title: "", author: "", uploadtime: "", path: "", userId: "", } ... } }
删除单个音乐
请求
POST /music/delete HTTP/1.1
{musicId: ""}
响应
{
status: 1/-1,
message: "",
data: ""
}
删除多个音乐
请求
POST /music/deleteMore HTTP/1.1
{musicId: "1 2 3 4 5"(数组)}
响应
{
status: 1/-1,
message: "",
data: ""
}
播放音乐
请求
GET /music/play?path="..." HTTP/1.1
响应
{
音乐的字节信息
}
登录功能
请求
POST /user/login HTTP/1.1
{username: "",password: ""}
响应
{
status: 1/-1,
message: "",
data: ""
}
注销功能
请求
GET /user/logout HTTP/1.1
响应
HTTP/1.1 200
注册功能
请求
POST /user/register HTTP/1.1
{username: "",password: ""}
响应
{
status: 1/-1,
message: "",
data: ""
}
这个类是用来让响应返回的格式统一的.
public class ResponseBodyMessage<T> {
private int status;
private String message;
private T data;
public ResponseBodyMessage(int status, String message, T data) {
this.status = status;
this.message = message;
this.data = data;
}
}
这个类是用来存储不变的常量的. 例如设置了session对象 , 是一个字符串. 不变的字符串.将来在其他地方获取对应的session需要通过这个字符串获取 .
public class Constant {
public static final String USER_SESSION_KEY = "user";
}
MD5
是一个安全的散列算法,输入两个不同的明文不会得到相同的输出值,根据输出值,不能得到原始的明文,即其过程不可逆; 但是虽然不可逆,但是不是说就是安全的。因为自从出现彩虹表后,这样的密码也"不安全"。
更安全的做法是加盐或者长密码等做法,让整个加密的字符串变的更长,破解时间变慢。
Bcrypt
就是一款加密工具,可以比较方便地实现数据的加密工作。你也可以简单理解为它内部自己实现了随机加盐处理 。我们使用MD5加密,每次加密后的密文其实都是一样的,这样就方便了MD5通过大数据的方式进行破解。
Bcrypt生成的密文是60位的。而MD5的是32位的。Bcrypt破解难度更大。
添加依赖
<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>
实现类
public class MD5Util { private static final String salt = "1q2w3e4r5t";//可任意设置 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); } /** * 第二次加密 * @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 inputPass * @param saltDB * @return */ public static String inputPassToDbPass(String inputPass, String saltDB) { String formPass = inputPassToFormPass(inputPass); String dbPass = formPassToDBPass(formPass, saltDB); return dbPass; } }
添加依赖
<!-- 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>
在springboot启动类添加:
@SpringBootApplication(exclude ={org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.class})
创建BCryptTest测试类:
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);
}
运行结果: (每次加密的密码都不同)
@Configuration
public class AppConfig implements WebMvcConfigurer {
@Bean
public BCryptPasswordEncoder getBCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
}
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession httpSession = request.getSession(false);
if(httpSession != null && httpSession.getAttribute(Constant.USER_SESSION_KEY) != null) {
return true;
}
response.sendRedirect("/login.html");
return false;
}
}
@Configuration public class AppConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { LoginInterceptor loginInterceptor = new LoginInterceptor(); registry.addInterceptor(loginInterceptor) .addPathPatterns("/**") .excludePathPatterns("/**/login.html") .excludePathPatterns("/**/css/**.css") .excludePathPatterns("/**/images/**") .excludePathPatterns("/**/fonts/**") .excludePathPatterns("/**/js/**.js") .excludePathPatterns("/**/scss/**") .excludePathPatterns("/**/user/login") .excludePathPatterns("/**/user/register") .excludePathPatterns("/**/user/logout"); } }
创建 model 包, 然后创建 User 类
@Data
public class User {
private int userId;
private String username;
private String password;
}
这里登录 需要进行 数据库的查询. 查询是否存在当前 username 的用户.
所以要设计, 通过用户名查找用户信息
public User selectByName(String username) {
return userMapper.selectByName(username);
}
/**
* 通过用户名去查找用户信息, 用来对比登录信息.
* @param username 用户名
* @return 对应用户名的用户信息
*/
User selectByName(String username);
<select id="selectByName" resultType="com.example.onlinemusicserver.model.User">
select * from user where username=#{username};
</select>
注意这里的登录.
- 首先去数据库根据用户名查询是否存在当前用户.
- 如果不存在, 登录失败.
- 如果存在, 用输入的密码, 和数据库中的密码进行比较, 看是否相等. (注: 数据中的密码是加密的)
- 如果不相等, 登录失败.
- 如果相等, 创建 session, 并登录成功.
@RestController @RequestMapping("/user") public class UserController { @Autowired private UserServer userServer; @Autowired private BCryptPasswordEncoder bCryptPasswordEncoder; /** * 用户登录 * @param user * @param req * @return */ @RequestMapping("/login") public ResponseBodyMessage<User> login(@RequestBody User user, HttpServletRequest req) { User truUser = userServer.selectByName(user.getUsername()); if(truUser != null) { System.out.println("登陆成功"); System.out.println(user.getPassword() + " " + truUser.getPassword()); boolean flg = bCryptPasswordEncoder.matches(user.getPassword(),truUser.getPassword()); if(!flg) { return new ResponseBodyMessage<>(-1,"当前账号密码错误!",user); } HttpSession session = req.getSession(true); session.setAttribute(Constant.USER_SESSION_KEY,truUser); return new ResponseBodyMessage<>(1,"登录成功!",truUser); }else{ System.out.println("登录失败"); return new ResponseBodyMessage<>(-1,"当前账号密码错误!",user); } } }
let loginButton = document.querySelector('#loginButton'); loginButton.onclick = function() { let username = document.querySelector('#loginUsername'); let password = document.querySelector('#loginPassword'); if (username.value.trim() == ""){ alert('请先输入用户名!'); username.focus(); return; } if (password.value.trim() == ""){ alert('请先输入密码!'); password.focus(); return; } $.ajax({ url: "user/login", method: "POST", data: JSON.stringify({username: username.value.trim(), password: password.value.trim()}), contentType: "application/json;charset=utf-8", success: function(data, status) { if(data.status == 1) { location.assign("index.html"); }else{ alert(data.message); username.value=""; password.value=""; username.focus(); } } }) }
这里注册, 需要查看当前用户是否存在, 存在就不能注册, 通过用户查找, 这里已经实现.
注册一个新用户还需要 向数据库中添加一个新的用户信息.
public int addnewUser(User newUser) {
return userMapper.addnewUser(newUser);
}
/**
* 注册新的用户
* @param newUser 新用户信息
* @return
*/
int addnewUser(User newUser);
<insert id="addnewUser">
insert into user(username,password) values (#{username},#{password});
</insert>
- 首先查看是否该用户是否存在
- 存在, 就注册失败
- 不存在, 就进行注册, 首先对当前密码进行加密.
- 加密之后对这个用户添加到数据库中.
/** * 注册用户 * @param user 用户信息 * @return */ @RequestMapping("/register") public ResponseBodyMessage<Boolean> register(@RequestBody User user) { User user1 = userServer.selectByName(user.getUsername()); if(user1 != null) { return new ResponseBodyMessage<>(-1,"当前用户已经存在",false); }else { User newUser = new User(); newUser.setUsername(user.getUsername()); String newPassword = bCryptPasswordEncoder.encode(user.getPassword()); newUser.setPassword(newPassword); userServer.addnewUser(newUser); return new ResponseBodyMessage<>(1,"注册成功",true); } }
let Reg = document.querySelector('#Reg'); Reg.onclick = function() { let username = document.querySelector('#RegUsername'); let password1 = document.querySelector('#RegPassword1'); let password2 = document.querySelector('#RegPassword2'); if(!$('#checkbox').is(':checked')) { alert("请勾选条款"); return; } if(username.value.trim() == ""){ alert("请先输入用户名!"); username.focus(); return; } if(password1.value.trim() == ""){ alert('请先输入密码!'); password1.focus(); return; } if(password2.value.trim() == ""){ alert('请再次输入密码!'); password2.focus(); return; } if(password1.value.trim() != password2.value.trim()) { alert('两次输入的密码不同!'); passwrod1.value=""; password2.value=""; return; } $.ajax({ url: "user/register", method: "POST", data: JSON.stringify({username: username.value.trim(), password: password1.value.trim()}), contentType: "application/json;charset=utf-8", success: function(data,status){ if(data.status == 1) { alert(data.message); location.assign("login.html"); }else{ alert(data.message); username.value=""; password1.value=""; password2.value=""; username.focus(); } } }) }
这里点击退出之后, 直接删除 对应 的 session 即可
直接删除对应session 为
Constant.USER_SESSION_KEY
, 然后跳转到login.html
@RequestMapping("/logout")
public void userLogout(HttpServletRequest request, HttpServletResponse response) throws IOException {
HttpSession session = request.getSession(false);
// 拦截器的拦截, 所以不可能出现session为空的情况
session.removeAttribute(Constant.USER_SESSION_KEY);
response.sendRedirect("login.html");
}
@Data
public class Music {
private int musicId;
private String title;
private String author;
private Timestamp uploadtime;
private String path;
private int userId;
private String srcPath;
}
上传音乐, 要上传 音乐名, 音乐歌手, 音乐地址, 上传作者Id. (音乐上传时间, 已经默认设置了. 不需要传也可以)
通过音乐名去查找歌曲, 这里用来对当前歌曲判断, 是否出现歌曲和歌手都相同的情况.
public int insert(String title, String author, String path, int userId){
return musicMapper.insert(title,author,path,userId);
}
public List<Music> selectByTitle(String title) {
return musicMapper.selectByTitle(title);
}
/** * 上传音乐 * @param title 音乐名 * @param author 歌手 * @param path 对应的地址 * @param userId 上传的用户Id * @return 返回影响行数 */ int insert(String title, String author, String path, int userId); /** * 通过音乐名去查找歌曲. * @param title 音乐名 * @return 对应音乐名的所有歌曲 */ List<Music> selectByTitle(String title);
<insert id="insert">
insert into music(title,author,path,userId) values (#{title},#{author},#{path},#{userId});
</insert>
<select id="selectByTitle" resultType="com.example.onlinemusicserver.model.Music">
select * from music where title = #{title};
</select>
这里首先对session判断, 判断是否存在session. (配置拦截器之后就不需要判断了)
去数据库中查询所有title相同的歌曲. 如果歌曲名相同,歌手也相同, 那么就上传失败.
创建文件夹. 将文件上传到文件夹中.(文件名是以歌手-歌名创建, 为了防止重名无法读取)
然后对该文件, 进行判断, 判断是不是 MP3 文件, 注意MP3文件, 字节码中有 字符"TAG"
在数据库中上传数据. 注意这里的path.
@RestController @RequestMapping("/music") public class MusicController { @Autowired private MusicServer musicServer; @Value("${upload.path}") public String SAVE_PATH; /** * 上传音乐 * @param singer * @param file * @param request * @return */ @RequestMapping("/upload") public ResponseBodyMessage<Boolean> insertMusic(@RequestParam String singer, @RequestPart("filename") MultipartFile file, HttpServletRequest request, HttpServletResponse response) { // 检测登录 HttpSession session = request.getSession(false); if (session == null || session.getAttribute(Constant.USER_SESSION_KEY) == null) { System.out.println("当前未登录!"); return new ResponseBodyMessage<>(-1,"请登录后上传",false); } // 文件的类型 String fileNameAndType = file.getOriginalFilename(); // 防止出现重复的相同歌曲和相同歌手.可以出现相同歌曲不同歌手 String title = fileNameAndType.substring(0,fileNameAndType.lastIndexOf('.')); // 可能出现多首名称相同的歌曲, 所以用 List List<Music> list = musicServer.selectByTitle(title); if(list != null){ for(Music music : list) { if(music.getAuthor().equals(singer)){ return new ResponseBodyMessage<>(-1,"当前歌手的歌曲已经存在!",false); } } } // 创建文件 String path = SAVE_PATH +singer+"-"+fileNameAndType; File dest = new File(path); if(!dest.exists()) { dest.mkdirs(); } try { file.transferTo(dest); //return new ResponseBodyMessage<>(1,"上传成功!",true); } catch (IOException e) { e.printStackTrace(); return new ResponseBodyMessage<>(-1,"服务器上传失败!",false); } // 这里对是不是 MP3 文件进行判断. 主要是判断是否存在 TAG 这个字符 File file1 = new File(path); byte[] res = null; try { res = Files.readAllBytes(file1.toPath()); if(res == null) { return new ResponseBodyMessage<>(-1,"当前文件不存在",false); } String str = new String(res); if(!str.contains("TAG")) { file1.delete(); return new ResponseBodyMessage<>(-1,"当前不是mp3文件",false); } }catch (IOException e){ e.printStackTrace(); return new ResponseBodyMessage<>(-1,"服务器出现问题", false); } // 在数据库中上传数据 User user = (User) session.getAttribute(Constant.USER_SESSION_KEY); // 这里传递的 path 没有带 `.MP3` 后期在前端进行设置 String uploadPath = "/music/play?path="+singer+"-"+title; try { int ret = musicServer.insert(title,singer,uploadPath,user.getUserId()); if(ret == 1) { response.sendRedirect("/index.html"); return new ResponseBodyMessage<>(1,"上传成功",true); }else { return new ResponseBodyMessage<>(-1,"数据库上传失败",false); } }catch (BindingException | IOException e) { dest.delete(); return new ResponseBodyMessage<>(-1,"数据库上传失败",false); } } }
<form method="post" enctype="multipart/form-data" action="music/upload">
文件上传: <input type="file" name="filename" id="filename" />
歌手名: <label>
<input type="text" name="singer" placeholder="请输入歌手名" id="singer" />
</label>
<input type="submit" value="上传" id="submit"/>
</form>
- 获取存储路径的文件.
- 读取文件中的所有字节,读入内存, 如果不为空, 返回字节码回去.
/** * 播放音乐 * @param path * @return */ @RequestMapping("/play") public ResponseEntity<byte[]> playMusic(@RequestParam String path){ File file = new File(SAVE_PATH + path); byte[] res = null; try { res = Files.readAllBytes(file.toPath()); if (res == null) { return ResponseEntity.badRequest().build(); } return ResponseEntity.ok(res); } catch (IOException e) { e.printStackTrace(); return ResponseEntity.badRequest().build(); } }
观察字节码可以看出, 有 TAG 这个字符
删除音乐, 主要是两个删除, 一个是删除单个, 根据单个musicId 删除. 另一个是删除多个, 根据多个 musicId 删除.
这里根据 musicId 删除, 需要去数据库里查找 是否存在当前 musicId 的歌曲. 存在删成功, 不存在删失败.
注意, 删除的时候, 不仅要删除 music表里的歌曲. 也要删除 collect 表里的歌曲.
musicServer
public Music selectById(int musicId) {
return musicMapper.selectById(musicId);
}
public int deleteById(int musicId) {
return musicMapper.deleteById(musicId);
}
collectServer
public int deleteLoveMusicById(int musicId){
return collectMapper.deleteLoveMusicById(musicId);
}
musicMapper
/**
* 通过音乐Id去查找歌曲
* @param musicId 音乐Id
* @return 查找到的音乐Id
*/
Music selectById(int musicId);
/**
* 删除对应音乐Id的歌曲
* @param musicId 音乐Id
* @return 返回影响行数
*/
int deleteById(int musicId);
collectMapper
/**
* 删除收藏表中音乐Id为musicId的
* @param musicId 音乐Id
* @return 返回受影响行数
*/
int deleteLoveMusicById(int musicId);
MusicMapper.xml
<select id="selectById" resultType="com.example.onlinemusicserver.model.Music">
select * from music where musicId = #{musicId};
</select>
<delete id="deleteById">
delete from music where musicId = #{musicId};
</delete>
CollectMapper.xml
<delete id="deleteLoveMusicById">
delete from collect where musicId = #{musicId};
</delete>
- 首先查看要删除的 musicId 的音乐是否存在
- 如果不存在就直接返回删除失败
- 如果存在, 就删除, 首先删除数据库中的记录, 再删除服务器上的数据
- 同时删除 collect 表中的 musicId 的数据
/** * 删除音乐 * @param musicId * @return */ @RequestMapping("/delete") public ResponseBodyMessage<Boolean> deleteMusic(@RequestParam String musicId) { // 1. 检测音乐是不是存在 Music music = musicServer.selectById(Integer.parseInt(musicId)); // 2. 不存在直接返回, 存在就删除 if (music == null) { System.out.println("该音乐不存在"); return new ResponseBodyMessage<>(-1,"没有你要删除的音乐",false); } // 2.1 删除数据库中的记录 int ret = musicServer.deleteById(Integer.parseInt(musicId)); if(ret == 1) { // 2.2 删除服务器上的数据 int index = music.getPath().lastIndexOf("="); String PathName = music.getPath().substring(index+1); File file = new File(SAVE_PATH + PathName+".mp3"); if(file.delete()){ collectServer.deleteLoveMusicById(Integer.parseInt(musicId)); return new ResponseBodyMessage<>(1,"删除成功!",true); }else{ return new ResponseBodyMessage<>(-1,"服务器删除失败!",false); } }else { return new ResponseBodyMessage<>(-1,"数据库删除失败!",false); } }
function deleteMusic(musicId) { $.ajax({ url: "music/delete", method: "post", data:{"musicId":musicId}, dataType: "json", success:function(data,status) { if(data.status == 1) { alert(data.message); location.assign("index.html"); }else{ alert(data.message); } } }) }
- 遍历传过来的 musicId的集合. 查询是否存在当前musicId 的音乐
- 存在就删除数据库中的数据, 然后删除服务器上的数据, 再删除 collect 表中的数据
- 都删除成功就计数. 如果和传来的集合的数据总数和计数的总数一样, 就返回删除成功.
/** * 删除多选音乐 * @param musicId * @return */ @RequestMapping("/deleteMore") public ResponseBodyMessage<Boolean> deleteMoreMusic(@RequestParam("musicId[]") List<Integer> musicId) { int sum = 0; for (int i = 0; i < musicId.size(); i++) { Music music = musicServer.selectById(musicId.get(i)); if(music == null) { return new ResponseBodyMessage<>(-1,"没有你要删除的音乐",false); } int ret = musicServer.deleteById(musicId.get(i)); if (ret == 1) { int index = music.getPath().lastIndexOf("="); String PathName = music.getPath().substring(index+1); File file = new File(SAVE_PATH + PathName+".mp3"); if(file.delete()){ collectServer.deleteLoveMusicById(musicId.get(i)); sum += ret; }else{ return new ResponseBodyMessage<>(-1,"服务器删除失败!",false); } }else { return new ResponseBodyMessage<>(-1,"数据库删除失败!",false); } } if(sum == musicId.size()) { return new ResponseBodyMessage<>(1,"音乐删除成功!",true); }else{ return new ResponseBodyMessage<>(-1,"音乐删除失败!",false); } }
$(function(){ $.when(load).done(function() { $("#deleteMore").click(function(){ let musicId = new Array(); let i =0; $("input:checkbox").each(function(){ if($(this).is(":checked")) { musicId[i] = $(this).attr("id"); i++; } }); $.ajax({ url: "music/deleteMore", method: "post", data:{"musicId":musicId}, dataType:"json", success:function(data,status) { if(data.status == 1) { alert(data.message); location.assign("index.html"); }else{ alert(data.message); } } }) }) }) })
@Data
public class Collect {
private int collectId;
private int userId;
private int musicId;
}
- 首先要通过 musicId 和 userId去查找当前是否存在 collect 表中
- 在通过 musicId 和 userId 去添加歌曲
public Collect findCollectMusic(int userId, int musicId) {
return collectMapper.findCollectMusic(userId,musicId);
}
public int insertLoveMusic(int userId, int musicId) {
return collectMapper.insertLoveMusic(userId, musicId);
}
/**
* 查看对应用户是否已经收藏了该音乐
* @param userId 用户Id
* @param musicId 音乐Id
* @return 收藏歌单
*/
Collect findCollectMusic(int userId, int musicId);
/**
* 收藏音乐
* @param userId 用户Id
* @param musicId 音乐Id
* @return 返回影响行数
*/
int insertLoveMusic(int userId, int musicId);
<select id="findCollectMusic" resultType="com.example.onlinemusicserver.model.Collect">
select * from collect where userId = #{userId} and musicId = #{musicId};
</select>
<insert id="insertLoveMusic">
insert into collect(userId,musicId) values(#{userId},#{musicId});
</insert>
- 通过用户Id 和 musicId查看是否存在歌曲
- 如果存在就返回收藏失败
- 如果不存在, 就根据用户id和musicId 添加收藏
/** * 点击收藏的时候, 收藏音乐 * @param musicId * @param request * @return */ @RequestMapping("/loveMusic") public ResponseBodyMessage<Boolean> AddLoveMusic(@RequestParam String musicId, HttpServletRequest request) { int music_Id = Integer.parseInt(musicId); HttpSession session = request.getSession(false); User user = (User) session.getAttribute(Constant.USER_SESSION_KEY); int userId = user.getUserId(); Collect collect = collectServer.findCollectMusic(userId,music_Id); if (collect != null) { return new ResponseBodyMessage<>(-1, "当前已经收藏了",false); }else{ int ret = collectServer.insertLoveMusic(userId,music_Id); if(ret == 1) { return new ResponseBodyMessage<>(1, "收藏成功!",true); }else{ return new ResponseBodyMessage<>(-1,"收藏失败",false); } } }
function collectMusic(musicId) { $.ajax({ url: "collect/loveMusic", method: "post", data:{"musicId":musicId}, dataType: "json", success:function(data,status){ if(data.status == 1) { alert(data.message); location.assign("collect.html"); }else{ alert(data.message); } } }) }
- 根据userId 和 musicId 删除歌曲
public int deleteLoveMusic(int userId,int musicId){
return collectMapper.deleteLoveMusic(userId,musicId);
}
/**
* 删除用户收藏的对应的音乐Id
* @param userId 用户Id
* @param musicId 音乐Id
* @return 受影响行数
*/
int deleteLoveMusic(int userId,int musicId);
<delete id="deleteLoveMusic">
delete from collect where userId = #{userId} and musicId = #{musicId}
</delete>
- 这里登录之后去收藏页面,去删除歌曲.
- 通过 musicId 和 userId 去删除歌曲
/** * 删除收藏的音乐 * @param musicId * @param request * @return */ @RequestMapping("/deleteLoveMusic") public ResponseBodyMessage<Boolean> deleteLoveMusic(@RequestParam String musicId,HttpServletRequest request) { HttpSession session = request.getSession(false); if(session == null) { return new ResponseBodyMessage<>(-1,"当前未登录",false); } User user = (User) session.getAttribute(Constant.USER_SESSION_KEY); int userId = user.getUserId(); int ret = collectServer.deleteLoveMusic(userId,Integer.parseInt(musicId)); if(ret == 1) { return new ResponseBodyMessage<>(1,"取消收藏成功!",true); }else{ return new ResponseBodyMessage<>(-1,"取消收藏失败!",false); } }
function deleteLoveMusic(musicId) { $.ajax({ url: "collect/deleteLoveMusic", method: "post", data:{"musicId":musicId}, dataType: "json", success:function(data,status) { if(data.status == 1) { alert(data.message); location.assign("collect.html"); }else{ alert(data.message); } } }) }
- 这里有空查询和模糊查询两种数据库操作
- 空查询 不带 name
- 模糊查询带name
public List<Music> findMusic() {
return musicMapper.findMusic();
}
public List<Music> findMusicByName(String name) {
return musicMapper.findMusicByName(name);
}
/**
* 查找所有的歌曲
* @return 所有的歌曲
*/
List<Music> findMusic();
/**
* 支持模糊查询的歌曲.
* @param name 部分歌曲名
* @return 对应所有的歌曲
*/
List<Music> findMusicByName(String name);
<select id="findMusic" resultType="com.example.onlinemusicserver.model.Music">
select * from music;
</select>
<select id="findMusicByName" resultType="com.example.onlinemusicserver.model.Music">
select * from music where title like concat('%',#{name},'%');
</select>
这里判断前端传来的 name是否为空
- 不为空, 进入模糊查询
- 为空, 进入空查询
/**
* 支持模糊查询, 支持空查询
* @param name
* @return
*/
@RequestMapping("/findMusic")
public ResponseBodyMessage<List<Music>> findMusic(@RequestParam(required = false) String name) {
List<Music> list = null;
if(name != null) {
list = musicServer.findMusicByName(name);
}else {
list = musicServer.findMusic();
}
return new ResponseBodyMessage<>(1,"查询完毕!",list);
}
$(function(){load()}); function load(musicName) { $.ajax({ url: 'music/findMusic', method: 'POST', data: {"name":musicName}, dataType: "json", success: function(data,status) { if(data.data!=null){ createMusic1(data.data); let audios = document.querySelectorAll('#player2'); for(let audio of audios) { new MediaElementPlayer(audio, { pluginPath: 'https://cdn.jsdelivr.net/npm/mediaelement@4.2.7/build/', shimScriptAccess: 'always', success: function () { let play = document.querySelector('.player'); play.style = "visibility: visible;"; } }); } } } }) } function createMusic1(lists) { let s = ''; for(let list of lists) { s+= '<div class="d-block d-md-flex podcast-entry bg-white mb-5" data-aos="fade-up">'; s+= '<img src="images/img_2.jpg" class="image">'; s+= '<div class="text">'; s+= '<input id="'+list.musicId+'" type="checkbox" class="checkbox">'; s+= '<h3 class="font-weight-light">'+list.title+'</h3>'; s+= '<div class="text-white mb-3"><span class="text-black-opacity-05"><small>'+list.author+'</small><span class="sep">/</span><small>'+DateFormat(list.uploadtime)+'</small></span></div>'; s+= '<input type="button" class="btn btn-primary" style="margin: 5px;" value="收藏音乐" οnclick="collectMusic(\''+list.musicId+'\')">'; s+= '<input type="button" class="btn btn-primary" style="margin: 5px;" value="删除音乐" οnclick="deleteMusic(\''+list.musicId+'\')">'; s+= '<div class="player">'; s+= '<audio id="player2" preload="none" controls style="max-width: 100%">'; s+= '<source src="'+ list.path+'.mp3'+'" type="audio/mp3">'; s+= '</audio></div></div></div>'; } $("#list23").html(s); } // 把毫秒级时间戳转化成格式化日期 function DateFormat(timeStampMS) { var date = new Date(timeStampMS); var year = date.getFullYear(), month = date.getMonth()+1,//月份是从0开始的 day = date.getDate(), hour = date.getHours(), min = date.getMinutes(), sec = date.getSeconds(); var newTime = year + '-' + (month < 10? '0' + month : month) + '-' + (day < 10? '0' + day : day) + ' ' + (hour < 10? '0' + hour : hour) + ':' + (min < 10? '0' + min : min) + ':' + (sec < 10? '0' + sec : sec); return newTime; } $(function(){ $("#submit1").click( function(){ var name = $("#exampleInputName2").val(); load(name); }); });
- 这里有空查询和模糊查询两种数据库操作
- 空查询 不带 name
- 模糊查询带name
public List<Music> findLoveMusicByUserId(int userId){
return collectMapper.findLoveMusicByUserId(userId);
}
public List<Music> findLoveMusicByNameAndUserId(String name,int userId){
return collectMapper.findLoveMusicByNameAndUserId(name,userId);
}
/**
* 查找用户收藏的所有音乐
* @param userId 用户Id
* @return 返回查询到的所有音乐
*/
List<Music> findLoveMusicByUserId(int userId);
/**
* 查找用户收藏音乐中名字带有 name的音乐
* @param name 部分名字
* @param userId 用户Id
* @return 返回查询到的所有音乐
*/
List<Music> findLoveMusicByNameAndUserId(String name,int userId);
<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};
</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},'%');
</select>
这里判断前端传来的 name是否为空
- 不为空, 进入模糊查询
- 为空, 进入空查询
/** * 1. 空查询, 查找所有的收藏音乐 * 2. 模糊查询, 查询包含部分 musicName 的所有收藏音乐 * @param musicName * @param request * @return */ @RequestMapping("findLoveMusic") public ResponseBodyMessage<List<Music>> findLoveMusic(@RequestParam(required = false) String musicName,HttpServletRequest request) { HttpSession session = request.getSession(false); if(session == null) { return new ResponseBodyMessage<>(-1,"当前未登录",null); } User user = (User) session.getAttribute(Constant.USER_SESSION_KEY); int userId = user.getUserId(); List<Music> list = null; if(musicName == null) { list = collectServer.findLoveMusicByUserId(userId); }else{ list = collectServer.findLoveMusicByNameAndUserId(musicName,userId); } return new ResponseBodyMessage<>(1,"查询成功!",list); }
$(function(){load()}); function load(musicName) { $.ajax({ url: 'collect/findLoveMusic', method: 'POST', data: {"musicName":musicName}, dataType: "json", success: function(data,status) { if(data.data!=null){ createMusic1(data.data); let audios = document.querySelectorAll('#player2'); for(let audio of audios) { new MediaElementPlayer(audio, { pluginPath: 'https://cdn.jsdelivr.net/npm/mediaelement@4.2.7/build/', shimScriptAccess: 'always', success: function () { let play = document.querySelector('.player'); play.style = "visibility: visible;"; } }); } } } }) } $(function(){ $("#submit1").click( function(){ var name = $("#exampleInputName2").val(); load(name); }); }); function createMusic1(lists) { let s = ''; for(let list of lists) { s+= '<div class="d-block d-md-flex podcast-entry bg-white mb-5" data-aos="fade-up">'; s+= '<img src="images/img_1.jpg" class="image">'; s+= '<div class="text">'; s+= '<h3 class="font-weight-light">'+list.title+'</h3>'; s+= '<div class="text-white mb-3"><span class="text-black-opacity-05"><small>'+list.author+'</small><span class="sep">/</span><small>'+DateFormat(list.uploadtime)+'</small></span></div>'; s+= '<input type="button" class="btn btn-primary" style="margin: 5px;" value="取消收藏" οnclick="deleteLoveMusic(\''+list.musicId+'\')">'; s+= '<div class="player">'; s+= '<audio id="player2" preload="none" controls style="max-width: 100%">'; s+= '<source src="'+ list.path+'.mp3'+'" type="audio/mp3">'; s+= '</audio></div></div></div>'; } $("#list23").html(s); } // 把毫秒级时间戳转化成格式化日期 function DateFormat(timeStampMS) { var date = new Date(timeStampMS); var year = date.getFullYear(), month = date.getMonth()+1,//月份是从0开始的 day = date.getDate(), hour = date.getHours(), min = date.getMinutes(), sec = date.getSeconds(); var newTime = year + '-' + (month < 10? '0' + month : month) + '-' + (day < 10? '0' + day : day) + ' ' + (hour < 10? '0' + hour : hour) + ':' + (min < 10? '0' + min : min) + ':' + (sec < 10? '0' + sec : sec); return newTime; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。