项目:在线音乐播放服务器——基于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=UTCusername: 你自己的数据库用户名password: 你自己的数据库密码driver-class-name: com.mysql.cj.jdbc.Driverservlet:multipart:max-file-size: 15MBmax-request-size: 100MB
#音乐上传后的路径music:local:path: E:/music/mybatis:configuration:map-underscore-to-camel-case: truelog-impl: org.apache.ibatis.logging.stdout.StdOutImplmapper-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 {@Autowiredprivate 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 {@Beanpublic BCryptPasswordEncoder getbCryptPasswordEncoder(){return new BCryptPasswordEncoder();}
}
创建UserService
request.getSession(),获取这次请求的session对象
.setAttribute()将用户信息存储到session中
因为 USERINFO_SESSION_KEY 这个常量容易拼错,所以我们将其定义在常量信息中
@Service
public class UserService {@Autowiredprivate UserMapper userMapper;@Autowiredprivate 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 {@Autowiredprivate 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;@Autowiredprivate MusicMapper mapper;@Autowiredprivate 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);//以 . 将名字和类型分开,得到titleif(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 {@Autowiredprivate LoveMusicService loveMusicService;@RequestMapping("addLikeMusic")public ResponseBodyMessage<Boolean> addLikeMusic(@RequestParam String id,HttpServletRequest request){return loveMusicService.addLikeMusic(id,request);}
}
LoveMusicService
@Slf4j
@Service
public class LoveMusicService {@Autowiredprivate 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 不为空且不为 nullif(!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 不为空且不为 nullif(!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 {@Overridepublic 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 {@Overridepublic void addInterceptors(InterceptorRegistry registry) {LoginInterceptor loginInterceptor = new LoginInterceptor();registry.addInterceptor(loginInterceptor).addPathPatterns("/**") // 拦截所有请求.excludePathPatterns("/js/**","/css/**","/images/**","/fonts/**","/player/**","/login.html","/user/login"); // 放行静态资源和登录接口}
}
项目在此全部结束,可以将项目部署到云服务器上
希望能对大家有所帮助!!!