我的收藏
分析
先登录→拿到当前登录的用户信息,从数据库中获取uid和对应uid的rid集合→将rid集合信息展示到我的收藏
前台代码
判断用户是否登录,传递uid,通过uid查找其对应的rid集合
当查询的属性涉及到多张表,则必须使用多表连接,此时子查询也不再适用
语法:
select 查询列表
from 表1 别名
【inner】 join 表2 别名 on 连接条件
where 筛选条件
group by 分组列表
having 分组后的筛选
order by 排序列表
limit 子句;
查询结果:
查询语句
SELECT *FROM tab_favorite f
INNER JOIN tab_route r on f.rid = r.rid
where uid=23;
后台代码
RouteServlet
/**
* 分页查询我的收藏
* 点击"我的收藏"展示该uid收藏的rid方法,收藏分页
*/
public void myFavorite(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取用户的uid和currentpage
String uidStr = request.getParameter("uid");
String currentPageStr = request.getParameter("currentPage");
int uid = Integer.parseInt(uidStr);
int currentPage = 1;
//处理参数
if (currentPageStr != null && currentPageStr.length() > 0) {
currentPage = Integer.parseInt(currentPageStr);
}
int pageSize = 4;
PageBean<Route> pb = favoriteService.myFavorite(uid, currentPage, pageSize);
writeValue(pb, response);
}
实体类中并无与tab_favorite表中对应的uid,rid,Date属性,
实体类Favorite只有
private Route route;//旅游线路对象
private String date;//收藏时间
private User user;//所属用户
这三个对象
于是为了和数据表对应,
创建MyFavorite实体类
/**
* @author 乱码酱
* @date :2023-02-15 20:43
* @program: hello_maven
* @create:创建tab_favorite表中对应的uid,rid,date属性
*/
public class MyFavorite {
private int uid;
private Date date;
private int rid;
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public int getRid() {
return rid;
}
public void setRid(int rid) {
this.rid = rid;
}
@Override
public String toString() {
return "MyFavorite{" +
"uid=" + uid +
", date=" + date +
", rid=" + rid +
'}';
}
}
FavoriteServiceImpl
通过分析PageBean可以得知:
totalCount总记录数 需要从数据库查询得到
currentPage当前页码 & pageSize每页显示的条数 这两条是通过客户端提交的
totalPage总页数 可以通过总记录数和每页显示的条数计算得到
所以在RouteDao上有以下方法声明:
*根据cid查询总的记录数
*根据cid,start,pageSize查询当前的数据集合
@Override //我的收藏
public PageBean<Route> myFavorite(int uid, int currentPage, int pageSize) {
//封装pagebean
PageBean<Route> pb = new PageBean<Route>();
//设置每页的大小
pb.setPageSize(pageSize);
//设置当前页(客户端提交的)
pb.setCurrentPage(currentPage);
//设置总记录数(数据库查询得到 )
int totalCount = myFavoriteDao.findMyFavoriteCount(uid);
pb.setTotalCount(totalCount);
//假如没有记录前台显示提示
if (totalCount == 0) {
return pb;
}
//开始的记录数,假设pageSize为5,,第2页是从5开始的
int start = (currentPage - 1) * pageSize;
//设置总页数(可以通过 总记录数/每页显示条数 计算得到)
int totalPage = (totalCount % pageSize == 0) ? (totalCount / pageSize) : (totalCount / pageSize + 1);
pb.setTotalPage(totalPage);
//将“我的收藏”以集合形式展示
List<MyFavorite> myFavoriteList = myFavoriteDao.myFavorite(uid, start, pageSize);
List<Route> routelist = new ArrayList<>();
//遍历出“我的收藏”中所有rid
for (MyFavorite myFavorite : myFavoriteList) {
//查出来的是每个用户的全部收藏路线
Integer rid = myFavorite.getRid();
//根据rid查找route
Route route = routeDao.findOne(rid);
//将route对象添加进list
routelist.add(route);
}
pb.setList(routelist);
return pb;
}
FavoriteDaoImpl
查询总记录数
查询语句
SELECT COUNT(*) FROM tab_favorite WHERE uid = 23;
查询结果
查询我的收藏
查询语句
-- 分页查询我的收藏
SELECT * FROM tab_favorite WHERE uid = 23 LIMIT 0,12;
SELECT * FROM tab_favorite WHERE uid = ? LIMIT ?,?;
其中limit后的两个问号,第一个表示从哪里开始,第二个表示查询多少个记录
查询结果
参考前面的RouteImpl代码
拼接没成功
@Override //将“我的收藏”以集合形式展示,分页查询我的收藏
public List<MyFavorite> myFavorite(int uid, int start, int pageSize) {
//1.定义sql模板
// String sql = "SELECT * FROM tab_favorite WHERE uid = ? LIMIT ? , ?";
// return jdbcTemplate.query(sql, new BeanPropertyRowMapper<MyFavorite>(MyFavorite.class), uid, start, pageSize);
// 改写一下
String sql = " select * from tab_favorite where 1 = 1 ";
StringBuilder sb = new StringBuilder(sql);
List params = new ArrayList();//条件们
//2.判断参数是否有值
if(uid != 0){
sb.append( " and uid = ? ");
params.add(uid);//添加?对应的值
}
// if(rname != null && rname.length() > 0 && !"null".equals(rname)){
// sb.append(" and rname like ? ");
// params.add("%"+rname+"%");
// }
sb.append(" limit ? , ? ");//分页条件
sql = sb.toString();//sql语句重新赋值,拼接多条件查询
params.add(start);
params.add(pageSize);
return jdbcTemplate.query(sql,new BeanPropertyRowMapper<Route>(Route.class),params.toArray());
}
查询收藏次数
查询代码
-- 人气旅游展示
SELECT rid,COUNT(rid) AS COUNT FROM tab_favorite GROUP BY rid ORDER BY COUNT(rid) DESC LIMIT 0, 513
查询结果
最新旅游展示
查询代码
-- 最新旅游展示
SELECT * FROM tab_route ORDER BY rdate DESC LIMIT 0,513;
查询结果
删除收藏
为了不影响后续的查看数据,先测试是否可以被查看
代码
-- 删除收藏
SELECT * FROM tab_favorite WHERE rid = 2 AND uid = 23;
DELETE FROM tab_favorite WHERE rid = 2 AND uid = 23;
查询结果
收藏量top前几的展示
代码
-- 找到收藏量按降序排列的route
SELECT * FROM (SELECT rid,COUNT(rid) AS count FROM tab_favorite GROUP BY rid ORDER BY COUNT(rid) DESC)as top;
-- 找到收藏量top前几的route
SELECT * FROM (SELECT rid,COUNT(rid) AS count FROM tab_favorite GROUP BY rid ORDER BY COUNT(rid) DESC) as top LIMIT 6;
查询结果
找到收藏量按降序排列的route
找到收藏量top前几的route
!!!找到所有的Favorite(不重复)
多条件查询,查询条件的字符串拼接
方法:
public List findRouteByRangePage(int start, int pageSize, String rname, int first, int last);
条件很多,足足五个之多
分开一层套一层
之前RouteDaoImpl亦是多条件查询, 并且其中有三个条件相同,可作为参考[4.旅游线路名称查询-参数传递]
查询语句
-- 找到所有的Favorite(不重复)
-- findRouteByRangePage(int start, int pageSize, String rname, int first, int last)
SELECT * FROM
(SELECT * FROM
(SELECT rid,COUNT(rid) AS COUNT FROM tab_favorite GROUP BY rid ORDER BY COUNT(rid) DESC)AS aa)
AS bb,tab_route t WHERE t.rid = bb.rid;
查询结果
参考的代码
/*根据cid,start,pageSize查询当前的数据集合*/
@Override
public List<Route> findByPage(int cid, int start, int pageSize, String rname) {
// String sql = "select * from tab_route where cid=? and rname like ? limit ? , ?";
//limit后的两个问号,第一个表示从哪里开始,第二个表示查询多少个记录
//1.定义sql模板
String sql = " select * from tab_route where 1 = 1 ";
//StringBuilder:可变字符序列、效率高、线程不安全;
StringBuilder sb = new StringBuilder(sql);
List params = new ArrayList();//条件们
//2.判断参数是否有值
if (cid != 0) {
sb.append(" and cid = ? ");
params.add(cid);//添加?对应的值
}
// 加上!"null".equals(rname)才不会报错,否则查找不到对应内容
if (rname != null && rname.length() > 0 && !"null".equals(rname)) {
sb.append(" and rname like ? ");
params.add("%" + rname + "%");
}
sb.append(" limit ? , ? ");//分页条件
sql = sb.toString();//sql语句重新赋值,拼接多条件查询
params.add(start);
params.add(pageSize);
return template.query(sql, new BeanPropertyRowMapper<Route>(Route.class), params.toArray());
}
改写的代码
@Override //找到所有的Favorite(不重复)
public List<Route> findRouteByRangePage(int start, int pageSize, String rname, int first, int last) {
// select * from table_name limit 10;//检索前10行记录
// String sql = "select * from tab_route where cid=? and rname like ? limit ? , ?";
//limit后的两个问号,第一个表示从哪里开始,第二个表示查询多少个记录
//1.定义sql模板
String sql = "SELECT * FROM (SELECT * FROM (SELECT rid,COUNT(rid) AS COUNT FROM tab_favorite GROUP BY rid ORDER BY COUNT(rid) DESC)AS aa)AS bb,tab_route t WHERE t.rid = bb.rid ";
//StringBuilder:可变字符序列、效率高、线程不安全;
StringBuilder sb = new StringBuilder(sql);
List params = new ArrayList();//条件们
//2.判断参数是否有值
if (first != 0) {
sb.append("and t.price > ? ");
//添加?对应的值
params.add(first);
}
if (last != 0) {
sb.append("and t.price < ? ");
//添加?对应的值
params.add(last);
}
//判断参数是否有值
// 加上!"null".equals(rname)才不会报错,否则查找不到对应内容
if (rname != null && rname.length() > 0 && !"null".equals(rname)) {
sb.append(" and rname like ? ");
params.add("%" + rname + "%");
}
//分页
sb.append(" limit ? ");//查询条件
sql += sb.toString();//sql语句重新赋值,拼接多条件查询
params.add(start);
params.add(pageSize);
return template.query(sql, new BeanPropertyRowMapper<Route>(Route.class), params.toArray());
}
前台代码的改写
myFavorite.html
在其中引入js文件
测试一下,说明能被取到
测试后304
服务端已经执行了GET,但文件未变化。
新增id作为标识,将动态内容改写
动态改写前
var li = '<div class="col-md-3">\n' +
' <a href="route_detail.html">\n' +
' <img src="images/collection_pic.jpg" alt="">\n' +
' <div class="has_border">\n' +
' <h3>上海直飞三亚5天4晚自由行(春节预售+亲子/蜜月/休闲游首选+豪华酒店任选+接送机)</h3>\n' +
' <div class="price">网付价<em>¥</em><strong>889</strong><em>起</em></div>\n' +
' </div>\n' +
' </a>\n' +
' </div>'
动态改写后
var li = '<div class="col-md-3">\n' +
' <a href="route_detail.html?rid='+route.rid+'">\n' +
' <img src="'+route.image+'" alt="">\n' +
' <div class="has_border">\n' +
' <h3>'+route.routeIntroduce+'</h3>\n' +
' <div class="price">网付价<em>¥</em><strong>'+route.price+'</strong><em>起</em></div>\n' +
' </div>\n' +
' </a>\n' +
' </div>'
输入网址localhost/travel/route/myFavorite测试一下,看到用户岁岁对应信息的json文件
将其复制下来放到网上的Json在线解析,
{"totalCount":7,"totalPage":2,"currentPage":1,"pageSize":5,"list":[{"rid":1,"rname":"【旅展 半价特惠 重走丝路•漫游宁夏 双飞4天】银川西部影视城 穆民新村 中卫沙坡头【品美酒 回族学唱花儿 感悟民俗】","price":999.0,"routeIntroduce":"走进【宁夏沙坡头】,感受西北大漠风情、体会“大漠孤烟直,长河落日圆”的塞上风光!","rflag":"1","rdate":"2018-02-09 01:13:16","isThemeTour":"0","count":0,"cid":5,"rimage":"img/product/small/m304b69a4c8328f7d6b8d5dadef020fe07.jpg","sid":1,"sourceId":"23677","category":null,"seller":null,"routeImgList":null},{"rid":2,"rname":"【官网专享 立减¥500 张家界天门山+大峡谷+凤凰古城+玻璃栈道+玻璃桥 高铁4天 无自费5钻】印象鲵宴-赶年宴+2晚蓝湾博格酒店","price":1799.0,"routeIntroduce":"官网专线,顶级品质!全程超豪华住宿,2晚入住超豪华铂金-蓝湾博格国际酒店,独家尊享金马VIP贵宾专用楼层。","rflag":"1","rdate":"2018-02-09 01:13:17","isThemeTour":"0","count":990,"cid":5,"rimage":"img/product/small/m34866f055de8630e94e25c40f277a79ba.jpg","sid":1,"sourceId":"22066","category":null,"seller":null,"routeImgList":null},{"rid":4,"rname":"【官网专享 送箱 ¥1099秒杀 华东五市+乌镇+南浔 双飞6天 南京进上海出】升级1晚豪华酒店 漫步西湖【水墨江南】","price":1099.0,"routeIntroduce":"升级入住1晚豪华酒店;畅玩江南两大经典水乡——乌镇水乡和南浔水乡,体验这里的历史文化底蕴、清丽婉约的水乡古镇风貌。","rflag":"1","rdate":"2018-02-09 01:13:17","isThemeTour":"0","count":0,"cid":5,"rimage":"img/product/small/m3d91ef60e0c7fdeee97a4e2d3e5a42e84.jpg","sid":1,"sourceId":"21943","category":null,"seller":null,"routeImgList":null},{"rid":7,"rname":"【¥1099秒杀 约惠华东五市+乌镇+木渎+灵山大佛 双飞6天 无锡进上海出】升级2晚豪华酒店","price":1099.0,"routeIntroduce":"畅玩乌镇水乡和木渎水乡,游览上海迪士尼小镇,其中升级入住2晚豪华酒店,品尝杭州特色宴“乾隆御茶宴”,送品尝金秋肥美大闸蟹一只!","rflag":"1","rdate":"2018-02-09 01:13:17","isThemeTour":"0","count":0,"cid":5,"rimage":"img/product/small/m370365f2ea91b638695218a6df13e3819.jpg","sid":1,"sourceId":"14974","category":null,"seller":null,"routeImgList":null},{"rid":9,"rname":"【豪叹喜来登 桂林 阳朔西街高铁4天纯玩 高级团】漓江 西山公园 象鼻山 银子岩","price":1299.0,"routeIntroduce":"1晚指定入住福朋喜来登酒店,船游全程大漓江,游览世界溶洞奇观银子岩","rflag":"1","rdate":"2018-02-09 01:13:17","isThemeTour":"0","count":0,"cid":5,"rimage":"img/product/small/m35c17b5b73d618bbdd2abe231f1307838.jpg","sid":1,"sourceId":"2702","category":null,"seller":null,"routeImgList":null}]}
得到
{
"totalCount": 7,
"totalPage": 2,
"currentPage": 1,
"pageSize": 5,
"list": [{
"rid": 1,
"rname": "【旅展 半价特惠 重走丝路•漫游宁夏 双飞4天】银川西部影视城 穆民新村 中卫沙坡头【品美酒 回族学唱花儿 感悟民俗】",
"price": 999.0,
"routeIntroduce": "走进【宁夏沙坡头】,感受西北大漠风情、体会“大漠孤烟直,长河落日圆”的塞上风光!",
"rflag": "1",
"rdate": "2018-02-09 01:13:16",
"isThemeTour": "0",
"count": 0,
"cid": 5,
"rimage": "img/product/small/m304b69a4c8328f7d6b8d5dadef020fe07.jpg",
"sid": 1,
"sourceId": "23677",
"category": null,
"seller": null,
"routeImgList": null
}, {
"rid": 2,
"rname": "【官网专享 立减¥500 张家界天门山+大峡谷+凤凰古城+玻璃栈道+玻璃桥 高铁4天 无自费5钻】印象鲵宴-赶年宴+2晚蓝湾博格酒店",
"price": 1799.0,
"routeIntroduce": "官网专线,顶级品质!全程超豪华住宿,2晚入住超豪华铂金-蓝湾博格国际酒店,独家尊享金马VIP贵宾专用楼层。",
"rflag": "1",
"rdate": "2018-02-09 01:13:17",
"isThemeTour": "0",
"count": 990,
"cid": 5,
"rimage": "img/product/small/m34866f055de8630e94e25c40f277a79ba.jpg",
"sid": 1,
"sourceId": "22066",
"category": null,
"seller": null,
"routeImgList": null
}, {
"rid": 4,
"rname": "【官网专享 送箱 ¥1099秒杀 华东五市+乌镇+南浔 双飞6天 南京进上海出】升级1晚豪华酒店 漫步西湖【水墨江南】",
"price": 1099.0,
"routeIntroduce": "升级入住1晚豪华酒店;畅玩江南两大经典水乡——乌镇水乡和南浔水乡,体验这里的历史文化底蕴、清丽婉约的水乡古镇风貌。",
"rflag": "1",
"rdate": "2018-02-09 01:13:17",
"isThemeTour": "0",
"count": 0,
"cid": 5,
"rimage": "img/product/small/m3d91ef60e0c7fdeee97a4e2d3e5a42e84.jpg",
"sid": 1,
"sourceId": "21943",
"category": null,
"seller": null,
"routeImgList": null
}, {
"rid": 7,
"rname": "【¥1099秒杀 约惠华东五市+乌镇+木渎+灵山大佛 双飞6天 无锡进上海出】升级2晚豪华酒店",
"price": 1099.0,
"routeIntroduce": "畅玩乌镇水乡和木渎水乡,游览上海迪士尼小镇,其中升级入住2晚豪华酒店,品尝杭州特色宴“乾隆御茶宴”,送品尝金秋肥美大闸蟹一只!",
"rflag": "1",
"rdate": "2018-02-09 01:13:17",
"isThemeTour": "0",
"count": 0,
"cid": 5,
"rimage": "img/product/small/m370365f2ea91b638695218a6df13e3819.jpg",
"sid": 1,
"sourceId": "14974",
"category": null,
"seller": null,
"routeImgList": null
}, {
"rid": 9,
"rname": "【豪叹喜来登 桂林 阳朔西街高铁4天纯玩 高级团】漓江 西山公园 象鼻山 银子岩",
"price": 1299.0,
"routeIntroduce": "1晚指定入住福朋喜来登酒店,船游全程大漓江,游览世界溶洞奇观银子岩",
"rflag": "1",
"rdate": "2018-02-09 01:13:17",
"isThemeTour": "0",
"count": 0,
"cid": 5,
"rimage": "img/product/small/m35c17b5b73d618bbdd2abe231f1307838.jpg",
"sid": 1,
"sourceId": "2702",
"category": null,
"seller": null,
"routeImgList": null
}]
}
和数据库查询得到的结果一致,说明编写的后台服务器端代码是正确的
header.html完整代码如下
<!--我不信邪了还-->
<!-- 头部 start -->
<script src="js/getParameter.js"></script>
<script>
$(function () {
var user;
//查询用户信息
$.get("user/findOne",{},function (data) {
// {uid:1,name:'hua'}
user = data;
var msg = "欢迎回来, "+data.name;
$("#span-username").html(msg)
});
//查询分类数据
$.get("category/findAll",{},function (data) {
// [{cid:1,cname:xxx},{},{}]
var str ='<li class="nav-active"><a href="index.html">首页</a></li>';
//遍历数组,字符串拼接<li><a href="route_list.html">门票</a></li>
for (var i = 0;i<data.length;i++){
var li = '<li><a href="route_list.html?cid='+data[i].cid+'">'+data[i].cname+'</a></li>';
str+=li;
}
//拼接收藏排行榜(最后一部分)
str+='<li><a href="favoriterank.html">收藏排行榜</a></li>';
//将str设置到ul的html内容中
$("#category").html(str);
})
//给搜索按钮绑定单击事件,获取搜索输入框的内容
$("#search_button").click(function () {
//用户输入的线路名称
var rname = $("#search_input").val();
// alert(rname);
//跳转路径http://localhost/travel/route_list.html?cid=23,拼接上rname=xxx
var cid = getParameter("cid");
location.href = "http://localhost/travel/route_list.html?cid="+cid+"&rname="+rname;
})
//点击我的收藏
judgeUser = function (){
//未登录
if(user == null){
alert("您尚未登录,请登录!")
location.href = "http://localhost/travel/login.html";
}else{
//已登录a
// alert(user.uid);
var uid = user.uid;
//跳转到我的收藏页面
location.href = "http://localhost/travel/myfavorite.html?uid="+uid;
}
}
})
</script>
<header id="header">
<div class="top_banner img-responsive">
<img src="images/top_banner.jpg" alt="">
</div>
<div class="shortcut">
<!-- 未登录状态 -->
<div class="login_out">
<a href="login.html">登录</a>
<a href="register.html">注册</a>
</div>
<!-- 登录状态 -->
<div class="login">
<span id="span-username"></span>
<!--//myfavorite.html-->
<a href="javascript:void(judgeUser())" id="myFavorite" class="collection">我的收藏</a>
<a href="javascript:location.href='user/exit';">退出</a>
</div>
</div>
<div class="header_wrap">
<div class="topbar">
<div class="logo">
<a href="/"><img src="images/logo.jpg" alt=""></a>
</div>
<div class="search">
<input name="" type="text" id="search_input" placeholder="请输入路线名称" class="search_input" autocomplete="off">
<a href="javascript:;" id="search_button" class="search-button">搜索</a>
</div>
<div class="hottel">
<div class="hot_pic">
<img src="images/hot_tel.jpg" alt="">
</div>
<div class="hot_tel">
<p class="hot_time">客服热线(9:00-6:00)</p>
<p class="hot_num">400-618-9090</p>
</div>
</div>
</div>
</div>
</header>
<!-- 头部 end -->
<!-- 首页导航 -->
<div class="navitem">
<ul id="category" class="nav">
<!--<li class="nav-active"><a href="index.html">首页</a></li>-->
<!--<li><a href="route_list.html">门票</a></li>-->
<!--<li><a href="route_list.html">酒店</a></li>-->
<!--<li><a href="route_list.html">香港车票</a></li>-->
<!--<li><a href="route_list.html">出境游</a></li>-->
<!--<li><a href="route_list.html">国内游</a></li>-->
<!--<li><a href="route_list.html">港澳游</a></li>-->
<!--<li><a href="route_list.html">抱团定制</a></li>-->
<!--<li><a href="route_list.html">全球自由行</a></li>-->
<!--<li><a href="favoriterank.html">收藏排行榜</a></li>-->
</ul>
</div>
要想点击介绍纪进入对应详情页
改写前端代码
我的收藏1
/*//我的收藏1
$(function () {
//引入js有了更方便的方法如下↓
//获取uid的参数值
var uid = getParameter("uid");
// alert(uid);
//当页码加载完成后,调用load方法,发送ajax请求加载数据
load(uid, null);
});
// “我的收藏”分页
function load(uid, currentPage) {
//发送ajax请求,请求route/pageQuery,传递cid
$.get("route/myFavorite", {uid: uid, currentPage: currentPage}, function (pb) {
if (pb.totalcount === 0) {
$("#favorite_route").html('<span id="nofavorite">您还没有任何收藏哦,去看一看线路列表吧</span>');
}
//解析pagebean数据,展示到页面上
//1.分页工具条数据展示
//1.1 展示总页码和总记录数
$("#totalPage").html(pb.totalPage);
$("#totalCount").html(pb.totalCount);
//分页展示
var lis = "";
//onclick="javascipt:load(5,1,\'西安\')" 出现两个引号,避免拼接使用转义字符\
var fristPage = '<li onclick="javascipt:load(' + uid + ',1)" style="cursor: pointer"><a href="javascript:void(0)">首页</a></li>';
//onclick放到这里就可以点击框框也可以跳转 //已是首页啥也不做
//计算上一页的页码 当前页码-1
var beforeNum = pb.currentPage - 1;
if (beforeNum <= 0) {
beforeNum = 1; //如果已经是最前页就回到第一页
}
var beforePage = '<li onclick="javascipt:load(' + uid + ',' + beforeNum + ')" style="cursor: pointer" class="threeword"><a href="javascript:void(0)">上一页</a></li>';
lis += fristPage;
lis += beforePage;
//1.2 展示分页页码
/!*
1.一共展示10个页码,能够达到前5后4的效果
2.如果前边不够5个,后边补齐10个
3.如果后边不足4个,前边补齐10个
*!/
// 定义开始位置begin,结束位置 end
var begin; // 开始位置
var end; // 结束位置
//1.要显示10个页码
if (pb.totalPage < 10) {
//a.总页码不够10页
begin = 1;
end = pb.totalPage;
} else {
//b.总页码超过10页
begin = pb.currentPage - 5;
end = pb.currentPage + 4;
//b.1.如果前边不够5个,后边补齐10个
if (begin < 1) {
begin = 1;
end = begin + 9;
}
//b.2如果后边不足4个,前边补齐10个
if (end > pb.totalPage) {
end = pb.totalPage;
begin = end - 9;
}
}
//加上判断更严谨
for (var i = begin; i <= end; i++) {
var li;
//为当前页码加上样式 判断当前页码是否等于i
if (pb.currentPage == i) {
li = '<li class="curPage"onclick="javascipt:load(' + uid + ',' + i + ')" style="cursor: pointer" ><a href="javascript:void(0)">' + i + '</a></li>';
//是当前页码添加当前页码样式class="curPage"
} else {
//创建页码的li //不是当前页码,不添加当前页码样式
li = '<li onclick="javascipt:load(' + uid + ',' + i + ')" style="cursor: pointer" ><a href="javascript:void(0)">' + i + '</a></li>';
}
//拼接字符串
lis += li;
}
//计算后一页的页码 当前页码+1
var afterNum = pb.currentPage + 1;
if (afterNum > pb.totalPage) { //如果已经是最末页就回到最末页
afterNum = pb.totalPage;
}
//后一页
var nextPage = '<li onclick="javascipt:load(' + uid + ',' + afterNum + ',\'' + rname + '\')" style="cursor: pointer" class="threeword"><a href="javascript:void(0)">下一页</a></li>';
//最后一页
var lastPage = '<li onclick="javascipt:load(' + uid + ',' + pb.totalPage + ',\'' + rname + '\')" style="cursor: pointer" class="threeword"><a href="javascript:void(0)">末页</a></li>';
lis += nextPage;
lis += lastPage;
//将lis内容设置到 ul
$("#ul").html(lis);
//2.列表数据展示
var route_lis = "";
for (var i = 0; i < pb.list.length; i++) {
//获取{rid:1,rname:"xxx"}
var route = pb.list[i];
var li = '<div class="col-md-3">\n' +
' <a href="route_detail.html?rid=' + route.rid + '">\n' +
' <img src="' + route.image + '" alt="">\n' +
' <div class="has_border">\n' +
' <h3>'+ route.routeIntroduce + '</h3>\n' +
' <div class="price">网付价<em>¥</em><strong>' + route.price + '</strong><em>起</em></div>\n' +
' </div>\n' +
' </a>\n' +
' </div>'
route_lis += li;
}
$("#myfavorite").html(route_lis);
//定位到页面顶部
window.scrollTo(0, 0);
});
}*/
我的收藏2
/*//我的收藏2
$(function () {
var uid = getParameter("uid");
// alert(location.href);
// alert(uid)
//当页面加载完成后,调用load方法,发送ajax请求,加载数据
load(uid,null)
});
load = function (uid,currentPage) {
$.get("route/myFavorite",{uid:uid,currentPage:currentPage},function (pb) {
//发送ajax请求,请求route/pageQuery,传递cid
// $.get("route/myFavorite", {uid: uid, currentPage: currentPage}, function (pb) {
if (pb.totalcount === 0) {
$("#favorite_route").html('<span id="nofavorite">您还没有任何收藏哦,去看一看线路列表吧</span>');
}
//解析pagebean数据,展示到页面上
//1.分页工具条数据展示
//1.1 展示总页码和总记录数
$("#totalPage").html(pb.totalPage);
$("#totalCount").html(pb.totalCount);
//分页显示
var lis = "";
var firstPage = '<li onclick="javascript:load('+uid+',1)" style="cursor: pointer"><a href="javascript:void(0)">首页</a></li>';
//上一页的序号
var beforeNum = pb.currentPage - 1;
if (beforeNum <= 0) {
beforeNum = 1;
}
var prevPage = '<li onclick="javascript:load(' + uid + ',' + beforeNum + ')" style="cursor: pointer" class="threeword"><a href="#">上一页</a></li>';
lis += firstPage;
lis += prevPage;
//展示分页页码
/!*
一共展示10个页码,能够达到前五后四的效果
如果前面不够5个后面补齐10个
如果后面不足4个,前面补齐10ge
*!/
//定义开始位置begin.结束位置end
var begin;
var end;
if(pb.totalPage<10){
//总页码<10
begin = 1;
end = pb.totalPage;
}else{
//总页码>=10
begin = pb.currentPage-5;
end = pb.currentPage+4;
//前面不够5个,后面补齐10个
if(begin<1){
begin = 1;
end = begin+9;
}
//后面不足4个,前面补齐10个
if(end>pb.totalPage){
end = pb.totalPage;
begin = end-9;
}
}
for (var i = begin; i <= end; i++) {
var li;
//为当前页码加上样式
if (pb.currentPage == i) {
li = '<li class="curPage" style="cursor: pointer" onclick="javascript:load(' + uid + ',' + i + ')"><a href="javascript:void(0)">' + i + '</a></li>';
} else {
//创建页码的li
li = '<li style="cursor: pointer" onclick="javascript:load(' + uid + ',' + i + ')"><a href="javascript:void(0)">' + i + '</a></li>';
}
//拼接字符串
lis += li;
}
var nextNum = currentPage + 1;
if (nextNum > pb.totalPage) {
nextNum = pb.totalPage;
}
var nextPage = '<li onclick="javascript:load(' + uid + ','+nextNum+')" style="cursor: pointer" class="threeword"><a href="javascript:void(0);">下一页</a></li>';
var lastPage = '<li onclick="javascript:load(' + uid + ','+pb.totalPage+')" style="cursor: pointer" class="threeword"><a href="javascript:void(0);">末页</a></li>';
lis += nextPage;
lis += lastPage;
//将list内容设置到ul中
$("#ul").html(lis);
//列表数据展示
var route_lis = "";
for (var i = 0; i < pb.list.length; i++) {
//获取{rid:1,rname:"xxx"}
var route = pb.list[i];
/!* <div class="col-md-3">
<a href="route_detail.html">
<img src="images/collection_pic.jpg" alt="">
<div class="has_border">
<h3>上海直飞三亚5天4晚自由行(春节预售+亲子/蜜月/休闲游首选+豪华酒店任选+接送机)</h3>
<div class="price">网付价<em>¥</em><strong>889</strong><em>起</em></div>
</div>*!/
var li = '<div class="col-md-3">\n' +
' <a href="route_detail.html?rid='+route.rid+'">\n' +
' <img src="'+route.rimage+'" alt="图片加载失败……">\n' +
' <div class="has_border">\n' +
' <h3>'+route.routeIntroduce+'</h3>\n' +
' <div class="price">网付价<em>¥</em><strong>'+route.price+'</strong><em>起</em></div>\n' +
' </div>\n' +
' </a>\n' +
' </div>';
route_lis += li;
}
$("#favorite").html(route_lis);
//定位到页面顶部
window.scrollTo(0,0);
})
}*/
我的收藏3(最终版)
//我的收藏3
$(function () {
var uid = getParameter("uid");
// alert(location.href);
// alert(uid)
//当页面加载完成后,调用load方法,发送ajax请求,加载数据
load(uid,null)
});
load = function (uid,currentPage) {
$.get("route/myFavorite",{uid:uid,currentPage:currentPage},function (pb) {
//发送ajax请求,请求route/pageQuery,传递cid
if (pb.totalcount === 0) {
$("#favorite_route").html('<span id="nofavorite">您还没有任何收藏哦,去看一看线路列表吧</span>');
}
//解析pagebean数据,展示到页面上
//1.分页工具条数据展示
//1.1 展示总页码和总记录数
$("#totalPage").html(pb.totalPage);
$("#totalCount").html(pb.totalCount);
// alert(pb.totalPage);
// alert(pb.totalCount);
//分页显示
var lis = "";
var firstPage = '<li onclick="javascript:load('+uid+',1)" style="cursor: pointer"><a href="javascript:void(0)">首页</a></li>';
//上一页的序号
var beforeNum = pb.currentPage - 1;
if (beforeNum <= 0) {
beforeNum = 1;
}
var prevPage = '<li onclick="javascript:load(' + uid + ',' + beforeNum + ')" style="cursor: pointer" class="threeword"><a href="#">上一页</a></li>';
lis += firstPage;
lis += prevPage;
//展示分页页码
/*
一共展示10个页码,能够达到前五后四的效果
如果前面不够5个后面补齐10个
如果后面不足4个,前面补齐10ge
*/
//定义开始位置begin.结束位置end
var begin;
var end;
if(pb.totalPage<10){
//总页码<10
begin = 1;
end = pb.totalPage;
}else{
//总页码>=10
begin = pb.currentPage-5;
end = pb.currentPage+4;
//前面不够5个,后面补齐10个
if(begin<1){
begin = 1;
end = begin+9;
}
//后面不足4个,前面补齐10个
if(end>pb.totalPage){
end = pb.totalPage;
begin = end-9;
}
}
for (var i = begin; i <= end; i++) {
var li;
//为当前页码加上样式
if (pb.currentPage == i) {
li = '<li class="curPage" style="cursor: pointer" onclick="javascript:load(' + uid + ',' + i + ')"><a href="javascript:void(0)">' + i + '</a></li>';
} else {
//创建页码的li
li = '<li style="cursor: pointer" onclick="javascript:load(' + uid + ',' + i + ')"><a href="javascript:void(0)">' + i + '</a></li>';
}
//拼接字符串
lis += li;
}
var nextNum = currentPage + 1;
if (nextNum > pb.totalPage) {
nextNum = pb.totalPage;
}
var nextPage = '<li onclick="javascript:load(' + uid + ','+nextNum+')" style="cursor: pointer" class="threeword"><a href="javascript:void(0);">下一页</a></li>';
var lastPage = '<li onclick="javascript:load(' + uid + ','+pb.totalPage+')" style="cursor: pointer" class="threeword"><a href="javascript:void(0);">末页</a></li>';
lis += nextPage;
lis += lastPage;
//将list内容设置到ul中
$("#ul").html(lis);
//列表数据展示
var route_lis = "";
for (var i = 0; i < pb.list.length; i++) {
//获取{rid:1,rname:"xxx"}
var route = pb.list[i];
/* <div class="col-md-3">
<a href="route_detail.html">
<img src="images/collection_pic.jpg" alt="">
<div class="has_border">
<h3>上海直飞三亚5天4晚自由行(春节预售+亲子/蜜月/休闲游首选+豪华酒店任选+接送机)</h3>
<div class="price">网付价<em>¥</em><strong>889</strong><em>起</em></div>
</div>*/
var li = '<div class="col-md-3">\n' +
' <a href="route_detail.html?rid='+route.rid+'">\n' +
' <img src="'+route.rimage+'" alt="图片加载失败……">\n' +
' <div class="has_border">\n' +
' <h3>'+route.routeIntroduce+'</h3>\n' +
' <div class="price">网付价<em>¥</em><strong>'+route.price+'</strong><em>起</em></div>\n' +
' </div>\n' +
' </a>\n' +
' </div>';
route_lis += li;
// alert(route.rid);
// alert(li)
}
$("#myfavorite").html(route_lis);
//定位到页面顶部
window.scrollTo(0,0);
})
}
要让“我的收藏”界面像国内游一样展示总记录数和页数
route_list.html
<div class="page_num_inf">
<i></i> 共
<span id="totalPage">12</span>页<span id="totalCount">132</span>条
</div>
展示结果
在myfavorite.html代码中加入同样的语句,
可以得到该用户的收藏数量和分页,但是很奇怪样式没有改变
经提醒可得知文件一开头并未引入该css文件,故没有任何改变,引入css文件后依旧没有变化???
getParameter.js文件也引入了,当不是此故。
后来找到问题所在,css样式设计不包括在里面,只能自己写
设计样式
<div class="page_num_inf">
<i></i> 共
<span id="totalPage">5</span>页<span id="totalCount">20</span>条
</div>
.page_one .xinxi .left .page_num_inf i {
float: left;
width: 4px;
background-color: #878787;
height: 20px;
margin-top: 5px;
margin-right: 10px;
}
.page_one .xinxi .left .page_num_inf span {
color: #ff4848;
}
就是油盐不进是吧?
重启后样式设置又好了
非得叛逆一下是吧?
收藏排行榜
分析
收藏排行榜默认排行方式是根据被收藏的次数降序排列,所以默认展示的收藏排行榜要查询所有线路被收藏次数,此外还有搜索框,可以根据线路名称和价格区间进行查询,名称采用的是模糊查询,价格区间则是拼接查询语句进行判断。
过程图
画图工具写到dao不知道为啥逆时针转了90°,可能一身逆骨无处发泄,该来的还是来了orz
后台代码
FavoriteDaoImpl
@Override //分页查询Favorite
public List<Favorite> findByPage(int uid, int start, int pageSize) {
//Collections.emptyList()返回一个空的List(使用前提是不会再对返回的list进行增加和删除操作)
List<Favorite> list = Collections.emptyList();
try {
String sql = "select * from tab_favorite where uid = ? limit ? , ?";
list = template.query(sql, new BeanPropertyRowMapper<Favorite>(Favorite.class), uid, start, pageSize);
} catch (Exception e) {
}
return list;
}
@Override //找到收藏量top前几的route
public List<Favorite> findTopFavorite(int top) {
List<Favorite> list = Collections.emptyList();
try {
String sql = "SELECT * FROM (SELECT rid,COUNT(rid) AS count FROM tab_favorite GROUP BY rid ORDER BY COUNT(rid) DESC) as top LIMIT ?";
list = template.query(sql, new BeanPropertyRowMapper<Favorite>(Favorite.class), top);
} catch (DataAccessException e) {
e.printStackTrace();
}
return list;
}
@Override //找到所有的Favorite(不重复)
public List<Route> findRouteByRangePage(int start, int pageSize, String rname, int first, int last) {
// select * from table_name limit 10;//检索前10行记录
// String sql = "select * from tab_route where cid=? and rname like ? limit ? , ?";
//limit后的两个问号,第一个表示从哪里开始,第二个表示查询多少个记录
//1.定义sql模板
// String sql = "SELECT * FROM (SELECT * FROM (SELECT rid,COUNT(rid) AS COUNT FROM tab_favorite GROUP BY rid ORDER BY COUNT(rid) DESC)AS aa)AS bb,tab_route t WHERE t.rid = bb.rid ";
String sql = "select * from tab_route where 1 = 1 ";
//StringBuilder:可变字符序列、效率高、线程不安全;
StringBuilder sb = new StringBuilder(sql);
List params = new ArrayList();//条件们
//2.判断参数是否有值
// 加上!"null".equals(rname)才不会报错,否则查找不到对应内容
if (rname != null && rname.length() > 0 && !"null".equals(rname)) {
sb.append(" and rname like ? ");
params.add("%" + rname + "%");
}
if (last != 0){
sb.append(" and price between ? and ?");
params.add(first);
params.add(last);
}
// if (first != 0) {
// sb.append(" and t.price > ? ");
// //添加?对应的值
// params.add(first);
// }
// if (last != 0) {
// sb.append(" and t.price < ? ");
// //添加?对应的值
// params.add(last);
// }
//分页
//按收藏次数降序排列
sb.append(" order by count desc ");
//加入分页查询
sb.append(" limit ? , ? ");//查询条件
// sql = sb.toString();//sql语句重新赋值,拼接多条件查询
params.add(start);
params.add(pageSize);
System.out.println(params);
return template.query(sb.toString(), new BeanPropertyRowMapper<Route>(Route.class), params.toArray());
}
@Override //根据rid查询收藏次数
public int findCountByRid(int rid) {
String sql = "select count(*) from tab_favorite where rid = ?";
return template.queryForObject(sql, Integer.class, rid);
}
@Override //不分页情况下的总数
public int findCountByRangeWithOutPage(String rname, int first, int last) {
// String sql = "SELECT COUNT(*) FROM (SELECT * FROM (SELECT rid,COUNT(rid) AS COUNT FROM tab_favorite GROUP BY rid ORDER BY COUNT(rid) DESC)AS aa)AS bb,tab_route t WHERE t.rid = bb.rid ";
String sql = " select count(*) from tab_route where 1 = 1 ";
StringBuilder sb = new StringBuilder(sql);
//条件们
List params = new ArrayList();
//判断参数是否有值
if(rname!=null && rname.length()>0 && !"null".equals(rname)){
sb.append(" and rname like ? ");
params.add("%"+rname+"%");
}
if (last != 0){
sb.append(" and price between ? and ?");
params.add(first);
params.add(last);
}
// if(first!=0){
// sb.append(" and t.price > ? ");
// //添加?对应的值
// params.add(first);
// }
// if(last!=0){
// sb.append("and t.price < ? ");
// //添加?对应的值
// params.add(last);
// }
//分页
sql = sb.toString();
int count = template.queryForObject(sql,Integer.class,params.toArray());
System.out.println("符合条件的记录数"+count);
return count;
}
前台代码
favoriterank.html
加上id
前端代码和后端代码都基本写好的前提下,数据组PageBean pb的获取出现问题
错误f12检查发现无法读取*2:
Cannot read properties of null (reading 'name' )
无法读取空属性(读取“名称”)
Cannot read properties of undefined (reading 'length')
无法读取未定义的属性(读取“长度”)
出现原因:
用户未登录,自然无法获取用户名name和长度length
解决方案:
用户登录即可,如此前端就不会报错了。
看看前端
错误:显示currentPage为null
因为RouteServlet中获取当前页码只限定了非空
在StringUtils中更改了符号,从||变成了&&
更正!!!
之前如果是每一个加个非!判断,name就是要短路或,因为只有这样出现任意一个非空情况都会输出真正的数据库获取的currentPage
在小梅同志的共同查看下终于发现后端集合pb无法获取上传的原因:
没有将查询语句放到拼接语句里,就这么简单困了我好久好久,可恶啊!
加上后成功啦!