当前位置: 首页 > news >正文

SSM项目实战——哈哈音乐(四)前台模块开发

1、项目准备

①导入依赖和前端资源

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"><parent><artifactId>hami-parent</artifactId><groupId>com.qcby</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>hami-portal</artifactId><packaging>war</packaging><name>hami-portal Maven Webapp</name><dependencies><dependency><groupId>com.qcby</groupId><version>1.0-SNAPSHOT</version><artifactId>hami-core</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId></dependency><dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><scope>provided</scope></dependency><dependency><groupId>javax.servlet.jsp</groupId><artifactId>jsp-api</artifactId><scope>provided</scope></dependency><dependency><groupId>jstl</groupId><artifactId>jstl</artifactId></dependency></dependencies></project>

 

②在resources下导入创建springmvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:context="http://www.springframework.org/schema/context"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><mvc:annotation-driven><mvc:message-converters><bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter"><property name="supportedMediaTypes" value="text/html;charset=UTF-8"/><property name="features"><array><value>WriteMapNullValue</value><value>WriteNullStringAsEmpty</value></array></property><property name="dateFormat" value="yyyy-MM-dd"></property></bean></mvc:message-converters></mvc:annotation-driven><context:component-scan base-package="com.qcby.controller"/><bean id="viewResource" class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/page/"></property><property name="suffix" value=".jsp"></property></bean><mvc:view-controller path="/index" view-name="index"></mvc:view-controller><mvc:default-servlet-handler/>
</beans>

③配置web.xml

<web-appversion="2.5"xmlns="http://java.sun.com/xml/ns/javaee"xmlns:xml="http://www.w3.org/XML/1998/namespace"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"><filter><filter-name>SpringCharacterEncodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param></filter><filter-mapping><filter-name>SpringCharacterEncodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><servlet><servlet-name>dispatcher</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc.xml</param-value></init-param><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>dispatcher</servlet-name><url-pattern>/</url-pattern></servlet-mapping><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><context-param><param-name>contextConfigLocation</param-name><param-value>classpath:applicationContext.xml</param-value></context-param>
</web-app>

2、歌曲界面

①展示所有歌曲

启动tomcat后,进入index.jsp页面,发送dofindAll,可以根据条件查询歌曲也可以查询所有歌曲信息

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body><jsp:forward page="/song/dofindAll"></jsp:forward>
</body>
</html>

 创建SongController,编写dofindAll,给search.jsp页面返回歌曲和所有专辑信息

package com.qcby.controller;import com.qcby.model.Mtype;
import com.qcby.model.Page;
import com.qcby.model.Song;
import com.qcby.query.SongQuery;
import com.qcby.service.MtypeService;
import com.qcby.service.SongService;
import com.qcby.service.SongerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;@Controller
@RequestMapping("/song")
public class SongController {@Autowiredprivate SongService songService;@Autowiredprivate MtypeService mtypeService;@RequestMapping("/dofindAll")public String list(SongQuery mq, Model model){if(mq.getPageNo() == 0){mq.setPageNo(1);}Page<Song> page = songService.selectObjectByCondition(mq);model.addAttribute("page", page);model.addAttribute("mq", mq);List<Mtype> mtypes = mtypeService.selectObjectAll();model.addAttribute("mtypes", mtypes);return "search";}

research.jsp界面展示歌曲信息

<div id="body" class="gap"><input id="tid" type="hidden" value="${mq.tid}"><input id="isHot" type="hidden" value="${mq.isHot}"><input id="isNew" type="hidden" value="${mq.isNew}"><div class="wrapper"><div class="content_wrapper"><div class="content"><div class="filter" data-spm="1392350033"><dl><dt>流派&nbsp;:</dt><dd><p><a href="#" ftype="mtype" value="" class="current">全部</a><c:forEach items="${mtypes}" var="mtype"><a href="#" ftype="mtype" value="${mtype.tid}">${mtype.tname}</a></c:forEach></p></dd></dl><dl><dt>热门&nbsp;:</dt><dd><p><a href="#" ftype="isHot" value="" class="current">全部</a><a href="#" ftype="isHot" value="1">热门</a></p></dd></dl><dl><dt>新歌&nbsp;:</dt><dd><p><a href="#" ftype="isNew" value="" class="current">全部</a><a href="#" ftype="isNew" value="1">最新</a></p></dd></dl></div><div class="chart" data-spm="1392350021"><table><thead><tr><td width="40"></td><td width="45"></td><td></td><td width="180"></td><td width="180"></td><td width="130"></td></tr><tr><th align="right"><input type="checkbox" checked onclick="selectall(this);"></th><th align="left" colspan="5"><b class="play" onclick="playsongs();"></b></th></tr></thead><tbody id="content"><c:forEach items="${page.list}" var="song" varStatus="status"><tr data-index="0"><td align="right"><input type="checkbox" name="chartids" checked="checked"value="${song.sid}"></td><td align="center">${status.count}</td><td><div class="song"><div class="image"><img src="${filePath}${song.songer.pic}" alt="Every Breath You Take"height="55" width="55"/><b></b></div><div class="info"><p><strong><a target="_blank" title="Every Breath You Take"href="#">${song.sname}</a></strong></p></div></div></td><td><span><a target="_blank" href="#" title="Karen Souza">${song.songer.srname}</a></span></td><td><span><a target="_blank" title="Essentials" href="#">${song.album.aname}</a></span></td><td><div class="action"><button class="play" onclick="play(${song.sid});" title="试听">试听</button><button class="download" title="下载">下载</button><button class="offline" title="发送到">发送到</button></div></td></tr></c:forEach></tbody></table></div><input type="hidden" id="pageNoPortal" value="${mq.pageNoPortal}"><c:if test="${page.pageNo < page.totalPage}"><div class="loadr" id="loader"><a href="javascript:void(0);" onclick="loadMore()"><b></b>查看更多</a></div></c:if><c:if test="${page.pageNo == page.totalPage}"><div class="loadr" id="nomore" style="font-size: 18px;">没有更多啦!</div></c:if></div></div><div class="sidebar" data-spm="1392350021"><div class="nav"><a class="index" href="#"><b></b>发现</a><a class="top" href="#"><b></b>排行榜</a><a class="magazines" href="#"><b></b>音乐人企划</a><a class="artists" href="/songer/dofindAll"><b></b>音乐人</a><a class="songs current" href="/song/dofindAll"><b></b>歌曲</a><a class="albums" href="#"><b></b>专辑<sup>无损</sup></a></div><div class="genre"><c:forEach items="${mtypes}" var="mtype"><a href="/song/dofindAll?tid=${mtype.tid}"><b></b>${mtype.tname}</a></c:forEach></div></div></div></div>

 

②根据条件搜索歌曲 

search.jsp页面的js请求

<script>var tid = "";var isHot = "";var isNew = "";$(function () {//指定点击事件$(".filter p a").click(function () {//移除同辈的a链接的样式$(this).siblings().removeClass("current");//把点击的a链接的样式加上$(this).addClass("current");//获得流派的选中值var tid = $("a[ftype='mtype'][class='current']").attr("value");var isHot = $("a[ftype='isHot'][class='current']").attr("value");var isNew = $("a[ftype='isNew'][class='current']").attr("value");//alert(tid+"   "+isHot+"   "+isNew);window.location.href = "/song/dofindAll?tid=" + tid + "&isHot=" + isHot + "&isNew=" + isNew;})tid = $("#tid").val();isHot = $("#isHot").val();isNew = $("#isNew").val();//流派的回显$("a[ftype='mtype'][class='current']").removeClass("current");$("a[ftype='mtype'][value='" + tid + "']").addClass("current");//热门回显$("a[ftype='isHot'][class='current']").removeClass("current");$("a[ftype='isHot'][value='" + isHot + "']").addClass("current");//新歌回显$("a[ftype='isNew'][class='current']").removeClass("current");$("a[ftype='isNew'][value='"+ isNew + "']").addClass("current");})

③查看更多

 js代码

function loadMore() {//2  111111  5 10 15 20var pageNoPortal = parseInt($("#pageNoPortal").val());//计算pageSizevar pageSize = 5 * (++pageNoPortal);window.location.href = "/song/dofindAll?tid=" + tid + "&isHot=" + isHot + "&isNew=" + isNew + "&pageSize=" + pageSize + "&pageNoPortal=" + pageNoPortal;}

前端代码

<c:if test="${page.pageNo < page.totalPage}">
<div class="loadr" id="loader"><a href="javascript:void(0);" onclick="loadMore()"><b></b>查看更多</a>
</div>
</c:if>
<c:if test="${page.pageNo == page.totalPage}">
<div class="loadr" id="nomore" style="font-size: 18px;">没有更多啦!</div>
</c:if>

上面三个功能都是通过controller中dofindAll这一个请求来实现,只是所传的参数不一致 

对于展示所有歌曲,dofindAll不传任何参数,直接查询所有的歌曲信息

对于根据条件搜索歌曲,传入歌曲流派、是否热门、是否是新歌这三个信息作为筛选条件进行歌曲搜索

对于查看更多,除了传入三个搜索条件还传入页面大小和当前页码作为条件进行查询

④歌曲播放

功能:可以通过点试听,单个歌曲播放,也可以选取多个歌曲放入播放列表中按顺序播放

实现思路:对于单个歌曲播放功能,直接根据当前传入的歌曲id查询歌曲信息,将歌曲信息传给play.jsp页面进行歌曲播放

对于播放列表播放歌曲,首先通过cookie获取上一次未播放完的歌曲id,然后本次传入的歌曲id列表加上上次的歌曲id列表,变成一个新的歌曲id列表,并将新的歌曲id列表存入cookie中。根据歌曲id列表查询歌曲信息,将其交给paly.jsp页面,进行歌曲播放

js代码

function selectall(checkallObj) {var checked = $(checkallObj).attr("checked");if(checked =="checked"){$("tbody tr td input[type='checkbox']").attr("checked","checked");}else{$("tbody tr td input[type='checkbox']").removeAttr("checked");}}function playsongs() {//拿到所有的复选框选中的元素var songs = $("tbody tr td input[type='checkbox']:checked")var sids = ""; //"1,2,3,4,5,"songs.each(function () {var sid = $(this).val();sids = sids + sid+","})window.open("/song/play?sids="+sids,"play");}function play(sid) {window.open("/song/play?sids="+sid,"play");}</script>

controller代码

/*** 实现歌曲播放列表* @param sids   选中的歌曲列表* @param model* @param request* @param response* @return* @throws UnsupportedEncodingException*/@RequestMapping("/play")public String play(String sids, Model model, HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {//1、处理sids字符串,变成集合给后台查询,变成cookie作为下一次使用的记录//idList记录歌曲播放列表,就是本次新添加的播放歌曲sids+上一次的播放歌曲列表List<String> idList = new ArrayList<>();String[] idArr = null;//程序严谨性判断if(sids != null && !"".equals(sids)){idArr = sids.split(",");for (String s : idArr) {idList.add(s);}}//如果是第一次添加歌曲列表,不考虑,否则需要拿到cookie查看上次播放记录//pids存储的是上次歌曲播放值String pids = "";Cookie[] cookies = request.getCookies();if(cookies != null && cookies.length > 0){for (Cookie cookie : cookies) {String name = cookie.getName();if("playids".equals(name)){//解码  防止乱码pids = URLDecoder.decode(cookie.getValue(),"UTF-8");}}}//oldArr存放的是上一次播放的歌曲列表String[] oldArr = pids.split(",");for (int i = 0; i < oldArr.length; i++) {//保证不重复添加相同的歌曲,如果上次歌曲播放列表中含有本次添加的播放列表,则不添加到新的播放列表if(!idList.contains(oldArr[i])){idList.add(oldArr[i]);}}//创建新的歌曲播放列表,原来存储的播放歌曲列表为list<String>类型,idsList变成list<Integer>,用于后台查询List<Integer> idsList = new ArrayList<>();//字符串类型的新的播放列表,用于cookie传值给前端作为上一次播放列表String playids = "";for (String s : idList) {if(!"".equals(s)){idsList.add(new Integer(s));playids = playids + s+",";}}List<Song> songs = new ArrayList<>();if(idsList.size() > 0)songs = songService.getSongByIds(idsList);model.addAttribute("songs",songs);System.out.println(songs);System.out.println(playids);playids = URLEncoder.encode(playids, "UTF-8");Cookie cookie = new Cookie("playids", playids);//cookie的有效时间cookie.setMaxAge(60*60*24*30);//设置cookie的访问有效路径cookie.setPath("/");response.addCookie(cookie);return "player";}/*** 获取播放的歌曲信息,实现歌曲播放* @param sid* @return*/@ResponseBody@RequestMapping("/getSong")public Song getSong(Integer sid){Song song = songService.getSong(sid);System.out.println(song);return song;}

 通过歌曲id获取歌曲信息的service接口

 //添加播放列表public List<Song> getSongByIds(List<Integer> idsList);
//实现歌曲播放Song getSong(Integer sid);

通过歌曲id获取歌曲信息的service实现类

 @Overridepublic List<Song> getSongByIds(List<Integer> idsList) {return songMapper.getSongByIds(idsList);}
//实现歌曲播放@Overridepublic Song getSong(Integer sid) {return songMapper.getSong(sid);}

通过歌曲id获取歌曲信息的mapper接口

//实现添加播放列表List<Song> getSongByIds(List<Integer> idsList);
//实现歌曲播放Song getSong(Integer sid);

通过歌曲id获取歌曲信息的sql

<resultMap id="getSongByIdsRM" type="com.qcby.model.Song" extends="ResultMapWithBLOBs"><association property="songer" javaType="com.qcby.model.Songer" resultMap="com.qcby.dao.SongerMapper.BaseResultMap"></association></resultMap><!--  查询要播放的歌曲集合返回--><select id="getSongByIds" parameterType="java.util.List" resultMap="selectObjectByConditionRM">select * from song s left join mtype m on s.tid=m.tid left join songer sr on s.srid=sr.srid left join album a on s.aid=a.aid<where>s.sid in<if test="list!=null"><foreach collection="list" open="(" close=")" separator="," item="sid">#{sid}</foreach></if>order by field (s.sid,<foreach collection="list" separator="," item="sid">#{sid}</foreach>)</where></select><resultMap id="getSongRM" type="com.qcby.model.Song" extends="ResultMapWithBLOBs"><association property="songer" javaType="com.qcby.model.Songer" resultMap="com.qcby.dao.SongerMapper.BaseResultMap"></association></resultMap><!--  实现歌曲播放--><select id="getSong" parameterType="int" resultMap="getSongRM">select * from song left join songer on song.srid=songer.srid where song.sid=#{sid}</select>

play.jsp页面

<c:forEach items="${songs}" var="song" varStatus="status"><li class="songList"><div class="songLMain"><div class="check"><input class="checkIn" type="checkbox" select="0" value="${song.sid}"></div><div class="start" ><em sonN="${status.count}" msid="${song.sid}">${status.count}</em></div><div class="songBd"><div class="col colsn">${song.sname}</div><div class="col colcn">${song.songer.srname}</div><div class="col">${song.album.aname}</div></div><div class="control"><a class="cicon love"></a><a class="cicon more" style="display:none"></a><a class="cicon dele" style="display:none"></a></div></div>									</li>
</c:forEach>

3、音乐人界面

①展示所有音乐人

创建SongerController,编写controller

package com.qcby.controller;import com.qcby.model.Mtype;
import com.qcby.model.Page;
import com.qcby.model.Songer;
import com.qcby.query.SongerQuery;
import com.qcby.service.MtypeService;
import com.qcby.service.SongService;
import com.qcby.service.SongerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;import java.util.ArrayList;
import java.util.List;@Controller
@RequestMapping("/songer")
public class SongerController {@Autowiredprivate SongerService songerService;@Autowiredprivate MtypeService mtypeService;@RequestMapping("/dofindAll")public String listType(SongerQuery mq, Model model) {if (mq.getPageNo() == 0) {mq.setPageNo(1);}mq.setPageSize(20);Page<Songer> page = songerService.selectObjectByCondition(mq);List<Mtype> mtypes = mtypeService.selectObjectAll();List<List<Songer>> list = new ArrayList<>();List<Songer> slist = (List<Songer>) page.getList();List<Songer> list1 = null;for (int i = 0; i < 20; i++) {if (i % 5 == 0) {list1 = new ArrayList<>();list.add(list1);}Songer s = null;if (i < slist.size()) {s = slist.get(i);list1.add(s);}}model.addAttribute("sList", list);model.addAttribute("page", page);model.addAttribute("mq", mq);model.addAttribute("mtypes", mtypes);return "songers";}

前端songers.jsp页面展示

<div id="body" class="gap"><input id="tid" type="hidden" value="${mq.tid}"><input id="isHot" type="hidden" value="${mq.isHot}"><div class="wrapper"><div class="content_wrapper"><div class="content"><div class="filter" data-spm="1392350033"><dl><dt>流派&nbsp;:</dt><dd><p><a href="#" ftype="mtype" value="" class="current">全部</a><c:forEach items="${mtypes}" var="mtype"><a href="#" ftype="mtype" value="${mtype.tid}">${mtype.tname}</a></c:forEach></p></dd></dl><dl><dt>热门&nbsp;:</dt><dd><p><a href="#" ftype="isHot" value="" class="current">全部</a><a href="#" ftype="isHot" value="1">热门</a></p></dd></dl></div><div class="albums" data-spm="1392350021"><c:forEach items="${sList}" var="subList"><div class="album_list"><c:forEach items="${subList}" var="songer"><div class="album" data-needpay="0" data-playstatus="1" data-downloadstatus="1"><div class="image"><a target="_blank" title="${songer.srname}" href="/songer/getSonger?srid=${songer.srid}"><img src="${filePath}${songer.pic}" alt="${songer.srname}"><b class="icon toplay" onclick="playalbum(406532);return false;" style="display: none;"></b><dl style="display: none;"><dt><b class="icon toheart"></b><b class="icon todropmenu"></b></dt><dd style="display: none;"><ul><li onclick="tag(406532,5);return false;"><b class="icon tofavourite"></b>收藏</li><li onclick="album2collect(406532);return false;"><b class="icon tocollect"></b>添加到</li><li onclick="recommend(406532,33);return false;"><b class="icon toshare"></b>分享到</li></ul></dd></dl><sup title="${songer.srname}"></sup>			</a></div><div class="info"><p><a target="_blank" title="${songer.srname}" href="#">${songer.srname}</a></p></div></div></c:forEach></div></c:forEach></div><input type="hidden" id="pageNoPortal" value="${mq.pageNoPortal}"><c:if test="${page.pageNo < page.totalPage}"><div class="loadr" id="loader"><a href="javascript:void(0);" onclick="loadMore01()"><b></b>查看更多</a></div></c:if><c:if test="${page.pageNo == page.totalPage}"><div class="loadr" id="nomore" style="font-size: 18px;">没有更多啦!</div></c:if></div></div><div class="sidebar" data-spm="1392350021"><div class="nav"><a class="index" href="#"><b></b>发现</a><a class="top" href="#"><b></b>排行榜</a><a class="magazines" href="#"><b></b>音乐人企划</a><a class="artists current" href="#"><b></b>音乐人</a><a class="songs " href="/song/dofindAll"><b></b>歌曲</a><a class="albums" href="#"><b></b>专辑<sup>无损</sup></a></div><div class="genre"><c:forEach items="${mtypes}" var="mtype"><a href="/songer/dofindAll?tid=${mtype.tid}"><b></b>${mtype.tname}</a></c:forEach></div></div></div></div>

②根据条件搜索音乐人

songers.jsp页面的js请求

<script>$(function () {var tid = "";var isHot = "";$(function () {//指定点击事件$(".filter p a").click(function () {//移除同辈的a链接的样式$(this).siblings().removeClass("current");//把点击的a链接的样式加上$(this).addClass("current");//获得流派的选中值var tid = $("a[ftype='mtype'][class='current']").attr("value");var isHot = $("a[ftype='isHot'][class='current']").attr("value");//alert(tid+"   "+isHot+"   "+isNew);window.location.href = "/songer/dofindAll?tid="+tid+"&isHot="+isHot;})tid = $("#tid").val();isHot = $("#isHot").val();//流派的回显$("a[ftype='mtype'][class='current']").removeClass("current");$("a[ftype='mtype'][value='"+tid+"']").addClass("current");//热门回显$("a[ftype='isHot'][class='current']").removeClass("current");$("a[ftype='isHot'][value='"+isHot+"']").addClass("current");})

③查看更多

songers.jsp页面的js请求

 function loadMore01() {var pageNoPortal = parseInt($("#pageNoPortal").val());//计算pageSizevar pageSize = 5*(++pageNoPortal);window.location.href = "/song/dofindAll?tid="+tid+"&isHot="+isHot+"&pageSize="+pageSize+"&pageNoPortal="+pageNoPortal;}

这里前三个共用一个请求—dofindAll,和歌曲界面相似,也只是请求参数不一样 

④查看音乐人的详细信息

点击音乐人的图片,就可以查看音乐人的详细信息,发送getSonger请求,并带有音乐人的id

<a target="_blank" title="${songer.srname}" href="/songer/getSonger?srid=${songer.srid}">

controller编写,根据音乐人的id联表查询歌曲信息,将其返回给songer,jsp页面

@RequestMapping("/getSonger")public String getSong(Integer srid, Model model) {Songer songer = songerService.getSongs(srid);model.addAttribute("songer",songer);System.out.println(songer);return "songer";}

根据音乐人的id联表查询歌曲信息的service接口

//根据歌手id联表查询歌曲信息public Songer getSongs(Integer srid);

根据音乐人的id联表查询歌曲信息的service实现类

@Overridepublic Songer getSongs(Integer srid) {return songerMapper.getSongs(srid);}

根据音乐人的id联表查询歌曲信息的mapper接口

 //根据歌手id联表查询歌曲信息public Songer getSongs(Integer srid);

根据音乐人的id联表查询歌曲信息的sql

 <resultMap id="getSongsRM" type="com.qcby.model.Songer" extends="ResultMapWithBLOBs"><collection property="songs" ofType="com.qcby.model.Song" resultMap="com.qcby.dao.SongMapper.BaseResultMap"></collection><collection property="mtype" ofType="com.qcby.model.Mtype" resultMap="com.qcby.dao.MtypeMapper.BaseResultMap"></collection></resultMap><select id="getSongs" parameterType="Integer" resultMap="getSongsRM">select sr.srid, sr.srname, sr.area, sr.intro, sr.pic, m.*, s.* from songer sr left join mtype m on sr.tid=m.tid left join song s on sr.srid=s.srid where sr.srid=#{srid}</select>

songer.jsp页面

 <div id="artist_info"><table><tbody><tr><td width="56" valign="top" class="item">地区:</td><td valign="top">${songer.area}</td></tr><tr><td width="56" valign="top" class="item">风格:</td><td valign="top"><a href="/songer/dofindAll?tid="${songer.mtype.tid}>${songer.mtype.tname}</a></td></tr><tr><td width="56" valign="top" class="item">档案:</td><td valign="top"><div class="record">${songer.intro}</div></td></tr></tbody></table></div><div id="artist_photo"><a id="cover_lightbox"href="#" target="_blank"title="${songer.srname}" data-lightbox="lightbox"> <imgsrc="${filePath}${songer.pic}"alt="${songer.srname}"/></a></div>

至此,一个哈哈音乐项目就全部完成啦!!!

相关文章:

SSM项目实战——哈哈音乐(四)前台模块开发

1、项目准备 ①导入依赖和前端资源 <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.x…...

Hadoop-入门

资料来源&#xff1a;尚硅谷-Hadoop 一、Hadoop 概述 1.1 Hadoop 是什么 1&#xff09;Hadoop是一个由Apache基金会所开发的分布式系统基础架构。 2&#xff09;主要解决&#xff1a;海量数据的存储和海量数据的分析计算问题。 3&#xff09;广义上来说&#xff0c;Hadoop…...

HarmonyOS(鸿蒙)——单击事件

2.4 实现ClickedListener接口并重写onClick方法 2.5 实现onClick方法中的具体逻辑&#xff0c;以此完成点击事件的相关业务操作 三、测试 3.1 登录远程模拟器 3.2 运行项目 四、精选好文 一、简介 1.1 什么是组件 组件就是文本、按钮、图片等元素的统称 1.2 什么是事件 …...

c# wpf template itemtemplate+dataGrid

1.概要 2.代码 <Window x:Class"WpfApp2.Window8"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d"http://schemas.microsoft.com/expression/blend…...

总结UDP协议各类知识点

前言 本篇博客博主将详细地介绍UDP有关知识点&#xff0c;坐好板凳发车啦~ 一.UDP特点 1.无连接 UDP传输的过程类似于发短信&#xff0c;知道对端的IP和端口号就直接进行传输&#xff0c;不需要建立连接&#xff1b; 2.不可靠传输 没有任何的安全机制&#xff0c;发送端发…...

设计模式 --5观察者模式

观察者模式 观察者模式的优缺点 优点 当一个对象改变的时候 需要同时改变其他对象的相关动作的时候 &#xff0c;而且它不知道有多少具体的对象需要改变 应该考虑使用观察者模式 。观察者模式的工作就是解除耦合 让耦合双方都依赖与抽象 而不是具体 是的各自改变都不会影响另…...

跨平台的组播测试工具mping、udp_sender及udp_reciver的源码及使用教程

文章目录 1.前言2.mping工具编译3.mping工具使用3.1 参数说明3.1 组播播发&#xff08;-s&#xff09;3.1 组播播发&#xff08;-r&#xff09;3.3 Linux下mping测试 4.Linux组播udp_sender及udp_reciver使用4.1 udp_sender源码4.1 udp_reciver源码4.3 编译方法4.4 测试使用4.4…...

Linux基础篇:文件系统介绍——根目录下文件夹含义与作用介绍

Linux文件系统介绍——文件夹含义与作用 Linux文件系统是一个组织和管理文件的层次结构。它包括了目录、子目录和文件&#xff0c;这些都是按照一定的规则和标准进行组织的。以下是Linux文件系统的一些关键组成部分&#xff1a; 1./bin&#xff1a; 该目录包含了系统启动和运…...

vulhub中Apache Solr RemoteStreaming 文件读取与SSRF漏洞复现

Apache Solr 是一个开源的搜索服务器。在Apache Solr未开启认证的情况下&#xff0c;攻击者可直接构造特定请求开启特定配置&#xff0c;并最终造成SSRF或任意文件读取。 访问http://your-ip:8983即可查看Apache Solr后台 1.访问http://your-ip:8983/solr/admin/cores?indexI…...

PHP在线加密系统网站源码

源码介绍 PHP在线加密系统网站源码&#xff0c;这个是sg的加密,免费可用(目前)并不会收费 源码说明&#xff1a;下载直接上传即可 下载地址 蓝奏云下载&#xff1a;https://wfr.lanzout.com/i6c331togiji...

【C++】哈希思想的应用(位图、布隆过滤器)及海量数据处理方法

文章目录 前言位图什么是位图简单实现一个自己的位图位图的应用场景 布隆过滤器位图的缺陷及布隆过滤器的提出布隆过滤器的概念简单实现一个自己的布隆过滤器布隆过滤器的优缺点布隆过滤器的应用场景 海量数据处理 前言 哈希思想的在实际中的应用除了哈希表这个数据结构之外还…...

蓝桥杯(5):python动态规划DF[2:背包问题]

1 0-1背包介绍【每件物品只能拿1件或者不拿】 1.1 简介 贪心是不可以的&#xff01;&#xff01;&#xff01; 1.2 状态 及状态转移 转移解释&#xff1a;要么不选 则上一个直接转移过来【dp[i-1][j]】&#xff0c;要么是选这个之后体积为j 则上一个对应的就是【dp[i-1][j-wi]…...

臻奶惠无人售货机:新零售时代的便捷消费革命

臻奶惠无人售货机&#xff1a;新零售时代的便捷消费革命 在新零售的浪潮中&#xff0c;智能无人售货机作为一个创新的消费模式&#xff0c;已经成为距离消费者最近的便捷购物点之一。这种模式不仅能够满足居民对消费升级的需求&#xff0c;还能通过建立多样化和多层次的消费体…...

4月04日,每日信息差

&#x1f396; 素材来源官方媒体/网络新闻 &#x1f384; 地震预警App被曝收10元年费&#xff0c;回应称仅限苹果系统 &#x1f30d; 2024清明档首日票房破2亿 &#x1f30b; 浙江省杭州市余杭区设立2亿元网络微短剧发展基金 &#x1f381; 抖音拟以超 7.5 亿元收购海联金汇旗下…...

C++数据结构——顺序表——数值统计

C数据结构——顺序表——数值统计 接着上一篇的顺序表模板。 输入数组&#xff0c;统计数组中的负数、零、正数的个数。第一个数字,表示数组有几个数,当n为0时&#xff0c;输入结束&#xff0c;不做处理。 例如&#xff1a; 输入6 0 1 2 3 -1 0 输出1 2 3 int main() {int n;…...

Linux+HA高可用24X7的安全保证

一&#xff0e; 介绍作为服务器&#xff0c;需要提供一定的24X7的安全保证&#xff0c;这样可以防止关键节点的宕机引起系统的全面崩溃。利用OpenSource开源软件&#xff0c;完成系统的高可靠双机热备方案。基于linux的 HA软件可靠稳定&#xff0c;比使用商业版本的HA软件降低成…...

【Tomcat】Apache官方结束Tomcat 8.5分支版本技术支持

根据 Apache 官方发布的声明&#xff0c;Apache官方将于2024年3月31日后正式结束对于Tomcat 8.5这个分支版本的技术支持&#xff0c;包括以下几点&#xff1a; 1&#xff09;不太可能继续为 8.5 分支发布新的版本&#xff1b; 2&#xff09;仅影响 8.5 分支的漏洞将不会被解决&…...

Go 源码之读写锁 sync.RWMutex

Go 源码之读写锁 sync.RWMutex 文章目录 Go 源码之读写锁 sync.RWMutex一、简介二、源码(一)RWMutex数据结构(二)Lock(三)Unlock(四)TryRLock(五)Rlock(六)RUnlock三、常见问题1. 什么是CAS,什么是原子操作2. 写操作是如何阻止写操作的3. 写操作是如何阻止读操作的…...

大数据实验统计-1、Hadoop安装及使用;2、HDFS编程实践;3、HBase编程实践;4、MapReduce编程实践

大数据实验统计 1、Hadoop安装及使用&#xff1b; 一&#xff0e;实验内容 Hadoop安装使用&#xff1a; 1&#xff09;在PC机上以伪分布式模式安装Hadoop&#xff1b; 2&#xff09;访问Web界面查看Hadoop信息。 二&#xff0e;实验目的 1、熟悉Hadoop的安装流程。 2、…...

PyTorch搭建Informer实现长序列时间序列预测

目录 I. 前言II. InformerIII. 代码3.1 输入编码3.1.1 Token Embedding3.1.2 Positional Embedding3.1.3 Temporal Embedding 3.2 Encoder与Decoder IV. 实验 I. 前言 前面已经写了很多关于时间序列预测的文章&#xff1a; 深入理解PyTorch中LSTM的输入和输出&#xff08;从i…...

脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)

一、数据处理与分析实战 &#xff08;一&#xff09;实时滤波与参数调整 基础滤波操作 60Hz 工频滤波&#xff1a;勾选界面右侧 “60Hz” 复选框&#xff0c;可有效抑制电网干扰&#xff08;适用于北美地区&#xff0c;欧洲用户可调整为 50Hz&#xff09;。 平滑处理&…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

python如何将word的doc另存为docx

将 DOCX 文件另存为 DOCX 格式&#xff08;Python 实现&#xff09; 在 Python 中&#xff0c;你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是&#xff0c;.doc 是旧的 Word 格式&#xff0c;而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

c#开发AI模型对话

AI模型 前面已经介绍了一般AI模型本地部署&#xff0c;直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型&#xff0c;但是目前国内可能使用不多&#xff0c;至少实践例子很少看见。开发训练模型就不介绍了&am…...

【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分

一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计&#xff0c;提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合&#xff1a;各模块职责清晰&#xff0c;便于独立开发…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列&#xff0c;以便知晓哪些列包含有价值的数据&#xff0c;…...

IP如何挑?2025年海外专线IP如何购买?

你花了时间和预算买了IP&#xff0c;结果IP质量不佳&#xff0c;项目效率低下不说&#xff0c;还可能带来莫名的网络问题&#xff0c;是不是太闹心了&#xff1f;尤其是在面对海外专线IP时&#xff0c;到底怎么才能买到适合自己的呢&#xff1f;所以&#xff0c;挑IP绝对是个技…...

毫米波雷达基础理论(3D+4D)

3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文&#xff1a; 一文入门汽车毫米波雷达基本原理 &#xff1a;https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...

「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案

在移动互联网营销竞争白热化的当下&#xff0c;推客小程序系统凭借其裂变传播、精准营销等特性&#xff0c;成为企业抢占市场的利器。本文将深度解析推客小程序系统开发的核心技术与实现路径&#xff0c;助力开发者打造具有市场竞争力的营销工具。​ 一、系统核心功能架构&…...

Android写一个捕获全局异常的工具类

项目开发和实际运行过程中难免会遇到异常发生&#xff0c;系统提供了一个可以捕获全局异常的工具Uncaughtexceptionhandler&#xff0c;它是Thread的子类&#xff08;就是package java.lang;里线程的Thread&#xff09;。本文将利用它将设备信息、报错信息以及错误的发生时间都…...