个人完成编写的schoolnet校园网的仿酷我音乐专辑模块中,用户可以收藏音乐专辑、下载专辑歌曲、关注好友音乐方面的最新动态及在线试听音乐,用户有权管理自己的收藏夹。
实现页面效果:
patent.jsp音乐专辑详情页面
music.jsp音乐大厅页面
mymusic.jsp我的音乐页面
好友动态页面
后台音乐管理设置:
数据库表原型设计:
Song歌曲表:包含主键id、歌曲名name、歌曲地址src、歌曲封面photo、歌手id(用于关联到singer歌手表,暂时未做歌手模块的功能,此字段用于以后做扩展)、所属专辑patentid。
Patent音乐专辑表:包含主键id、专辑名称name、专辑描述descript、专辑封面photo。
Usermusic用户音乐关系表:包含主键id、用户userid、音乐专辑patentid
1、完成编写的schoolnet校园网主要目录结构如下
音乐播放器的开发是比较艰辛的,从前端在html基础上运用用于媒介回放的 video 和 audio 元素、使用css控制样式并在CSS基础上运用圆角边框,向图片添加阴影,字体图标,2D转换,过渡,动画等CSS3新技术、使用javascript实现相关音乐播放、暂停、快进、后退、上一首、下一首、显示相应歌曲图片、歌曲名称、歌手名称等功能,到后台准备数据下了不少功夫。
<div id="t_wrapper">
<div id="t_cover"> <img src="images/logo_meitu_1.jpg"> </div>
<div id="t_top">
<div id="t_title_info"> <span class="singername"></span> <span class="songname"></span> </div>
</div>
<div id="t_middle">
<span id="prev"></span>
<div id="play"></div>
<div id="pause" class="hidden">
</div>
<span id="next"></span>
<div class="ui-slider ui-slider-horizontal ui-widget ui-widget-content ui-corner-all" id="t_progress">
<div id="trackInfo">
<div id="error"> </div>
<div id="current">0:00</div>
<div id="duration">0:00</div>
</div>
<div style="width: 0%;" class="ui-slider-range ui-widget-header ui-corner-all ui-slider-range-min"></div>
<span style="left: 0%;" class="ui-slider-handle ui-state-default ui-corner-all" tabindex="0"></span> </div>
</div>
<div id="t_bottom">
<div id="range">
<div id="val"></div>
<div id="vol"></div>
<div id="rangeVal"></div>
</div>
</div>
</div>
3、音乐播放器设计的javascript代码:
var styleChange = {pause:{}, play:{}, plsbutton:{}};
styleChange.play.change = function(){
$('#play').addClass('hidden');
$('#pause').removeClass('hidden');
};
styleChange.pause.change = function(){
$('#pause').addClass('hidden');
$('#play').removeClass('hidden');
};
styleChange.plsbutton.change = function(){
$('#t_pls_show').addClass('selectpls');
$('#t_pls_show').removeClass('noselectpls');
};
styleChange.plsbutton.recovery = function(){
$('#t_pls_show').addClass('noselectpls');
$('#t_pls_show').removeClass('selectpls');
};
function initAudio(elem) {
var songname = elem.attr('songname');
var cover = elem.attr('t_cover');
var singername = elem.attr('singername');
$('.songname').text(' - ' + songname);
$('.singername').text(singername);
$('#t_cover').html('<img src="' + cover+'">');
}
$(document).ready(function(){
var dur, durM, val, mus, elem, prog;
var Pl = 0;
$('#playlist ul li a').click(function(){
$('#t_title_info').animate({top: "-1.5em",opacity: "hide"}, 0);
initAudio($(this).parent("li"));
$('#error').text('');
styleChange.play.change();
console.log(mus);
if(mus){mus[0].pause();
mus[0].currentTime = 0;
$('li').removeClass('active');
}
mus = $(this).next("audio");
$(this).parent("li").addClass('active');
mus[0].play();
});
$('#t_progress').slider({
value: 0,
orientation: "horizontal",
range: "min",
animate: true,
step: 1
});
$('audio').on("timeupdate", function() {
mus[0].volume = val/100;
d = this.duration;
c = this.currentTime;
curM = Math.floor(c/60);
curS = Math.round(c - curM*60);
$('#current').text(curM + ':' + curS);
$('#t_progress').slider({
max: d,
min: 0,
value: c
});
});
$('audio').on("playing", function () {
dur = this.duration;
durM = Math.floor(dur/60) + ':' + Math.round((dur - Math.floor(dur/60))/10);
$('#duration').text(durM);
$(this).parent("li").addClass('active');
$('#t_title_info').animate({top: "0.5em",opacity: "show"}, 500);
});
$('audio').on("ended", function(){
mus = $(this).parent('li').next('li').first();
mus = mus.children('audio');
$(this).parent("li").addClass('active');
var next = $('li.active').next();
$('li').removeClass('active');
if(mus[0]){
initAudio(next);
mus[0].play();
}
else{
$('#error').text('');
$('#t_cover').html('<img src="images/userhead/01.gif">');
}
});
//play button
$('#play').click(function(){
if(mus){
mus[0].play();
styleChange.play.change();
$('#error').text('');
}
else {
$('#error').text();
}
});
// pause button
$('#pause').click(function() {
if(mus){
mus[0].pause();
styleChange.pause.change();
}
else {
$('#error').text();
}
});
//next button
$('#next').click(function(){
mus[0].pause();
mus[0].currentTime = 0;
mus = mus.parent('li').next('li').first();
mus = mus.children('audio');
var next = $('li.active').next();
$('#t_title_info').animate({top: "-1.25em",opacity: "hide"}, 0);
$('li').removeClass('active');
if(mus[0]){
initAudio(next);
mus[0].play();
}
else{
$('#error').text('');
$('#t_cover').html('<img src="images/userhead/02.gif">');
mus = null;
}
});
//prev button
$('#prev').click(function(){
mus[0].pause();
mus[0].currentTime = 0;
mus = mus.parent('li').prev('li').last();
mus = mus.children('audio');
var prev = $('li.active').prev();
$('li').removeClass('active');
$('#t_title_info').animate({top: "-1.25em",opacity: "hide"}, 0);
if(mus[0]){
initAudio(prev);
mus[0].play();
}
else{
$('#error').text('');
$('#t_cover').html('<img src="images/userhead/03.gif">');
mus = null;
}
});
//volume
$('#rangeVal').slider({
value: 60,
orientation: "horizontal",
range: "min",
animate: true,
step: 1
});
// volume text
val = $('#rangeVal').slider("value");
$('#val').text(val);
var tooltip = $('#val');
tooltip.hide();
$('#rangeVal').slider({
start: function( event, ui ) {
tooltip.fadeIn('fast');
},
stop: function(event,ui) {
tooltip.fadeOut('fast');
},
slide: function( event, ui ) {
val = ui.value;
tooltip.css('left', val-30).text(ui.value);
$('#val').text(val);
if(mus){
mus[0].volume = val/100;
}
else {
$('#error').text();
}
}
});
// progress
$('#t_progress').slider({
start: function( event, ui ) {
mus[0].pause();
},
stop: function( event, ui ) {
prog = ui.value;
mus[0].currentTime = prog;
mus[0].play();
styleChange.play.change();
}
});
//playlist button
$('#t_pls_show').click(function(){
if (Pl == 0) {
styleChange.plsbutton.change();
Pl = 1;
}
else {
styleChange.plsbutton.recovery();
Pl = 0;
}
$('#playlist').slideToggle();
});
});
4、几个常用的service层组件,暂时不做dao层
// 获得所有音乐歌单(专辑)
public List<Patent>getallPatents(){
List<Patent>allPatents=getResult("from Patent order by id desc", null );
returnallPatents;
}
// 获得所有音乐歌单(分页)
public List<Patent>getallPatentsByPage(intpageNow,intpageSize){
List<Patent>allpPatentsByPage=executeQueryByPage("from Patent order by id desc", null, pageNow, pageSize);
returnallpPatentsByPage;
}
// 获得某个音乐歌单的所有歌曲
public List<Song>getSongsByPatent(Patent patent)
{
List<Song> songs=getResult("from Song where pagentId=?", new Object[]{patent.getId()});
return songs;
}
// 分页获得好友在音乐方面的最新动态
@Override
public List<Usermusic>getUsermusicByFriend(List<Users>list,intpageNow,intpageSize) {
// TODO Auto-generated method stub
List<Usermusic>musicList = newArrayList<Usermusic>();
List<Usermusic>usermusics=null;
for(inti=0;i<list.size();i++)
{
usermusics=executeQueryByPage("from Usermusic where userId=? order by id desc", newObject[]{list.get(i).getId()},pageNow,pageSize);
for(int j=0;j<usermusics.size();j++)
{
//由于用户音乐关系表usermusic最初设计时,没有设置创建时间CreTime字段,此处暂时没做音乐动态更新的最近时间设置
// try {
// if(MyTools.strDate(usermusics.get(j).getCreTime())<=date)
// {
musicList.add(usermusics.get(j));
// }
// } catch (Exception e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
}
}
returnmusicList;
}
其中executeQueryByPage引用基础Service类
/**
* 定义基础Service类,并实现相应的接口,供各个模块的Service类继承
* */
@Transactional
public abstract class BaseServiceImpl implements BaseServiceInter {
//Spring属性注入,会话工厂
@Resource SessionFactory sessionFactory;
//实现分页查询,下行的注解表示该方法不需开启事务
@Transactional(propagation=Propagation.NOT_SUPPORTED)
/**
* @param hql: 传入的hql语句
* @param parameters:hql语句中问号对应的参数数组
* @param pageNow:当前页面
* @param pageSize:每个页面容纳记录数
* */
Public List executeQueryByPage(String hql, Object[] parameters,
int pageNow, int PagesSize) {
Query query=sessionFactory.getCurrentSession().createQuery(hql);
if(parameters!=null && parameters.length>0){
for(int i=0;i<parameters.length;i++){
query.setParameter(i, parameters[i]);
}
}
if(pageNow<1) {pageNow=1;}
//体现分页
return query.setFirstResult((pageNow-1)*PagesSize).setMaxResults(PagesSize).list();
5、Controller层几个核心处理代码
// 获取当前的网站的session情况
Users user=(Users) request.getSession().getAttribute("loginuser");
// 获取该用户所在的大学
Useruniversityuseruniversity = userService.getUseruniversity(user);
// 获得该用户所在的高中
Userseniorusersenior = userService.getUsersenior(user);
// 获得该用户所在的初中
Junior junior = userService.getJunior(user);
// 获得该用户所在的城市
City city = userService.getCity(user);
// 获得该用户所在的省份
Province province = userService.getProvince(user);
// 获得该用户的好友个性表
List<Friend> friends = userService.getResult(
"from Friend where f_hostId=? order by id desc",
new Object[] { Long.valueOf(user.getId()) });
// List<Friend>
// lists=userService.executeQueryByPage("from Friend where f_hostId=? order by id desc",
// new Object[]{Long.valueOf(user.getId())}, 1, 6);
// 通过好友关系表获取该用户的好友列表
List<Users>friendlList = userService.getFriends(friends);
List<Friendapply>friendapplies = userService.getResult(
"fromFriendapply where fa_getId=? andfa_read=?",
new Object[] { Long.valueOf(user.getId()),
Integer.valueOf("0") });
// 获取向我发送了加好友申请的网页
List<Users>friendSends = userService
.getUsersByFriapp(friendapplies);
// System.out.print(friends.size());
// 通过好友发表的日志,获取该好友信息
String pageNow=request.getParameter("pageNow");
intpageSize=10;
intallrows=userService.getallPatents().size();
intpageCount=(allrows-1)/pageSize+1;
if(pageNow.equals("0"))
{
pageNow="1";
}
if(Integer.parseInt(pageNow)>pageCount)
{
pageNow=pageCount+"";
}
// 获得所有音乐歌单(分页)
List<Patent> patents=userService.getallPatentsByPage(Integer.valueOf(pageNow), pageSize);
// 移除用户收藏的音乐专辑
String pid=request.getParameter("pid");
Usermusicusermusic=(Usermusic) userService.uniqueQuery("from Usermusic where patentId=?", new Object[]{Integer.valueOf(pid)});
userService.delete(usermusic);
Users user=(Users) request.getSession().getAttribute("loginuser");
//如果用户等级小于4,则限制用户音乐下载功能
if(user.getLevel()<4)
{
PrintWriter out = null;
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
try {
out = response.getWriter();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
out.print("<script>alert('用户等级达到4以上才能下载,你的等级不够');window.history.go(-1);</script>");
}
else {
String patentid=request.getParameter("patentid");
//获取下载歌曲的id号
String songid=request.getParameter("songid");
//根据id号获得歌曲
Song song=(Song) userService.findById(Song.class, Integer.valueOf(songid));
//获取歌曲名称
String displayname=song.getName();
//获取歌曲路径
String songsrc=song.getSrc();
//调用业务逻辑层的歌曲下载功能
MyTools.downmusic(displayname, patentid, songsrc, request, response);
//获取用户的积分
int website=user.getWebsite();
//扣除用户5点积分
user.setWebsite(website-5);
6、前端音乐专辑展示页面html代码:
<!-- s_img begin -->
<div class="s_img">
<img src="/schoolnet/Media/patent/${patent.photo }" width="240"
height="240" alt="${patent.name }" title="${patent.name }">
</div>
<!-- s_img end -->
<!-- comm begin -->
<div class="comm">
<h1 title="校园歌曲永远不会老">${patent.name }</h1>
<p class="button">
<img src="/schoolnet/images/front/bluray.png" />
</p>
<ul>
<li style="margin:5px">歌曲数:<span>${fn:length(songs)}</span></li>
<li style="margin:5px">制作者:<span>校园admin</span></li>
<li style="margin:5px">已有<span>${fn:length(patent.usermusics)}</span>个用户收藏</li>
</ul>
<p class="tag" style="margin:10px">
标签:<span title="校园">校园</span>
</p>
</div>
<!-- comm end -->
</div>
<!-- singer end -->
<div class="tipcomm">
<div id="moreContent" style="height: auto; overflow: hidden;">
<p id="intro" style="word-wrap:break-word;">${patent.name
}简介:${patent.descript }</p>
</div>
</div>
<!-- musiclist begin -->
<div class="m_list">
<div class="pages">
<p class="fl" style="margin-left:20px; display:inline;">共${fn:length(songs)
}首歌</p>
<p class="fr">
<input id="patentid" value="${patent.id }" type="hidden"> <input
id="userid" value="${loginuser.id }" type="hidden"> <a
href="/schoolnet/music.do?flag=goMyMusic&pageNow=1" title="去我的收藏"
class="current2" style="background:#1093d7;">去我的收藏</a>
<c:if test="${usermusic==null }">
<span class="setmusic"><a href="javascript:void(0);"
οnclick="setPatent()" title="加入收藏" class="current"
style="background:#1093d7;">加入收藏</a> </span>
</c:if>
<c:if test="${usermusic!=null }">
<a title="已经收藏" class="current" style="background:#999;">已经收藏</a>
</c:if>
</p>
</div>
<br /> <br />
<p style="float:right;margin-top:-30px;">每次下载歌曲,将扣除5点经验值</p>
<div class="list">
<div id="playlist" style="margin-top:5px">
<ul>
<c:forEach var="song" items="${patent.songs }">
<li id="ll" t_cover="Media/patent/${patent.photo }"
singername="${song.singername }" songname="${song.name }"><a
href="javascript:void(0)">${song.singername } – ${song.name }</a>
<audio preload="none">
<source src="Media/song/${patent.id }/${song.src }" type="audio/mp3">
<source src="http://www.sucaijiayuan.com" type="audio/ogg; codecs=vorbis">
</audio></li>
<a href="/schoolnet/music.do?flag=downmusic&patentid=${patent.id }&songid=${song.id }"
style="float:right;margin-top:-35px;margin-right:10px;">下载 </a>
</c:forEach>
</ul>
</div>
<div class="page" id="ge_page"></div>
</div>
</div>