殷-黑马旅游第3天V3


typora-copy-images-to: img

day03-黑马旅游

学习目标

  • 能够完成国内游数据列表分页查询
  • 能够完成头部搜索框关键字搜索线路列表功能
  • 能够完成查看旅游线路详情案例
  • 能够完成添加收藏案例
  • 能够完成查看我的收藏案例

第一章 国内游数据列表分页查询

1.1 需求分析

​ 点击页面导航栏位置“国内游”后,分页显示符合数据的数据列表。

1.2 实现效果

在这里插入图片描述

1.3 实现分析

​ 由于线路数据过多需要使用分页技术展示数据。页面上显示的分页结果可以分为两部分,分页数据和分页条。所以,这个查询分两部分实现:

  1. 分页数据实现:分页数据是从数据库中通过sql:select * from tab_route limit n1,n2 。其中n1是起始记录数索引(startCount),n2是每页显示的数据量(pageSize);
  2. 分页条实现:分页条中需要查询的数据是总记录数(totalCount),根据总记录数可以计算出总页数(totalPage)。总页数计算出来后便可遍历生成分页按钮和上一页以及下一页等数据;

​ 由于分页功能实现结构比较复杂,我们学习需要分成静态分页实现、动态分页实现、优化PageBean工个步骤来实现。首先我们实现静态分页,所谓静态分页就是数据都是模拟的,并不是来自于数据库实现的分页效果模拟。

1.4 静态分页实现

1.4.1 分页数据查询

​ 分页数据查询使用关键字limit,需要两个参数:startCountpageSize 。其中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>&yen;</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>&yen;</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为结束也

  1. 如果总页数<=10,那么
    begin=1
    end=totalPage
  2. 如果总页数>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>&yen;</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 实现步骤

  1. header.html代码,点击搜索框提交搜索关键字跳转到rout_list.html并传递cid和搜索关键字
  2. route_list.html代码,获取搜索关键字,并提交到分页查询数据请求中,保证每个分页请求都要增加搜索内
    容提交请求参数。
  3. RouteServlet.java代码,获取到搜索内容数据,并查询分页数据方法增加搜索内容参数传递。
  4. RouteService.java代码,获取总记录数据和当前页数据列表方法中增加搜索内容参数传递。
  5. 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 实现步骤

  1. route_list.html代码,route_list.html旅游线路列表页面中每个旅游线路的“查看详情”,点击请求跳转到
    route_detail.html旅游线路详情页面,并传递旅游线路标识符rid=X;
  2. route_detail.html代码,route_detail.html旅游线路详情页面获取传过来的rid数据,并提交异步请求到
    RouteServlet获取当前旅游线路对象数据,并传递requestMethod请求类型和rid线路的标识符数据。获取到web后端servlet返回的数据之后,进行解析将返回的数据更新数据到详情页面上指定的位置。
  3. RouteServlet.java代码,RouteServlet是后端处理根据rid获的旅游线路对象数据的请求,首先获取rid数据,
    并调用业务类RouteService的相关方法实现获取旅游线路数据业务。
  4. RouteService.java代码,RouteService业务类根据传递过来的rid数据调用数据访问类RouteDao相关方法实
    现数据库获取Route旅游线路对象数据,之后根据rid还要获取当前旅游线路的图片列表数据封装到Route对象
    中。最后返回Route对象给业务类RouteService。
  5. 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;
    }
  });

}

第四章 今日作业

  1. 能够完成国内游线路分页查询;
  2. 能够完成头部关键字搜索旅游线路功能;
  3. 能够完成线路详情查询功能;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值