前端将后端list转换为json_猿进化系列17——实战之一文学会前后端分离套路

看完上一个章节,相信你已经掌握了一个高效无误地编写SQL的办法,学会了完成小项目的注册功能,对如何使用之前学过的一些知识有了一定的认识,今天我们继续学习,一起来搞懂前后端分离的套路。

       猿进化是一个原创系列文章,帮助你从一只小白快速进化为一个猿人,更多精彩内容,敬请大家关注公主号猿人工厂,点击猿人养成获取

6360b9bbadaac820848c37afe7dc8635.png

943b547e548c446757dbc695ac621783.png

c66f28a2c051b9d892749e33dd57ebcf.png

a839c6110383999d55bae75a6b510d85.png

963aebc10eaf28a1e45ba5c3914dbd74.png

dd614fd23644dd8309e16a19ca99eb01.png

34d4a983df2a1b64884a98d79dfb5fd2.png

a10cc5a93e21973704885304e41c931f.png

31a907356e6db490c73364c3c91c135f.png

a143de28836c137285d8b5bcf757427b.png

       在搞懂MVC框架原理一文中,上面这个MVC的模型图片大家应该有点印象了,客户端发起响应,服务端使用模板技术从当了view的角色,在服务端的应用服务器中渲染html,然后返回给客户端,客户端完成解析。

但实际上,对于浏览器而言,关心的只是html,css,js等元素,对于是谁返回给它的,它并不关心。浏览器解析html,完成样式渲染,加载运行脚本语言。在这个过程中,js是可以去改变页面结构的,也可以再次发起请求。那么问题就来了,js可以改变页面结构,那渲染页面html代码的事情,交给它不就完了?

从这个点考虑,前端脚本只用做两件事情就可以了——获取后端动态数据和改变html的页面结构。后端只用提供改变html的结构所需要的数据就好了。这样子,前端的开发人员可以只用关注前端的事情,后端的开发人员关注返回的数据,职责上明确了,程序的开发方式也就明确了。前端和后端程序的开发相对独立了,也就是所谓的前后端分离了。分离的是职责,是工作方式,具体使用什么技术,做到了就好,而不是框架,不是一堆技术名词……

2e0a606feb636eb8c465bce967ebdc9a.png

708b6eb0e3fd5284f90daea6b570e738.png

返回静态页面的事情,可以交给web服务器,在这种静态文件的处理能力上,web服务器比应用服务器强悍多了。浏览器获取到web服务器返回的静态资源,html,css,js……然后在渲染的过程中,js通常发起一个异步请求,到后端获取数据,至于为什么后端应用服务器中的程序返回JSON格式的数据,其实只是JSON是一种比较方便的能够序列化对象数据的格式而已,用其他的也可以,只是JSON格式的数据和javascript的对象和数组可以方便转换,用着比较方便。

 这样做了之后,页面还可以保留一些静态节点,即使后端程序挂了,这些静态节点的存在,也不影响页面的展示功能。

bdc88ba3fe793af7a0796773a0cb8653.png

1a01c8da5c366cce31b7617f81fcb8eb.png

动态导航栏

d69a5d9fa144fac2725ab1eed50267c4.png

导航栏属于公共头部的一部分,导航栏的内容,实际上属于ul标签下的li标签。想要动态的展示导航栏的内容,需要从数据库里查询分类数据(查询travel_category表),可以使用json的方式返回。页面需要解析json数据,拼接成导航内容的,然后将内容插入到ul标签下即可。

后端代码

package com.pz.route.dao; importjava.util.List; importcom.pz.route.domain.TravelCategory;  /** * * @author pangzi * */public interface TravelCategoryDao {    /**     * 查询所有     * @return     */    public ListfindAllTravelCategory();}
public class TravelCategoryDaoImpl implements TravelCategoryDao {     private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());     @Override    public ListfindAllTravelCategory() {        String sql = "select travel_cid,travel_name fromtravel_category ";        returntemplate.query(sql,newBeanPropertyRowMapper(TravelCategory.class));    }}
package com.pz.route.service; import java.util.List; import com.pz.route.domain.TravelCategory; public interface TravelCategoryService {     public ListfindAll();}
package com.pz.route.service.impl; import java.util.List; import com.pz.route.dao.TravelCategoryDao;import com.pz.route.dao.impl.TravelCategoryDaoImpl;import com.pz.route.domain.TravelCategory;import com.pz.route.service.TravelCategoryService; public class TravelCategoryServiceImpl implements TravelCategoryService {    //初始化数据访问接口    private TravelCategoryDao travelCategoryDao= new TravelCategoryDaoImpl();     @Override    public ListfindAll(){                List catrgoryList= null;                  //调用数据访问接口从数据库查询类目信息            catrgoryList =travelCategoryDao.findAllTravelCategory();                   return catrgoryList;    }}

编写类目servlet

package com.pz.route.web.servlet; import java.io.IOException;import java.util.List; import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse; import com.pz.route.domain.TravelCategory;import com.pz.route.service.TravelCategoryService;import com.pz.route.service.impl.TravelCategoryServiceImpl;//继承之前封装的BaseServlet通配符匹配所有/category/的路径@WebServlet("/category/*")public class CategoryServlet extends BaseServlet {//初始化service接口    private TravelCategoryService service = new TravelCategoryServiceImpl();     /**     * 查询所有     * @param request     * @param response     * @throws ServletException     * @throws IOException     */    publicvoidfindAll(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        //1.调用service查询所有        List<TravelCategory> cs = service.findAll();        //返回json数据       responseJson(cs,response);     } }

前端脚本

$.get("category/findAll",{},function (data) {             //通过url获取travelCid参数,决定哪个分类被选中             var reg = new RegExp('(^|&)' + cid + '=([^&]*)(&|$)', 'i');             var r =window.location.search.substr(1).match(reg);                         var cid=null;             var lis ='';             cid=getUrlParam("cid");                        //[{travelCid:1,travelCname:国内游},{},{}]            if(cid==null){                lis= '首页';            }else{                lis= '首页';            }            //遍历数组,拼接字符串()            for (var i = 0; i < data.length; i++) {                var li ='';                if(cid!=null&&cid==data[i].travelCid){                        var li = ''+data[i].travelCname+'';                }                else{                       li= '+data[i].travelCid+'">'+data[i].travelCname+'';                }                 lis += li;                           }                        //拼接收藏排行榜的li,收藏排行榜                       lis+= '收藏排行榜';             //将lis字符串,设置到ul的html内容中            $("#category").html(lis);            $(window).trigger("categoryLoaded");        });
分类列表页面

86e01c3264e1226a336f3065cfb74ed8.png

我们在动态生成的导航栏上加了a标签,点击之后页面会发生跳转到分类列表页面,所以我们需要编写一个新的页面——分类列表页面。页面跳转时,浏览器会发起get请求,将类目的id传过来,所以我们通过分类id来确定列表页面需要展示哪个分类下线路信息的数据,后端程序完成线路数据的查询,返回给列表页。由于线路的数据包含:线路基本信息、线路图片信息、线路商家信息、线路收藏信息、所以一次操作可能涉及多个表的数据。因为某个类型的线路信息可能很多,一次也没必要展示完全,所以列表页下方,有分页标记,我们浏览数据需要像“翻书”一样查看。也就是说,我们需要设定分页的大小,每一次,获取每一页的数据就好了。

后端代码

package com.pz.route.domain; import java.util.List; /** * 分页列表对象在list基础长增加分页的参数 * @author pangzi * * @param */public class PageList {     private int totalCount;//总记录数    private int totalPage;//总页数    private int currentPage;//当前页码    private int pageSize;//每页显示的条数     private Listlist;//每页显示的数据集合     publicintgetTotalCount() {        returntotalCount;    }     publicvoid setTotalCount(int totalCount) {        this.totalCount =totalCount;    }     publicint getTotalPage(){        returntotalPage;    }     publicvoid setTotalPage(int totalPage) {        this.totalPage = totalPage;    }     publicintgetCurrentPage() {        returncurrentPage;    }     publicvoidsetCurrentPage(int currentPage) {        this.currentPage =currentPage;    }     publicint getPageSize(){        returnpageSize;    }     publicvoid setPageSize(int pageSize) {        this.pageSize = pageSize;    }     public List getList() {        returnlist;    }     publicvoidsetList(Listlist) {        this.list = list;    }}
package com.pz.route.service; import com.pz.route.domain.PageList;import com.pz.route.domain.TravelRoute; /** * 线路Service */public interface TravelRouteService {     /**     * 根据类别进行分页查询     * @param travelRouteCid     * @param currentPage     * @param pageSize     * @param travelRouteName     * @return     */    publicPageListpageQuery(long travelRouteCid,int currentPage,intpageSize,String travelRouteName);     /**     * 根据id查询     * @param rid     * @return     */    public TravelRoutefindTravelRouteById(String travelRouteId);}
package com.pz.route.service.impl; import java.util.List; import com.pz.route.dao.TravelFavoriteDao;import com.pz.route.dao.TravelRouteDao;import com.pz.route.dao.TravelRouteImgDao;import com.pz.route.dao.TravelSellerDao;import com.pz.route.dao.impl.TravelFavoriteDaoImpl;import com.pz.route.dao.impl.TravelRouteDaoImpl;import com.pz.route.dao.impl.TravelRouteImgDaoImpl;import com.pz.route.dao.impl.TravelSellerDaoImpl;import com.pz.route.domain.PageList;import com.pz.route.domain.TravelRoute;import com.pz.route.domain.TravelRouteImg;import com.pz.route.domain.TravelSeller;import com.pz.route.service.TravelRouteService; public class TravelRouteServiceImpl implements TravelRouteService {    private TravelRouteDaotravelRouteDao = new TravelRouteDaoImpl();     private TravelRouteImgDaotravelRouteImgDao = new TravelRouteImgDaoImpl();     private TravelSellerDaotravelsellerDao = new TravelSellerDaoImpl();     private TravelFavoriteDaotravelFavoriteDao = new TravelFavoriteDaoImpl();     @Override    publicPageListpageQuery(long travelRouteCid,int currentPage,intpageSize,String travelRouteName) {        //创建分页bean        PageListpage = new PageList();               //设置默认当前页,默认为第一页        if(0==currentPage){             currentPage=1;        }               //设置默认分页大小,默认为10条每页        if(0==pageSize){             pageSize=10;        }               //设置当前页码       page.setCurrentPage(currentPage);        //设置每页显示条数        page.setPageSize(pageSize);               //设置线路总数        int totalCount =travelRouteDao.findTotalCount(travelRouteCid,travelRouteName);       page.setTotalCount(totalCount);        //设置当前页显示的数据集合,mysql分页第一个参数,从0开始        int start = (currentPage -1) * pageSize;        //返回符合查询条件的线路列表        Listlist = travelRouteDao.findTravelRouteByPage(travelRouteCid,start,pageSize,travelRouteName);        page.setList(list);         //计算总页数,需要考虑能除尽和不能除尽的情况,不能除尽的情况下,会多一页        int totalPage = totalCount% pageSize == 0 ? totalCount / pageSize :(totalCount / pageSize) + 1 ;       page.setTotalPage(totalPage);          return page;    }     @Override    public TravelRoutefindTravelRouteById(String travelRouteId) {        //1.根据线路id查询线路对象        TravelRoute travelRoute =travelRouteDao.findTravelRouteById(Long.parseLong(travelRouteId));         //2.根据线路id查询线路图片        ListrouteImgList =travelRouteImgDao.findByTravelRouteId(travelRoute.getTravelRouteId());             travelRoute.setRouteImgList(routeImgList);        //3.根据商家ID查询商家        TravelSeller seller =travelsellerDao.findTravelSellerById(travelRoute.getTravelRouteSellerId());       travelRoute.setSeller(seller);        //4. 查询收藏次数        int count =travelFavoriteDao.findCountByTravelRouteId(travelRoute.getTravelRouteId());       travelRoute.setTravelRouteCount(count);          return travelRoute;    }}
package com.pz.route.dao.impl; import com.pz.route.dao.TravelRouteDao;import com.pz.route.domain.TravelRoute;import com.pz.route.util.JDBCUtils;import org.springframework.jdbc.core.BeanPropertyRowMapper;import org.springframework.jdbc.core.JdbcTemplate; import java.util.ArrayList;import java.util.List; public class TravelRouteDaoImpl implements TravelRouteDao {    private JdbcTemplate template =new JdbcTemplate(JDBCUtils.getDataSource());     @Override    public int findTotalCount(longtravelRouteCid,String travelRouteName) {        //String sql = "selectcount(*) from tab_route where cid = ?";        //1.定义sql模板        String sql = "selectcount(*) from travel_route where 1=1 ";        StringBuilder sb = newStringBuilder(sql);         List params = newArrayList();//条件们        //2.判断参数是否有值        if(travelRouteCid != 0){            sb.append( " andtravel_route_cid = ? ");            params.add(travelRouteCid);//添加?对应的值        }         if(travelRouteName != null&& travelRouteName.length() > 0){            sb.append(" andtravel_route_name like ? ");            params.add("%"+travelRouteName+"%");        }         sql = sb.toString();          returntemplate.queryForObject(sql,Integer.class,params.toArray());    }     @Override    public ListfindTravelRouteByPage(long travelRouteCid , int start , int pageSize,StringtravelRouteName) {        //String sql = "select* from tab_route where cid = ? and rname like ? limit ? , ?";        String sql = " selecttravel_route_id,travel_route_name,travel_route_price,travel_route_introduce,travel_route_flag,travel_route_date,travel_route_count,travel_route_cid,travel_route_image,travel_route_seller_idfrom travel_route where 1 = 1 ";        //1.定义sql模板        StringBuilder sb = newStringBuilder(sql);         List params = newArrayList();//条件们        //2.判断参数是否有值        if(travelRouteCid != 0){            sb.append( " andtravel_route_cid = ? ");            params.add(travelRouteCid);//添加?对应的值        }         if(travelRouteName != null&& travelRouteName.length() > 0){            sb.append(" and travel_route_name likeconcat('%',?,'%') ");            params.add(travelRouteName);        }        sb.append(" limit ? ,? ");//分页条件         sql = sb.toString();         params.add(start);        params.add(pageSize);        return template.query(sql,newBeanPropertyRowMapper(TravelRoute.class),params.toArray());    }     @Override    public TravelRoutefindTravelRouteById(long travelRouteId) {        String sql = "selecttravel_route_id,travel_route_name,travel_route_price,travel_route_introduce,travel_route_flag,travel_route_date,travel_route_count,travel_route_cid,travel_route_image,travel_route_seller_idfrom travel_route where travel_route_id = ?";        returntemplate.queryForObject(sql,new BeanPropertyRowMapper(TravelRoute.class),travelRouteId);    }}
package com.pz.route.dao.impl; import com.pz.route.dao.TravelRouteImgDao;import com.pz.route.domain.TravelRouteImg;import com.pz.route.util.JDBCUtils;import org.springframework.jdbc.core.BeanPropertyRowMapper;import org.springframework.jdbc.core.JdbcTemplate; import java.util.List; public class TravelRouteImgDaoImpl implements TravelRouteImgDao {     private JdbcTemplate template =new JdbcTemplate(JDBCUtils.getDataSource());      @Override    publicListfindByTravelRouteId(long travelRouteId) {        String sql = "selecttravel_route_img_id,travel_route_id,travel_route_img_big_pic,travel_route_img_small_picfrom travel_route_img where travel_route_id = ? ";        returntemplate.query(sql,newBeanPropertyRowMapper(TravelRouteImg.class),travelRouteId);    }}
package com.pz.route.dao.impl; import com.pz.route.dao.TravelFavoriteDao;import com.pz.route.domain.TravelFavorite;import com.pz.route.util.JDBCUtils;import org.springframework.dao.DataAccessException;import org.springframework.jdbc.core.BeanPropertyRowMapper;import org.springframework.jdbc.core.JdbcTemplate; import java.util.Date; public class TravelFavoriteDaoImpl implements TravelFavoriteDao {     private JdbcTemplate template =new JdbcTemplate(JDBCUtils.getDataSource());     @Override    public TravelFavoritefindByTravelRouteIdAndUserId(long travelRouteId, long travelRouteUserId) {        TravelFavorite favorite =null;        try {            String sql = "select travel_route_id,travel_create_date,travel_user_id from travel_favoritewhere travel_route_id = ? and travel_user_id = ?";            favorite =template.queryForObject(sql, newBeanPropertyRowMapper(TravelFavorite.class),travelRouteId, travelRouteUserId);        } catch(DataAccessException e) {            e.printStackTrace();        }        return favorite;    }     @Override    public intfindCountByTravelRouteId(long travelRouteId) {        String sql = "SELECTCOUNT(*) FROM travel_favorite WHERE travel_route_id = ?";         return template.queryForObject(sql,Integer.class,travelRouteId);    }     @Override    public void add(longtravelRouteId, long travelUserId) {        String sql = "insertinto travel_favorite values(?,?,?)";        template.update(sql,travelRouteId,new Date(),travelUserId);    }}
package com.pz.route.dao.impl; import org.springframework.jdbc.core.BeanPropertyRowMapper;import org.springframework.jdbc.core.JdbcTemplate; import com.pz.route.dao.TravelSellerDao;import com.pz.route.domain.TravelSeller;import com.pz.route.util.JDBCUtils; public class TravelSellerDaoImpl implements TravelSellerDao {     private JdbcTemplate template =new JdbcTemplate(JDBCUtils.getDataSource());       @Override    public TravelSellerfindTravelSellerById(long travelSellerId) {         String sql = "selecttravel_seller_id,travel_seller_name,travel_seller_consphone,travel_seller_address  from travel_seller where travel_seller_id = ?";        returntemplate.queryForObject(sql,newBeanPropertyRowMapper(TravelSeller.class),travelSellerId);    }}

前端脚本

$(function () {           //获取cid的参数值           var cid = getUrlParam("cid");            //获取rname的参数值            var rname = getUrlParam("rname");            //判断rname如果不为null或者""            if(rname){                //url解码                rname =window.decodeURIComponent(rname);            }             //当页码加载完成后,调用load方法,发送ajax请求加载数据            load(cid,null,rname);        });         function load(cid ,currentPage,rname){            //发送ajax请求,请求route/pageQuery,传递cid            $.get("route/pageQuery",{cid:cid,currentPage:currentPage,rname:rname},function (pb) {                //解析pagebean数据,展示到页面上                 //1.分页工具条数据展示                //1.1 展示总页码和总记录数                $("#totalPage").html(pb.totalPage);                $("#totalCount").html(pb.totalCount);                var lis = "";                 var fristPage = '首页';                 //计算上一页的页码                var beforeNum = pb.currentPage - 1;                if(beforeNum <= 0){                    beforeNum = 1;                }                 var beforePage = '上一页';                 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){                    //总页码不够10页                     begin = 1;                    end = pb.totalPage;                }else{                    //总页码超过10页                    begin = pb.currentPage - 5;                    end = pb.currentPage + 4 ;                    //2.如果前边不够5个,后边补齐10个                    if(begin < 1){                        begin = 1;                        end = begin + 9;                    }                    //3.如果后边不足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 = '+cid+','+i+',\''+rname+'\')">'+i+'';                     }else{                        //创建页码的li                        li = ''+i+'';                    }                    //拼接字符串                    lis += li;                }                 var nextPage =null;lastPage=null;                if(pb.totalPage==1){                     lastPage = '末页';                      nextPage = '下一页';                }else{                   lastPage = '末页';                   nextPage='下一页';                }                 lis += nextPage;                lis += lastPage;                 //将lis内容设置到 ul                $("#pageNum").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 = '\n' +                        '                        
\n' + '
\n' + '

'

+route.travelRouteName+'\n' + '
\n' +
'

'

+route.travelRouteIntroduce+'\n' + '
\n' + '
\n' + '

\n'

+ ' ¥\n' + ' '+route.travelRoutePrice+'\n' + ' 起\n' + ' \n' + '

+route.travelRouteId+'">查看详情

\n' + '
\n' + ' '; route_lis += li; } $("#route").html(route_lis); //定位到页面顶部 window.scrollTo(0,0); }); } //根据传递过来的参数name获取对应的值functiongetUrlParam(name) { var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)","i"); var r = location.search.substr(1).match(reg); if (r!=null) return (r[2]); returnnull;}

      我建了一个群,诚心邀请喜欢技术的小伙伴们加入讨论。

ea9ad1094def958720d5cf0d40b3da2c.png

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值