项目笔记第三天

    xiaoxiao2022-07-12  196

    项目第3天

    一、查看路线详情

    要求:

    用户在路线列表页面,点击“查看详情”,跳转到详情页面

    在详情页面上发Ajax请求,得到并显示路线的详细信息

    案例要求:点击route_list.html搜索列表中旅游线路的“查看详情”进入route_detail.html旅游线路详情页面并显示相关数据

    分析:

    用户在路线列表页面,点击“查看详情”时,要把路线的id,传递给详情页面

    步骤:

    0.在路线列表页面,点击“查看详情”跳转到route_detail.html

    跳转到route_detail.html时,需要传参路线的id:rid

    1.在route_detail.html里发Ajax请求到Servlet

    接收参数:rid(路线的id)

    发Ajax请求到Servlet,把参数rid传递给Servlet

    2.在Servlet里,处理请求,完成功能,返回结果给页面

    /* *查看信息的路线 * */ public void routeDetail(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ResultInfo info = null; try { //1.接收参数 final String rid = request.getParameter("rid"); //2.封装实体,略 //3.完成功能 //调用service Route route = routeService.routeDetail(rid); //4.处理结果 info = new ResultInfo(true, request); } catch (Exception e) { e.printStackTrace(); info = new ResultInfo(false, "服务器正在忙,请你等下访问."); } /*装换成json格式*/ final ObjectMapper mapper = new ObjectMapper(); final String json = mapper.writeValueAsString(info); response.getWriter().print(json); }

    接收参数:rid

    完成功能:调用service,查询页面需要的数据

    在Service里做的事情:

     

    调用dao,查询路线信息Route对象

    //查看路线信息 @Override public Route findById(String rid) { Route route = null; try { String sql = ""; //把Route封装成Route.class对象 route = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(Route.class), rid); } catch (DataAccessException e) { e.printStackTrace(); System.out.println("找不到路线的信息Route[rid=" + rid + "]"); } return route; } @Override public Seller findSellerById(Integer sid) { Seller seller = null; try { String sql = ""; seller = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(Seller.class), sid); } catch (DataAccessException e) { e.printStackTrace(); System.out.println("找不到商家信息Seller[sid=" + sid + "]"); } return seller; } @Override public Category findCategoryById(Integer cid) { Category category = null; try { String sql = ""; category = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(Category.class), cid); } catch (DataAccessException e) { e.printStackTrace(); System.out.println("找不到分类的信息Category[cid="+cid+"]"); } return category; } @Override public List<RouteImg> findImages(String rid) { String sql=""; //这个把集合返回给service return jdbcTemplate.query(sql,new BeanPropertyRowMapper<>(RouteImg.class),rid); }

    调用dao,查询商家信息Seller对象,放到Route对象里

    调用dao,查询分类信息Category对象,放到Route对象里

    调用dao,查询路线的图片集合List<RouteImg>,放到Route对象里

    返回Route对象

    得到结果Route对象

    把Route对象放到ResultInfo里,把ResultInfo转换成json,返回客户端页面

    3.在route_detail.html页面里处理结果

    得到路线信息对象route

    把路线的信息,显示到页面上

    把路线的图片,进行循环遍历,拼接成轮播图的HTML代码

    左边大图片:默认显示第一张

    在边小图片列表:

    循环每个图片,拼接显示小图片的html代码

    第一张图片,要增加一个类名:cur_img

    只显示前4张小图片,其它的图片要隐藏掉

    轮播图相关的事件代码,是未来元素绑定的

    方案一:把事件的代码改成未来元素绑定事件,麻烦

    方案二:把事件绑定的代码,放在轮播图HTML拼接显示完成之后,再手动绑定

    route_detail.html旅游线路详情页面获取传过来的rid数据,并提交异步请求到RouteServlet获取当前旅游线路对象 数据,并传递action请求类型和rid线路的标识符数据。获取到web后端servlet返回的数据之后,进行解析将返回的 数据更新数据到详情页面上指定的位置

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>路线详情</title> <link rel="stylesheet" type="text/css" href="css/bootstrap.min.css"> <link rel="stylesheet" type="text/css" href="css/common.css"> <link rel="stylesheet" type="text/css" href="css/route-detail.css"> </head> <body> <!--引入头部--> <div id="header"></div> <!-- 详情 start --> <div class="wrap"> <div class="bread_box"> <a href="/">首页</a> <span> ></span> <a href="#">国内游</a><span> ></span> <a href="#">全国-曼谷6-7天自由行 泰国出境旅游 特价往返机票自由行二次确认</a> </div> <div class="prosum_box"> <dl class="prosum_left"> <dt> <img alt="" class="big_img" src="http://www.jinmalvyou.com/Public/uploads/goods_img/img_size4/201703/m49788843d72171643297ccc033d9288ee.jpg"> </dt> <dd> <a class="up_img up_img_disable"></a> <a title="" class="little_img" data-bigpic="http://www.jinmalvyou.com/Public/uploads/goods_img/img_size4/201703/m40920d0669855e745d97f9ad1df966ebb.jpg"> <img src="http://www.jinmalvyou.com/Public/uploads/goods_img/img_size2/201703/m20920d0669855e745d97f9ad1df966ebb.jpg"> </a> <a title="" class="little_img cur_img" data-bigpic="http://www.jinmalvyou.com/Public/uploads/goods_img/img_size4/201703/m49788843d72171643297ccc033d9288ee.jpg"> <img src="http://www.jinmalvyou.com/Public/uploads/goods_img/img_size2/201703/m29788843d72171643297ccc033d9288ee.jpg"> </a> <a title="" class="little_img" data-bigpic="http://www.jinmalvyou.com/Public/uploads/goods_img/img_size4/201703/m4531a8dbceefa2c44e6d0e35627cd2689.jpg"> <img src="http://www.jinmalvyou.com/Public/uploads/goods_img/img_size2/201703/m2531a8dbceefa2c44e6d0e35627cd2689.jpg"> </a> <a title="" class="little_img" data-bigpic="http://www.jinmalvyou.com/Public/uploads/goods_img/img_size4/201703/m46d8cb900e9f6c0a762aca19eae40c00c.jpg"> <img src="http://www.jinmalvyou.com/Public/uploads/goods_img/img_size2/201703/m26d8cb900e9f6c0a762aca19eae40c00c.jpg"> </a> <a title="" class="little_img" data-bigpic="http://www.jinmalvyou.com/Public/uploads/goods_img/img_size4/201703/m45ea00f6eba562a767b5095bbf8cffe07.jpg" style="display:none;"> <img src="http://www.jinmalvyou.com/Public/uploads/goods_img/img_size2/201703/m25ea00f6eba562a767b5095bbf8cffe07.jpg"> </a> <a title="" class="little_img" data-bigpic="http://www.jinmalvyou.com/Public/uploads/goods_img/img_size4/201703/m4265ec488cd1bc7ce749bc8c9b34b87bc.jpg" style="display:none;"> <img src="http://www.jinmalvyou.com/Public/uploads/goods_img/img_size2/201703/m2265ec488cd1bc7ce749bc8c9b34b87bc.jpg"> </a> <a title="" class="little_img" data-bigpic="http://www.jinmalvyou.com/Public/uploads/goods_img/img_size4/201703/m4e7e964909d7dd1a9f6e5494d4dc0c847.jpg" style="display:none;"> <img src="http://www.jinmalvyou.com/Public/uploads/goods_img/img_size2/201703/m2e7e964909d7dd1a9f6e5494d4dc0c847.jpg"> </a> <a title="" class="little_img" data-bigpic="http://www.jinmalvyou.com/Public/uploads/goods_img/img_size4/201703/m467db00e1b76718fab0fe8b96e10f4d35.jpg" style="display:none;"> <img src="http://www.jinmalvyou.com/Public/uploads/goods_img/img_size2/201703/m267db00e1b76718fab0fe8b96e10f4d35.jpg"> </a> <a title="" class="little_img" data-bigpic="http://www.jinmalvyou.com/Public/uploads/goods_img/img_size4/201703/m487bbbc6e43eba6aa6a36cc1a182f7a20.jpg" style="display:none;"> <img src="http://www.jinmalvyou.com/Public/uploads/goods_img/img_size2/201703/m287bbbc6e43eba6aa6a36cc1a182f7a20.jpg"> </a> <a class="down_img down_img_disable" style="margin-bottom: 0;"></a> </dd> </dl> <div class="prosum_right"> <p class="pros_title">【尾单特卖】全国-曼谷6-7天自由行 泰国出境旅游 特价往返机票自由行二次确认</p> <p class="hot">1-2月出发,网付立享¥1099/2人起!爆款位置有限,抢完即止!</p> <div class="pros_other"> <p>经营商家 :黑马国旅</p> <p>咨询电话 : 400-618-9090</p> <p>地址 : 传智播客黑马程序员</p> </div> <div class="pros_price"> <p class="price"><strong>¥2699.00</strong><span>起</span></p> <p class="collect"> <!--变成禁用:增加类,类名是already; 增加属性,disabled="disabled"--> <a class="btn" onclick="addFavorite()"><i class="glyphicon glyphicon-heart-empty"></i>点击收藏</a> <!--<a class="btn already" disabled="disabled"><i class="glyphicon glyphicon-heart-empty"></i>点击收藏</a>--> <span>已收藏100次</span> </p> </div> </div> </div> <div class="you_need_konw"> <span>旅游须知</span> <div class="notice"> <p>1、旅行社已投保旅行社责任险。建议游客购买旅游意外保险 <br> <p>2、旅游者参加打猎、潜水、海边游泳、漂流、滑水、滑雪、滑草、蹦极、跳伞、滑翔、乘热气球、骑马、赛车、攀岩、水疗、水上飞机等属于高风险性游乐项目的,敬请旅游者务必在参加前充分了解项目的安全须知并确保身体状况能适应此类活动;如旅游者不具备较好的身体条件及技能,可能会造成身体伤害。</p> <p>3、参加出海活动时,请务必穿着救生设备。参加水上活动应注意自己的身体状况,有心脏病、冠心病、高血压、感冒、发烧和饮酒及餐后不可以参加水上活动及潜水。在海里活动时,严禁触摸海洋中各种鱼类,水母,海胆,珊瑚等海洋生物,避免被其蛰伤。老人和小孩必须有成年人陪同才能参加合适的水上活动。在海边游玩时,注意保管好随身携带的贵重物品。</p> <p>4、根据中国海关总署的规定,旅客在境外购买的物品,在进入中国海关时可能需要征收关税。详细内容见《中华人民共和国海关总署公告2010年第54号文件》。</p> <p>5、建议出发时行李托运,贵重物品、常用物品、常用药品、御寒衣物等请随身携带,尽量不要托运。行李延误属于不可抗力因素,我司将全力协助客人跟进后续工作,但我司对此不承担任何责任。</p> <p>1、旅行社已投保旅行社责任险。建议游客购买旅游意外保险 <br> <p>2、旅游者参加打猎、潜水、海边游泳、漂流、滑水、滑雪、滑草、蹦极、跳伞、滑翔、乘热气球、骑马、赛车、攀岩、水疗、水上飞机等属于高风险性游乐项目的,敬请旅游者务必在参加前充分了解项目的安全须知并确保身体状况能适应此类活动;如旅游者不具备较好的身体条件及技能,可能会造成身体伤害。</p> <p>3、参加出海活动时,请务必穿着救生设备。参加水上活动应注意自己的身体状况,有心脏病、冠心病、高血压、感冒、发烧和饮酒及餐后不可以参加水上活动及潜水。在海里活动时,严禁触摸海洋中各种鱼类,水母,海胆,珊瑚等海洋生物,避免被其蛰伤。老人和小孩必须有成年人陪同才能参加合适的水上活动。在海边游玩时,注意保管好随身携带的贵重物品。</p> <p>4、根据中国海关总署的规定,旅客在境外购买的物品,在进入中国海关时可能需要征收关税。详细内容见《中华人民共和国海关总署公告2010年第54号文件》。</p> <p>5、建议出发时行李托运,贵重物品、常用物品、常用药品、御寒衣物等请随身携带,尽量不要托运。行李延误属于不可抗力因素,我司将全力协助客人跟进后续工作,但我司对此不承担任何责任。</p> </div> </div> </div> <!-- 详情 end --> <!--引入头部--> <div id="footer"></div> <!-- jQuery (necessary for Bootstrap's JavaScript plugins) --> <script src="js/jquery-3.3.1.js"></script> <!-- Include all compiled plugins (below), or include individual files as needed --> <script src="js/bootstrap.min.js"></script> <script src="js/getParameter.js"></script> <!--导入布局js,共享header和footer--> <script type="text/javascript" src="js/include.js"></script> <script> //1. 接收参数rid var rid = getParameter("rid"); //2. 发Ajax请求,得到rid对应的路线信息,显示 $.post("route","action=routeDetail&rid="+rid, function(result){ if (result.ok) { var route = result.data; //1. 显示路线本身信息 //1.1 显示路线名称 $(".pros_title").html(route.rname); //1.2 显示路线介绍 $(".hot").html(route.routeIntroduce); //1.3 显示路线价格 $(".price strong").html("¥" + route.price); //1.4 显示收藏数量 $(".collect span").html("已收藏"+route.count+"次"); //2. 显示商家信息 var seller = route.seller; $(".pros_other").html("<p>经营商家 :"+seller.sname+"</p>\n" + " <p>咨询电话 : "+seller.consphone+"</p>\n" + " <p>地址 : "+seller.address+"</p> "); //3. 显示分类信息 var category = route.category; $(".bread_box").html("<a href=\"index.html\">首页</a> <span> ></span>\n" + " <a href=\"route_list.html?cid="+category.cid+"\">"+category.cname+"</a><span> ></span>\n" + " <a href=\"#\">"+route.rname+"</a>"); //4. 显示图片列表 var images = route.routeImgList; //4.1 显示左边的大图片:路线的第一张图片 $(".big_img").attr("src", images[0].bigPic); //4.2 显示右边所有的小图片:拼接html代码 var imagehtml = "<a class=\"up_img up_img_disable\"></a>"; for (var i = 0; i < images.length; i++) { //从索引i的值为4开始,都隐藏不显示 var showStyle = i>=4?"style='display:none;'":""; var curClass = i===0?"cur_img":""; imagehtml += "<a title=\"\" "+showStyle+" class=\"little_img "+curClass+"\" data-bigpic=\""+images[i].bigPic+"\">\n" + " <img src=\""+images[i].smallPic+"\">\n" + " </a>"; } imagehtml += "<a class=\"down_img down_img_disable\" style=\"margin-bottom: 0;\"></a>"; $(".prosum_left dd").html(imagehtml); //给图片元素绑定事件 imageGo(); }else { alert(result.msg); } },"json"); //3. 发Ajax请求,判断路线是否被收藏。如果已经收藏,把按钮设置为禁用状态 $.post("favorite","action=isFavorite&rid="+rid, function(result){ if (result.ok) { var isFavorite = result.data; if (isFavorite) {//已收藏,按钮设置为禁用状态。加类already, 加属性disabled $(".btn").addClass("already").attr("disabled", "disabled").removeAttr("onclick"); } }else { alert(result.msg); } }, "json"); /** * 添加收藏 */ function addFavorite(){ $.post("favorite","action=addFavorite&rid="+rid, function(result){ if (result.ok) { var v = result.data; if (v === -1) {//收藏失败 alert("收藏失败,请联系系统管理员"); }else if (v === -2) {//未登录 location.href = "login.html"; }else{//收藏成功,v的值就是最新的收藏数量 $(".collect span").html("已收藏"+v+"次"); $(".btn").addClass("already").attr("disabled", "disabled").removeAttr("onclick"); } }else { alert(result.msg); } },"json"); } function imageGo() { //焦点图效果 //点击图片切换图片 $('.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()", 2000); } //自动轮播方法 function auto_play() { var cur_index = $('.prosum_left dd').find('a.cur_img').index(); cur_index = cur_index - 1; var num = $('.little_img').length; var max_index = 3; if ((num - 1) < 3) { max_index = num - 1; } if (cur_index < max_index) { var next_index = cur_index + 1; var big_pic = $('.little_img:eq(' + next_index + ')').data('bigpic'); $('.little_img').removeClass('cur_img'); $('.little_img:eq(' + next_index + ')').addClass('cur_img'); $('.big_img').attr('src', big_pic); } else { var big_pic = $('.little_img:eq(0)').data('bigpic'); $('.little_img').removeClass('cur_img'); $('.little_img:eq(0)').addClass('cur_img'); $('.big_img').attr('src', big_pic); } } </script> </body> </html>

    代码实现:

     

    二、判断是否收藏

    要求:

    当打开route_detail.html详情页面时,“收藏”按钮默认是可用的,点击能够收藏

    自动发Ajax判断路线是否被收藏

    如果被收藏了:显示禁用的“收藏”按钮,点击的时候不能添加收藏

    分析:

    什么时候,路线是被收藏了呢?

    如果是未登录状态,我们认识是“未收藏”的,可以收藏的

    如果登录了,判断tab_favorite表里是否有数据:uid为当前用户,rid是当前路线

    如果找到数据了:是收藏了

    如果没有找到:是未收藏

    步骤:

    1. 页面route_detail.html加载完成,自动发Ajax请求到Servlet

    请求到Servlet,让Servlet判断,路线是否被收藏了

    请求时,需要传参:rid

    2. Servlet里:处理请求,判断是否收藏,返回结果给页面

    如果是未登录:返回结果“未收藏”

    如果是已登录:

    接收参数:rid

    根据rid和登录的User,调用Service,判断有没有收藏数据

    如果有收藏数据,说明是已经收藏了,返回结果:“已收藏”

    如果没有收藏数据,返回结果“未收藏”

    把结果放到ResultInfo里,转换成json,返回客户端

    3. 在route_detail.html页面里,接收处理结果

    如果是“已收藏”状态:

    把“收藏”按钮设置为禁用状态:增加类名"already",增加属性disabled="disabled"

    去掉按钮上绑定的单击事件:删除onclick属性

    三、添加收藏(带事务)

    要求:

    用户在“路线详情”页面上,点击“添加收藏”按钮,要添加收藏

    如果添加成功:

    页面上要显示:最新的收藏数量

    把“添加收藏”按钮禁用掉,单击事件删除

    分析:

    如果是未登录状态,要如何处理?

    跳转到登录页面

    怎样实现添加收藏?

    在tab_favorite表里插入一条记录

    修改tab_route表里count字段,值要加1

    需要使用事务管理添加收藏的SQL执行

    步骤:

    1. 在route_detail.html页面上,发Ajax请求到Servlet

    用户点击“添加收藏“按钮,向Servlet发Ajax请求

    发请求的时候,要传参路线的id:rid

    2. 在Servlet里:处理请求,添加收藏,返回结果到页面

    判断有没有登录,如果没有登录,结果:-1

    如果已登录,添加收藏

    调用Service,添加收藏,得到结果

    在Service里,要使用事务进行管理

    开启事务

    添加收藏记录

    修改收藏记录+1

    关闭事务:

    如果没有异常,提交事务,返回true

    如果有异常,回滚事务,返回false

    得到添加收藏的结果:boolean(成功是true,失败是false)

    如果添加收藏成功:

    查询最新的收藏数量:调用之前写好的RouteService里的方法,查询路线,得到收藏数量

    把最新收藏数量放到ResultInfo里

    如果添加收藏失败:

    向ResultInfo里放结果:-2

    把ResultInfo转换成json,返回客户端

    3. 在route_detail.html页面里,接收并处理结果

    如果结果是-1:未登录状态

    跳转到登录页面

    如果结果是-2:收藏失败

    弹窗提示:收藏失败,请重试或联系管理员

    如果是其它值:收藏成功,这个值就是最新的收藏数量

    把收藏数量显示到页面上

    把“添加收藏”按钮设置为禁用状态,去掉按钮上的单击事件

    四、其它

    1. 注册时用户名是否已经存在的校验

    在页面上validator校验中增加:

    表单jQuery对象.validate({    submitHandler:function(form){},    rules:{        username:{            ......,            //如果服务端传回值是true,说明是校验通过了;否则是校验不通过            romote:"校验的地址,不需要传参数username的值"       }   },    messages:{        username:{            ......,            remote:"用户名已存在"       }   } });

    2. debug调试

    2.1 idea的debug

    以debug模式启动,才能够进行debug调试

     

    debug调试的操作:

    debug调试的关键:

    在于对程序运行的整体掌握,需要自己明白程序运行的正确预期效果。拿预期效果和debug调试看到的结果对比,哪一步不一样了,就说明哪一步出问题了

    2.2 浏览器里debug调试js

    打断点:在F12的sources,在窗口左边找到页面,点击页面,中间就会显示页码的代码。在行号上点击打断点

    3. 多表查询回顾

    3.1 多表查询的步骤

    把多表关联合并成一张表:一定要有表之间的关联条件

    再使用单表查询的技巧,查询合并之后的大表

    3.2 多表查询方式

    内连接查询

    效果:查询表之间必定有关联的数据

    语法:

    显式内连接:select * from 表1 inner join 表2 on 表关联条件 where 过滤条件

    隐式内连接:select * from 表1, 表2 where 表关联条件 and 过滤条件

    外连接查询

    效果:查询一张表的全部数据,以及另外一张表的关联数据

    左外连接:查询左表的全部数据,及右表的关联数据

    select * from 表1 left join 表2 on 表关联条件 where 过滤条件

    右外连接:查询右表的全部数据,及左表的关联数据

    select * from 表1 right join 表2 on 表关联条件 where 过滤条件

    子查询

    没有固定语法,是一种查询技巧。多个SQL嵌套

    子查询结果是:一个值

    -- 查询id为3的员工的部门信息 select * from dept where id = (select dept_id from emp where id = 3)

    子查询结果是:一个集合

    -- 查询工资大于5000的员工 所属的部门信息 select * from dept where id in (select dept_id from emp where salary > 5000)

    子查询结果是:一张虚拟表

    -- 查询工资大于5000的员工 和 所属部门的信息 select * from dept d, (select * from emp where salary > 5000) t where d.id = t.dept_id;

     

    4. 事务

    4.1 事务作用

    保证事务里的多个操作,要么全部成功,要么全部失败

    4.2 JDBC的事务管理

    JDBC的事务管理,是基于Connection对象的

    相关的API:

    开启事务的方法:connection.setAutoCommit(false)

    提交事务的方法:connection.commit()

    回滚事务的方法:connection.rollback()

    事务管理的步骤

    try{   1.注册驱动   2.获取连接   ===开启事务===   3.创建SQL执行平台   4.执行SQL语句:可以执行多条   5.处理结果 ===关闭事务:提交事务=== }catch(Exception e){ ===关闭事务:回滚事务=== }finally{ 6.释放资源 }

    4.3 JDBCTemplate的事务管理

    JDBCTemplate是Spring框架的一部分,事务管理的步骤非常麻烦。

    目前只需要能够实现JDBCTemplate事务管理的效果即可。

    如果是完整的Spring框架,可以实现声明式事务管理

    最新回复(0)