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>流派 :</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>热门 :</dt><dd><p><a href="#" ftype="isHot" value="" class="current">全部</a><a href="#" ftype="isHot" value="1">热门</a></p></dd></dl><dl><dt>新歌 :</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>流派 :</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>热门 :</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-入门
资料来源:尚硅谷-Hadoop 一、Hadoop 概述 1.1 Hadoop 是什么 1)Hadoop是一个由Apache基金会所开发的分布式系统基础架构。 2)主要解决:海量数据的存储和海量数据的分析计算问题。 3)广义上来说,Hadoop…...

HarmonyOS(鸿蒙)——单击事件
2.4 实现ClickedListener接口并重写onClick方法 2.5 实现onClick方法中的具体逻辑,以此完成点击事件的相关业务操作 三、测试 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有关知识点,坐好板凳发车啦~ 一.UDP特点 1.无连接 UDP传输的过程类似于发短信,知道对端的IP和端口号就直接进行传输,不需要建立连接; 2.不可靠传输 没有任何的安全机制,发送端发…...

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

跨平台的组播测试工具mping、udp_sender及udp_reciver的源码及使用教程
文章目录 1.前言2.mping工具编译3.mping工具使用3.1 参数说明3.1 组播播发(-s)3.1 组播播发(-r)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文件系统是一个组织和管理文件的层次结构。它包括了目录、子目录和文件,这些都是按照一定的规则和标准进行组织的。以下是Linux文件系统的一些关键组成部分: 1./bin: 该目录包含了系统启动和运…...

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

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

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

蓝桥杯(5):python动态规划DF[2:背包问题]
1 0-1背包介绍【每件物品只能拿1件或者不拿】 1.1 简介 贪心是不可以的!!! 1.2 状态 及状态转移 转移解释:要么不选 则上一个直接转移过来【dp[i-1][j]】,要么是选这个之后体积为j 则上一个对应的就是【dp[i-1][j-wi]…...

臻奶惠无人售货机:新零售时代的便捷消费革命
臻奶惠无人售货机:新零售时代的便捷消费革命 在新零售的浪潮中,智能无人售货机作为一个创新的消费模式,已经成为距离消费者最近的便捷购物点之一。这种模式不仅能够满足居民对消费升级的需求,还能通过建立多样化和多层次的消费体…...
4月04日,每日信息差
🎖 素材来源官方媒体/网络新闻 🎄 地震预警App被曝收10元年费,回应称仅限苹果系统 🌍 2024清明档首日票房破2亿 🌋 浙江省杭州市余杭区设立2亿元网络微短剧发展基金 🎁 抖音拟以超 7.5 亿元收购海联金汇旗下…...
C++数据结构——顺序表——数值统计
C数据结构——顺序表——数值统计 接着上一篇的顺序表模板。 输入数组,统计数组中的负数、零、正数的个数。第一个数字,表示数组有几个数,当n为0时,输入结束,不做处理。 例如: 输入6 0 1 2 3 -1 0 输出1 2 3 int main() {int n;…...

Linux+HA高可用24X7的安全保证
一. 介绍作为服务器,需要提供一定的24X7的安全保证,这样可以防止关键节点的宕机引起系统的全面崩溃。利用OpenSource开源软件,完成系统的高可靠双机热备方案。基于linux的 HA软件可靠稳定,比使用商业版本的HA软件降低成…...
【Tomcat】Apache官方结束Tomcat 8.5分支版本技术支持
根据 Apache 官方发布的声明,Apache官方将于2024年3月31日后正式结束对于Tomcat 8.5这个分支版本的技术支持,包括以下几点: 1)不太可能继续为 8.5 分支发布新的版本; 2)仅影响 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安装及使用; 一.实验内容 Hadoop安装使用: 1)在PC机上以伪分布式模式安装Hadoop; 2)访问Web界面查看Hadoop信息。 二.实验目的 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. 前言 前面已经写了很多关于时间序列预测的文章: 深入理解PyTorch中LSTM的输入和输出(从i…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...

(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...

20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)
引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...

【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看
文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...
BLEU评分:机器翻译质量评估的黄金标准
BLEU评分:机器翻译质量评估的黄金标准 1. 引言 在自然语言处理(NLP)领域,衡量一个机器翻译模型的性能至关重要。BLEU (Bilingual Evaluation Understudy) 作为一种自动化评估指标,自2002年由IBM的Kishore Papineni等人提出以来,…...
Leetcode33( 搜索旋转排序数组)
题目表述 整数数组 nums 按升序排列,数组中的值 互不相同 。 在传递给函数之前,nums 在预先未知的某个下标 k(0 < k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nu…...