接上篇黑马旅游网(番外1):“自动登录”,本篇博客介绍我对黑马旅游网项目的第 2 个扩展功能:用户收藏界面展示。在用户已经登录网站且收藏了一些旅游线路的情况下。点击页面 header 区域中的 我的收藏 即可跳转至收藏界面。
这里需要处理两种特殊情况:1. 用户尚未登陆;2. 用户没有收藏任何旅游线路。在前端都要给与相应的提示信息。
收藏列表中的很多功能细节和之前实现的功能具备较大的重复度,但是整个业务逻辑和之前比还是存在区别,对数据库的查询要比之前稍微复杂一些。先不考虑未登录/无收藏等特殊情况,一般情况下,首先要查询当前登录用户的收藏内容,这一步需要查询 tab_favorite 表,这张表关联了 uid 和 rid:
将当前登录用户的 uid 作为查询条件,查找满足约束的所有记录的 rid 。再将 rid 作为查询条件去 tab_route 表中做分页查询相应的旅游线路信息。参考黑马旅游网(5):旅游线路分页展示,后端的查询结果是将 PageBean<Route> 转换为 json 形式响应给客户端浏览器,前端再做处理和展示,功能完成。
用户身份的获取方式我总结为两种:
后端:从 Session 中直接获取 User bean 对象,进而获取 uid;前端:利用后端之前返回的登录用户 json 数据,抓取 uid 并以 GET 请求方式提交给后端,后端采用 getParameter() 方法获取到 uid。在我的代码中使用后端方式获取,实现起来也相对容易。
可以通过一张简图理解 另外,查询用户收藏内容时,在 Dao 层需要定专门在 domain 包中义一个 Bean 对象接收收藏数据。
public class MyFavorite { private int uid; private String date; private int rid; /* setter & getter */ }UserServlet.java
/** * 获取`我的收藏`方法 */ public void findMyFavorite(HttpServletRequest request, HttpServletResponse response) throws IOException { // 获取session,取得用户对象 HttpSession session = request.getSession(); User user = (User) session.getAttribute("user"); if (user == null) { // 用户未登录 writeValue(null, response); return; } // 获取并处理浏览器请求属性 String currentPageStr = request.getParameter("currentPage"); // 当前页数 String pageSizeStr = request.getParameter("pageSize"); // 每页显示条数 int currentPage = this.parseInt(currentPageStr, 1); int pageSize = this.parseInt(pageSizeStr, 8); // 2.获取service,根据uid查rid,再根据rid查详情数据 PageBean<Route> routePageBean = service.favorPageQuery(user.getUid(), currentPage, pageSize); // 3.将数据回写至浏览器 writeValue(routePageBean, response); }UserServiceImpl.java
/** * 查询`我的收藏` * @param uid 用户uid * @return 泛型为Route类的PageBean对象, * 收藏结果的分页展示 */ @Override public PageBean<Route> favorPageQuery(int uid, int currentPage, int pageSize) { // 创建PageBean<Route>对象 PageBean<Route> routePageBean = new PageBean<>(); // 查询总记录数totalCount int totalCount = favoriteDao.findCountByUid(uid); if (totalCount == 0) {// 没有查到收藏记录 return routePageBean; } // 计算起始记录数start,计算总页数totalPage int start = (currentPage - 1) * pageSize; int totalPage = (totalCount % pageSize == 0) ? (totalCount / pageSize) : (totalCount / pageSize + 1); // 分页查询rid列表(封装在MyFavorite类中) List<MyFavorite> pageFavoriteList = favoriteDao.findByUidAndPage(uid, start, pageSize); // 创新一个空的List<Route>集合 List<Route> routeList = new ArrayList<>(); // 遍历pageFavoriteList组装routeList for (MyFavorite myFavorite : pageFavoriteList) { // 根据其rid属性利用routeDao查route对象 Route route = routeDao.findOne(myFavorite.getRid()); // 向routeList中追加route属性 routeList.add(route); } // 并组装PageBean<Route>对象 routePageBean.setCurrentPage(currentPage); // 设置当前页码 routePageBean.setPageSize(pageSize); // 设置每页显示条数 routePageBean.setTotalPage(totalPage); // 设置总页数 routePageBean.setTotalCount(totalCount); // 查询并设置总记录数 routePageBean.setList(routeList); return routePageBean; }FavoriteDaoImpl.java
/** * 查询用户uid的收藏总数 * @param uid 用户uid * @return 收藏路线总数 */ @Override public int findCountByUid(int uid) { String sql = "SELECT COUNT(*) FROM tab_favorite WHERE uid = ?"; return template.queryForObject(sql, Integer.class, uid); } /** * 分页查询用户uid的收藏记录 * @param uid 用户uid * @param start 起始条目 * @param pageSize 每页显示条数 * @return MyFavorite Bean 对象构成的 List 集合 */ @Override public List<MyFavorite> findByUidAndPage(int uid, int start, int pageSize) { String sql = "SELECT * FROM tab_favorite WHERE uid = ? LIMIT ? , ?"; return template.query(sql, new BeanPropertyRowMapper<>(MyFavorite.class), uid, start, pageSize); }RouteDaoImpl.java (复用之前的线路信息查询代码)
/** * 根据线路id查询详细信息 * @param rid 线路id * @return Route Bean 对象 */ @Override public Route findOne(int rid) { String sql = "SELECT * FROM tab_route WHERE rid = ?"; return template.queryForObject(sql, new BeanPropertyRowMapper<>(Route.class), rid); }前端这里我基本参考之前的旅游线路分页展示的代码实现的。主体逻辑就是页面跳转来后,执行一个 AJAX 请求向后端要数据,提交请求时需要传递 currentPage,后端默认处理为 1。接收 json 形式的 PageBean 对象:
PageBean 为空:说明用户没有登录,给与相应的提示信息PageBean 中的 totalCount 属性为 0,说明用户没有收藏任何线路,给与相应的提示信息正常情况,参考分页线路展示实现即可,这里对这种情况不再做具体展示,可以参考黑马旅游网(5):旅游线路分页展示,或者访问我的 GitHub 仓库 阅读。myfavorite.html
/** * 我的收藏分页展示 */ $(function () { let currentPage = getParameter("currentPage"); load(currentPage); }); function load(currentPage) { $.get("user/findMyFavorite", {currentPage: currentPage}, function (pageBean) { // 解析pageBean数据,展示到页面上 if (pageBean == null) { // 可以添加一些渲染,由于我主学后端,这里就不展开了 $("#favorite_routes").html('<span id="notlogin">您尚未登录,请<a href="login.html"> 【【登录】 </a></span>'); } if (pageBean["totalCount"] === 0) { // 可以添加一些渲染,由于我主学后端,这里就不展开了 $("#favorite_routes").html('<span id="nofavorite">您还没有任何收藏哦,去看一看线路列表吧</span>'); } /*分页栏展示*/ /*旅游线路展示*/ }); }项目课程链接:https://www.bilibili.com/video/BV1CE411E7h4 完整课程连接:https://www.bilibili.com/video/BV1uJ411k7wy 《黑马旅游网》系列博客及笔者源码传送门:https://blog.csdn.net/xing123456jl/article/details/109173068