项目描述:
类似于喜马拉雅听书的项目,普通用户可以根据自己的喜欢选择相应的专辑进行专辑列表的歌曲播放。
分享者需要注册并且登录后才可以上传、录制自己的音频和查看所有音频,并创建新的专辑与音频进行绑定,上架发布,供普通用户选择使用。
项目主要功能:
普通用户
无需登录,可以查看专辑列表,选择专辑进行音频播放。
创作者页面,
用户管理:登录功能、注册功能和注销功能;
音频管理:上传音频、录制音频和查看音频列表功能;
专辑管理:新建专辑、显示专辑列表(包括各个专辑状态)和专辑与音频关联功能。
项目结构分析 :
数据库
E-R:
3个实体(Entity):用户,音频,专辑;1个关系(Relation):关系表实体间关系分析
用户 -> 音频 : 一对多 关系字段在多表(音频表中有uid字段)用户 -> 专辑 : 一对多 关系字段在多表(专辑表中有uid字段)
音频 <-> 专辑 : 多对多 多对多关系需要借助中间表,变成两个一对多
表结构和表关系
实体表:用户表 users {uid,用户名,密码(经过加密)}
音频表 tracks {tid,标题,上传用户id,类型,二进制内容}
TODO:使用MySQL进行音频数据以及诸如此类的较大的二进制数据是不合理的
专辑表 albums {aid,uid,专辑标题,专辑封面图URL,专辑状态}
TODO:专辑封面没有上传功能(因为图片也是较大的二进制数据)
关系表
音频专辑关系表 relations {rid,aid,tid}
总体设计:本系统采用了浏览器/服务器模式,即B/S模式。对表现层、业务层、持久层三层结构均进行了实现。
表现层(data_view):在表现层通过前端界面处理(html+css+JavaScript)配合前端框架进行实现。前端与用户直接接触,保证良好的设计风格和视觉体验。前端数据通过javaScript发送Ajax传输给后端,再通过后端servlet返回的数据进行DOM树的渲染,形成了最终的页面。
业务层(service包和servlet包):service对从数据库或者前端页面获取来的数据进行转换,转换为当下需要的数据格式。在业务层通过Servlet处理,进行前后端交互。由于前端数据需要向后端发出请求。所以在前后端交互处理使用了JavaScript的开源框架jQuery-Ajax进行数据请求响应处理。后端通过servlet接收对应数据进行处理。
持久层(util包、data_object、repository):通过JDBC对数据库进行了连接,创建了用户表、音频表、专辑表、以及关系表,用来存储信息,并创建建了四个表在后端的实体类(UserDo,TrackDo,AlbumDo,TidToCountDo),以及在view_object包下面定义我们需要的json格式的数据,以及对repository对数据库中数据的增删查改。
准备工作:
1、库表的创建
(1)用户表users(做主表):
uid(用户编号) 、 username(用户名)、password(密码)。(2) 音频表track :
tid(音频编号)、title(标题)、uid 、type(类型)、content(内容)。(3)专辑表albums:
aid(专辑编号)、title(标题)、uid、cover(封面图)、state(状态)。(4)关系表relations:
rid、aid、tid。2、后端对象(类)的类型:
1、主要负责过程的对象:
1、servlet对象:动态资源(负责处理HTTP输入,输出)。
2、service对象:当数据来自多张表的时候,需要在代码中组装,就在service中进行。
3、dao对象/repository对象:单表访问Datebase操作。2、主要表示数据的对象:
1、date_object(DO)对象:描述从Datebase取得的数据。
2、view_object(VO)对象:描述展示出的额数据(一般会通过JSON序列化)
3.准备环境
1.使用Maven创建项目
完善项目------在main目录下创建webapp目录,在webapp目录下再创建WEB-INF目录,在WEB-INF目录下创建web.xml。
2.配置pom.xml内容(添加依赖)
通过<packaging>war</packaging>为后续打包,打成war包。通过第三方仓库导入MYSQL,Servlet,Thymeleaf,jackson的依赖。通过<build><finalName>${project.artifactld}</finalName></build>将war包名称改变,方便后续部署到云服务器。
3.配置Tomcat和MYSQL
一、文件的存放
data_object:用来存放与数据库直接交互的实体类
Repository:用来对直接数据库中的数据进行操作
Service:服务层:把数据转换为当前需要的格式
Servlet:进行前后端的交互,接收请求和发送响应给浏览器
Util:使用JDBC与数据库进行连接
view_object:定义浏览器需要的JSON格式的属性
org包:存储了对密码进行加密的哈希算法
sql包:存放建表语句
webapp中存储前端文档以及动态的资源,实现了页面的动态呈现。
数据库中的表信息与data_object包对应,在后端操作的实际上是这里定义的数据库属性。
下面是对各表的详细介绍:
用户表:用户(uid)主键自增、用户名(username)、密码(password)
音频表:音频(tid)主键自增、用户(uid)、标题(title)、type(音频类型)、content(音频内容)
专辑表:albums:aid()主键自增、标题(title)、用户(uid)、封面图(cover)、状态(state)
注:状态中 0代表已下线、1代表未发布、2代表已发布
关系表:relations:rid()主键自增、专辑(aid)、音频(tid)
relations表用于维护专辑与音频之间多对多的关系
数据库中的四个表对应data_object中的四个实体类
二、用户管理
1、注册
前端:利用form表单进行一个提交用户所填写的用户名和密码,属于静态资源。
代码如下:<form method="post" action="/studio/user/register.do"> <input type="text" name="username"> <input type="password" name="password"> <button>注册</button> </form>
后端:进行注册的具体操作,需要多个类配合进行工作。
1、在UsersDO类(处理users表)对象中设置和数据库中相对应的属性名称(方便操作)。
2、在UserServlet类中从前端获取信息并调用UesrSerice来进行插入用户信息。插入完成后重定向到首页。
3、在UesrService类中将从form表单中获取的用户信息调用UserRepo中的方法添加到数据库中,实现数据的整合。
4、在UserRepo类中使用SQL来对数据库进行增删查改,由于是注册操作所以是插入操作。String sql = "select uid, username, password from users where username = ?";
5、最后将插入好的用户信息转换成UserVo来呈现给前端。
2、登录
前端: 在login.html中使用form表单来进行用户的登录。
代码如下:<form method="post" action="/studio/user/login.do"> <input type="text" name="username"> <input type="password" name="password"> <button>登录</button> </form>
后端:
1、在UserServlet类中从前端获取信息并调用UesrSerice来查询用户输入的用户名和密码是否正确。
2、在UesrService类中将从form表单中获取的用户信息调用UserRepo来查询用户名和密码是否在数据库中并且一一对应。
3、在UserRepo类中使用SQL来对数据库进行增删查改,因为是登录操作所以使用的是查询操作。
代码如下:String sql = "select uid, username, password from users where username = ?";
4 、登录成功后,使用相对应的UserVo来呈现前端。
注销
注销必须是在登录后才可以使用不需要进行数据的增删查改,所以只使用QuitServlet类来进行操作,在该类下使用session.removeAttribute方法来销毁用户关联的session,并且重定向到登录界面。登录用到的类的介绍:
UserVO: 是对外表现的对象,存放在session中,传给前端,只定义了uid 和username ,并没有把password写进这个类里面。
UserService:(3个操作) 对密码做加密,保证数据库中存的密码不是明文,哈希操作,和完成注册(完成数据库地插入操作),在类中把UserDO(数据库需要的形式)转化为UserVO(我们需要的形式)。
UserDO:这里的数据是被数据库操作的,所以为了方便操作,属性名称都与数据库相同。
UserRepo:进行sql操作,对User表操作。为了代码简洁,直接用@SneakyThrows (lombok包下),不添加throws也可以正常抛出受查异常。
三、音频管理
1.音频上传
**前端:**这个功能必须当用户登录后才可浏览使用,验证放在后端进行处理。
代码如下:<form method="post" action="/studio/track/upload.do" enctype="multipart/form-data"> <input type="text" name="title"> <input type="file" name="track"> <button>上传</button> </form>
后端:因为要接受 enctype="multipart/form-data"的form表单,所以后端使用@MultipartConfig注解类修饰,读取用getPrat(…)。
1、在TrackServlet类中验证用户是否登录,若登录后从前端获取到用户所上传的信息并交给TrackService处理。
2、在TrackService类中将获得的信息与此时已经存在的UserVo中的uid一起使用TrackRepo的插入方法插入到数据库中。
3、在UserRepo类中使用SQL来对数据库进行增删查改,因为是上传,所以是增加操作
2、音频列表
前端:通过list.html文件来加载JS,并显示最终的列表信息,。
代码如下:<div class="who"></div> <table> <thead> <tr> <th>#tid</th> <th>标题</th> <th>和专辑的关联次数</th> </tr> </thead> <tbody></tbody> </table> <div class="pagination"> <a href="/studio/track/list.html?page=1">第一页</a> <a href="/studio/track/list.html?page=" class="prevPage">上一页</a> <span>每页 <span class="countPerPage"></span> 个</span> <span>第 <span class="currentPage"></span> 页</span> <span>共 <span class="totalPage"></span> 页</span> <a href="/studio/track/list.html?page=" class="nextPage">下一页</a> <a href="/studio/track/list.html?page=" class="lastPage">最后一页</a> </div> <script src="./js/list.js"></script>
JS做了什么呢?
答:发起ajax请求,渲染html文件。
后端:通过JSON,根据当前用户找出相应的列表信息。
1、需要两个VO类来进行前端显示
2、在TrackServlet类t中验证是否登录,并添加ObjectMapper类来转换JSON,并把获取的数据交给TrackService类处理。
3、在TrackService类中调用TrackRepo类的方法进行查询操作,通过此时的登录的uid来进行匹配。
4、在TrackRepo类中使用SQL来对数据库进行增删查改,是查询操作。
列表分页
1、在list.js中写处理上一页下一页的函数并创建关于Page的VO类(html文件显示的信息)。
2、在TrackServlet中读入page信息,并交给TrackService处理。
3、在TrackService中定义每页有最多有多少个信息,利用TrackRepo区查询一共有多少个数据,并计算有多少页。
4、在TrackRepo类中使用SQL来对数据库进行增删查改,是查询操作。
引用次数
设置RelationDO类取得relations表中的数据,根据当前所要查询的音频的tid来进行查询,查询的工作在RelationRepo中进行查询操作。
3、音频录制
前端:使用html和js相互配合,html使用audio标签来开始录制,js使用navigator.mediaDevices来使用麦克风配合录制并保存下来给后端保存在数据库。
html代码如下:
<body>
<input type="text" id="title">
<button id="stop">停止录制</button>
<audio controls></audio>
<script src="./js/record.js"></script>
</body>
后端:在RecordServlet类中判断用户是否登录,若登录就将录制好的音频文件进行保存,过程和音频的上传类似。
四、专辑
1、专辑创建
前端:用户必须登陆后才能使用,用form表单进行提交。
代码如下
<form method="post" action="/studio/album/create.do">
<input type="text" name="title">
<input type="text" name="cover">
<button>新建</button>
</form>
后端:
1、在CreatServlet中验证用户是否登录,若登录从用户提交的保存交给CreatRepo处理。
2、在CreatRepo执行SQL操作因为是创建所以是插入操作。
2、专辑列表的展现
前端:html与js配合使用,将专辑列表页展现出来。
后端:
1、首先在ListServlet类验证用户是否登录,若登录根据当前用户的uid来查找对应的信息并交给前端展示。
2、在ListRepo的执行查询操作。
3、专辑于音频的绑定列表页有绑定选项,可以向该专辑绑定想要绑定的歌曲。
前端:由html文件和js文件配合工作,点击绑定后就可以选择想要绑定的音频。
后端:
1、在CandidateServlet中将当前已将登录用户的音频列表查询出来,并交给前端展现出来。
2、在AddServlet中将用户选择绑定的音频的tid和专辑的aid插入relations表中。
这样就可以完成绑定。
4、专辑的发布和下线
会在专辑列表中每个专辑会有发布和下线操作。如果发布,所有人可以浏览;若下线,其他人不能浏览。如图所示:
前端:js中根据不同状态来执行不同操作。
代码如下:
if (a.state === '已发布') {
anchor = `<a href="/studio/album/withdraw.do?aid=${a.aid}">下线</a>`
} else {
anchor = `<a href="/studio/album/publish.do?aid=${a.aid}">发布</a>`
}
后端:
1、如果状态是发布,前端点击a标签就会跳转到未发布的状态,WithdrawServlet就会执行下线操作,将数据库中该专辑的状态修改为未发布。
2、如果状态是未发布,前端点击a标签就会跳转到发布的状态,PublishServlet就会执行上线操作,将数据库中该专辑的状态修改为发布。
五、播放功能
主体为一个audio标签,但是要播放音乐需要数据库提供音频数据的URL,还需要一个统一的数据接口来实现。
后端:
1、根据用户要播放音频的tid来进行查询,查询到之后利用“桶”将该音频的二进制流传递给播放器(数据从 content(InputStream) 搬到 os(OutputStream))。
2、设置统一的数据接口,将专辑表albums、音频表track、关系表relations的数据统一起来。
六、总结
1、开发环境:
1.前端开发:
技术:Html、Css、JavaScript
工具:Intellij IDEA 2020.1.4
2.后端开发:
算法:哈希算法进行加密
技术:jdk1.8、workbench、servlet、Maven
服务器:tomcat-8.5.50
工具:Intellij IDEA 2020.1.4
3.开发环境:Windows10 家庭版
4.运行环境:Intellij IDEA 2020.1.4
2、整体框架
项目整体基于HTTP协议,前端采用HTML+JS+CSS来进行页面的整体布局,后端采用分层结构,分为Service层,Servlet层、Repo层、Dao层的设计,便于分类设计。
总体设计:
本系统采用了浏览器/服务器模式,即B/S模式。对表现层、业务层、持久层三层结构均进行了实现。
表现层(data_view):在表现层通过前端界面处理(html+css+JavaScript)配合前端框架进行实现。前端与用户直接接触,保证良好的设计风格和视觉体验。前端数据通过javaScript发送Ajax传输给后端,再通过后端servlet返回的数据进行DOM树的渲染,形成了最终的页面。
业务层(service包和servlet包):service对从数据库或者前端页面获取来的数据进行转换,转换为当下需要的数据格式。在业务层通过Servlet处理,进行前后端交互。由于前端数据需要向后端发出请求。所以在前后端交互处理使用了JavaScript的开源框架jQuery-Ajax进行数据请求响应处理。后端通过servlet接收对应数据进行处理。
持久层(util包、data_object、repository):通过JDBC对数据库进行了连接,创建了用户表、音频表、专辑表、以及关系表,用来存储信息,并创建建了四个表在后端的实体类(UserDo,TrackDo,AlbumDo,TidToCountDo),以及在view_object包下面定义我们需要的json格式的数据,以及对repository对数据库中数据的增删查改。
3、项目核心功能:
(1)用户的注册,登录,注销。
(2)音频的上传,录制,播放。
(3)专辑的设计与创建,专辑和音频的绑定,专辑发布与下线。
4、涉及知识:
简单的web服务器使用、Java操作MySQL数据库、数据库的设计、json的使用、
HTTP协议的理解、Java集合的使用、Servlet的使用、前端知识的简单使用如:CSS、JS、HTML等。
数据流转流程(以专辑功能为例)
用户->浏览器->网络->Tomcat->MySQL
新建专辑 | 用户填写信息后,点击按钮,专辑发布成功
1.用户点击按钮,按钮输入form表单,所以,点击按钮会触发一个新的HTTP请求
2.该HTTP请求的方法按照form表单的method属性(get/post)确定,路径按照action属性确定,携带的内容按照form包
含的input标签带有name属性的内容确定
3.该HTTP经过网络到达Tomcat,Tomact根据Context Path + Servlet Path 确定有那个Servlet对象对其进行处理(@WebServlet指定的)
4.Tomcat根据HTTP请求方法,调用doGet,doPost....
5.读取参数即用户填写的专辑必要信息,以及必要的参数合法性校验
6.根据读到的参数执行SQL插入语句
7.根据业务,进行重定向或显示创建成功
MySQL->Tomact->浏览器->用户
专辑列表显示
1.在浏览器进入list.html
2.浏览器会发起get请求list.html
3.Tomcat根据相应路径,找到对应的静态资源并响应其内容
4.浏览器解析html内容,发现<script>标签,会发起一个新的请求
5.浏览器发起get请求list.js
6.Tomcat根据相应路径,找到对应资源并响应其内容
7.浏览器执行JS中的语句
8.在js中有发起ajax的语句
9.浏览器发起get请求list.json
10.Tomcat根据资源路径,找到Servlet对象进行处理
Servlet->Service->Repository(DAO)的内部处理
(1).判断当前用户(Servlet)
(2).执行必要SQL(具体到每个dao类)
(3).组合(在Service中将SQL结果整合)
(4).响应(最终Servelt将组合得到的数据发出)
11.浏览器继续执行xhr,onload函数
12.语句根据list.json返回的结果,修改DOM树结构(添加新的列表项)
13.浏览器根据DOM树,渲染出用户看到的结果