当前位置: 首页 > 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…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度​

一、引言&#xff1a;多云环境的技术复杂性本质​​ 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时&#xff0c;​​基础设施的技术债呈现指数级积累​​。网络连接、身份认证、成本管理这三大核心挑战相互嵌套&#xff1a;跨云网络构建数据…...

Chapter03-Authentication vulnerabilities

文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

Flask RESTful 示例

目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题&#xff1a; 下面创建一个简单的Flask RESTful API示例。首先&#xff0c;我们需要创建环境&#xff0c;安装必要的依赖&#xff0c;然后…...

简易版抽奖活动的设计技术方案

1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

Java 8 Stream API 入门到实践详解

一、告别 for 循环&#xff01; 传统痛点&#xff1a; Java 8 之前&#xff0c;集合操作离不开冗长的 for 循环和匿名类。例如&#xff0c;过滤列表中的偶数&#xff1a; List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

Robots.txt 文件

什么是robots.txt&#xff1f; robots.txt 是一个位于网站根目录下的文本文件&#xff08;如&#xff1a;https://example.com/robots.txt&#xff09;&#xff0c;它用于指导网络爬虫&#xff08;如搜索引擎的蜘蛛程序&#xff09;如何抓取该网站的内容。这个文件遵循 Robots…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)

文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

QT: `long long` 类型转换为 `QString` 2025.6.5

在 Qt 中&#xff0c;将 long long 类型转换为 QString 可以通过以下两种常用方法实现&#xff1a; 方法 1&#xff1a;使用 QString::number() 直接调用 QString 的静态方法 number()&#xff0c;将数值转换为字符串&#xff1a; long long value 1234567890123456789LL; …...

蓝桥杯3498 01串的熵

问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798&#xff0c; 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...