文章目录
黑马旅游网项目总结3
查询模块
前端分析
设计一个点击事件,在点击搜索之后将内容和cid提取出来并且传回route_list。html中,然后
上面这是route_list中的处理办法,在页面加载完成之后,取出刚才传过来的值,这里有一点需要注意,汉字在页面传输过程中会自动转码为html格式,要先进行转码,decodeUriConmponent方法就是在进行转码。然后将之前的查询路线功能进行修改,多加上一个参数rname;相应的前端页面中的代码也需要进行部分修正,因为之前只传两个值,这里需要多加上一个值
function load(cid, currentPage, rname) {
$.get("routeServlet/getList", {cid: cid, currentPage: currentPage, rname: rname}, function (pd) {
$("#totalCount").html(pd.totalCount);
$("#totalPage").html(pd.totalPage);
//导航栏数据展示
var lis = '<li onclick="javascipt:load(' + cid + ',1,\'' + rname + '\')"><a href="javascript:void(0)">首页</a></li>'
var c1 = pd.currentPage - 1;
if (c1 <= 1) {
c1 = 1
}
lis += '<li onclick="javascript:load(' + cid + ',' + c1 + ',\'' + rname + '\')" class="threeword"><a href="javascript:void(0)">上一页</a></li>'
var start = 0;
var end = 0;
//如果一开始就不足10页
if (pd.totalPage < 10) {
start = 1;
end = pd.totalPage;
} else {
start = pd.currentPage - 5;
end = pd.currentPage + 4;
//如果前面不足5页
if (start < 1) {
start = 1;
end = start + 9;
}
//如果后面不足4页
if (end > pd.totalPage) {
end = pd.totalPage;
start = end - 9;
}
}
for (var i = start; i <= end; i++) {
if (pd.currentPage == i) {
var li = '<li class="curPage" onclick="load(' + cid + ',' + i + ',\'' + rname + '\')"><a href="#">' + i + '</a></li>'
} else
var li = '<li onclick="load(' + cid + ',' + i + ',\'' + rname + '\')"><a href="#">' + i + '</a></li>'
lis += li;
}
var c2 = pd.currentPage + 1;
if (c2 >= pd.totalPage) {
c2 = pd.totalPage;
}
lis += ' <li onclick="javascipt:load(' + cid + ',' + c2 + ',\'' + rname + '\')" class="threeword"><a href="javascript:void(0);">下一页</a></li>'
var t1 = pd.totalPage
lis += '<li onclick="javascipt:load(' + cid + ',' + t1 + ',\'' + rname + '\')" class="threeword"><a href="javascript:void(0);">末页</a></li>'
$("#footerList").html(lis)
//列表数据展示
var a = "";
for (let i = 0; i < pd.list.length; i++) {
var route = pd.list[i];
var b = ' <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?rid=' + route.rid + '">查看详情</a></p>\n' +
' </div>\n' +
' </li>'
a += b;
}
$("#bodyList").html(a)
})
}
后端分析
Dao
public List<Route> getRouteList(int cid, int start, int pageSize, String rname) {
StringBuilder sql=new StringBuilder("select * from tab_route where 1=1") ;
List p=new ArrayList<>();
if(cid!=0){
sql.append(" and cid = ? ");
p.add(cid);
}
if(rname!=null&& rname.length()>0 && !"null".equals(rname)){
sql.append(" and rname like ?");
p.add("%"+rname+"%");
}
sql.append(" limit ? , ?");
p.add(start);
p.add(pageSize);
List<Route> routes=jdbcTemplate.query(sql.toString(),new BeanPropertyRowMapper<Route>(Route.class),p.toArray());
return routes;
}
public int getTotalCount(int cid, String rname) {
StringBuilder sql=new StringBuilder("select count(*) from tab_route where 1 = 1 ");
List p=new ArrayList<>();
if(cid!=0){
sql.append(" and cid = ? ");
p.add(cid);
}
if(rname!=null && rname.length()>0 &&!"null".equals(rname)){
sql.append(" and rname like ?");
p.add("%"+rname+"%");
}
int count = jdbcTemplate.queryForObject(sql.toString(), Integer.class,p.toArray());
return count;
}
这里对之前的RouteDao进行方法的修改,可以看到我们给参数加上一个rname,利用cid和rname进行联合查询,这里使用到两个技巧。
1.在这种模糊查询的方法中,我们可以先写select count(*) from tab_route where 1 = 1 这样保证整个sql语句是正确的,然后在后面进行判断,如果cid不等于0就给sql加上一个and cid=?,rname也是同理,这样做的原因是cid和rname都可能为0.
2.这里使用一个list来装条件,然后在jdbcTemplate.queryForObject()的最后将其转换成为数组,这样给我们的程序带来很大的灵活性,
Service
public PageBean<Route> getPageBean(int cid, int currentPage, int pagesize, String rname) {
//这里处理两件事,第一件事就是查找一共有多少数据,第二件事就是去分页查询拿到想要的数据,然后封装成一个PageBean传回去
//一共有多少页是通过计算得到的
PageBean<Route> pageBean=new PageBean<>();
int totalCount=routeDao.getTotalCount(cid,rname);
System.out.println(totalCount);
//总页数
int totalPage=totalCount%pagesize==0?totalCount/pagesize:(totalCount/pagesize)+1;
int start=(currentPage-1)*pagesize;
List<Route> route = routeDao.getRouteList(cid, start, pagesize,rname);
pageBean.setTotalPage(totalPage);
pageBean.setPageSize(pagesize);
pageBean.setCurrentPage(currentPage);
pageBean.setList(route);
pageBean.setTotalCount(totalCount);
System.out.println(route.size());
for(Route route1:route){
System.out.println(route1);
}
return pageBean;
}
service中改动较小,主要还是去拿到PageBean,因此只需要改动参数即可
Servlet
//分页查询
public void getList(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {
//接受三个数据:cid,当前页码,每页显示条数
//分别接受
String rname;
int cid = 1;
int currentPage = 0;
int pagesize = 0;
String scid = request.getParameter("cid");
String scurrentPage = request.getParameter("currentPage");
String spagesize = request.getParameter("pagesize");
//接收查询条件
rname = request.getParameter("rname");
//tomcat7没有自动处理乱码的功能,需要手动设置
rname = new String(rname.getBytes("iso-8859-1"), "utf-8");
//System.out.println("scid="+scid);
// System.out.println(scid != null && scid.length() > 0);
// System.out.println(scid == null && scid.length() > 0);
if (scid != null && scid.length() > 0 && !"null".equals(scid) ) {
cid = Integer.parseInt(scid);
}
//如果不传递就默认当前页码为第一页
if (scurrentPage != null && scurrentPage.length() > 0 && !"null".equals(scurrentPage)) {
currentPage = Integer.parseInt(scurrentPage);
} else {
currentPage = 1;
}
//如果不传递就默认每页显示5条数据
if (spagesize != null && spagesize.length() > 0 && !"null".equals(spagesize)) {
pagesize = Integer.parseInt(spagesize);
} else {
pagesize = 5;
}
//现在目标就是通过service去拿到PageBean
PageBean<Route> pageBean = service.getPageBean(cid, currentPage, pagesize, rname);
writeValues(pageBean, response);
}
servlet层中主要改动需要注意的是当我们去获取rname值的时候实际上传回来的是乱码,因为tomcat直到tomcat8才有自动处理乱码的能力,这里我们就必须手动处理乱码了
rname = new String(rname.getBytes(“iso-8859-1”), “utf-8”);
旅游路线详情展示
逻辑分析
这里可以看到一条旅游线路通过rid和路线图片表进行联系,通过sid和商家表联系,因此我们只需要这两个值,然后将结果封装在一个route对象之中然后传回即可。
前端分析
<script>
function getimg() {
//焦点图效果
//点击图片切换图片
$('.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;
}
});
//自动播放
// var timer = setInterval("auto_play()", 5000);
}
function collection(rid) {
$.get("routeServlet/collectionQuery", {rid: rid}, function (flag) {
if (flag) {
$("#collection").addClass("btn already");
$("#collection").attr("disabled", "disabled");
$("#collection").removeAttr("onclick");//click属于原本的属性
} else {
}
})
}
function load(rid) {
$.get("routeServlet/getDetail", {rid: rid}, function (route) {
$("#pPrice").html("¥" + route.price);
$("#prname").html(route.rname);
$("#prouteIntroduce").html(route.routeIntroduce);
$("#pSellerName").html(route.seller.sname);
$("#pSellerPhone").html(route.seller.consphone);
$("#pSellerDress").html(route.seller.address);
$("#collectionNum").html("已被收藏 " + route.count + " 次");
var dds = '<a class="up_img up_img_disable"></a>';
for (let i = 0; i < route.routeImgList.length; i++) {
if (i > 4) {
var dd;
dd = ' <a title="" class="little_img"\n' +
' data-bigpic="' + route.routeImgList[i].bigPic + '"style="display:none">\n' +
' <img src="' + route.routeImgList[i].smallPic + '">\n' +
' </a>'
} else {
dd = ' <a title="" class="little_img"\n' +
' data-bigpic="' + route.routeImgList[i].bigPic + '">\n' +
' <img src="' + route.routeImgList[i].smallPic + '">\n' +
' </a>'
}
dds += dd;
}
dds += '<a class="down_img down_img_disable" style="margin-bottom: 0;"></a>';
$("#pdd").html(dds)
getimg()
})
}
$(function () {
var rid = getParameter("rid");
load(rid);
collection(rid);
})
</script>
这里我们只要传入rid就可以查出这条旅游线路的信息以及旅游路线图片的信息,然后根据信息中的sid去查询商家信息,再将所有信息整合成一个route传回,值得注意的是getimg()方法,是对后面大图进行轮换的代码进行一个封装,然后在页面加载完成的时候执行一次,在异步请求结束之后再执行一次,这样就能实现图片轮换。
后端分析
Dao
public Route getRoute(int rid) {
String sql="select * from tab_route where rid=?";
Route route = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<Route>(Route.class), rid);
return route;
}
@Override
public List<RouteImg> getRouteImg(int rid) {
String sql="select * from tab_route_img where rid=?";
List<RouteImg> routeImgs=jdbcTemplate.query(sql,new BeanPropertyRowMapper<RouteImg>(RouteImg.class),rid);
return routeImgs;
}
@Override
public Seller getRouteSeller(int sid) {
String sql="select * from tab_seller where sid=?";
Seller seller=jdbcTemplate.queryForObject(sql,new BeanPropertyRowMapper<Seller>(Seller.class),sid);
return seller;
}
提供三个方法
主要是通过传入rid查出这条旅游线路的信息以及旅游路线图片的信息,然后根据信息中的sid去查询商家信息
Service
public Route getRoute(int rid) {
Route route=routeDao.getRoute(rid);
List<RouteImg>routeImgs=routeDao.getRouteImg(rid);
Seller seller=routeDao.getRouteSeller(route.getSid());
int num= routeDao.getCollectionNum(rid);
route.setCount(num);
route.setSeller(seller);
route.setRouteImgList(routeImgs);
return route;
}
主要是调用dao层拿到数据之后封装成一个route,然后返回。
Servlet
//获取路线详情
public void getDetail(HttpServletRequest request,HttpServletResponse response){
String srid = request.getParameter("rid");
int rid=0;
if(srid != null && srid.length() > 0 && !"null".equals(srid)){
rid=Integer.parseInt(srid);
}
Route route=service.getRoute(rid);
writeValues(route,response);
}
这里就是调用service层拿到信息完整的route返回给前端即可
旅游线路收藏功能(判断当前登录用户是否收藏过该线路)
逻辑分析
首先要进行收藏,先要判断用户到底有没有收藏过这条路线,通过分析得知,收藏表中的数据是由rid,和uid,也就是路线id和用户id再加上一个收藏时间构成的,因此我们只需要这两个值就可以查询到该路线有没有被收藏过,如果收藏过就将按钮的样式变为灰色并且不可点击。rid在传回route中即可获得,uid则在session中获取。
前端分析
function collection(rid) {
$.get("routeServlet/collectionQuery", {rid: rid}, function (flag) {
if (flag) {
$("#collection").addClass("btn already");
$("#collection").attr("disabled", "disabled");
$("#collection").removeAttr("onclick");//click属于原本的属性
} else {
}
})
}
我们在route_detail.html中定义一个函数,如果传回一个rid,传回一个flag,如果为真,说明用户已经收藏过了,那么改变收藏按钮的样式,并且取消它的点击事件。如果为假就不改动
后端分析
servlet
public void collectionQuery(HttpServletRequest request,HttpServletResponse response){
//1.接收rid
String srid = request.getParameter("rid");
int rid=0;
if (srid != null && srid.length() > 0 && !"null".equals(srid) ) {
rid = Integer.parseInt(srid);
}
//2.接收uid
User user = (User) request.getSession().getAttribute("user");
int uid;
if(user==null){
uid=0;
}
else {
uid=user.getUid();
}
Boolean flag=service.collectionQuery(rid,uid);
writeValues(flag,response);
}
rid由前端传回,uid从session中获取。
service
public Boolean collectionQuery(int rid, int uid) {
return routeDao.collectionQuery(rid,uid);
}
调用dao层,通过rid和uid对收藏表进行查询
Dao
public Boolean collectionQuery(int rid, int uid) {
String sql="select * from tab_favorite where rid=? and uid=?";
System.out.println(rid);
System.out.println(uid);
try {
Favorite favorite = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<Favorite>(Favorite.class),rid,uid);
return true;
} catch (DataAccessException e) {
return false;
}
}
通过rid和uid对收藏表进行查询,如果查不到就会报一个异常,这里使用trycatch进行包裹,一旦报错就返回false,否则返回true。
旅游线路收藏功能(点击收藏按钮收藏)
逻辑分析
用户点击收藏按钮之后,从url中截取rid,从session中获取uid,然后将二者数据外加一个当前时间写入数据库的收藏表中。
前端分析
function collectionOrNot() {
$.get("userServlet/findUser", {}, function (user) {
if (user) {
var rid=getParameter("rid");
var uid=user.uid;
$.get("routeServlet/collection",{rid:rid,uid:uid},function () {
location.reload();
})
} else {
alert("您还没有登录,请登录")
location.href=("http://localhost:81/travel/login.html");
}
})
}
这里给收藏按钮绑定一个点击事件,如果还没有登录就会跳转到登录页面
后端分析
Servlet
public void collection(HttpServletRequest request,HttpServletResponse response){
String srid = request.getParameter("rid");
User user = (User)request.getSession().getAttribute("user");
int rid=0;
if (srid != null && srid.length() > 0 && !"null".equals(srid) ) {
rid = Integer.parseInt(srid);
}
int uid;
if(user==null){
uid=0;
}
else {
uid=user.getUid();
}
service.collection(rid,uid);
}
这里servlet主要目的拿到rid和uid并且传给service去进行数据库的写入
Service
@Override
public void collection(int rid, int uid) {
routeDao.collect(rid,uid);
}
service层只负责将rid和uid传入Dao层
Dao
@Override
public void collect(int rid, int uid) {
String sql="insert into tab_favorite values(?,?,?)";
jdbcTemplate.update(sql,rid,new Date(),uid);
}
这里拿到rid和uid之后再传入当前时间即可写入数据。