JavaWeb——在线音乐播放器
文章目錄
- 效果演示
- 1. 創(chuàng)建SpringBoot項(xiàng)目
- 2. 數(shù)據(jù)庫設(shè)計(jì)
- 3. 配置數(shù)據(jù)庫和xml
- 4. 登錄模塊設(shè)計(jì)
-
- 4.1 創(chuàng)建User類
- 4.2 創(chuàng)建對應(yīng)的Mapper和Controller
- 5. 實(shí)現(xiàn)登錄
-
- 5.1 登錄的請求和響應(yīng)設(shè)計(jì)
- 5.2 請求實(shí)現(xiàn)
- 5.3 響應(yīng)實(shí)現(xiàn)
-
- 5.31 設(shè)置統(tǒng)一的響應(yīng)體類工具類
- 5.32 創(chuàng)建常量工具類
- 5.33 優(yōu)化后完整代碼
- 6. 實(shí)現(xiàn)加密登錄
-
- 6.1 Bcrypt加密設(shè)計(jì)
- 6.2 加密登錄實(shí)現(xiàn)
-
- 6.21 創(chuàng)建包c(diǎn)onfig,新建AppConfig類
- 6.3 加密登錄完整實(shí)現(xiàn)
- 7. 上傳音樂模塊設(shè)計(jì)
-
- 7.1 上傳音樂的請求和響應(yīng)設(shè)計(jì)
- 7.2 新建 music 實(shí)體類
- 7.3 實(shí)現(xiàn)服務(wù)器上傳
-
- 創(chuàng)建 MusicController 類
- 7.4 如何判斷上傳的文件是mp3
- 7.5 實(shí)現(xiàn)數(shù)據(jù)庫上傳
-
- 實(shí)現(xiàn) MusicMapper
- 實(shí)現(xiàn) MusicMapper.xml
- 進(jìn)行 數(shù)據(jù)庫上傳
- 完整代碼
- 8. 播放音樂模塊設(shè)計(jì)
-
- 8.1 實(shí)現(xiàn) ResponseEntity 類
- 9. 刪除音樂模塊設(shè)計(jì)
-
- 9.1 刪除單個音樂
- 9.2 批量刪除
- 10. 查詢音樂模塊設(shè)計(jì)
-
- 10.1 實(shí)現(xiàn) MusicMapper
- 10.2 實(shí)現(xiàn) MusicMapper.xml
- 10.3 實(shí)現(xiàn) MusicController
- 11. 收藏/喜歡音樂模塊設(shè)計(jì)
-
- 11.1 實(shí)現(xiàn) LoveMusicMapper
- 11.2 實(shí)現(xiàn) LoveMusicMapper.xml
- 11.3 實(shí)現(xiàn) LoveMusicController
- 12. 查詢收藏/喜歡音樂模塊設(shè)計(jì)
-
- 12.1 實(shí)現(xiàn) LoveMusicMapper
- 12.2 實(shí)現(xiàn) LoveMusicMapper.xml
- 12.3 實(shí)現(xiàn) LoveMusicController
- 13. 取消音樂收藏模塊設(shè)計(jì)
-
- 13.1 實(shí)現(xiàn) LoveMusicMapper
- 13.2 實(shí)現(xiàn) LoveMusicMapper.xml
- 13.3 實(shí)現(xiàn) LoveMusicController
- 13.4 存在BUG分析
- 14. 刪除音樂完善
- 15. 注冊實(shí)現(xiàn)
- 前端頁面實(shí)現(xiàn)
- 16. 實(shí)現(xiàn) 登錄界面 login.html
- 17. 實(shí)現(xiàn)上傳音樂 upload.html
- 18. 實(shí)現(xiàn)音樂列表頁 list.html
- 19. 實(shí)現(xiàn)播放歌曲
- 20. 實(shí)現(xiàn)刪除單個音樂
- 21. 實(shí)現(xiàn)查詢音樂功能
- 22. 實(shí)現(xiàn)刪除選中音樂功能
- 23. 實(shí)現(xiàn)喜歡音樂列表頁功能
- 24. 實(shí)現(xiàn)收藏音樂列表功能
- 25 實(shí)現(xiàn)注冊功能
- 26 配置攔截器
- 項(xiàng)目部署
效果演示
1. 創(chuàng)建SpringBoot項(xiàng)目
2. 數(shù)據(jù)庫設(shè)計(jì)
創(chuàng)建 user 表:
用戶 id,用戶名 username,用戶密碼 password
創(chuàng)建 music 表:
音樂 id,音樂名稱 title,歌手名稱 singer,時(shí)間 time,歌曲路徑 url,對應(yīng)上傳音樂的用戶 userid
創(chuàng)建 lovemusic 表(中間表):
音樂 id,對應(yīng)的用戶id user_id,對應(yīng)的音樂id music_id
-- 數(shù)據(jù)庫
drop database if exists `onlinemusic`;
create database if not exists `onlinemusic` character set utf8;-- 使用數(shù)據(jù)庫
use `onlinemusic`;-- 創(chuàng)建 user表
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` INT PRIMARY KEY AUTO_INCREMENT,
`username` varchar(20) NOT NULL,
`password` varchar(255) NOT NULL
);-- 創(chuàng)建 music 表
DROP TABLE IF EXISTS `music`;
CREATE TABLE `music` (
`id` int PRIMARY KEY AUTO_INCREMENT,
`title` varchar(50) NOT NULL,
`singer` varchar(30) NOT NULL,
`time` varchar(13) NOT NULL,
`url` varchar(1000) NOT NULL,
`userid` int(11) NOT NULL
);-- 創(chuàng)建 lovemusic
DROP TABLE IF EXISTS `lovemusic`;
CREATE TABLE `lovemusic` (
`id` int PRIMARY KEY AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`music_id` int(11) NOT NULL
);
3. 配置數(shù)據(jù)庫和xml
打開application.properties配置如下信息:
#配置數(shù)據(jù)庫
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/onlinemusic?characterEncoding=utf8&useSSL=false
spring.datasource.username=root
spring.datasource.password=你的密碼
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver#配置xml
mybatis.mapper-locations=classpath:mybatis/**Mapper.xml#配置springboot上傳文件的大小,默認(rèn)每個文件的配置最大為15Mb,單次請求的文件的總數(shù)不能大于100Mb
spring.servlet.multipart.max-file-size = 15MB
spring.servlet.multipart.max-request-size=100MB# 配置springboot日志調(diào)試模式是否開啟
debug=true# 設(shè)置打印日志的級別,及打印sql語句
#日志級別:trace,debug,info,warn,error
#基本日志
logging.level.root=INFO
logging.level.com.example.onlinemusic.mapper=debug#掃描的包:druid.sql.Statement類和frank包
logging.level.druid.sql.Statement=DEBUG
logging.level.com.example=DEBUG
4. 登錄模塊設(shè)計(jì)
4.1 創(chuàng)建User類
在package com.example.onlinemusic.model包中創(chuàng)建User類
@Data
public class User {private int id;private String username;private String password;
}
4.2 創(chuàng)建對應(yīng)的Mapper和Controller
1.新建mapper包,在mapper包下新建UserMapper
@Mapper
public interface UserMapper {User login(User loginUser);
}
2.在resource目錄下,新建mybatis文件夾,新建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.example.onlinemusic.mapper.UserMapper"></mapper>
5. 實(shí)現(xiàn)登錄
5.1 登錄的請求和響應(yīng)設(shè)計(jì)
5.2 請求實(shí)現(xiàn)
@RestController // 這個注解是 @Controller 和 @RequestBody 的組合注解
@RequestMapping("/user") // 一級路由
public class UserController {@Autowiredprivate UserMapper userMapper; // 注入 UserMapper// 后面要用 UserMapper里面的方法,去進(jìn)行數(shù)據(jù)查詢// 登錄功能@RequestMapping("/login")// 傳遞兩個參數(shù) 一個是 username 一個是 passwordpublic void login(@RequestParam String username,@RequestParam String password) { // @RequestParam 注解,可以H后端參數(shù)重命名,也可以制定傳參// 拿到 userLogin 對象,設(shè)置 用戶名和密碼User userLogin = new User();userLogin.setUsername(username);userLogin.setPassword(password);// 調(diào)用 userMapper的 login 方法 在數(shù)據(jù)庫中 進(jìn)行查詢,返回 UserUser user = userMapper.login(userLogin);if(user != null ) {System.out.println("登錄成功!");}else {System.out.println("登錄失敗!");}}
}
UserMapper 中:
@Mapper
public interface UserMapper {// 登錄功能,查詢操作User login(User userLogin);// login 方法,返回為 User 對象
}
UserMapper.xml中:
<!-- 登錄操作,查詢 username 和 password,后面查詢那個,就目錄就是誰的,比如這里查詢是User--><select id="login" resultType="com.example.onlinemusic.model.User">select * from user where username=#{username} and password=#{password};</select>
5.3 響應(yīng)實(shí)現(xiàn)
5.31 設(shè)置統(tǒng)一的響應(yīng)體類工具類
@Data
// 這是統(tǒng)一響應(yīng)體工具類
public class ResponseBodyMessage <T> {private int status; // 狀態(tài)碼private String message; // 返回的信息[出錯或者沒出錯的原因]private T data; // 返回給前端的數(shù)據(jù),有可能是 boolean 類型,類型很多這里直接用 泛型// 構(gòu)造方法public ResponseBodyMessage(int status, String message, T data) {this.status = status;this.message = message;this.data = data;}
}
5.32 創(chuàng)建常量工具類
5.33 優(yōu)化后完整代碼
加了響應(yīng)體之后,登錄成功,我們再存儲一下 Session
完整代碼如下:
@RestController // 這個注解是 @Controller 和 @RequestBody 的組合注解
@RequestMapping("/user") // 一級路由
public class UserController {@Autowiredprivate UserMapper userMapper; // 注入 UserMapper// 后面要用 UserMapper里面的方法,去進(jìn)行數(shù)據(jù)查詢// 登錄功能@RequestMapping("/login")// 傳遞兩個參數(shù) 一個是 username 一個是 password// 加了統(tǒng)一響應(yīng)體類之后 返回值 不在是 void ,而是 我們的 ResponseBodyMessagepublic ResponseBodyMessage<User> login(@RequestParam String username,@RequestParam String password,HttpServletRequest request) {// @RequestParam 注解,可以H后端參數(shù)重命名,也可以制定傳參// 拿到 userLogin 對象,設(shè)置 用戶名和密碼User userLogin = new User();userLogin.setUsername(username);userLogin.setPassword(password);// 調(diào)用 userMapper的 login 方法 在數(shù)據(jù)庫中 進(jìn)行查詢,返回 UserUser user = userMapper.login(userLogin);if(user != null ) {System.out.println("登錄成功!");// 存儲 session
// request.getSession().setAttribute("USERINFO_SESSION_KEY",user);// 做出優(yōu)化后的代碼,我們將 USERINFO_SESSION_KEY 寫在我們的工具包中request.getSession().setAttribute(Constant.USERINFO_SESSION_KEY,user);/*** request.getSession.setAttribute()是獲得當(dāng)前會話的session* 然后再setAttribute到session里面去,有效范圍是session而不是request。*/// 返回響應(yīng)體return new ResponseBodyMessage<>(0,"登錄成功老鐵!",userLogin);}else {System.out.println("登錄失敗!");// 登錄失敗,做出響應(yīng)// 在這里規(guī)定 status -1 為失敗 0為成功return new ResponseBodyMessage<>(-1,"登錄失敗老鐵!",userLogin);}}
}
6. 實(shí)現(xiàn)加密登錄
6.1 Bcrypt加密設(shè)計(jì)
Bcrypt就是一款加密工具,可以比較方便地實(shí)現(xiàn)數(shù)據(jù)的加密工作。你也可以簡單理解為它內(nèi)部自己實(shí)現(xiàn)了隨機(jī)加鹽處理 。我們使用MD5加密,每次加密后的密文其實(shí)都是一樣的,這樣就方便了MD5通過大數(shù)據(jù)的方式進(jìn)行破解。Bcrypt生成的密文是60位的。而MD5的是32位的。Bcrypt破解難度更大
添加如下依賴到 pom.xml:
<!-- 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})
為什么要加 spring-boot 啟動類注解:
當(dāng)啟動類,沒有加這個過濾的時(shí)候,我們發(fā)現(xiàn)不能進(jìn)行登錄。
這是因?yàn)樵赟pringBoot中,默認(rèn)的Spring Security生效了的,此時(shí)的接口都是被保護(hù)的,我們需要通過驗(yàn)證才能正常的訪問。此時(shí)通過上述配置,即可禁用默認(rèn)的登錄驗(yàn)證。
實(shí)質(zhì)我們并沒有用到 Security 這個框架,而是用到了里面其中的一個類,僅此而以
創(chuàng)建 BcryptTest 測試類:
public class BcryptTest {public static void main(String[] args) {
//模擬從前端獲得的密碼// String password = "123456";// 獲取 BCrypt 對象BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();// encode 對我們輸入的密碼進(jìn)行加密處理 得到新的密碼String newPassword = bCryptPasswordEncoder.encode(password);System.out.println("加密的密碼為: " + newPassword);//使用matches方法進(jìn)行密碼的校驗(yàn)boolean same_password_result = bCryptPasswordEncoder.matches(password, newPassword);
//返回trueSystem.out.println("加密的密碼和正確密碼對比結(jié)果: " + same_password_result);boolean other_password_result = bCryptPasswordEncoder.matches("987654", newPassword);
//返回falseSystem.out.println("加密的密碼和錯誤的密碼對比結(jié)果: " + other_password_result);}
}
6.2 加密登錄實(shí)現(xiàn)
邏輯如下:
1.根據(jù)用戶名名稱 查詢 當(dāng)前是否存在這樣的用戶[用戶名:默認(rèn)是唯一的]
2.取出當(dāng)前用戶的密碼,進(jìn)行匹配,查看密碼是否是一樣的,一樣就登錄成功
6.21 創(chuàng)建包c(diǎn)onfig,新建AppConfig類
這里為什么要建一個 AppConfig 類,是為了方便我們后面的對象注入,比如我 我們要在 加密登錄中 注入 BCryptPasswordEncoder,我們就需要先創(chuàng)建一個對象,通過 @Bean 注解,將它輸入到 Spring 容器中
當(dāng)然直接在 UserController 當(dāng)中進(jìn)行 實(shí)例化創(chuàng)建 BCryptPasswordEncoder 對象也是一樣的
//@Configuration:表明當(dāng)前類是一個配置類,被注解的類內(nèi)部包含有一個或多個被@Bean注解的方法,用于構(gòu)建
//bean定義,初始化Spring容器。
//@Bean注解:用于告訴方法,產(chǎn)生一個Bean對象,然后這個Bean對象交給Spring管理。產(chǎn)生這個Bean對象的方
//法Spring只會調(diào)用一次,隨后這個Spring將會將這個Bean對象放在自己的IOC容器中。
//SpringIOC 容器管理一個或者多個bean,這些bean都需要在@Configuration注解下進(jìn)行創(chuàng)建,在一個方法上使用
//@Bean注解就表明這個方法需要交給Spring進(jìn)行管理。
@Configuration
public class AppConfig {@Beanpublic BCryptPasswordEncoder getBCryptPasswordEncoder() {return new BCryptPasswordEncoder();}
}
UserMapper 代碼如下:
UserMapper.xml 內(nèi)容如下:
6.3 加密登錄完整實(shí)現(xiàn)
/*** 實(shí)現(xiàn)加密登錄*/@RequestMapping("/login")// 傳遞兩個參數(shù) 一個是 username 一個是 password// 加了統(tǒng)一響應(yīng)體類之后 返回值 不在是 void ,而是 我們的 ResponseBodyMessagepublic ResponseBodyMessage<User> login(@RequestParam String username,@RequestParam String password,HttpServletRequest request) {// User userLogin = new User();
// userLogin.setUsername(username);
// userLogin.setPassword(password);
// User user = userMapper.login(userLogin);// 1. 先去查詢我們 用戶,是否存在User user = userMapper.selectByName(username);if(user != null ) {// 2. 如果用戶存在,找到當(dāng)前用戶的密碼,通過 Bcrypt 中的 matches 方法 判斷密碼是否一致// password 為原來的密碼,user.getPassword 為加密后的密碼boolean flg = bCryptPasswordEncoder.matches(password,user.getPassword());if(!flg) {// 說明密碼不匹配return new ResponseBodyMessage<>(-1,"登錄失敗,用戶名或密碼錯誤",user);}System.out.println("登錄成功!");request.getSession().setAttribute(Constant.USERINFO_SESSION_KEY,user);return new ResponseBodyMessage<>(0,"登錄成功老鐵!",user);}else {System.out.println("登錄失敗!");return new ResponseBodyMessage<>(-1,"登錄失敗,沒找到用戶!",user);}}
7. 上傳音樂模塊設(shè)計(jì)
7.1 上傳音樂的請求和響應(yīng)設(shè)計(jì)
7.2 新建 music 實(shí)體類
@Data
public class Music {private int id;private String title;private String singer;private String time;private String url;private int userId;
}
7.3 實(shí)現(xiàn)服務(wù)器上傳
創(chuàng)建 MusicController 類
@RestController // 組合注解 @Controller + @ResponseBody
@RequestMapping("/music")
public class MusicController {/*** 上傳音樂* @return*/// 從配置文件中 將 路徑 讀取出來@Value("${music.local.path}")private String SAVE_PATH;@RequestMapping("/upload")public ResponseBodyMessage<Boolean> insertMusic(@RequestParam String singer,@RequestParam("filename") MultipartFile file,HttpServletRequest request) {// 1. 檢查是否登錄// 獲取 sessionHttpSession session = request.getSession(false);// 判空if(session == null || session.getAttribute(Constant.USERINFO_SESSION_KEY) == null) {System.out.println("沒有登錄!");return new ResponseBodyMessage<>(-1,"請登錄后上傳!",false);}// 2. 上傳到了服務(wù)器 ---- 拿到完整的文件名稱 xxx.mp3String fileNameAndType = file.getOriginalFilename(); // 獲取完整文件名稱System.out.println("fileNameAndType" + fileNameAndType);String path = SAVE_PATH + fileNameAndType;File dest = new File(path); // dest 目錄if(!dest.exists()) {dest.mkdir(); // 如果 dest(目錄)不存在 創(chuàng)建目錄}// 如果存在,通過 file.transferTo 將文件上傳try {file.transferTo(dest);return new ResponseBodyMessage<>(0,"上傳成功!",true);} catch (IOException e) {e.printStackTrace();}return new ResponseBodyMessage<>(-1,"上傳失敗!",false);}}
7.4 如何判斷上傳的文件是mp3
每個種類的文件都要自己的格式,檢測當(dāng)前你上傳的格式,判斷這個文件的格式是不是 mp3 文件
不能通過后綴名進(jìn)行判斷,后綴名可以進(jìn)行更改的
7.5 實(shí)現(xiàn)數(shù)據(jù)庫上傳
實(shí)現(xiàn) MusicMapper
實(shí)現(xiàn) MusicMapper.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 所對應(yīng)的目錄-->
<mapper namespace="com.example.onlinemusic.mapper.MusicMapper"><insert id="insert" >insert into music(title,singer,time,url,userid)values(#{title},#{singer},#{time},#{url},#{userid});</insert></mapper>
進(jìn)行 數(shù)據(jù)庫上傳
分別獲取需要的數(shù)據(jù):
tilte,singer,userid,url,time
/*** 進(jìn)行 數(shù)據(jù)庫 上傳*/// 1. 先準(zhǔn)備需要數(shù)據(jù)// 1.1 獲取title xxx.mp3 -- > title = xxxint index = fileNameAndType.lastIndexOf(".");String title = fileNameAndType.substring(0,index); // 拿到 xxx// 1.2 獲取 singer 已經(jīng)確定,我們傳參已經(jīng)傳了// 1.3 獲取 useridUser user = (User) session.getAttribute(Constant.USERINFO_SESSION_KEY);int userid = user.getId();// 1.4 獲取 url,播放音樂-》http請求String url = "/music/get?path="+title;// 1.5 獲取 年-月-日SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");// 把當(dāng)前的日期格式化為 time format()格式化String time = sf.format(new Date());// 2. 調(diào)用 insertint ret = 0; // 插入影響的是行數(shù),這里我們初始化一下,看看他等不等于1,等于1說明插入成功ret = musicMapper.insert(title,singer,time,url,userid);if(ret ==1 ) {return new ResponseBodyMessage<>(1,"數(shù)據(jù)庫上傳成功",true);}else {return new ResponseBodyMessage<>(-1,"數(shù)據(jù)庫上傳失敗",false);}}
完整代碼
@RestController // 組合注解 @Controller + @ResponseBody
@RequestMapping("/music")
public class MusicController {/*** 上傳音樂* @return*/@Autowiredprivate MusicMapper musicMapper;// 從配置文件中 將 路徑 讀取出來@Value("${music.local.path}")private String SAVE_PATH;@RequestMapping("/upload")public ResponseBodyMessage<Boolean> insertMusic(@RequestParam String singer,@RequestParam("filename") MultipartFile file,HttpServletRequest request) {// 1. 檢查是否登錄// 獲取 sessionHttpSession session = request.getSession(false);// 判空if(session == null || session.getAttribute(Constant.USERINFO_SESSION_KEY) == null) {System.out.println("沒有登錄!");return new ResponseBodyMessage<>(-1,"請登錄后上傳!",false);}// 先查詢數(shù)據(jù)庫當(dāng)中是否有當(dāng)前音樂[歌曲名 + 歌手]// TODD:// 2. 上傳到了服務(wù)器 ---- 拿到完整的文件名稱 xxx.mp3String fileNameAndType = file.getOriginalFilename(); // 獲取完整文件名稱System.out.println("fileNameAndType" + fileNameAndType);String path = SAVE_PATH + fileNameAndType;File dest = new File(path); // dest 目錄if(!dest.exists()) {dest.mkdir(); // 如果 dest(目錄)不存在 創(chuàng)建目錄}// 如果存在,通過 file.transferTo 將文件上傳try {file.transferTo(dest);} catch (IOException e) {e.printStackTrace();return new ResponseBodyMessage<>(-1,"服務(wù)器上傳失敗!",false);}/*** 進(jìn)行 數(shù)據(jù)庫 上傳*/// 1. 先準(zhǔn)備需要數(shù)據(jù)// 1.1 獲取title xxx.mp3 -- > title = xxxint index = fileNameAndType.lastIndexOf(".");String title = fileNameAndType.substring(0,index); // 拿到 xxx// 1.2 獲取 singer 已經(jīng)確定,我們傳參已經(jīng)傳了// 1.3 獲取 useridUser user = (User) session.getAttribute(Constant.USERINFO_SESSION_KEY);int userid = user.getId();// 1.4 獲取 url,播放音樂-》http請求String url = "/music/get?path="+title;// 1.5 獲取 年-月-日SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");// 把當(dāng)前的日期格式化為 time format()格式化String time = sf.format(new Date());try {// 2. 調(diào)用 insertint ret = 0; // 插入影響的是行數(shù),這里我們初始化一下,看看他等不等于1,等于1說明插入成功ret = musicMapper.insert(title,singer,time,url,userid);if(ret ==1 ) {return new ResponseBodyMessage<>(0,"數(shù)據(jù)庫上傳成功",true);}else {return new ResponseBodyMessage<>(-1,"數(shù)據(jù)庫上傳失敗",false);}}catch (BindingException e) {dest.delete();return new ResponseBodyMessage<>(-1,"數(shù)據(jù)庫上傳失敗",false);}// 另外一個問題: 如果重復(fù)上傳一首歌曲 能否上傳成功? 可以}}
8. 播放音樂模塊設(shè)計(jì)
8.1 實(shí)現(xiàn) ResponseEntity 類
/*** 播放音樂模塊設(shè)計(jì)*/// 播放音樂的時(shí)候,路徑:/music/get?path=xxx.mp3@RequestMapping("/get")public ResponseEntity<byte[]> get(String path) {File file = new File(SAVE_PATH + path);byte[] a = null;try {a = Files.readAllBytes(file.toPath());//Files.readAllBytes(String path) :// 讀取文件中的所有字節(jié),讀入內(nèi)存 ,參數(shù)path是文件的路徑if(a == null) {// 無參ok方法返回OK狀態(tài)// 有參ok方法返回body內(nèi)容和OK狀態(tài)return ResponseEntity.badRequest().build();}return ResponseEntity.ok(a);} catch (IOException e) {e.printStackTrace();}return ResponseEntity.badRequest().build();
// return ResponseEntity.internalServerError().build();
// return ResponseEntity.notFound().build();}
9. 刪除音樂模塊設(shè)計(jì)
9.1 刪除單個音樂
請求和響應(yīng)設(shè)計(jì):
data: 成功 or 失敗
1.MusicMapper 內(nèi)容如下:
2.MusicMapper.xml 內(nèi)容如下
3.MusicController 內(nèi)容如下:
@RequestMapping("/delete")public ResponseBodyMessage<Boolean> deleteMusicById(@RequestParam String id) {// 1. 先檢查音樂是否存在int iid = Integer.parseInt(id);// 2. 如果存在進(jìn)行刪除Music music = musicMapper.findMusicById(iid);if(music == null) {return new ResponseBodyMessage<>(-1,"沒有你要刪除的音樂!",false);}else {// 2.1 刪除數(shù)據(jù)庫int ret = musicMapper.deleteMusicById(iid);// 如果 ret 等于1 說明 數(shù)據(jù)庫數(shù)據(jù)刪除成功if(ret == 1) {// 2.2 刪除服務(wù)器上的數(shù)據(jù)(file)// 這里需要拿到 title,可以通過 url 去拿,也可以直接 music.getTitleint index = music.getUrl().lastIndexOf("=");String fileName = music.getUrl().substring(index+1);File file = new File(SAVE_PATH + fileName + ".mp3");System.out.println("當(dāng)前的路徑: " + file.getPath());if(file.delete()){return new ResponseBodyMessage<>(0,"服務(wù)器當(dāng)中的音樂刪除成功!",true);}else {return new ResponseBodyMessage<>(-1,"服務(wù)器當(dāng)中的音樂刪除失敗!",false);}}else {return new ResponseBodyMessage<>(-1,"數(shù)據(jù)庫當(dāng)中的音樂沒有刪除成功",false);}}}
9.2 批量刪除
約定前后端相互接口:
MusicController 內(nèi)容如下:
/*** 批量刪除* id[1,3,5,7,9]*/@RequestMapping("/deleteSel")public ResponseBodyMessage<Boolean> deleteSelMusic(@RequestParam("id[]")List<Integer> id) {System.out.println("所有的id:" + id);int sum = 0;// 因?yàn)槭桥縿h除,這里用數(shù)組存儲我們要刪除的 音樂 idfor (int i = 0; i < id.size(); i++) {// 1. 查詢 音樂是否存在Music music = musicMapper.findMusicById(id.get(i));if (music == null) {System.out.println("沒有這個id的音樂");return new ResponseBodyMessage<>(-1, "沒有你要刪除的音樂", false);}// 2. 如果音樂存在我們進(jìn)行刪除// 2.1 進(jìn)行數(shù)據(jù)庫刪除int ret = musicMapper.deleteMusicById(id.get(i));if (ret == 1) {// 說明 數(shù)據(jù)庫刪除成功,進(jìn)行服務(wù)器刪除// 先拿到 titleint index = music.getUrl().lastIndexOf("=");String fileName = music.getUrl().substring(index + 1);File file = new File(SAVE_PATH + fileName + ".mp3");System.out.println("當(dāng)前路徑:" + file.getPath());if (file.delete()) {sum += ret;} else {return new ResponseBodyMessage<>(-1, "服務(wù)器當(dāng)中的音樂刪除失敗!", false);}}else {return new ResponseBodyMessage<>(-1,"數(shù)據(jù)庫當(dāng)中音樂刪除失敗",false);}}// 判斷 sum 的值是否等于 id.size 如果等于說明 刪完啦if(sum == id.size()) {System.out.println("整體刪除成功!");return new ResponseBodyMessage<>(0,"音樂刪除成功",true);}else {System.out.println("整體刪除失敗!");return new ResponseBodyMessage<>(-1,"音樂刪除失敗",false);}}
10. 查詢音樂模塊設(shè)計(jì)
此處查詢需要滿足幾個功能:
- 支持模糊查詢
- 支持傳入?yún)?shù)為空
請求和響應(yīng)設(shè)計(jì):
10.1 實(shí)現(xiàn) MusicMapper
10.2 實(shí)現(xiàn) MusicMapper.xml
模糊查詢:
select * from music where title like concat('%',#{musicName},'%');
10.3 實(shí)現(xiàn) MusicController
@RequestMapping("/findmusic")// 這里有一個小細(xì)節(jié),我們可能不傳參那么 我們的 @RequestParam 這里 需要 required = falsepublic ResponseBodyMessage<List<Music>> findMusic(@RequestParam(required = false)String musicName) {List<Music> musicList = null;if(musicName != null) {// 不為空 查詢指定音樂musicList = musicMapper.findMusicByName(musicName);}else {// 為空 查詢所有音樂musicList = musicMapper.findMusic();}return new ResponseBodyMessage<>(0,"查詢到了所有的音樂",musicList);}
11. 收藏/喜歡音樂模塊設(shè)計(jì)
請求和響應(yīng)設(shè)計(jì):
11.1 實(shí)現(xiàn) LoveMusicMapper
11.2 實(shí)現(xiàn) LoveMusicMapper.xml
11.3 實(shí)現(xiàn) LoveMusicController
/*** 收藏音樂,需要獲取到 userId 和 musicId,musicId 傳入的參數(shù),userId 通過 session 獲取*/@RequestMapping("/likeMusic")public ResponseBodyMessage<Boolean> likeMusic(@RequestParam String id, HttpServletRequest request) {// 字符串變?yōu)檎麛?shù)int musicId = Integer.parseInt(id);System.out.println("musicId:" + musicId);// 1. 檢查是否登錄HttpSession session = request.getSession(false); // 獲取 session// 判斷 session 是否為空if(session == null || session.getAttribute(Constant.USERINFO_SESSION_KEY) == null) {System.out.println("沒有登錄!");return new ResponseBodyMessage<>(-1,"請先登錄!",false);}// 如果不為空 獲取 session 信息User user = (User) session.getAttribute(Constant.USERINFO_SESSION_KEY);int userId = user.getId();System.out.println("userId:" + userId);Music music = loveMusicMapper.findLoveMusic(userId,musicId);if(music != null) {// 如果不等于null,說明之前收藏過當(dāng)前的音樂,不能進(jìn)行收藏 TODD:加一個取消收藏的音樂return new ResponseBodyMessage<>(-1,"之前收藏過這個音樂",false);}// 如果等于空,收藏這首音樂 (插入)boolean effect = loveMusicMapper.insertLoveMusic(userId,musicId);if(effect) {return new ResponseBodyMessage<>(0,"收藏成功",true);}else {return new ResponseBodyMessage<>(-1,"收藏失敗",false);}}
12. 查詢收藏/喜歡音樂模塊設(shè)計(jì)
此處查詢需要滿足幾個功能:
- 支持模糊查詢
- 支持傳入?yún)?shù)為空
請求和響應(yīng)設(shè)計(jì),和查詢音樂模塊是一樣的,這里不在做過多的闡述
12.1 實(shí)現(xiàn) LoveMusicMapper
12.2 實(shí)現(xiàn) LoveMusicMapper.xml
支持模糊查詢,多表聯(lián)合查詢
12.3 實(shí)現(xiàn) LoveMusicController
@RequestMapping("/findlovermusic")public ResponseBodyMessage<List<Music>> findLoveMusic(@RequestParam(required = false) String musicName,HttpServletRequest request) {// 1. 檢查是否登錄HttpSession session = request.getSession(false);if(session == null || session.getAttribute(Constant.USERINFO_SESSION_KEY) == null) {System.out.println("沒有登錄");return new ResponseBodyMessage<>(-1,"沒有登錄",null);}// 如果不為空,進(jìn)行查詢// 先獲取 userIdUser user = (User) session.getAttribute(Constant.USERINFO_SESSION_KEY);int userId = user.getId();List<Music> musicList = null;if(musicName == null) {// 如果等于空,查詢所有的音樂musicList = loveMusicMapper.findLoveMusicByUserId(userId);}else {// 如果不等于空,查詢 指定收藏的音樂musicList = loveMusicMapper.findLoveMusicByKeyAndUid(musicName,userId);}return new ResponseBodyMessage<>(0,"查詢到了所有的歌曲信息",musicList);}
13. 取消音樂收藏模塊設(shè)計(jì)
請求和響應(yīng)設(shè)計(jì)
13.1 實(shí)現(xiàn) LoveMusicMapper
13.2 實(shí)現(xiàn) LoveMusicMapper.xml
13.3 實(shí)現(xiàn) LoveMusicController
@RequestMapping("/deletelovemusic")public ResponseBodyMessage<Boolean> deleteLoveMusic(@RequestParam String id,HttpServletRequest request) {// 將 id 轉(zhuǎn)為 整數(shù)int musicId = Integer.parseInt(id);// 拿到 useId,先檢查是否 登錄HttpSession session = request.getSession(false);if(session == null || session.getAttribute(Constant.USERINFO_SESSION_KEY) == null) {System.out.println("沒有登錄");return new ResponseBodyMessage<>(-1,"沒有登錄",false);}// 如果 session 不等于 空 拿到 use 信息User user = (User) session.getAttribute(Constant.USERINFO_SESSION_KEY);int userId = user.getId();// 獲取到 userId 和 musicId 后調(diào)用 mapper 中的方法 去刪除 ,首先判斷是否存在int ret = loveMusicMapper.deleteLoveMusic(userId,musicId);if(ret == 1) {System.out.println("取消收藏成功!");return new ResponseBodyMessage<>(0,"取消收藏成功",true);}else {System.out.println("取消收藏失敗");return new ResponseBodyMessage<>(-1,"取消收藏失敗",false);}}
13.4 存在BUG分析
當(dāng)刪除 music 表 當(dāng)中的 musicId 為 5的這首音樂的時(shí)候,請問 lovemusic這張表中,是不是應(yīng)該也被刪除?
music 表
lovemusic表
14. 刪除音樂完善
我們在刪除 音樂模塊中,進(jìn)行刪除,需要同步刪除我們 喜歡的音樂(lovemuisc),因此,我們對 MusicController 中進(jìn)行優(yōu)化和完善。
在 MusicController 中,刪除 單個音樂中 添加以下內(nèi)容:
在 批量刪除中 添加以下內(nèi)容:
15. 注冊實(shí)現(xiàn)
@RequestMapping("/logon")public ResponseBodyMessage<User> logon(@RequestParam String username,@RequestParam String password,HttpServletRequest request) {// 1. 先對 輸入的 password 進(jìn)行加密String newPassword = bCryptPasswordEncoder.encode(password);// 創(chuàng)建 User 對象User user = new User();// 設(shè)置賬號和 賬號 和 密碼user.setUsername(username);user.setPassword(newPassword);// 在數(shù)據(jù)庫中進(jìn)行查詢 看用戶是否存在User user1 = userMapper.selectByName(username);if(user1 != null) {System.out.println("用戶已注冊");return new ResponseBodyMessage<>(-1,"用戶已注冊,換個其他的吧",user);}// 注冊,往數(shù)據(jù)庫中插入 新的 用戶int ret = userMapper.insertUser(user);if(ret == 1) {System.out.println("注冊成功啦,我的老baby,一起來聽音樂吧!");return new ResponseBodyMessage<>(0,"注冊成功啦,我的老baby,一起來聽音樂吧!",user);}else {System.out.println("注冊失敗!達(dá)咩~");return new ResponseBodyMessage<>(-1,"注冊失敗!達(dá)咩~",user);}}
以上,后端邏輯全部完善~~~~,接下來是后端模塊實(shí)現(xiàn)。
前端頁面實(shí)現(xiàn)
將前端頁面模板,導(dǎo)入到我們 resources 底下的 static 中
jquery參考手冊
16. 實(shí)現(xiàn) 登錄界面 login.html
JS核心代碼如下:
<script>// 1. 登錄核心業(yè)務(wù)邏輯 //原本是$(document).ready(function(){}) 表示當(dāng)這個頁面的dom樹加載完成后才會執(zhí)行這個,而后面的(document).ready可以省略,因此這里就是這樣寫也是可以的$(function(){//此時(shí)設(shè)置提交按鈕的click事件,通過id選擇器來獲取$("#submit").click(function(){//此時(shí)就需要獲取到用戶名和密碼的值let username = $("#user").val();let password = $("#password").val();//檢查一下用戶名和密碼是否為空,以及去掉空格使用trim方法if(username.trim() == "" || password.trim() == ""){alert("用戶名或密碼不能為空!");return;}//如果都不為空,就需要使用ajax來發(fā)送請求到后端,然后處理這個請求及返回響應(yīng)$.ajax({type:"POST", // 請求url:"/user/login", // 指定路徑// 返回?cái)?shù)據(jù)data:{"username":username,"password":password},//服務(wù)器返回?cái)?shù)據(jù)類型dataType:"json",success:function(data){//看狀態(tài)碼if(data.status == 0){console.log(data);alert("登錄成功,點(diǎn)擊進(jìn)行跳轉(zhuǎn)!");//登錄成功,這里就可以進(jìn)行頁面的跳轉(zhuǎn)window.location.href="list.html";}else{alert("登錄失敗,用戶名或密碼錯誤!");$("#password").val("");}}});});});</script>
17. 實(shí)現(xiàn)上傳音樂 upload.html
- 修改后端代碼,上傳音樂成功后,跳轉(zhuǎn)到 音樂 列表頁
- 前端代碼 upload.html 實(shí)現(xiàn):
<!DOCTYPE html>
<html>
<head><meta http-equiv="Content-Type" content="text/html;charset=utf-8"><meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"/></head>
<body>
<!--enctype="multipart/form-data" action 提交 url 地址-->
<form method="POST" enctype="multipart/form-data" action="/music/upload"> 文件上傳:<input type="file" name="filename"/>歌手名: <label><input type="text" name="singer" placeholder="請輸入歌手名"/></label><input type="submit" value="上傳"/>
</form>
</body>
</html>
18. 實(shí)現(xiàn)音樂列表頁 list.html
當(dāng)我們跳轉(zhuǎn)到 list.html 以后,我們要像服務(wù)器發(fā)起請求,查詢到所有的音樂信息,動態(tài)的生成表格
之前我們前面說到,當(dāng)我們 查詢音樂的時(shí)候,如果不傳參數(shù),那么查詢到所有的音樂,傳遞參數(shù),查詢到指定的音樂
JS代碼如下:
script type="text/javascript">// 核心代碼實(shí)現(xiàn)// 1. 上傳音樂// <!-- 核心代碼實(shí)現(xiàn) -->$(function(){load();});// musicName 可以 默認(rèn)傳參 和 不傳參// 不傳參 匹配的就是所有的 音樂function load(musicName) {$.ajax({type:"GET",url:"/music/findmusic",//數(shù)據(jù)data:{"musicName":musicName},//服務(wù)器返回?cái)?shù)據(jù)類型dataType:"json",// 如果服務(wù)器返回成功,會返回我們的回調(diào)函數(shù)success:function(obj) {console.log(obj);// obj包含了所有的返回信息,然后其中的data就包含了所有的音樂信息,可以先獲取到var data = obj.data;var s = ''; // 最原始的拼接方式// data[i].id data[i].singer data[i].title 這種形式來獲取 obj里面的信息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>';// <th> <input id="1" type="checkbox"></th>s += '<td>' + data[i].title + '</td>';s += '<td>' + data[i].singer + '</td>';//s += "<td <a href=\"\"> <audio src= \""+ musicUrl+"\" + controls=\"controls\" preload=\"none\" loop=\"loop\"> >" + "</audio> </a> </td>";s += '<td> <button class="btn btn-primary" onclick="playerSong(\''+musicUrl+'\')"> 播放歌曲 </button>' + '</td>';s += '<td> <button class="btn btn-primary" onclick="deleteInfo('+data[i].id+')"> 刪除 </button> <button class="btn btn-primary" onclick="loveInfo('+data[i].id+')"> 喜歡 </button>' + '</td>';s += '</tr>';}//然后將所有的數(shù)據(jù)放到tbody里面$('#info').html(s);}});}</script>
19. 實(shí)現(xiàn)播放歌曲
這里播放歌曲,我們采用開源的播放控件:
碼云地址
GitHub
將該開源項(xiàng)目,下載到本地,取出player文件夾,放入static文件夾下
JS 核心代碼,就是調(diào)用 播放器的 toPlay() 方法
toPlay(url,title,startTime,autoPlay) 這里的 autoPlay 設(shè)置為 true 代表 我們點(diǎn)擊播放的時(shí)候,它才會播放
// 實(shí)現(xiàn)音樂播放function playerSong(obj) {// toPlay(url,title,startTime,autoPlay)//obj: http://localhost:8080/music/get?path=xxx.mp3// 從等號下標(biāo) 下一個位置開始截取 [)var title = obj.substring(obj.lastIndexOf("=") + 1);SewisePlayer.toPlay(obj,title,0,true);}
20. 實(shí)現(xiàn)刪除單個音樂
之前約定好的 前后端交互接口
前端傳入的數(shù)據(jù)和后端返回的響應(yīng),響應(yīng)的 data 為 true or false
JS 核心代碼如下:
// 刪除音樂 傳入的參數(shù)是 idfunction deleteInfo(obj){console.log(obj);$.ajax({type:"POST",url:"/music/delete",data:{"id":obj},dataType:"json",success:function(body){console.log(body);//判斷是否刪除成功if(body.data == true){//表示刪除成功alert("刪除成功了老鐵!,重新加載當(dāng)前頁面哈!");window.location.href="list.html";}else{alert("刪除失敗了老鐵!");}}});}
21. 實(shí)現(xiàn)查詢音樂功能
思路很簡單,我們前面實(shí)現(xiàn)音樂列表頁的時(shí)候 完成了 load 查詢函數(shù),這里我們只需要點(diǎn)擊 按鈕,執(zhí)行我們的回調(diào)函數(shù),拿到我們的 輸入框的信息,即可,進(jìn)行查詢
JS核心代碼如下:
// 查詢和刪除// 查詢~~~~~~$(function(){// 點(diǎn)擊 提交按鈕執(zhí)行 回調(diào)函數(shù)$("#submit1").click( function(){//這里的功能就是進(jìn)行查詢而框里面不傳參數(shù)就是默認(rèn)的查詢所有音樂//傳了參數(shù)就進(jìn)行模糊查詢var name = $("#exampleInputName2").val();load(name);});});
22. 實(shí)現(xiàn)刪除選中音樂功能
這里的刪除,我們的刪除邏輯為,點(diǎn)擊刪除,如圖:
我們需要獲取到 每一行 中的 input 標(biāo)簽中的 checkbox
首先獲取到我們需要刪除的音樂id并存儲起來,其次再通過ajax和后端建立聯(lián)系,進(jìn)行刪除。
JS 核心代碼如下:
// 刪除音樂/*** 1. 先拿到 需要刪除的 id* 拿到 需要刪除的 id 就存儲起來* */// when 當(dāng)執(zhí)行完 load函數(shù),則執(zhí)行 done 當(dāng)中的回調(diào)函數(shù)$.when(load).done(function() {//刪除選中的回調(diào)事件$("#delete").click(function(){//由于這里存儲的不止一條數(shù)據(jù),因此這里需要將這些選中的存儲下來var id = new Array();var i = 0; //然后遍歷所有的checkbox標(biāo)簽$("input:checkbox").each(function(){//看有沒有被選中,被選中了就記錄下來,沒有選中就不用管//this 發(fā)生事件的 demo元素,checked表示看是否選中了if($(this).is(":checked")){id[i] = $(this).attr("id");i++;}});console.log(id);/*** 2. 找到 id以后我們通過 ajax 給后端發(fā)送請求,傳遞給后端我們需要* 刪除的音樂* */$.ajax({url:"/music/deleteSel",type:"POST",data:{"id":id},dataType:"json",// 執(zhí)行成功 回調(diào)這個函數(shù)success:function(obj){// 看是否刪除成功if(obj.status == 0) {alert("刪除成功,重新加載此頁面!");window.location.href="list.html";}else{alert("刪除失敗!");}}});
23. 實(shí)現(xiàn)喜歡音樂列表頁功能
收藏音樂列表頁,和 list.html 基本一樣,但是需要注意我們需要將ajax中的 url 進(jìn)行修改:
列入如下:
loveMusci.html 如下:
<script type="text/javascript">function load(musicName) {$.ajax({type:"GET",url:"/lovemusic/findlovermusic",//數(shù)據(jù)data:{"musicName":musicName},//服務(wù)器返回?cái)?shù)據(jù)類型dataType:"json",// 如果服務(wù)器返回成功,會返回我們的回調(diào)函數(shù)success:function(obj) {console.log(obj);// obj包含了所有的返回信息,然后其中的data就包含了所有的音樂信息,可以先獲取到var data = obj.data;var s = ''; // 最原始的拼接方式// data[i].id data[i].singer data[i].title 這種形式來獲取 obj里面的信息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> <button class="btn btn-primary" onclick="playerSong(\''+musicUrl+'\')"> 播放歌曲 </button>' + '</td>';s += '<td> <button class="btn btn-primary" onclick="deleteInfo('+data[i].id+')"> 移除 </button>' + '</td>';s += '</tr>';}//然后將所有的數(shù)據(jù)放到tbody里面$('#info').html(s);}});}// 實(shí)現(xiàn)音樂播放function playerSong(obj) {// toPlay(url,title,startTime,autoPlay)//obj: http://localhost:8080/music/get?path=xxx.mp3// 從等號下標(biāo) 下一個位置開始截取 [)var title = obj.substring(obj.lastIndexOf("=") + 1);SewisePlayer.toPlay(obj,title,0,true);}// 刪除喜歡音樂 傳入的參數(shù)是 idfunction deleteInfo(obj){console.log(obj);$.ajax({type:"POST",url:"/lovemusic/deletelovemusic",data:{"id":obj},dataType:"json",success:function(body){console.log(body);//判斷是否刪除成功if(body.data == true){//表示刪除成功alert("刪除成功了老鐵!,重新加載當(dāng)前頁面哈!");window.location.href="list.html";}else{alert("刪除失敗了老鐵!");}}});}</script>
24. 實(shí)現(xiàn)收藏音樂列表功能
在 list.html 中 實(shí)現(xiàn)如下核心代碼:
// 添加喜歡的音樂/收藏音樂function loveInfo(obj){//直接發(fā)送請求$.ajax({type:"POST",url:"/lovemusic/likeMusic",data:{"id":obj},dataType:"json",success:function(body){//然后這里判斷看是否收藏成功了if(body.data == true){alert("收藏成功,^^,厲害了老鐵!");window.location.href="loveMusic.html";}else{alert("收藏失敗,^^,咋回事兒呢!");}}});}
25 實(shí)現(xiàn)注冊功能
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="utf-8"/><meta http-equiv="X-UA-Compatible" content="IE=edge"/><meta name="viewport" content="width=device-width, initial-scale=1"/><meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"/><title>注冊頁面</title><!-- 1. 導(dǎo)入CSS的全局樣式 --><link href="css/bootstrap.min.css" rel="stylesheet"><!-- 2. jQuery導(dǎo)入,建議使用1.9以上的版本 --><script src="js/jquery-3.1.1.min.js"></script><script src="js/md5.min.js"></script><!-- 3. 導(dǎo)入bootstrap的js文件 --><!--<script src="js/bootstrap.min.js"></script>--><script type="text/javascript"></script><style>#body{background-image: url("images/rose3.png");background-repeat: repeat;background-position: 0 20%;background-size: contain;}</style><script>// 登錄核心業(yè)務(wù)邏輯//原本是$(document).ready(function(){}) 表示當(dāng)這個頁面的dom樹加載完成后才會執(zhí)行這個,而后面的(document).ready可以省略,因此這里就是這樣寫也是可以的$(function(){//此時(shí)設(shè)置提交按鈕的click事件,通過id選擇器來獲取$("#submit").click(function(){//此時(shí)就需要獲取到用戶名和密碼的值let username = $("#user").val();let password = $("#password").val();//檢查一下用戶名和密碼是否為空,以及去掉空格使用trim方法if(username.trim() == "" || password.trim() == ""){alert("用戶名或密碼不能為空!");return;}//如果都不為空,就需要使用ajax來發(fā)送請求到后端,然后處理這個請求及返回響應(yīng)$.ajax({type:"POST",url:"/user/logon",//數(shù)據(jù)data:{"username":username,"password":password},//服務(wù)器返回?cái)?shù)據(jù)類型dataType:"json",success:function(data){//看狀態(tài)碼if(data.status == 0){console.log(data);alert("注冊成功了我的老寶貝,要跳轉(zhuǎn)了哦!");//登錄成功,這里就可以進(jìn)行頁面的跳轉(zhuǎn)window.location.href="login.html";}else{alert("注冊失敗,用戶名已存在,--!");}}});});});</script>
</head>
<body id="body">
<div class="container" style="width: 400px;margin-top: 110px;background-color: rgba(255,255,255,0.9)"><h3 style="text-align: center;">回溯</h3><!-- <form action="login" method="post">--><div class="form-group" ><label for="user">用戶名:</label><input type="text" name="username" class="form-control" id="user" placeholder="請輸入用戶名"/></div><div class="form-group"><label for="password">密碼:</label><input type="password" name="password" class="form-control" id="password" placeholder="請輸入密碼"/></div><hr/><div class="form-group" style="text-align: center;"><!--class="form-group"--><input style="width: 200px;height: 40px" id="submit" class="btn btn btn-primary" type="button" value="注冊" ></div><!-- </form>--><!-- 出錯顯示的信息框 -->
</div>
</body>
</html>
26 配置攔截器
當(dāng)我們直接訪問列表頁的時(shí)候,我們需要用攔截器攔截,否則 不登錄也能直接訪問,這是不行的
以上所有功能全部實(shí)現(xiàn)完畢。
項(xiàng)目部署
- 修改配置文件
修改音樂存放路徑:
在配置文件當(dāng)中,修改如下:
- 將數(shù)據(jù)庫在服務(wù)器上重新進(jìn)行建表等操作
輸入指令 mysql,進(jìn)入數(shù)據(jù)庫:
將如下內(nèi)容添加進(jìn)去:
-- 數(shù)據(jù)庫
drop database if exists `onlinemusic`;
create database if not exists `onlinemusic` character set utf8;-- 使用數(shù)據(jù)庫
use `onlinemusic`;-- 創(chuàng)建 user表
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` INT PRIMARY KEY AUTO_INCREMENT,
`username` varchar(20) NOT NULL,
`password` varchar(255) NOT NULL
);-- 創(chuàng)建 music 表
DROP TABLE IF EXISTS `music`;
CREATE TABLE `music` (
`id` int PRIMARY KEY AUTO_INCREMENT,
`title` varchar(50) NOT NULL,
`singer` varchar(30) NOT NULL,
`time` varchar(13) NOT NULL,
`url` varchar(1000) NOT NULL,
`userid` int(11) NOT NULL
);-- 創(chuàng)建 lovemusic
DROP TABLE IF EXISTS `lovemusic`;
CREATE TABLE `lovemusic` (
`id` int PRIMARY KEY AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`music_id` int(11) NOT NULL
);
輸入指令 exit 退出數(shù)據(jù)庫
- 導(dǎo)包
4. 上傳
-
云服務(wù)器配置防火墻端
-
啟動項(xiàng)目
剛開始可以使用 java -jar xxxx.jar 啟動項(xiàng)目【前臺運(yùn)行的方式】
運(yùn)行好之后沒有問題,我們可以使用下面的命令來對項(xiàng)目進(jìn)行運(yùn)行
nohup java -jar xxx.jar >> log.log &
nohup :后臺運(yùn)行項(xiàng)目的指令
使用 >> log.log 將運(yùn)行的日志記錄到 log.log 中
& 表示 一直運(yùn)行
tips:重新部署
如果更新了項(xiàng)目,先將 jar刪除
輸入如下指令:
rm -ri xxx.jar
查看進(jìn)程
ps -ef | grep java
kill [ID] 即可刪除進(jìn)程
總結(jié)
以上是生活随笔為你收集整理的JavaWeb——在线音乐播放器的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Jewels
- 下一篇: 归并排序 自带时间复杂度测试