云计算百科
云计算领域专业知识百科平台

项目:在线音乐播放服务器——基于SSM框架和mybatis

介绍项目

项目主要是基于SSM框架和mybatis进行实现

主要的功能:

登陆界面,用户注册,音乐的播放列表,删除指定的歌曲,批量删除指定的歌曲,收藏歌曲,查询歌曲,从收藏列表中删除收藏音乐。

功能展示:

登录界面

用户注册

 

音乐列表

 喜欢列表

添加歌曲 

 

首先创建一个Sping Boot项目

再创建musicserver数据库

数据库一共有三个表:收藏歌曲表,歌曲表,用户表

lovemusic表

music表

user表

在.yml文件中配置数据库和xml

spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/musicserver?characterEncoding=utf8&serverTimezone=UTC
username: 你自己的数据库用户名
password: 你自己的数据库密码
driver-class-name: com.mysql.cj.jdbc.Driver

servlet:
multipart:
max-file-size: 15MB
max-request-size: 100MB
#音乐上传后的路径
music:
local:
path: E:/music/

mybatis:
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mapper-locations: classpath:mapper/**.xml
logging:
file:
name: spring-book.log

创建项目的结构目录 

登录模块的设计

创建user类

对应数据库的user表,创建用户的实体类

@Data
public class User {
private Integer id;
private String username;
private String password;
}

创建UserMapper接口

@Mapper
public interface UserMapper {
User login(User loginUser);

User selectByName(String username);
}

 创建UserMapper.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.blame.onlinemusicserver.mapper.UserMapper">

<select id="login" resultType="com.blame.onlinemusicserver.model.User" parameterType="com.blame.onlinemusicserver.model.User">
select * from user where username=#{username} and password=#{password}
</select>

<select id="selectByName" resultType="com.blame.onlinemusicserver.model.User">
select * from user where username=#{username}
</select>

</mapper>

实现登录的请求和响应

创建响应类的工具类

@Data
public class ResponseBodyMessage<T> {
private Integer status;
private String message;
private T data;

public ResponseBodyMessage(Integer status, String message, T data) {
this.status = status;
this.message = message;
this.data = data;
}
}

创建UserController

        @RequestParam:将请求参数绑定到你控制器的⽅法参数上,如果你这个参数不是必须要传的,@RequestParam(required = false) ,默认是true

@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {

@Autowired
private UserService userService;

@RequestMapping("/login")
public ResponseBodyMessage<User> login(@RequestParam("username") String username,
@RequestParam("password") String password,
HttpServletRequest request){
ResponseBodyMessage<User> result = userService.login(username, password, request);
return result;
}
}

我们在登录时使用BCrypt加密设计

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>

在项目的启动类中添加@SpringBootApplication(exclude =         {org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.class})

//在@SpringBootApplication注解后添加(exclude =
//{org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.class})的作用:
//我们虽然引用了 security的依赖,但是我们只是使用了它框架中的一个类,不适用其他的,如果不添加这个的话,SpringSecurity⽣效了的,
//此时的接⼝都是被保护的,我们需要通过验证才能正常的访问,导致我们无法登录
@SpringBootApplication(exclude =
{org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.class})
public class OnlineMusicServerApplication {

public static void main(String[] args) {
SpringApplication.run(OnlineMusicServerApplication.class, args);
}

}

创建AppConfig

定义config包,创建AppConfig,使用@Configuration注解

@Configuration
public class AppConfig implements WebMvcConfigurer {

@Bean
public BCryptPasswordEncoder getbCryptPasswordEncoder(){
return new BCryptPasswordEncoder();
}
}

创建UserService 

request.getSession(),获取这次请求的session对象

.setAttribute()将用户信息存储到session中

因为  USERINFO_SESSION_KEY  这个常量容易拼错,所以我们将其定义在常量信息中

@Service
public class UserService {
@Autowired
private UserMapper userMapper;

@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;

public ResponseBodyMessage<User> login(String username,
String password,
HttpServletRequest request) {
User loginUser=new User();
loginUser.setUsername(username);
loginUser.setPassword(password);
User user=userMapper.selectByName(username);
if(user==null){
return new ResponseBodyMessage<>(-1,"用户不存在",loginUser);
}
if(!bCryptPasswordEncoder.matches(password,user.getPassword())){
return new ResponseBodyMessage<>(-1,"密码错误,请重新登录",loginUser);
}else {
request.getSession().setAttribute(Constant.USERINFO_SESSION_KEY,user);
return new ResponseBodyMessage<>(0,"登陆成功",loginUser);
}

}
}

public class Constant {
public static final String USERINFO_SESSION_KEY="USERINFO_SESSION_KEY";
}

 验证

 

新增功能:注册用户功能的实现

修改数据库,在user表中添加email

ALTER TABLE user
ADD COLUMN email VARCHAR(100) NOT NULL;

UserMapper

void insertUser(User user);
<insert id="insertUser">
insert into user (username, password, email) VALUES (#{username}, #{password}, #{email})
</insert>

UserService

public ResponseBodyMessage<Boolean> register(String username,String password,String email){
User existUser=userMapper.selectByName(username);
if(existUser!=null){
return new ResponseBodyMessage<>(-1,"该用户存在",false);
}
// 将注册的密码进行加密
String encoderPassword=bCryptPasswordEncoder.encode(password);
User user=new User();
user.setUsername(username);
user.setPassword(encoderPassword);
user.setEmail(email);
userMapper.insertUser(user);
return new ResponseBodyMessage<>(0,"注册成功",true);
}

UserController

使用@Valid来校验参数

使用@Valid记得添加其依赖

<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
<version>3.0.2</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>8.0.0.Final</version>
</dependency>

定义RequestRegister来进行请求数据的封装

@Data
public class RequestRegister {

@Size(min = 3, max = 20, message = "用户名长度应在3到20个字符之间")
@NotBlank(message = "username不能为空")
private String username;

@NotBlank(message = "password不能为空")
private String password;

@Email(message = "邮箱格式不正确")
@NotBlank(message = "email不能为空")
private String email;
}

@RequestMapping("/register")
public ResponseBodyMessage<Boolean> register(@Valid @RequestBody RequestRegister requestRegister){
return userService.register(requestRegister.getUsername(), requestRegister.getPassword(), requestRegister.getEmail());
}
}

 

上传音乐模块的实现 

请求和响应的接口实现

定义music实体类

对应数据库中的music表的字段

@Data
public class Music {
private Integer id;
private String title;
private String singer;
private String time;
private String url;
private Integer userid;

}

定义MusicController

将音乐文件上传到这个路径

Slf4j
@RestController
@RequestMapping("/music")
public class MusicController {

@Autowired
private MusicService musicService;

@RequestMapping("/upload")
public ResponseBodyMessage<Boolean> insertMusic(@RequestParam String singer,
@RequestParam("filename") MultipartFile file,
HttpServletRequest request,
HttpServletResponse response){
return musicService.insertMusic(singer, file, request, response);

}
}

定义MusicService

@Slf4j
@Service
public class MusicService {

@Value("${spring.music.local.path}")
private String SAVE_PATH;

@Autowired
private MusicMapper mapper;

@Autowired
private LoveMusicMapper loveMusicMapper;

//添加音乐
public ResponseBodyMessage<Boolean> insertMusic(String singer,
MultipartFile file,
HttpServletRequest request,
HttpServletResponse response){
//1.检查登录
HttpSession session=request.getSession(false);
if(session==null || session.getAttribute(Constant.USERINFO_SESSION_KEY)==null){
log.error("未登录,请先进行登录");
return new ResponseBodyMessage<>(0,"没有登录",false);

}
//2.检查数数据库中是否有此音乐

//得到文件的名字和类型
String fileNameAndType=file.getOriginalFilename();
System.out.println("fileNameAndType"+fileNameAndType);
//以 . 将名字和类型分开,得到title
if(fileNameAndType==null || !fileNameAndType.contains(".")){
return new ResponseBodyMessage<>(0,"文件不合法,必须包含拓展名",false);
}
String title=fileNameAndType.substring(0,fileNameAndType.lastIndexOf("."));

log.info("Checking if music exists: title = {}, singer = {}", title, singer);
//判断数据库中是否有此歌曲
Integer exist= mapper.selectByTitleAndSinger(title,singer);
if(exist!=null && exist>0){
return new ResponseBodyMessage<>(0,"数据库中已经存在此音乐",false);
}

//3..上传音乐到服务器
String path=SAVE_PATH + fileNameAndType;
File dest=new File(path);
System.out.println("dest"+dest.getPath());
if(!dest.exists()){

dest.mkdirs();
}
//上传文件到目标
try {
file.transferTo(dest);
log.info("服务器上传成功");
} catch (IOException e) {
throw new RuntimeException(e);
}

//将歌曲上传到数据库
SimpleDateFormat sf=new SimpleDateFormat("yyyy-MM-dd");
String time=sf.format(new Date());

String url="music/get?path="+title;
User user=(User) session.getAttribute(Constant.USERINFO_SESSION_KEY);
int userId=user.getId();

try {
int ret= mapper.insert(title,singer,time,url,userId);

if(ret==1){
response.sendRedirect("/list.html");
return new ResponseBodyMessage<>(1,"数据库上传成功",true);
}else {

return new ResponseBodyMessage<>(-1,"数据库上传失败",false);
}
}catch (BindingException e){
boolean delete= dest.delete();
if(delete){
log.info("数据库插入失败,已成功删除服务器上的音乐文件");
}else{
log.warn("数据库插入失败,未删除服务器上的音乐文件,可能需要手动删除:{}",dest.getAbsolutePath());
}
return new ResponseBodyMessage<>(-1,"数据库上传失败,在服务器中删除音乐",false);
} catch (IOException e) {
throw new RuntimeException(e);
}
}

新增方法:判断上传的文件是否是MP3的形式

我们需要对上传的文件进行MP3文件类型检测,包括文件扩展名和MIME类型的两种检查

文件拓展名是文件名称的一部分,它可以轻易被修改,从而伪装成另一种文件

MIME类型是一种表示文件类型和格式的标准,比拓展名更加可靠

//根据文件的拓展名来判断是否为.MP3文件
String extension=fileNameAndType.substring(fileNameAndType.lastIndexOf(".")).toLowerCase();
if(!extension.equals(".mp3")){
return new ResponseBodyMessage<>(-0,"只支持MP3文件上传",false);
}
//根据MINE判断
try {
String mimeType=file.getContentType();
log.info("文件的MINI类型:{}",mimeType);
if(mimeType==null || !mimeType.equals("audio/mpeg")){
return new ResponseBodyMessage<>(0,"文件格式不正确,只支持MP3音频上传",false);
}
}catch (Exception e){
log.error("文件检验异常:{}",e.getMessage());
return new ResponseBodyMessage<>(0,"文件类型检验异常",false);

}

 

上传数据库的实现

@Mapper
public interface MusicMapper {

Integer insert(String title,String singer,String time,String url,Integer userid);
}
<?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.blame.onlinemusicserver.mapper.MusicMapper">

<insert id="insert">
insert into music (title,singer,time,url,userid) values (#{title},#{singer},#{time},#{url},#{userid})
</insert>

测试

播放⾳乐模块设计 

请求和响应的接口实现

在MusicController中新增get方法

是Spring框架中用于构建Http响应的对象

这里返回的是一个字节数组,通常用于传输二进制的数据,图片,音频

我们在这时传入的是音频

@GetMapping("/get")
public ResponseEntity<byte[]> get(@RequestParam String path){
return musicService.get(path);
}

MsuicService

ResponseEntity对象是Spring对请求响应的封装。它继承了HttpEntity对象,包含了Http的响应码 (httpstatus)、响应头(header)、响应体(body)三个部分。

//播放音乐
public ResponseEntity<byte[]> get(String path){
File file=new File(SAVE_PATH+path);
if(!file.exists()){
return ResponseEntity.notFound().build();
}
try {
byte[] bytes= Files.readAllBytes(file.toPath());
HttpHeaders headers=new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.setContentLength(bytes.length);
return ResponseEntity.ok().headers(headers).body(bytes);
} catch (IOException e) {
e.printStackTrace();
return ResponseEntity.internalServerError().build();
}
}

 验证

删除⾳乐模块设计

请求和响应的接口实现

实现MusicMapper

Integer deleteMusicById(Integer musicId);

Music selectMusicById(Integer musicId);
<delete id="deleteMusicById">
delete from music where id=#{id}
</delete>

<select id="selectMusicById" resultType="com.blame.onlinemusicserver.model.Music">
select * from music where id=#{id}
</select>

实现MusicController

根据Id来进行删除

@RequestMapping("/delete")
public ResponseBodyMessage<Boolean> deleteMusicById(@RequestParam Integer id){
return musicService.deleteMusicById(id);
}

实现MusicService 

如果要将一个歌曲删除,需要判断它是否在收藏歌曲中,如果在,则需要将其从收藏音乐中删除 

Boolean deleteLoveMusicByMusicId(Integer musicId);

Boolean selectLoveMusicByMusicId(Integer musicId);

判断删除是否成功

 

//删除音乐
public ResponseBodyMessage<Boolean> deleteMusicById(Integer id){
Music music=mapper.selectMusicById(id);
if(music==null){
return new ResponseBodyMessage<>(0,"该音乐不存在,无法删除",false);
}
//此时integer表示删除的行数,如果行数又0变为1则表示已经进行了删除的步骤
Integer integer = mapper.deleteMusicById(id);
Boolean isLoved = loveMusicMapper.selectLoveMusicByMusicId(id);
if (isLoved != null && isLoved) {
// 如果在收藏中,删除收藏记录
loveMusicMapper.deleteLoveMusicByMusicId(id);
} else {
log.info("歌曲不在收藏音乐中");
}
if(integer==1){
String title=music.getTitle();
File file=new File(SAVE_PATH+File.separator+ title+".mp3");
boolean delete=file.delete();

if(delete){
log.info("服务器中音乐删除成功");
return new ResponseBodyMessage<>(1,"服务器中音乐删除成功",true);
}else {
log.error("服务器中音乐删除失败");
return new ResponseBodyMessage<>(-1,"服务器中音乐删除失败",false);
}
}
return new ResponseBodyMessage<>(-1,"音乐删除失败",false);
}

 验证

批量删除选中的⾳乐

请求和响应的接口实现

实现MusicController

只需要先刚刚单首歌曲删除的基础上,在外层套一层for循环,依次进行删除,知道for循环结束,删除全部的歌曲

public ResponseBodyMessage<Boolean> deleteMusicByIdMany(List<Integer> id){
System.out.println("所有的Id: " + id);
int sum=0;
for (int i = 0; i < id.size(); i++) {
int musicId=id.get(i);
Music music=mapper.selectMusicById(musicId);
Boolean isLoved = loveMusicMapper.selectLoveMusicByMusicId(musicId);
if (isLoved != null && isLoved) {
// 如果在收藏中,删除收藏记录
loveMusicMapper.deleteLoveMusicByMusicId(musicId);
} else {
log.info("歌曲不在收藏音乐中");
}
System.out.println("当前正在处理的 ID: " + id);
if(music==null){
log.error("该歌曲不存在");
continue;
}
//此时integer表示删除的行数,如果行数又0变为1则表示已经进行了删除的步骤
Integer integer = mapper.deleteMusicById(musicId);
if(integer==1){
String title=music.getTitle();
File file=new File(SAVE_PATH+File.separator+ title+".mp3");
boolean delete=file.delete();
if(delete){
sum+=integer;
log.info("服务器中音乐删除成功");
}else {
log.error("服务器中音乐删除失败");
}
}else {
log.error("数据库删除失败");
}
}
if(sum==id.size()){
log.info("批量删除成功");
return new ResponseBodyMessage<>(1,"服务器中音乐批量删除成功",true);
}else {
log.info("批量删除失败");
return new ResponseBodyMessage<>(-1,"服务器中音乐批量删除失败",false);
}
}

验证

查询⾳乐模块设计

功能:支持模糊查询,支持输入的参数为空

输入参数为空时,查出所有的歌曲

MusicMapper

一个是根据歌名进行查询,另一个是查询全部的歌曲

List<Music> findMusicByTitle(String name);

List<Music> findMusic();

MusicController 

@RequestParam不传递参数时候,可以为空 

@RequestMapping("/findmusic")
public ResponseBodyMessage<List<Music>> findMusic(@RequestParam(required = false) String musicName){
return musicService.findMusic(musicName);
}

MusicService 

public ResponseBodyMessage<List<Music>> findMusic(String musicName){
List<Music> musics=null;
//musicName!=null是判断传入的歌曲名是否为空
//musicName.trim().isEmpty()是去掉前后的空格,判断字符串是否为空,加上这个更加的严谨
if(musicName!=null && !musicName.trim().isEmpty()){
log.info("已找到该歌曲");
musics=mapper.findMusicByTitle(musicName);
if(musics.isEmpty()){
return new ResponseBodyMessage<>(-1,"没有找到该歌曲",musics);
}
return new ResponseBodyMessage<>(1,"成功找到该歌曲",musics);
}else {
log.info("找到全部的歌曲");
musics=mapper.findMusic();
return new ResponseBodyMessage<>(1,"成功找到全部的歌曲",musics);
}
}

验证

输入为空,查询全部的歌曲

输入不为空,查询单个歌曲

 

添加⾳乐⾄喜欢的列表模块设计 

请求和响应的接口实现

LoveMusicMapper

@Mapper
public interface LoveMusicMapper {

//检查该音乐是否已经被收藏
Music selectMusicIsExist(Integer userId,Integer musicId);

//将该音乐加入收藏夹
Boolean insertLoveMusic(Integer userId,Integer musicId);
}
<select id="selectMusicIsExist" resultType="com.blame.onlinemusicserver.model.Music">
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>

 

LoveMusicController

@RestController
@RequestMapping("/lovemusic")
public class LoveMusicController {

@Autowired
private LoveMusicService loveMusicService;

@RequestMapping("addLikeMusic")
public ResponseBodyMessage<Boolean> addLikeMusic(@RequestParam String id,HttpServletRequest request){
return loveMusicService.addLikeMusic(id,request);
}
}

LoveMusicService

@Slf4j
@Service
public class LoveMusicService {

@Autowired
private LoveMusicMapper loveMusicMapper;

//添加收藏
public ResponseBodyMessage<Boolean> addLikeMusic(String id,HttpServletRequest request){

Integer musicId=Integer.parseInt(id);
System.out.println("musicId"+musicId);

//1.检查登录
HttpSession session=request.getSession(false);
if(session==null || session.getAttribute(Constant.USERINFO_SESSION_KEY)==null){
log.error("未登录,请先进行登录");
return new ResponseBodyMessage<>(0,"没有登录",false);
}
User user =(User) session.getAttribute(Constant.USERINFO_SESSION_KEY);

Integer userId=user.getId();
System.out.println("userId"+userId);

Music music=loveMusicMapper.selectMusicIsExist(userId,musicId);

if(music!=null){
return new ResponseBodyMessage<>(-1,"该音乐已经加入了收藏夹",false);
}
Boolean successAdd=loveMusicMapper.insertLoveMusic(userId,musicId);
if(successAdd){
return new ResponseBodyMessage<>(1,"音乐加入收藏夹成功",true);
}
return new ResponseBodyMessage<>(-1,"音乐加入收藏夹失败",false);
}

验证

查询喜欢的⾳乐模块设计

请求和响应的接口实现

LoveMusicMapper

//根据用户信息查询收藏的歌曲,支持模糊查询
List<Music> findLoveMusicByUserId(Integer userId);

//根据用户信息来查询想要查询的收藏的歌曲
List<Music> findLoveMusicByUserIdAndMusicId(Integer userId,String musicName);
<select id="findLoveMusicByUserId" resultType="com.blame.onlinemusicserver.model.Music">
select m.* from lovemusic lm,music m where lm.music_id=m.id and lm.user_id=#{userId}
</select>

<select id="findLoveMusicByUserIdAndMusicId" resultType="com.blame.onlinemusicserver.model.Music">
select m.* from lovemusic lm,music m where lm.music_id=m.id and lm.user_id=#{userId} and title like concat('%',#{musicName},'%')
</select>

LoveMusicController

@RequestMapping("/findlovemusic")
public ResponseBodyMessage<List<Music>> findLoveMusic(HttpServletRequest request,@RequestParam(required = false)
String musicName){
return loveMusicService.findLoveMusic(request, musicName);
}

 LoveMusicService

public ResponseBodyMessage<List<Music>> findLoveMusic(HttpServletRequest request,String musicName){
//判断是否登录
HttpSession session= request.getSession(false);
if(session==null || session.getAttribute(Constant.USERINFO_SESSION_KEY)==null){
log.error("未登录,请先进行登录");
return new ResponseBodyMessage<>(0,"没有登录",null);
}
User user=(User) session.getAttribute(Constant.USERINFO_SESSION_KEY);
Integer userId=user.getId();
System.out.println("userId"+userId);
List<Music> musics=null;
if(userId==null){
return new ResponseBodyMessage<>(-1,"用户不存在",null);
}
log.info("已经找到该用户");
//查询用户的全部收藏音乐
if(musicName==null){
musics= loveMusicMapper.findLoveMusicByUserId(userId);
//判断 musics 不为空且不为 null
if(!CollectionUtils.isEmpty(musics)){
return new ResponseBodyMessage<>(0,"已经找到用户的全部收藏音乐",musics);
}else {
return new ResponseBodyMessage<>(-1,"用户的收藏音乐为空",null);
}
}else { //根据用户信息来查询想要查询的收藏的歌曲
System.out.println("musicName"+musicName);
musics=loveMusicMapper.findLoveMusicByUserIdAndMusicId(userId,musicName);
//判断 musics 不为空且不为 null
if(!CollectionUtils.isEmpty(musics)){
return new ResponseBodyMessage<>(0,"已经找到用户查询的收藏歌曲",musics);
}else {
return new ResponseBodyMessage<>(-1,"用户没有收藏此音乐",null);
}

}
}

验证 

移除喜欢的⾳乐模块设计 

请求和响应的接口实现

LoveMusicMapper

Boolean deleteLoveMusic(Integer userId,Integer musicId);
<delete id="deleteLoveMusic">
delete from lovemusic where user_id=#{userId} and music_id=#{musicId}
</delete>

LoveMusicController

@RequestMapping("deleteLikeMusic")
public ResponseBodyMessage<Boolean> deleteLikeMusic(@RequestParam String id,HttpServletRequest request){
return loveMusicService.deleteLikeMusic(id,request);
}

LoveMusicService

//取消收藏
public ResponseBodyMessage<Boolean> deleteLikeMusic(String id,HttpServletRequest request){
Integer musicId=Integer.parseInt(id);
System.out.println("musicId"+musicId);

//检查登录
HttpSession session=request.getSession(false);
if(session==null || session.getAttribute(Constant.USERINFO_SESSION_KEY)==null){
log.error("未登录,请先进行登录");
return new ResponseBodyMessage<>(0,"没有登录",false);
}
User user =(User) session.getAttribute(Constant.USERINFO_SESSION_KEY);

Integer userId=user.getId();
System.out.println("userId"+userId);
Music music=loveMusicMapper.selectMusicIsExist(userId,musicId);
if(music==null){
return new ResponseBodyMessage<>(-1,"该音乐不在收藏夹内",false);
}
Boolean successDelete=loveMusicMapper.deleteLoveMusic(userId,musicId);
if(successDelete){
return new ResponseBodyMessage<>(1,"音乐已经从收藏夹中删除",true);
}
return new ResponseBodyMessage<>(-1,"音乐从收藏夹中删除失败",false);
}

验证

实现客户端的代码

登录界面

<script>
$(function () {
$("#submit").click(function () {
var username = $("#user").val().trim();
var password = $("#password").val().trim();

if (username === "" || password === "") {
$("#message").text("请输入用户名和密码!");
$("#messageBox").fadeIn();
return;
}

$.ajax({
url: "/user/login",
type: "post",
dataType: "json",
data: {
username: username,
password: password
},
success: function (result) {
if (result.status === 0) {
alert("登录成功!");
window.location.href = "list.html";
} else {
$("#message").text("账号或密码错误,请重试!");
$("#messageBox").fadeIn();
$("#user").val("");
$("#password").val("");
}
},
error: function () {
$("#message").text("服务器连接失败,请稍后重试!");
$("#messageBox").fadeIn();
}
});
});
});
</script>

注册界面

<script>
$(function () {
$("#registerBtn").click(function () {
var username = $("#regUser").val().trim();
var email = $("#regEmail").val().trim();
var password = $("#regPassword").val().trim();

if (username === "" || email === "" || password === "") {
$("#regMessage").text("请完善注册信息!");
$("#regMessageBox").fadeIn();
return;
}

$.ajax({
url: "/user/register",
type: "post",
dataType: "json",
contentType: "application/json",
data: JSON.stringify({
username: username,
password: password,
email: email
}),
success: function (result) {
if (result.status === 0) {
alert("注册成功!");
window.location.href = "login.html";
} else {
$("#regMessage").text(result.message);
$("#regMessageBox").fadeIn();
}
},
error: function () {
$("#regMessage").text("服务器连接失败,请稍后重试!");
$("#regMessageBox").fadeIn();
}
});
});
});
</script>

音乐列表界面

<script type="text/javascript">
$(function() {
load(); // 页面加载时默认加载所有歌曲
});

function load(musicName) {
$.ajax({
url: "/music/findmusic",
data: { musicName: musicName },
type: "get",
dataType: "json",
success: function(result) {
var data = result.data;
var s = '';
for (var i = 0; i < data.length; i++) {
var musicUrl = data[i].url + ".mp3";
s += '<tr>';
s += '<th> <input id="' + data[i].id + '" type="checkbox"> </th>';
s += '<td>' + data[i].title + '</td>';
s += '<td>' + data[i].singer + '</td>';
s += '<td><button class="btn" onclick="playerSong(\\'' + musicUrl + '\\')">播放歌曲</button></td>';
s += '<td><button class="btn" onclick="deleteInfo(' + data[i].id + ')">删除</button>';
s += '<button class="btn" onclick="loveInfo(' + data[i].id + ')">喜欢</button></td>';
s += '</tr>';
}
$("#info").html(s); // 更新表格
}
});
}

function playerSong(musicUrl) {
var name = musicUrl.substring(musicUrl.lastIndexOf('/') + 1); // 获取音乐名称
SewisePlayer.toPlay(musicUrl, name, 0, true); // 播放歌曲
}

function deleteInfo(musicId) {
$.ajax({
url: "/music/delete",
data: { id: musicId },
type: "post",
dataType: "json",
success: function(result) {
if (result.data) {
alert("删除成功");
window.location.href = "list.html"; // 页面跳转
} else {
alert("删除失败");
}
}
});
}
$(function(){
$("#submit1").click( function(){
var name = $("#exampleInputName2").val();
load(name);
});

$.when(load).done(function(){
$("#delete").click(function(){
var id = new Array();
var i = 0;//数组的小标
//
$("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:{"id":id},
dataType:"json",
type:"post",

success:function(obj){
if(obj.data == true) {
alert("删除成功!");
window.location.href = "list.html";
}else{
alert("删除失败!");
}
}
});
});
});
});
function loveInfo(musicId) {
$.ajax({
url: "lovemusic/addLikeMusic",
data: { "id": musicId },
type: "post",
dataType: "json",
success: function(result) {
if (result.data) {
alert("添加收藏成功");
window.location.href = "list.html"; // 页面跳转
} else {
alert("添加收藏失败");
}
}
});
}
</script>

收藏音乐界面

<script>
$(function() {
load();

$("#submit1").click(function() {
var name = $("#exampleInputName2").val();
load(name);
});
});

function load(musicName) {
$.ajax({
url: "/lovemusic/findlovemusic",
data: {"musicName": musicName},
type: "GET",
dataType: "json",
success: function(obj) {
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><audio src="' + musicUrl + '" controls preload="none" loop></audio></td>';
s += '<td><button class="btn btn-primary" onclick="deleteInfo(' + data[i].id + ')">移除</button></td>';
s += '</tr>';
}
$("#info").html(s);
}
});
}

function deleteInfo(id) {
$.ajax({
url: "/lovemusic/deleteLikeMusic",
type: "POST",
data: {"id": id},
dataType: "json",
success: function(val) {
if (val.data == true) {
alert("删除成功!,重新加载当前页面!");
window.location.href = "list.html";
} else {
alert("删除失败!");
}
}
});
}
</script>

上传音乐界面

<form method="POST" enctype="multipart/form-data" action="/music/upload">
<div class="form-group">
<label for="file">🎶 音乐文件</label>
<input type="file" id="file" name="filename" required />
</div>
<div class="form-group">
<label for="singer">👤 歌手名</label>
<input type="text" id="singer" name="singer" placeholder="请输入歌手名" required />
</div>
<input type="submit" value="📤 上传" />
</form>

 在这里的播放音乐的工具,我们使用的是一个开源的播放工具

demos/例子说明.md · Jack Zhang/sewise-player – Gitee.com

<div style="width: 180px; height: 140px; position: absolute; bottom: 10px; right: 10px;">
<script type="text/javascript" src="player/sewise.player.min.js"></script>
<script type="text/javascript">
SewisePlayer.setup({
server: "vod",
type: "mp3",
videourl: "http://jackzhang1204.github.io/materials/where_did_time_go.mp3",
skin: "vodWhite",
autostart: "false",
});
</script>
</div>

实现播放

function playerSong(musicUrl) {
var name = musicUrl.substring(musicUrl.lastIndexOf('/') + 1); // 获取音乐名称
SewisePlayer.toPlay(musicUrl, name, 0, true); // 播放歌曲
}

 配置拦截器

自定义拦截器

@Component
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.USERINFO_SESSION_KEY) != null) {
return true;
}
// 未登录提示
//是告诉浏览器内容是 JSON,并且是 UTF-8 编码;
response.setContentType("application/json;charset=utf-8");
//手动返回一段json数据,进行错误提示
response.getWriter().write("{\\"code\\":401,\\"msg\\":\\"未登录,请先登录\\"}");
return false;
}
}

使用拦截器

只释放静态资源和登录接口

@Configuration
public class AppConfig implements WebMvcConfigurer {

@Override
public void addInterceptors(InterceptorRegistry registry) {
LoginInterceptor loginInterceptor = new LoginInterceptor();
registry.addInterceptor(loginInterceptor)
.addPathPatterns("/**") // 拦截所有请求
.excludePathPatterns(
"/js/**",
"/css/**",
"/images/**",
"/fonts/**",
"/player/**",
"/login.html",
"/user/login"
); // 放行静态资源和登录接口
}
}

 项目在此全部结束,可以将项目部署到云服务器上

希望能对大家有所帮助!!!

赞(0)
未经允许不得转载:网硕互联帮助中心 » 项目:在线音乐播放服务器——基于SSM框架和mybatis
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!