目录
2.2.1在application.properties 中添加配置文件
5.4在Config中 注入 BCryptPasswordEncoder 对象
11.1.1 在 MusicServer 和 CollectServer 中添加代码
11.1.2在 MusicMapper 和 CollectMapper 中添加代码
11.1.3在 MusicMapper.xml 和 CollectMapper.xml 中添加代码
12.2.3在 CollectMapper.xml 中添加代码
13.1.3在 CollectMapper.xml 中添加代码
15.1.3在 CollectMapper.xml 中添加代码
1.项目设计
前端:HTML+CSS+JavaScript+JQuery
后端:Spring MVC+Spring Boot + MyBatis
2.创建项目 配置文件
2.1创建项目
2.2配置文件
2.2.1在application.properties 中添加配置文件
配置数据库
spring.datasource.url=jdbc:mysql://localhost:3306/onlinemusicserver?characterEncoding=utf8&useSSL=true
spring.datasource.username=root
spring.datasource.password=1234
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/
2.2.2在resources 目录下创建mapper
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>
3.数据库的设计与实现
用户表
- 用户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
);
4.交互接口的设计
上传音乐
请求
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: ""
}
5.工具包
5.1设置统一响应类
这个类是用来让响应返回的格式统一的
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;
}
}
5.2Constant类
这个类是用来存储不变的常量的. 例如设置了session对象 , 是一个字符串. 不变的字符串.将来在其他地方获取对应的session需要通过这个字符串获取
public class Constant {
public static final String USER_SESSION_KEY = "user";
}
5.3了解 MD5 加密 和 BCrypt 加密
MD5是一个安全的散列算法,输入两个不同的明文不会得到相同的输出值,根据输出值,不能得到原始的明文,即其过程不可逆; 但是虽然不可逆,但是不是说就是安全的。因为自从出现彩虹表后,这样的密码也"不安全"。
更安全的做法是加盐或者长密码等做法,让整个加密的字符串变的更长,破解时间变慢。
Bcrypt就是一款加密工具,可以比较方便地实现数据的加密工作。你也可以简单理解为它内部自己实现了随机加盐处理 。我们使用MD5加密,每次加密后的密文其实都是一样的,这样就方便了MD5通过大数据的方式进行破解。
Bcrypt生成的密文是60位的。而MD5的是32位的。Bcrypt破解难度更大。
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>
实现类
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;
}
}
BCrypt使用示例
添加依赖
<!-- 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);
}
运行结果(每次加密结果都不一样)
5.4在Config中 注入 BCryptPasswordEncoder 对象
@Configuration
public class AppConfig implements WebMvcConfigurer {
@Bean
public BCryptPasswordEncoder getBCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
}
5.5添加拦截器
5.5.1LoginInterceptor 类
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;
}
}
5.5.2AppConfig 类
@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");
}
}
6.登录模块
6.1创建User实体类
@Data
public class User {
private int userId;
private String username;
private String password;
}
6.2使用 Mybatis 操作数据库
这里登录 需要进行 数据库的查询. 查询是否存在当前 username 的用户.
所以要设计, 通过用户名查找用户信息
6.2.1 在 UserServer 中添加代码
public User selectByName(String username) {
return userMapper.selectByName(username);
}
6.2.2在 UserMapper 中添加代码
/**
* 通过用户名去查找用户信息, 用来对比登录信息.
* @param username 用户名
* @return 对应用户名的用户信息
*/
User selectByName(String username);
6.2.3在 UserMapper.xml 中添加代码
<select id="selectByName" resultType="com.example.onlinemusicserver.model.User">
select * from user where username=#{username};
</select>
6.3创建 UserConroller 添加代码
- 首先去数据库根据用户名查询是否存在当前用户.
- 如果不存在, 登录失败.
- 如果存在, 用输入的密码, 和数据库中的密码进行比较, 看是否相等. (注: 数据中的密码是加密的)
- 如果不相等, 登录失败.
- 如果相等, 创建 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);
}
}
}
7.注册模块
7.1使用 Mybatis 操作数据库
这里注册, 需要查看当前用户是否存在, 存在就不能注册, 通过用户查找, 这里已经实现.
注册一个新用户还需要 向数据库中添加一个新的用户信息
7.1.1在 UserServer 中添加代码
public int addnewUser(User newUser) {
return userMapper.addnewUser(newUser);
}
7.1.2在 UserMapper 中添加代码
/**
* 注册新的用户
* @param newUser 新用户信息
* @return
*/
int addnewUser(User newUser);
7.1.3在 UserMapper.xml 中添加代码
<insert id="addnewUser">
insert into user(username,password) values (#{username},#{password});
</insert>
7.2向 UserController 中添加代码
- 首先查看是否该用户是否存在
- 存在, 就注册失败
- 不存在, 就进行注册, 首先对当前密码进行加密.
- 加密之后对这个用户添加到数据库中.
/**
* 注册用户
* @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);
}
}
8.退出功能
这里点击退出之后, 直接删除 对应 的 session 即可
8.1向 UserController 中添加代码
直接删除对应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");
}
8.2登录注册测试
9.上传音乐模块
9.1创建Music 实体类
@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;
}
9.2使用Mybatis 操作数据库
上传音乐, 要上传 音乐名, 音乐歌手, 音乐地址, 上传作者Id. (音乐上传时间, 已经默认设置了. 不需要传也可以)
通过音乐名去查找歌曲, 这里用来对当前歌曲判断, 是否出现歌曲和歌手都相同的情况.
9.2.1 在 MusicServer 中添加代码
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);
}
9.2.2在 MusicMapper 中添加代码
/**
* 上传音乐
* @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);
9.2.3在 MusicMapper.xml 中添加代码
<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>
9.3向 MusicController 中添加代码
这里首先对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);
}
}
}
10.播放音乐模块
10.1向 MusicController 中添加代码
- 获取存储路径的文件.
- 读取文件中的所有字节,读入内存, 如果不为空, 返回字节码回去
/**
* 播放音乐
* @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();
}
}
11.删除音乐模块
11.1使用 Mybatis 操作数据库
删除音乐, 主要是两个删除, 一个是删除单个, 根据单个musicId 删除. 另一个是删除多个, 根据多个 musicId 删除.
这里根据 musicId 删除, 需要去数据库里查找 是否存在当前 musicId 的歌曲. 存在删成功, 不存在删失败.
注意, 删除的时候, 不仅要删除 music表里的歌曲. 也要删除 collect 表里的歌曲
11.1.1 在 MusicServer 和 CollectServer 中添加代码
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);
}
11.1.2在 MusicMapper 和 CollectMapper 中添加代码
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);
11.1.3在 MusicMapper.xml 和 CollectMapper.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>
<delete id="deleteLoveMusicById">
delete from collect where musicId = #{musicId};
</delete>
11.2删除单一音乐功能
11.2.1向 MusicController 中添加代码
- 首先查看要删除的 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);
}
}
11.3删除多个音乐功能
11.3.1向 MusicConroller 中添加代码
- 遍历传过来的 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);
}
}
12.收藏音乐模块
12.1创建 Collect 实体类
@Data
public class Collect {
private int collectId;
private int userId;
private int musicId;
}
12.2使用 Mybatis 操作数据库
首先要通过 musicId 和 userId去查找当前是否存在 collect 表中
在通过 musicId 和 userId 去添加歌曲
12.2.1在 CollectServer 中添加代码
public Collect findCollectMusic(int userId, int musicId) {
return collectMapper.findCollectMusic(userId,musicId);
}
public int insertLoveMusic(int userId, int musicId) {
return collectMapper.insertLoveMusic(userId, musicId);
}
12.2.2 在 CollectMapper 中添加代码
/**
* 查看对应用户是否已经收藏了该音乐
* @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);
12.2.3在 CollectMapper.xml 中添加代码
<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>
12.3向 CollectControll 中添加代码
- 通过用户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);
}
}
}
13.取消收藏音乐模块
13.1使用 Mybatis 操作数据库
- 根据userId 和 musicId 删除歌曲
13.1.1 在 CollectServer 中添加代码
public int deleteLoveMusic(int userId,int musicId){
return collectMapper.deleteLoveMusic(userId,musicId);
}
13.1.2 在 CollectMapper 中添加代码
/**
* 删除用户收藏的对应的音乐Id
* @param userId 用户Id
* @param musicId 音乐Id
* @return 受影响行数
*/
int deleteLoveMusic(int userId,int musicId);
13.1.3在 CollectMapper.xml 中添加代码
<delete id="deleteLoveMusic">
delete from collect where userId = #{userId} and musicId = #{musicId}
</delete>
13.2向 CollectControll 中添加代码
- 这里登录之后去收藏页面,去删除歌曲.
- 通过 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);
}
}
14.主页面 - 查询模块
14.1使用 Mybatis 操作数据库
- 这里有空查询和模糊查询两种数据库操作
- 空查询 不带 name
- 模糊查询带name
14.1.1 在 MusicServer 中添加代码
public List<Music> findMusic() {
return musicMapper.findMusic();
}
public List<Music> findMusicByName(String name) {
return musicMapper.findMusicByName(name);
}
14.1.2在 MusicMapper 中添加代码
/**
* 查找所有的歌曲
* @return 所有的歌曲
*/
List<Music> findMusic();
/**
* 支持模糊查询的歌曲.
* @param name 部分歌曲名
* @return 对应所有的歌曲
*/
List<Music> findMusicByName(String name);
14.1.3在 MusicMapper.xml 中添加代码
<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>
14.2向 MusicController 中添加代码
这里判断前端传来的 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);
}
15.收藏页面 - 查询模块
15.1 使用 Mybatis 操作数据库
- 这里有空查询和模糊查询两种数据库操作
- 空查询 不带 name
- 模糊查询带name
15.1.1 在 CollectServer 中添加代码
public List<Music> findLoveMusicByUserId(int userId){
return collectMapper.findLoveMusicByUserId(userId);
}
public List<Music> findLoveMusicByNameAndUserId(String name,int userId){
return collectMapper.findLoveMusicByNameAndUserId(name,userId);
}
15.1.2在 CollectMapper 中添加代码
/**
* 查找用户收藏的所有音乐
* @param userId 用户Id
* @return 返回查询到的所有音乐
*/
List<Music> findLoveMusicByUserId(int userId);
/**
* 查找用户收藏音乐中名字带有 name的音乐
* @param name 部分名字
* @param userId 用户Id
* @return 返回查询到的所有音乐
*/
List<Music> findLoveMusicByNameAndUserId(String name,int userId);
15.1.3在 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};
</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>
15.2向 CollectController 中添加代码
这里判断前端传来的 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);
}