typora-copy-images-to: img
day03-黑马旅游
学习目标
- 能够完成国内游数据列表分页查询
- 能够完成头部搜索框关键字搜索线路列表功能
- 能够完成查看旅游线路详情案例
- 能够完成添加收藏案例
- 能够完成查看我的收藏案例
第一章 国内游数据列表分页查询
1.1 需求分析
点击页面导航栏位置“国内游”后,分页显示符合数据的数据列表。
1.2 实现效果
1.3 实现分析
由于线路数据过多需要使用分页技术展示数据。页面上显示的分页结果可以分为两部分,分页数据和分页条。所以,这个查询分两部分实现:
- 分页数据实现:分页数据是从数据库中通过sql:
select * from tab_route limit n1,n2
。其中n1是起始记录数索引(startCount),n2是每页显示的数据量(pageSize); - 分页条实现:分页条中需要查询的数据是总记录数(totalCount),根据总记录数可以计算出总页数(totalPage)。总页数计算出来后便可遍历生成分页按钮和上一页以及下一页等数据;
由于分页功能实现结构比较复杂,我们学习需要分成静态分页实现、动态分页实现、优化PageBean工个步骤来实现。首先我们实现静态分页,所谓静态分页就是数据都是模拟的,并不是来自于数据库实现的分页效果模拟。
1.4 静态分页实现
1.4.1 分页数据查询
分页数据查询使用关键字limit
,需要两个参数:startCount
和 pageSize
。其中pageSize固定等于10,所以我们只需要考虑一个参数:startCount
。
但是,分页数据页面上传过来的是页数:pageNum
经过分析得出startCount的计算公式:startCount=(pageNum-1)*pageSize
。所以,前台传递参数pageNum
可实现分页查询。
SELECT * FROM tab_route;
# 每页显示10条数据(pageSize=10)
#第1页 起始条数startCount:0
SELECT * FROM tab_route LIMIT 0,10; #页数:1 -- 0
#第2页 起始条数startCount:10
SELECT * FROM tab_route LIMIT 10,10; #页数:2-- 10
#第3页 起始条数startCount:20
SELECT * FROM tab_route LIMIT 20,10; #页数:3 -- 20
# 结论: startCount = (pageNum-1)*pageSize;
1.4.2 静态查询前端实现
修改route_list.html页面,绑定点击事件修改如下:
<ul>
<li><a href="">首页</a></li>
<li class="threeword"><a href="#">上一页</a></li>
<li><a href="javascript:;" onclick="getPageData(1,8)">1</a></li>
<li><a href="javascript:;" onclick="getPageData(2,8)">2</a></li>
<li><a href="javascript:;" onclick="getPageData(3,8)">3</a></li>
<li><a href="javascript:;" onclick="getPageData(4,8)">4</a></li>
<li><a href="javascript:;" onclick="getPageData(5,8)">5</a></li>
<li><a href="javascript:;" onclick="getPageData(6,8)">6</a></li>
<li><a href="javascript:;" onclick="getPageData(7,8)">7</a></li>
<li><a href="javascript:;" onclick="getPageData(8,8)">8</a></li>
<li><a href="javascript:;" onclick="getPageData(9,8)">9</a></li>
<li><a href="javascript:;" onclick="getPageData(10,8)">10</a></li>
<li class="threeword"><a href="javascript:;">下一页</a></li>
<li class="threeword"><a href="javascript:;">末页</a></li>
</ul>
点击分页按钮后,触发函数getPageData(),在这个函数中发送请求,加载分页数据:
<script>
//加载分页数据
function getPageData(pageNum,pageSize) {
//发送异步请求加载分页数据
$.get("/routeServlet?methodName=routePageQuery",{pageSize:pageSize,pageNum:pageNum},function (pageData) {
console.log(pageData);
},"json");
}
</script>
1.4.3 静态查询后台实现
【web层】接收和响应数据—RouteServlet.java
/**
* 分页查询路线
* @param request
* @param response
* @throws Exception
*/
public void routePageQuery(HttpServletRequest request,HttpServletResponse response) throws Exception {
//1.获取请求数据
String strPageSize = request.getParameter("pageSize");
String strPageNum = request.getParameter("pageNum");
//2.处理数据
String jsonPageData = routeService.pageQuery(strPageNum, strPageSize);
//3.响应数据
response.getWriter().println(jsonPageData);
}
【service层】RouteService.java
String pageQuery(String strPageNum, String strPageSize);
【service层】RouteServiceImpl.java
引入依赖:commons-lang3 处理字符串:
<!--处理字符串的工具类-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
/**
* 分页查询路线
* @param strPageNum
* @param strPageSize
* @return
*/
public String pageQuery(String strPageNum, String strPageSize) {
//处理请求数据
int pageNum = 1;
int pageSize = 10;
if (StringUtils.isNoneBlank(strPageNum)) {
pageNum = Integer.valueOf(strPageNum);
}
if (StringUtils.isNotBlank(strPageSize)) {
pageSize = Integer.valueOf(strPageSize);
}
//计算起始记录数
int startCount = (pageNum - 1) * pageSize;
//调用dao层查询数据
List<Route> routeList = routeDao.pageQuery(startCount, pageSize);
//封装数据并返回
Map<String, Object> pageResult = new HashMap<>();
pageResult.put("data", routeList);
String jsonPageData = JSON.toJSONString(pageResult);
return jsonPageData;
}
【dao层】RouteDao.java
List<Route> pageQuery(int startCount, int pageSize);
【dao层】RouteDaoImpl.java
/**
* 分页查询旅游线路
* @param startCount
* @param pageSize
* @return
*/
@Override
public List<Route> pageQuery(int startCount, int pageSize) {
String sql = "SELECT * FROM tab_route WHERE rflag = 1 LIMIT ?,?";
return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Route.class), startCount, pageSize);
}
【前端】解析分页数据—route_list.html
第一步:删除页面死数据,给ul添加id
第二步:解析数据,填充页面
<script>
//加载分页数据
function getPageData(pageNum,pageSize) {
//发送异步请求加载分页数据
$.get("routeServlet?methodName=routePageQuery",{pageSize:pageSize,pageNum:pageNum},function (pageData) {
console.log(pageData);
if(pageData) {
//获取分页数据
var routeList = pageData.data;
var routeHtml = "";
//解析数据
$(routeList).each(function (index, route) {
routeHtml+= '<li>\n' +
'<div class="img"><img src='+route.rimage+' alt=""></div>\n' +
'<div class="text1">\n' +
'<p>'+route.rname+'</p>\n' +
'<br/>\n' +
'<p>'+route.routeIntroduce+'</p>\n' +
'</div>\n' +
'<div class="price">\n' +
'<p class="price_num">\n' +
'<span>¥</span>\n' +
'<span>'+route.price+'</span>\n' +
'<span>起</span>\n' +
'</p>\n' +
'<p><a href="route_detail.html">查看详情</a></p>\n' +
'</div>\n' +
'</li>';
});
$("#routePageList").html(routeHtml);
}
},"json");
}
</script>
1.5 分页条实现
4.5.1 分页按钮实现
在上面的静态分页实现中,我们只在route_list.html写了10个a标签当做按钮。实际的页数可能不止10页,需要根据数据库中的数据量进行计算。
分页按钮栏中需要的数据:总页数 ,总记录数 。这两个数据需要通过后台的查询传递过来。具体实现如下:
【service层】RouteServiceImpl.java
在RouteServiceImpl的pageQuery方法中添加查询总记录数和计算总页数的逻辑。
【dao层】RouteDao.java
int queryTotalCount();
【dao层】RouteDaoImpl.java
/**
* @return
*/
@Override
public int queryTotalCount() {
String sql = "SELECT COUNT(*) FROM tab_route WHERE rflag=1 ";
Integer totalCount = null;
try {
totalCount = jdbcTemplate.queryForObject(sql, Integer.class);
} catch (DataAccessException e) {
totalCount = 0;
}
return totalCount;
}
【前端】解析分页数据
把总页数,总条数删除。分别给总页数和总条数的span添加id属性值。
【解析数据】
【动态生成分页按钮】
<script>
//页面加载完成后 默认查询第一页的数据
$(function () {
getPageData(1, 8);
});
//加载分页数据
function getPageData(pageNum,pageSize) {
//发送异步请求加载分页数据
$.get("routeServlet?methodName=routePageQuery",{pageSize:pageSize,pageNum:pageNum},function (pageData) {
console.log(pageData);
if(pageData) {
//获取分页数据
var routeList = pageData.data;
var routeHtml = "";
//解析数据
$(routeList).each(function (index, route) {
routeHtml+= '<li>\n' +
'<div class="img"><img src='+route.rimage+' alt=""></div>\n' +
'<div class="text1">\n' +
'<p>'+route.rname+'</p>\n' +
'<br/>\n' +
'<p>'+route.routeIntroduce+'</p>\n' +
'</div>\n' +
'<div class="price">\n' +
'<p class="price_num">\n' +
'<span>¥</span>\n' +
'<span>'+route.price+'</span>\n' +
'<span>起</span>\n' +
'</p>\n' +
'<p><a href="route_detail.html">查看详情</a></p>\n' +
'</div>\n' +
'</li>';
});
$("#routePageList").html(routeHtml);
//拼接分页条
var totalCout = pageData.totalCount;
var totalPage = pageData.totalPage;
$("#totalCountSpan").html(totalCout);
$("#totalPageSpan").html(totalPage);
var pageLineHtml= '<li><a href="javascript:;" >首页</a></li>\n' +
'<li class="threeword"><a href="javascript:;" >上一页</a></li>';
for (var i = 1;i<=totalPage;i++) {
if(pageNum == i){
pageLineHtml+='<li class="curPage"><a href="javascript:;" οnclick="getPageData('+i+',8)">'+i+'</a></li>';
}else{
pageLineHtml+='<li><a href="javascript:;" οnclick="getPageData('+i+',8)">'+i+'</a></li>';
}
}
pageLineHtml+='<li class="threeword"><a href="javascript:;">下一页</a></li>\n' +
' <li class="threeword"><a href="javascript:;" >末页</a></li>';
$("#pageLine").html(pageLineHtml);
}
},"json");
}
</script>
【实现效果】
4.5.2 分页按钮优化
在上面的实现中,分页数据比较多的时候,生成的分页按钮太多,在页面上显示也不是太好。下面就仿照百度的分页条(总共显示10个分页按钮,前5后4)实现。
观察数字分页进行分析
显示的数字只要计算出起始页和结束页就可以显示出来,假如begin为起始页和end为结束也
- 如果总页数<=10,那么
begin=1
end=totalPage - 如果总页数>10,那么
begin=curPage-5;
end=curPage+4;
由于有加减计算,begin和end计算出来的结果就有可能越界,所以我们需要判断边界
如果,begin<1
begin=1;
end=10;
如果,end>totalPage总页数
end=totalPage;
begin=totalPage-9;
将原来的遍历分页数字数据代码注释,在其下面添加如下代码:
【完整代码】route_list.html
<script>
$(function () {
getPageData(1, 8);
});
//加载分页数据
function getPageData(pageNum,pageSize) {
//发送异步请求加载分页数据
$.get("/routeServlet?methodName=routePageQuery",{pageSize:pageSize,pageNum:pageNum},function (pageData) {
console.log(pageData);
if(pageData) {
//获取分页数据
var routeList = pageData.data;
var routeHtml = "";
//解析数据
$(routeList).each(function (index, route) {
routeHtml+= '<li>\n' +
'<div class="img"><img src='+route.rimage+' alt=""></div>\n' +
'<div class="text1">\n' +
'<p>'+route.rname+'</p>\n' +
'<br/>\n' +
'<p>'+route.routeIntroduce+'</p>\n' +
'</div>\n' +
'<div class="price">\n' +
'<p class="price_num">\n' +
'<span>¥</span>\n' +
'<span>'+route.price+'</span>\n' +
'<span>起</span>\n' +
'</p>\n' +
'<p><a href="route_detail.html">查看详情</a></p>\n' +
'</div>\n' +
'</li>';
});
$("#routePageList").html(routeHtml);
//拼接分页条
var totalCout = pageData.totalCount;
var totalPage = pageData.totalPage;
$("#totalCountSpan").html(totalCout);
$("#totalPageSpan").html(totalPage);
//动态生成分页按钮
var begin;
var end;
if(totalPage<10){
begin = 1;
end = totalPage;
}else{
begin = pageNum-5;
end = pageNum+4;
//控制起始按钮
if(begin<1) {
begin=1;
end=10;
}
//控制结束按钮
if(end>totalPage) {
end = totalPage;
begin=totalPage-9;
}
}
var pageLineHtml= '<li><a href="javascript:;" >首页</a></li>\n' +
'<li class="threeword"><a href="javascript:;" >上一页</a></li>';
for (var i = begin;i<=end;i++) {
if(pageNum == i){
pageLineHtml+='<li class="curPage"><a href="javascript:;" οnclick="getPageData('+i+',8)">'+i+'</a></li>';
}else{
pageLineHtml+='<li><a href="javascript:;" οnclick="getPageData('+i+',8)">'+i+'</a></li>';
}
}
pageLineHtml+='<li class="threeword"><a href="javascript:;">下一页</a></li>\n' +
' <li class="threeword"><a href="javascript:;" >末页</a></li>';
$("#pageLine").html(pageLineHtml);
}
},"json");
}
</script>
4.5.3 完善首页,末页,上一页和下一页
在RouteService的pageQuery方法中计算上一页和下一页,并将数据封装到pageResult中。
route_list.html中获取上一页和下一页数据,并将其拼接到a标签的链接中。
【首页和上一页】
var pageLineHtml= '<li><a href="javascript:;" onclick="getPageData(1,8)">首页</a></li>\n' +
'<li class="threeword"><a href="javascript:;" onclick="getPageData('+prePage+',8)">上一页</a></li>';
【下一页和末页】
pageLineHtml+='<li class="threeword"><a href="javascript:;" onclick="getPageData('+nextPage+',8)">下一页</a></li>\n' +
' <li class="threeword"><a href="javascript:;" onclick="getPageData('+totalPage+',8)">末页</a></li>';
$("#pageLine").html(pageLineHtml);
1.6 根据路线类别分页查询
当我们点击导航栏上的线路类别查询线路时,页面应该根据路线的类别加载路线的分页数据。具体实现如下:
1.6.1 修改商品类别链接
在header.html页面,动态拼接category列表数据时,url后面拼接cid。
$(function () {
//加载类别列表信息
$.get("categoryServlet?methodName=queryAllCategory",function (result) {
console.log(result);
//遍历categoryList数组
var categoryHtml = "<li class='nav‐active'><a href='index.html'>首页</a></li>";
if(result){
$(result).each(function (index, element) {
categoryHtml+=' <li><a href="route_list.html?cid='+element.cid+'">'+element.cname+'</a></li>';
});
}
categoryHtml+="<li><a href='favoriterank.html'>收藏排行榜</a></li>";
//把拼接的数据插入到ul中
$(categoryHtml).appendTo($("#categoryList"));
},"json");
});
当我们点击线路类别时,请求的地址如下:
1.6.2 根据添加查询条件cid
当点击导航栏上的任意一个路线分类时,都会跳转到route_list页面,同时会将类别id—cid传递到route_list页面。所以,需要在route_list.html页面加载完成后,立即加载分页数据。
【前端】route_list.html
引入getParameter.js文件。使用getParameter方法,获取地址栏后面传入的参数。
页面跳转到route_list.html后,获取cid,将cid传递到分页查询的方法中作为一个条件:
分页查询方法:getPageData()增加一个参数 cid
【web层】RouteServlet.java
/**
* 分页查询路线
* @param request
* @param response
* @throws Exception
*/
public void routePageQuery(HttpServletRequest request,HttpServletResponse response) throws Exception {
//1.获取请求数据
String strPageSize = request.getParameter("pageSize");
String strPageNum = request.getParameter("pageNum");
String cid = request.getParameter("cid");
//2.处理数据
String jsonPageData = routeService.pageQuery(strPageNum, strPageSize,cid);
//3.响应数据
response.getWriter().println(jsonPageData);
}
【service层】RouteService.java
String pageQuery(String strPageNum, String strPageSize,String cid);
【service层】RouteServiceImpl.java
/**
* 分页查询路线
* @param strPageNum
* @param strPageSize
* @return
*/
public String pageQuery(String strPageNum, String strPageSize,String cid) {
//处理请求数据
int pageNum = 1;
int pageSize = 10;
if (StringUtils.isNotBlank(strPageNum)) {
pageNum = Integer.valueOf(strPageNum);
}
if (StringUtils.isNotBlank(strPageSize)) {
pageSize = Integer.valueOf(strPageSize);
}
//计算起始记录数
int startCount = (pageNum - 1) * pageSize;
//查询分页数据
List<Route> routeList = routeDao.pageQuery(startCount, pageSize,cid);
//查询总记录数
int totalCount = routeDao.queryTotalCount(cid);
//计算总页数
int totalPage = totalCount%pageSize==0?totalCount/pageSize:totalCount/pageSize+1;
//计算上一页
int prePage = pageNum==1?1:pageNum-1;
//计算下一页
int nextPage = pageNum==totalPage?totalPage:pageNum-1;
//封装数据并返回
Map<String, Object> pageResult = new HashMap<>();
pageResult.put("data", routeList);
pageResult.put("totalCount", totalCount);
pageResult.put("totalPage", totalPage);
pageResult.put("prePage", prePage);
pageResult.put("nextPage", nextPage);
String jsonPageData = JSON.toJSONString(pageResult);
return jsonPageData;
}
【dao层】RouteDao.java
【dao层】RouteDaoInpl.java
动态拼接查询条件和查询参数
第二章 头部搜索旅游线路数据分页展现
2.1 需求分析
点击网页头部搜索框输入旅游线路名称,点击搜索安全进行模糊搜索,符合条件的结果进行分页展现数据列表。
2.2 实现效果
2.3 实现分析
2.4 实现步骤
- header.html代码,点击搜索框提交搜索关键字跳转到rout_list.html并传递cid和搜索关键字
- route_list.html代码,获取搜索关键字,并提交到分页查询数据请求中,保证每个分页请求都要增加搜索内
容提交请求参数。 - RouteServlet.java代码,获取到搜索内容数据,并查询分页数据方法增加搜索内容参数传递。
- RouteService.java代码,获取总记录数据和当前页数据列表方法中增加搜索内容参数传递。
- RouteDao.java及RouteDaoImpl代码,获取总记录数增加搜索内容数据条件过滤,获取当前页数据列表增加搜索内容数据条件
过滤。
2.5 实现代码
2.5.1 步骤1:header.html代码
点击搜索框提交搜索内容跳转到rout_list.html并传递cid和搜索内容:给输入框添加id属性值searchKey,给按钮绑定点击事件searchByRname();
点击搜索后跳转到route_list.html页面,同时把请求参数cid和rname传递过去。
//根据关键字搜索
function searchByRname() {
//首先获取关键字
var rname = $("#rname").val();
alert("根据" + rname + "搜索");
//跳转到route_list.html即可
location.href = "route_list.html?rname=" + rname;
}
2.5.2 步骤2:route_list.html代码
获取搜索内容数据,并提交到分页查询数据请求中,保证每个分页请求都要增加搜索内容提交请求参数。
修改route_list.html页面加载后的查询链接地址:getPageData方法中获取rname参数。
2.5.3 步骤3:RouteServlet.java代码
在RouteServlet.java中获取参数rname,并通过rname模糊查询数据。
2.5.4 步骤4:RouteService.java代码
获取总记录数据和当前页数据列表方法中增加搜索内容参数传递
/**
* 分页查询路线
* @param strPageNum
* @param strPageSize
* @return
*/
public String pageQuery(String strPageNum, String strPageSize,String cid,String rname) {
//处理请求数据
int pageNum = 1;
int pageSize = 10;
if (StringUtils.isNoneBlank(strPageNum)) {
pageNum = Integer.valueOf(strPageNum);
}
if (StringUtils.isNotBlank(strPageSize)) {
pageSize = Integer.valueOf(strPageSize);
}
//计算起始记录数
int startCount = (pageNum - 1) * pageSize;
//查询分页数据
List<Route> routeList = routeDao.pageQuery(startCount, pageSize,cid,rname);
//查询总记录数
int totalCount = routeDao.queryTotalCount(cid,rname);
//计算总页数
int totalPage = totalCount%pageSize==0?totalCount/pageSize:totalCount/pageSize+1;
//计算上一页
int prePage = pageNum==1?1:pageNum-1;
//计算下一页
int nextPage = pageNum==totalPage?totalPage:pageNum-1;
//封装数据并返回
Map<String, Object> pageResult = new HashMap<>();
pageResult.put("data", routeList);
pageResult.put("totalCount", totalCount);
pageResult.put("totalPage", totalPage);
pageResult.put("prePage", prePage);
pageResult.put("nextPage", nextPage);
String jsonPageData = JSON.toJSONString(pageResult);
return jsonPageData;
}
2.5.5 步骤5:RouteDao.java代码
获取总记录数增加搜索内容数据条件过滤,获取当前页数据列表增加搜索内容数据条件过滤。
【代码】
List<Route> pageQuery(int startCount, int pageSize,String cid,String rname);
int queryTotalCount(String cid,String rname);
2.5.6 步骤6:RouteDaoImpl.java代码
获取总记录数增加搜索内容数据条件过滤,获取当前页数据列表增加搜索内容数据条件过滤。
【查询分页数据】
/**
* 分页查询旅游线路
* @param startCount
* @param pageSize
* @return
*/
@Override
public List<Route> pageQuery(int startCount, int pageSize,String cid,String rname) {
// String sql = "SELECT * FROM tab_route WHERE rflag = 1 LIMIT ?,?";
// return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Route.class), startCount, pageSize);
//动态拼接sql
StringBuilder sb = new StringBuilder("SELECT * FROM tab_route WHERE rflag = 1 ");
//动态拼接查询参数
List<Object> params = new ArrayList<>();
if (StringUtils.isNotBlank(cid)) {
sb.append(" AND cid = ?");
params.add(cid);
}
if (StringUtils.isNotBlank(rname)) {
sb.append(" AND rname LIKE ?");
params.add("%" + rname + "%");
}
sb.append(" LIMIT ?,?");
params.add(startCount);
params.add(pageSize);
return jdbcTemplate.query(sb.toString(), new BeanPropertyRowMapper<>(Route.class), params.toArray());
}
【查询分页记录数】
@Override
public int queryTotalCount(String cid,String rname) {
// String sql = "SELECT COUNT(*) FROM tab_route WHERE rflag=1 ";
// Integer totalCount = null;
// try {
// totalCount = jdbcTemplate.queryForObject(sql, Integer.class);
// } catch (DataAccessException e) {
// totalCount = 0;
// }
// return totalCount;
//动态拼接sql
StringBuilder sb = new StringBuilder("SELECT COUNT(*) FROM tab_route WHERE rflag=1 ");
//动态拼接查询参数
List<Object> params = new ArrayList<>();
if (StringUtils.isNotBlank(cid)) {
sb.append(" AND cid = ?");
params.add(cid);
}
if (StringUtils.isNotBlank(rname)) {
sb.append(" AND rname LIKE ?");
params.add("%" + rname + "%");
}
try {
return jdbcTemplate.queryForObject(sb.toString(), Integer.class, params.toArray());
} catch (DataAccessException e) {
e.printStackTrace();
return 0;
}
}
2.5.7 步骤7:优化–将搜索关键字回显到搜索框中
header.html中,页面加载完成之后,获取URL中的rname。将其回显到搜索框中。
$(function () {
var rname = getParameter("rname");
if(rname) {
rname = decodeURI(rname);
//优化---将rname回显到搜索框中
$("#rname").val(rname);
}
});
第三章 查看旅游线路详情
3.1 案例需求
点击route_list.html搜索列表中旅游线路的“查看详情”进入route_detail.html旅游线路详情页面并显示相关数据
3.2 实现效果
3.3 实现分析
3.4 实现步骤
- route_list.html代码,route_list.html旅游线路列表页面中每个旅游线路的“查看详情”,点击请求跳转到
route_detail.html旅游线路详情页面,并传递旅游线路标识符rid=X; - route_detail.html代码,route_detail.html旅游线路详情页面获取传过来的rid数据,并提交异步请求到
RouteServlet获取当前旅游线路对象数据,并传递requestMethod请求类型和rid线路的标识符数据。获取到web后端servlet返回的数据之后,进行解析将返回的数据更新数据到详情页面上指定的位置。 - RouteServlet.java代码,RouteServlet是后端处理根据rid获的旅游线路对象数据的请求,首先获取rid数据,
并调用业务类RouteService的相关方法实现获取旅游线路数据业务。 - RouteService.java代码,RouteService业务类根据传递过来的rid数据调用数据访问类RouteDao相关方法实
现数据库获取Route旅游线路对象数据,之后根据rid还要获取当前旅游线路的图片列表数据封装到Route对象
中。最后返回Route对象给业务类RouteService。 - RouteDao.java代码,RouteDao数据访问类根据rid获取tab_route表当前旅游线路数据、tab_category表当
前旅游线路所属分类数据和tab_route_img表当前旅游线路所属图片列表数据。
3.5 实现代码
步骤1:route_list.html代码
route_list.html旅游线路列表页面中每个旅游线路的“查看详情”,点击请求跳转到route_detail.html旅游线路详情页面,并传递旅游线路标识符rid=X;
[外链图片转存失败(img-JNZLvdNn-1562519704443)(img/1537348995855.png)]
步骤2:route_detail.html代码
route_detail.html旅游线路详情页面获取传过来的rid数据,并提交异步请求到RouteServlet获取当前旅游线路对象数据,并传递action请求类型和rid线路的标识符数据。获取到web后端servlet返回的数据之后,进行解析将返回的数据更新数据到详情页面上指定的位置。
【前端】route_detail.html
引入getParameter.js文件
<script src="js/getParameter.js"></script>
页面加载完成后,立即加载路线详情数据。
//在页面加载完成之后,根据rid查询线路详情
$(function () {
var rid = getParameter("rid");
//向后台发请求 rid
$.get("routeServlet?methodName=queryRouteDetail",{rid:rid},function(result){
console.log(result);
},"json");
});
步骤3:RouteServlet.java代码
RouteServlet是后端处理根据rid获的旅游线路对象数据的请求,首先获取rid数据,并调用业务类RouteService的
相关方法实现获取旅游线路数据业务。
/**
* 根据rid查询线路详情
* @param request
* @param response
* @throws IOException
*/
private void queryRouteDetail(HttpServletRequest request, HttpServletResponse response) throws IOException {
//1、接收请求数据
String rid = request.getParameter("rid");
//2、处理数据--查询
String detailJson = routeService.queryRouteDetailByRid(rid);
//3、响应数据--文本
response.getWriter().println(detailJson);
}
步骤4:RouteService.java代码
RouteService业务类根据传递过来的rid数据调用数据访问类RouteDao相关方法实现数据库获取Route旅游线路对
象数据,之后根据rid还要获取当前旅游线路的图片列表数据封装到Route对象中。最后返回Route对象给业务类
RouteService。
String queryRouteDetailByRid(String rid);
【实现类】
/**
* 根据rid查询线路详情
* @param rid
* @return
*/
@Override
public String queryRouteDetailByRid(String rid) {
//1、详情信息
Map<String,Object> detail = routeDao.queryDetailByRid(rid);
//2、详情图片查询
List<RouteImg> imgList = routeDao.queryImgByRid(rid);
detail.put("imgList", imgList);
//把map转换成JSON字符串
String jsonString = JSON.toJSONString(detail);
return jsonString;
}
步骤5:RouteDao.java代码
RouteDao数据访问类根据rid获取tab_route表当前旅游线路数据、tab_category表当前旅游线路所属分类数据和
tab_route_img表当前旅游线路所属图片列表数据。
Map<String,Object> queryDetailByRid(String rid);
List<RouteImg> queryImgByRid(String rid);
【实现类】
/**
* 查询详情基本信息---多表关联查询
* @param rid
* @return
*/
@Override
public Map<String, Object> queryDetailByRid(String rid) {
String sql = "SELECT * FROM tab_route tbr INNER JOIN tab_category tbc ON tbr.cid=tbc.cid INNER JOIN tab_seller tbs ON tbr.sid=tbs.sid WHERE tbr.rid=?";
try {
Map<String, Object> map = jdbcTemplate.queryForMap(sql, rid);
return map;
} catch (DataAccessException e) {
return null;
}
}
/**
* 查询线路图片
* @param rid
* @return
*/
@Override
public List<RouteImg> queryImgByRid(String rid) {
String sql = "SELECT * FROM tab_route_img WHERE rid=?";
return jdbcTemplate.query(sql,new BeanPropertyRowMapper<>(RouteImg.class),rid);
}
步骤6:route_detail.html解析数据
前端页面得到的数据格式如下,我们可以根据这个数据格式进行解析;
第一步:删除页面上的html数据
给上述死数据删除后,分别给span和p标签添加id属性值,以便填充数据:
第二步:解析查询到的详情数据
【填充大图片】
//拼接大图片
var bigImgHtml = '<img alt="" class="big_img" src='+result.rimage+'>';
$("#bigImg").html(bigImgHtml);
【填充小图片】
//拼接小图片
var littleImgHtml = '<a class="up_img up_img_disable"></a>';
var imgList = result.imgList;
$(imgList).each(function (index,element) {
if(index<=3){
littleImgHtml+=' <a title="" class="little_img cur_img" data-bigpic='+element.bigPic+'>\n' +
' <img src='+element.smallPic+'>\n' +
' </a>';
}else{
littleImgHtml+=' <a title="" class="little_img cur_img" data-bigpic='+element.bigPic+' style="display:none">\n' +
' <img src='+element.smallPic+'>\n' +
' </a>';
}
});
littleImgHtml+='<a class="down_img down_img_disable" style="margin-bottom: 0;"></a>';
$("#littleImg").html(littleImgHtml);
//触发图片动画
imgGo();
【注意】imgGo方法要定义在页面加载事件之外。
function imgGo() {
//焦点图效果
//点击图片切换图片
$('.little_img').on('mousemove', function() {
$('.little_img').removeClass('cur_img');
var big_pic = $(this).data('bigpic');
$('.big_img').attr('src', big_pic);
$(this).addClass('cur_img');
});
//上下切换
var picindex = 0;
var nextindex = 4;
$('.down_img').on('click',function(){
var num = $('.little_img').length;
if((nextindex + 1) <= num){
$('.little_img:eq('+picindex+')').hide();
$('.little_img:eq('+nextindex+')').show();
picindex = picindex + 1;
nextindex = nextindex + 1;
}
});
$('.up_img').on('click',function(){
var num = $('.little_img').length;
if(picindex > 0){
$('.little_img:eq('+(nextindex-1)+')').hide();
$('.little_img:eq('+(picindex-1)+')').show();
picindex = picindex - 1;
nextindex = nextindex - 1;
}
});
}
【填充其他信息】
//拼接详细信息--文字
$("#routeNameP").html(result.rname);
$("#routeIntroduceP").html(result.routeIntroduce);
$("#sellerNameP").html("商家名称:"+result.sname);
$("#sellerPhoneP").html("联系电话"+result.consphone);
$("#sellerAddrP").html("商家地址"+result.address);
$("#routeCountS").html("已收藏"+result.count+"次");
$("#routePriceS").html("¥"+result.price);
//种类
$("#categoryHtml").html(result.cname);
$("#headerRname").html(result.rname);
【完整代码】
//在页面加载完成之后,根据rid查询线路详情
$(function () {
var rid = getParameter("rid");
//向后台发请求 rid
$.get("routeServlet?methodName=queryRouteDetail",{rid:rid},function(result){
console.log(result);
//拼接大图片
var bigImgHtml = '<img alt="" class="big_img" src='+result.rimage+'>';
$("#bigImg").html(bigImgHtml);
//拼接小图片
var littleImgHtml = '<a class="up_img up_img_disable"></a>';
var imgList = result.imgList;
$(imgList).each(function (index,element) {
if(index<=3){
littleImgHtml+=' <a title="" class="little_img cur_img" data-bigpic='+element.bigPic+'>\n' +
' <img src='+element.smallPic+'>\n' +
' </a>';
}else{
littleImgHtml+=' <a title="" class="little_img cur_img" data-bigpic='+element.bigPic+' style="display:none">\n' +
' <img src='+element.smallPic+'>\n' +
' </a>';
}
});
littleImgHtml+='<a class="down_img down_img_disable" style="margin-bottom: 0;"></a>';
$("#littleImg").html(littleImgHtml);
imgGo();
//拼接详细信息--文字
$("#routeNameP").html(result.rname);
$("#routeIntroduceP").html(result.routeIntroduce);
$("#sellerNameP").html("商家名称:"+result.sname);
$("#sellerPhoneP").html("联系电话"+result.consphone);
$("#sellerAddrP").html("商家地址"+result.address);
$("#routeCountS").html("已收藏"+result.count+"次");
$("#routePriceS").html("¥"+result.price);
//种类
$("#categoryHtml").html(result.cname);
$("#headerRname").html(result.rname);
},"json");
});
function imgGo() {
//焦点图效果
//点击图片切换图片
$('.little_img').on('mousemove', function() {
$('.little_img').removeClass('cur_img');
var big_pic = $(this).data('bigpic');
$('.big_img').attr('src', big_pic);
$(this).addClass('cur_img');
});
//上下切换
var picindex = 0;
var nextindex = 4;
$('.down_img').on('click',function(){
var num = $('.little_img').length;
if((nextindex + 1) <= num){
$('.little_img:eq('+picindex+')').hide();
$('.little_img:eq('+nextindex+')').show();
picindex = picindex + 1;
nextindex = nextindex + 1;
}
});
$('.up_img').on('click',function(){
var num = $('.little_img').length;
if(picindex > 0){
$('.little_img:eq('+(nextindex-1)+')').hide();
$('.little_img:eq('+(picindex-1)+')').show();
picindex = picindex - 1;
nextindex = nextindex - 1;
}
});
}
第四章 今日作业
- 能够完成国内游线路分页查询;
- 能够完成头部关键字搜索旅游线路功能;
- 能够完成线路详情查询功能;