目录
一、项目任务
实现一款基于Java Servlet 构建的在线音乐服务器。
二、核心功能
- 登录、注册
- 上传音乐
- 删除某一个音乐信息
- 删除选中的音乐信息
- 查询音乐(包含查找指定/模糊匹配的音乐)
- 添加音乐到“喜欢列表”
- 查询喜欢的音乐(包含查找指定/模糊匹配的音乐)
三、整体架构
项目整体基于HTTP协议,前端使用HTML+CSS+JS构建页面整体布局,后端采用分层结构,分为Servlet层,Dao层的设计,以达到在设计上的高内聚低耦合(就是整体架构不变但分层)。本项目先从Dao层开始写,Severlet连接前端和后端。在Servlet和Dao层中间还可以加一个Service层,把Dao层中部分程序整合出来写到Service层。
四、项目步骤
1.数据库的设计
(1)数据库设计框架
数据库设计了music、lovemusic、user三张表。music表用于存放在线音乐服务器的所有音乐,其中包括音乐的id、歌名、歌手名、上传的时间、音乐存放的位置、上传音乐的用户id的信息。lovemusic表用于存放用户喜爱的音乐(一个音乐可以被多个用户喜欢,一个用户可以喜欢多个音乐),其中喜爱的音乐的id、用户id以及音乐的id。user表用于存放用户的信息包括用户id、用户名、密码、年龄、性别和邮箱地址。下图为示例。
(2)数据库操作代码
-- 创建数据库
drop database if exists `musicserver`;
create database if not exists `musicserver` character set utf8;
-- 使用数据库
use `musicserver`;
-- 创建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
);
-- 创建 user表 输入相关信息
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` INT PRIMARY KEY AUTO_INCREMENT,
`username` varchar(20) NOT NULL,
`password` varchar(32) NOT NULL,
`age` INT NOT NULL,
`gender` varchar(2) NOT NULL,
`email` varchar(50) NOT NULL
);
--创建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
);
2.用户+音乐模块设计
创建entity包
(1)创建User类
public class User {
private int id;
private String username;
private String password;
private String gender;
private int age;
private String email;
}
(2)创建Music类
public class Music {
private int id;
private String title;
private String singer;
private Date time; private String url;
private int userid;
}
3.服务器 API 设计
(1)关于 Json
Json 是一种常见是数据格式组织方式. 源于JavaScript,是一种键值对风格的数据格式. 在Java中我们可以采用Jackson库中的ObjectMapper类来完成 Json 的解析和构造。要去Maven中查找对应依赖并进行json转换导入相关包:
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
浏览器请求是通过 ajax 把 json 对象发送出去,服务器把 json对象解析成 java 对象,再通过对应的 servlet 进行处理,结果转换成 json 字符串,返回给浏览器,这样做降低了前端和后端的耦合
(2)登录
请求:
POST /loginServlet
data:{username,password}
响应:
{msg: true}
(3)上传音乐
请求1:上传音乐到服务器目录
POST /upload
请求2:将音乐信息同步插入到数据库当中
POST /uploadsucess
(4) 删除某一个音乐信息
请求:
POST /deleteServlet
data: {“id”: id}
响应:
{msg: true}
(5)删除选中的音乐信息
请求:
POST /deleteSelMusicServlet
data:{“id”:id}//id为数组
响应:
{msg: true}
(6)查询音乐(包含查找指定/模糊匹配的音乐)
请求:
POST /findLoveMusic
data:{musicName:musicName}
(7)添加音乐到“喜欢列表”
请求:
POST /loveMusicServlet
data: {“id”: obj}
响应:
{msg: true}
(8) 查询喜欢的音乐(包含查找指定/模糊匹配的音乐)
请求:
POST /findLoveMusic
data:{musicName:musicName}
(9)移除喜欢的某个音乐
请求:
POST /removeLoveServlet
data: {“id”: obj}
4.创建一个JavaWeb项目
Web项目:B/S:Browse/Server
手机架构都是C/S:client/server 例:客户端/app
(1)创建JDBCUtils类
连接数据库的四大参数是:驱动类、URL、用户名、密码,这些参数都是与特定数据库关联,如果将来想要更改数据库,那么就要去修改这四大参数,那么为了不去修改代码,我们需要写一个JDBCUtils类,让它从配置文件中读取到配置参数,然后创建连接对象。一般是固定格式。
package util;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.sql.DataSource;
public class DBUtils {
//编写配置文件的键值
private static String url = "jdbc:mysql://127.0.0.1:3306/musicserver?useSSL=false";
private static String password = "";
private static String username = "root";
private static volatile DataSource DATASOURCE;
public DBUtils() {
}
private static DataSource getDataSource() {
//双重校验锁
if (DATASOURCE == null) {
Class var0 = DBUtils.class;
synchronized(DBUtils.class) {
if (DATASOURCE == null) {
DATASOURCE = new MysqlDataSource();
((MysqlDataSource)DATASOURCE).setUrl(url);
((MysqlDataSource)DATASOURCE).setUser(username);
((MysqlDataSource)DATASOURCE).setPassword(password);
}
}
}
return DATASOURCE;
}
public static Connection getConn() {
try {
//从池子里获取连接
Connection connection = getDataSource().getConnection();
return connection;
} catch (SQLException var1) {
var1.printStackTrace();
throw new RuntimeException("获取数据库连接失败");
}
}
//关闭连接
public static void getClose(Connection connection, PreparedStatement statement, ResultSet resultSet) {
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException var6) {
var6.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException var5) {
var5.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException var4) {
var4.printStackTrace();
}
}
}
}
(2)创建Dao包和UserDao类
UserDao类包含登录模块和注册模块以登录模
UserDao. login为例,注册模块UserDao.register相当于给登录中插入数据。
//登录模块
public User login(User loginUser) {
User user = null;//
Connection conn = null; //获取连接
PreparedStatement ps = null; //预编译
ResultSet rs = null;//结果集合
try {
conn = DBUtils.getConn();
ps = conn.prepareStatement("select*from user where username=? and password=?"); //对sql语句的预编译
ps.setString(1, loginUser.getUsername());
ps.setString(2, loginUser.getPassword());
//执行SQL语句
rs = ps.executeQuery();
while(rs.next()) {
user = new User();
user.setId(rs.getInt("id"));
user.setUsername(rs.getString("username"));
user.setPassword(rs.getString("password"));
user.setAge(rs.getInt("age"));
user.setGender(rs.getString("gender"));
user.setEmail(rs.getString("email"));
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}finally {
DBUtils.getClose(conn, ps, rs);
}
return user;
}
(3)创建MusicDao类
MusicDao类包括查询全部歌单、根据音乐id查找音乐、根据关键字查询歌单、上传音乐、 删除歌曲、添加音乐到“喜欢”列表中、 移除当前用户喜欢的这首音乐、根据关键字查询该用户喜欢的某个音乐等模块。
1 查询全部歌单
用链表
/**
* 查询全部歌单
*/
public List<Music> findMusic(){
List<Music> musics = new ArrayList<>();
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = DBUtils.getConn();
ps = conn.prepareStatement("select*from music");
rs = ps.executeQuery();//查找
while(rs.next()) {
Music music = new Music();
music.setId(rs.getInt("id"));
music.setTitle(rs.getString("title"));
music.setSinger(rs.getString("singer"));
music.setTime(rs.getDate("time"));
music.setUrl(rs.getString("url"));
music.setUserid(rs.getInt("userid"));
musics.add(music);//整合前面的信息
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}finally {
DBUtils.getClose(conn, ps, rs);
}
return musics;
}
2 根据音乐id查找音乐
把1稍作修改
ps = conn.prepareStatement("select * from music where id=?");
3 根据关键字查找音乐
进行like模糊查询,查的歌名只能少于歌名的字或者等于歌名的字。
ps = conn.prepareStatement("select*from music where title like '%"+str+"%'");
4 上传音乐
音乐要具有title, singer, time, url,userid的信息。上传音乐本身给服务器,将音乐信息插入到数据库当中
public int Insert(String title, String singer, String time, String url,
int userid) {
Connection conn = DBUtils.getConn();
PreparedStatement pst=null;
int number = 0;
try {
pst=conn.prepareStatement("insert into music(title,singer,time,url,userid) values(?,?,?,?,?)");
pst.setString(1,title);
pst.setString(2,singer);
pst.setString(3,time);
pst.setString(4,url);
pst.setInt(5,userid);
number=pst.executeUpdate();//返回值代表当前受影响的行数
return number;
} catch (SQLException e) {
e.printStackTrace();
}finally
{
DBUtils.getClose(conn, pst, null);
}
return 0;
}
5 删除歌曲
需要先看该歌曲之前是否被添加到了,喜欢的音乐列表当中,当删除服务器上的音乐时,同时在我喜欢的列表的数据库中进行删除。
public int deleteMusicById(int id) {
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
String sql = "delete from music where id=?";
connection = DBUtils.getConn();
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1,id);
int ret = preparedStatement.executeUpdate();
if(ret == 1) {
//同时删除中间表中的数据
//1、看中间表是否有数据,如果有删除
if(findLoveMusicOnDel(id)) {
int ret2 = removeLoveMusicOnDelete(id);
if(ret2 == 1){
return 1;
}
} else {
//如果没有找到,说明这首歌,没有被添加到喜欢的列表
return 1;
}
}
}catch (SQLException e) {
e.printStackTrace();
}finally {
DBUtils.getClose(connection,preparedStatement,null);
}
return 0;
}
/**
* 看中间表是否有该id的音乐数据
*/
public boolean findLoveMusicOnDel(int id) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
String sql = "select * from lovemusic where music_id=?";
connection = DBUtils.getConn();
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1,id);
resultSet = preparedStatement.executeQuery();
if(resultSet.next()) {
return true;
}
}catch (SQLException e) {
e.printStackTrace();
}finally {
DBUtils.getClose(connection,preparedStatement,null);
}
return false;
}
/**
* 当删除服务器上的音乐时,同时在我喜欢的列表的数据库中进行删除。
* @param musicId
* @return
*/
public int removeLoveMusicOnDelete(int musicId) {
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
String sql = "delete from lovemusic where music_id=?";
connection = DBUtils.getConn();
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1,musicId);
int ret = preparedStatement.executeUpdate();
if(ret == 1) {
return ret;
}
}catch (SQLException e) {
e.printStackTrace();
}finally {
DBUtils.getClose(connection,preparedStatement,null);
}
return 0;
}
6 添加音乐到“喜欢”列表中
用户和音乐之间多对多的关系,需要中间表。添加喜欢的音乐的时候,需要先判断该音乐是否存在,也就是说,该用户是否之前添加过这个音乐为喜欢。
public boolean insertLoveMusic(int userId,int musicId) {
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
String sql = "insert into lovemusic(user_id, music_id) VALUES (?,?)";
connection = DBUtils.getConn();
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1,userId);
preparedStatement.setInt(2,musicId);
int ret = preparedStatement.executeUpdate();
if (ret == 1) {
return true;
}
return false;
}catch (SQLException e) {
e.printStackTrace();
}finally {
DBUtils.getClose(connection,preparedStatement,null);
}
return false;
}
/**
* 添加喜欢的音乐的时候,需要先判断该音乐是否存在
* @param musicID
* @return
*/
public boolean findMusicByMusicId(int user_id,int musicID) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = DBUtils.getConn();
ps = conn.prepareStatement("select * from lovemusic where music_id=? and user_id=?");
ps.setInt(1,musicID);
ps.setInt(2,user_id);
rs = ps.executeQuery();
if(rs.next()) {
return true;
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}finally {
DBUtils.getClose(conn, ps, rs);
}
return false;
}
7 移除当前用户喜欢的这首音乐
因为同一首音乐可能多个用户喜欢,所以需要传入当前用户的id。
public int removeLoveMusic(int userId,int musicId) {
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
String sql = "delete from lovemusic where user_id=? and music_id=?";
connection = DBUtils.getConn();
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1,userId);
preparedStatement.setInt(2,musicId);
int ret = preparedStatement.executeUpdate();
if(ret == 1) {
return ret;
}
}catch (SQLException e) {
e.printStackTrace();
}finally {
DBUtils.getClose(connection,preparedStatement,null);
}
return 0;
}
8 查询该用户喜欢的全部歌单
只查询一张lovemusic是做不到的。需要联表查询。和1的思路相同。
ps = conn.prepareStatement("select m.id as music_id,title,singer,time,url,userid from lovemusic lm,music m where lm.music_id=m.id and user_id=?");
9 根据关键字查询该用户喜欢的某个音乐
在8的基础上进行like模糊查询
ps = conn.prepareStatement("select m.id as music_id,title,singer,time,url,userid from lovemusic lm,music m where lm.music_id=m.id and user_id=? and title like '%"+str+"%'");
5.Servlet实现与实现
首先在项目根目录下创建一个 servlet 包。包装实现如下servlet类。
(1)登陆注册
@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");//请求体编码
resp.setContentType("application/json;charset=utf-8");//响应体编码响应类型是json
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println("username:"+username);
System.out.println("password:"+password);
UserDao dao = new UserDao();
Map<String ,Object> return_map = new HashMap<>();//返回前端以map的形式
try {
User user = dao.login(username);//调用后台数据
if(user != null && user.getPassword().equals(password)) {
//将该用户的信息写入到session,取得时候就取了
req.getSession().setAttribute("user", user);//绑定数据
return_map.put("msg",true);
System.out.println("发发发发发 ");
}else {
System.out.println("密码错误!");
return_map.put("msg",false);
}
} catch (Exception e) {
e.printStackTrace();
}
//如何将return——map返回给前端
ObjectMapper mapper = new ObjectMapper(); //利用Jackson将map转化为json对象
mapper.writeValue(resp.getWriter(),return_map);//把return_map写到resp.getWriter()传给前端
}
}
(2)查询音乐
用户进行登录后,需要先进行查询,将查询结果显示到页面上。
@WebServlet("/findMusic")//通过注解找到servlet类
public class FindMusicServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html; charset=utf-8");
String str = req.getParameter("musicName");//没有这个歌曲的话默认找到的是全部的歌曲
MusicDao dao = new MusicDao();
List<Music> musics = null;
if(str!=null) {
musics = dao.ifMusic(str);//关键字查询模糊查询
}else {
musics = dao.findMusic();
}
for (Music music : musics) {
System.out.println(music.getUrl());
}
//返回给前端
ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(resp.getWriter(),musics);
}
}
(3)上传音乐
分为2步:
第一步将音乐上传到服务器
@WebServlet("/upload")
//@MultipartConfig
public class UploadMusicServlet extends HttpServlet {
private final String SAVEPATH="/home/gaobo/apache-tomcat-8.5.51/webapps/GaoBoMusic/music/";//上传的音乐文件放入的路径
// /home/gaobo/apache-tomcat-8.5.51/webapps/GaoBoMusic/music
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html; charset=utf-8");
User user = (User) request.getSession().getAttribute("user");//获取当前登录用户的session中的信息
if (user == null) {
request.setAttribute("Msg", "请登录后再进行上传");
/*request.getRequestDispatcher("uploadmusic.jsp").forward(request,
response);*/
} else {
//上传
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
List<FileItem> items = null;
try {
items = upload.parseRequest(request);//上传的信息从请求体获得 用list说明有可能批量上传
} catch (FileUploadException e) {
e.printStackTrace();
return;
}
System.out.println("items:"+items );
FileItem item = items.get(0);//一般里面只放一个元素
System.out.println("item: "+item);
//将文件放入music之下
String fileName = item.getName();//获取文件名
System.out.println("fileName"+fileName);
request.getSession().setAttribute("fileName", fileName);
try {
item.write(new File(SAVEPATH, fileName));
} catch (Exception e) {
e.printStackTrace();
}
response.sendRedirect("uploadsucess.html");//上传到数据库中,上传成功了以后跳转到uploadsucess.html的界面再跳转到uploadsucess界面手动上传
}
}
}
第二步将音乐信息存放到数据库,输入歌手名点提交了以后跳转到uploadsucess界面.
//将音乐信息写到数据库中
@WebServlet("/uploadsucess")
public class UploadInsertServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html; charset=utf-8");
String strings = (String)req.getSession().getAttribute("fileName");//实际传到数据库的是点歌的人.MP3
String[] titles = strings.split("\\.");//进行分割 传到数据库中为点歌的人
String title = titles[0];//0号下标放的是点歌的人 1号下标放的是.MP3
System.out.println("title:" + title);
String url = "music/"+title;
System.out.println("url:"+url);
String singer = req.getParameter("singer");//拿到歌手名
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");//年月日2021-1-1
String time=sdf.format(new Date());//当前日期格式化
MusicDao dao = new MusicDao();
User user = (User) req.getSession().getAttribute("user");
int user_id = user.getId();
int num = dao.Insert(title,singer,time,url,user_id);//上传音乐
if(num!=0){
resp.sendRedirect("list.html");//跳转页面
}
}
}
存在问题:已经上传到服务器在这一瞬间断网了,还没写到数据库中,该如何处理?
解决方案:
1.缩短每次请求的数据量,在连接断开之前,发出一次新的请求,使其保持连接状态;
2.不使用“单例模式”的全局Connection对象,在多线程场景中,某个线程使用完连接对象之后,会把连接关闭;当其他线程访问到已被关闭的全局连接对象,也会报错说“该连接已经被关闭”。每次请求方法时,创建一个新的连接,前一个连接用完就释放资源。
(4)删除音乐
分为删除单个音乐和批量删除了两个模块。通过获取前端选中的id数组实现。
1 删除某个音乐
@WebServlet("/deleteServlet")
public class DeleteMusicServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("删除指定音乐!");
req.setCharacterEncoding("utf-8");
resp.setContentType("application/json;charset=utf-8");
Map<String,Object> map=new HashMap<>();//删除成功或者失败要写入map中
String strId = req.getParameter("id");//
int id = Integer.parseInt(strId);//把id转换为整型id
System.out.println("id:"+ id);
try {
MusicDao musicDao = new MusicDao();
//1.查找有没有当前id
Music music = musicDao.findMusicById(id);
//没有这个id的音乐 直接返回
if(music == null) return;
//2、如果有就开始删除库中的音乐
int delete = musicDao.deleteMusicById(id);
System.out.println("delete:"+delete);
if(delete == 1){
//3、数据库删除完成后,检查还是否存在。如果不存在,那么删除掉磁盘上的文件
//File file = new File("E:\\Javaproject\\GaoBoMusic\\web\\"+music.getUrl()+".mp3");
File file = new File("/home/gaobo/apache-tomcat-8.5.51/webapps/GaoBoMusic/"+music.getUrl()+".mp3");
System.out.println("文件是否存在:"+file.exists());
System.out.println("file: "+file);
if(file.delete()){
//证明删除成功
map.put("msg",true);
}else {
map.put("msg",false);
System.out.println("文件名:"+file.getName());
System.out.println("删除文件失败!");
}
}else {
map.put("msg",false);
}
}catch (Exception e) {
e.printStackTrace();
}
//将map转化为json
ObjectMapper mapper=new ObjectMapper();
mapper.writeValue(resp.getWriter(),map);
}
}
2 删除多组音乐
@WebServlet("/deleteSelMusicServlet")
public class DeleteSelMusicServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("application/json;charset=utf-8");
//values数组中存放的是所有需要删除的歌曲的id
String[] values = req.getParameterValues("id[]");
System.out.println("deleteSelectedServlet:"+Arrays.toString(values));
//删除
int sum=0;
Map<String,Object> map=new HashMap<>();
MusicDao musicDao = new MusicDao();
for(int i=0;i<values.length;i++){
int j = Integer.parseInt(values[i])//需要把id转换成整型
System.out.println("j :"+j);
//调用Service层方法删除
Music music = musicDao.findMusicById(j);//歌曲是否存在
int delete = musicDao.deleteMusicById(j);
//sum=sum+delete;
if(delete == 1) {
//3、数据库删除完成后,检查还是否存在。如果不存在,那么删除掉磁盘上的文件
//File file = new File("E:\\Javaproject\\GaoBoMusic\\web\\" + music.getUrl() + ".mp3");
File file = new File("/home/gaobo/apache-tomcat-8.5.51/webapps/GaoBoMusic/"+music.getUrl()+".mp3");
System.out.println("文件是否存在:" + file.exists());
System.out.println("file: " + file);
if (file.delete()) {
//证明删除成功
//map.put("msg", true);
sum=sum+delete;//删除成功一个加一个
} else {
//map.put("msg", false);
System.out.println("文件名:" + file.getName());
System.out.println("删除文件失败!");
}
}
}
System.out.println("sum: "+sum);
//sum==values.length 说明选中的所有元素已经全部删除了
if(sum==values.length){
//证明删除成功
map.put("msg",true);
}else {
map.put("msg",false);
}
//将map转化为json
ObjectMapper mapper=new ObjectMapper();
mapper.writeValue(resp.getWriter(),map);
}
}
(5) 添加喜欢的音乐到喜欢列表
@WebServlet("/loveMusicServlet")
public class LoveMusicServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("application/json;charset=utf-8");
String strId = req.getParameter("id");
int musicId = Integer.parseInt(strId);
System.out.println("musicID: "+musicId);
User user = (User) req.getSession().getAttribute("user");
int user_id = user.getId();
MusicDao musicDao = new MusicDao();
Map<String,Object> map=new HashMap<>();
//插入之前需要先查看是否该音乐已经被添加到喜欢列表
boolean effect = musicDao.findMusicByMusicId(user_id,musicId);
if(effect) {
//以前这首歌被你添加过为喜欢,不能重复添加
map.put("msg",false);
}else {
boolean flg = musicDao.insertLoveMusic(user_id,musicId);
if(flg) {
//添加成功
map.put("msg",true);
}else {
map.put("msg",false);
}
}
//将map返回给前端
ObjectMapper mapper=new ObjectMapper();
mapper.writeValue(resp.getWriter(),map);
}
}
(6)查找我喜欢的音乐列表
@WebServlet("/findLoveMusic")
public class FindLoveMusicServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("application/json;charset=utf-8");
String str = req.getParameter("loveMusicName");
System.out.println("loveMusicName:"+str);
User user = (User) req.getSession().getAttribute("user");
int user_id = user.getId();//可能会有音乐被多个人喜欢
MusicDao musicDao = new MusicDao();
List<Music> musics = null;
if(str!=null) {
musics = musicDao.ifMusicLove(str,user_id);//关键字查询
}else {
musics = musicDao.findLoveMusic(user_id);
}
for (Music music : musics) {
System.out.println(music.getUrl());
}
ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(resp.getWriter(),musics);
}
}
(7)移除我喜欢的音乐
@WebServlet("/removeLoveServlet")
public class RemoveLoveServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("application/json;charset=utf-8");
User user = (User) req.getSession().getAttribute("user");
int user_id = user.getId();
Map<String,Object> map=new HashMap<>();
String strId = req.getParameter("id");
int music_id = Integer.parseInt(strId);
MusicDao musicDao = new MusicDao();
int delete = musicDao.removeLoveMusic(user_id,music_id);
if(delete == 1) {
map.put("msg",true);
}else {
map.put("msg",false);
}
ObjectMapper mapper=new ObjectMapper();
mapper.writeValue(resp.getWriter(),map);
}
}
6.前端页面的设计
前端采用HTML+CSS+JS设计。直接在百度上搜索 “免费网页模板”, 能找到很多免费模板网站. 可以直接基于现成的漂亮的页面进行修改.将网页模板解压缩, 拷贝到项目的 webapp 或者 web 目录中.
网址分享:网页模板
前后端服务器数据交互-以登录为例:添加jsjquery库
<!-- 1. 导入CSS的全局样式 -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- 2. jQuery导入,建议使用1.9以上的版本 -->
<script src="js/jquery-3.1.1.min.js"></script>
<!-- 3. 导入bootstrap的js文件 -->
<!--<script src="js/bootstrap.min.js"></script>-->
<script type="text/javascript"></script>
<style>
#body{
background-image: url("images/3.png");
/*background-size:100% 100%;
background-attachment: fixed;*/
}
</style>
<script>
//登录请求
$(function ()//自动执行 {
$("#submit").click(function () {//点击登陆的时候就会触发 id:submit #id是唯一的
var username=$("#user").val();//拿到了文本框的值
var password=$("#password").val();
$.ajax({//方法
url:"/loginServlet",//发送请求的地址
data:{"username":username,"password":password},//发送给服务器(后端)的数据
type:"POST",//请求方式 ("POST" 或 "GET"), 默认为 "GET"
dataType:"json",//预期服务器返回的数据类型(后端返回给前端)
success:function (data) {//请求成功后的回调函数 data里就是后端返回的数据 json
console.log(data);
if(data.msg===true){
window.location.href="list.html";//跳转到这个网页
}else{
/*window.location.reload();数据清空*/
$("#message").text("账号或密码错误,请重试!");
$("#user").val("");
$("#password").val("");
$("#verifycode").val("");
}
}
});
});
});