欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JavaWeb - 黑马旅游网(4):分类数据展示

程序员文章站 2022-04-03 21:41:46
...

项目课程链接:https://www.bilibili.com/video/BV1CE411E7h4
完整课程连接:https://www.bilibili.com/video/BV1uJ411k7wy

1 功能描述

接上篇黑马旅游网(3):登录与退出,本篇博客将分析和实现旅游线路分类内容的查询和展示。此功能旨在控制 banner 顶部的展示内容。如以下H5页面所示:

JavaWeb - 黑马旅游网(4):分类数据展示

2 功能分析

2.1 功能逻辑抽象

分类展示功能在逻辑上并不复杂:每当需要加载 <header> 标签中的内容时,都会向后端提交一个 GET 请求来获取分类数据内容。后端在收到请求后查询数据库并以 json 形式返回展示内容。

JavaWeb - 黑马旅游网(4):分类数据展示
查询旅游线路分类内的功能需要面向数据库中的另一张表 tab_category,为了区分不同类型的数据查询业务以及代码的维护性和扩展性。在开发时基于三层架构体系建立对应的 CategoryServlet 类、CategoryService 接口和实现类、CategoryDao 接口和实现类。

2.2 性能优化策略

不难发现,线路分类展示的内容在短时间内几乎不会发生改动。考虑引入 Redis 缓存数据,即降低数据库的负担,也提高了查询性能。

JavaWeb - 黑马旅游网(4):分类数据展示

3 代码实现

JavaWeb - 黑马旅游网(4):分类数据展示

3.2 后端

3.1.1 Servlet

在 CategoryServlet 类中定义查询所有线路分类内容的主体逻辑

public void findAll(HttpServletRequest request, HttpServletResponse response) throws IOException {
    // 1.调用service查询所有categories
    List<Category> categories = service.findAll();
    // 2.序列化json,并回写客户端浏览器
    this.writeValue(categories, response);
}

3.1.2 Service

在 CategoryServiceImpl 类中定义 findAll() 方法,定义旅游线路分类内容的具体查询业务逻辑

public List<Category> findAll() {
    // 1.从redis中查询,使用 sorted set 实现排序查询
    Set<Tuple> categories_cache = jedis.zrangeWithScores("category", 0, -1);
    // 2.判断查询结果是否为空
    List<Category> categories;
    if (categories_cache == null || categories_cache.size() == 0) {     // 空
        System.out.println("从数据库中查询...");
        // 从数据库中查询
        categories = dao.findAll();
        // 根据cid排序,保证从数据库结果和redis结果一致
        categories.sort(Comparator.comparingInt(Category::getCid));
        // 将数据存储到redis中
        for (Category category : categories) {
            jedis.zadd("category", category.getCid(), category.getCname());
        }
    } else {    // 非空
        System.out.println("从redis中查询...");
        // 统一输出数据类型,将从redis中拿到的字符串转为List<Category>形式
        categories = new ArrayList<>();
        for (Tuple tuple : categories_cache) {
            Category category = new Category();
            category.setCid((int) tuple.getScore());
            category.setCname(tuple.getElement());
            categories.add(category);
        }
    }
    return categories;
}

3.1.3 Dao

在 CategoryDaoImpl 类中定义 findAll() 方法,操作数据库查询 tab_category 表中的所有内容

public List<Category> findAll() {
    String sql = "SELECT * FROM tab_category";
    return template.query(sql, new BeanPropertyRowMapper<>(Category.class));
}

3.2 前端

后端程序执行顺利的话,返回的响应结果可以使用 FireFox 浏览器的自动 json 解析功能观察到以下效果。

JavaWeb - 黑马旅游网(4):分类数据展示

前端在加载 <header> 内容时便向后端提交异步请求。在 header.html 的 <script> 标签中定义以下 jQuery 代码:

/**
 * 查询分类数据信息
 */
$.get("category/findAll", {}, function (data) {
    // data: [{cid: 1, cname: 国内游}, {CategoryBean}, {CategoryBean}]
    let lis = '<li class="nav-active"><a href="index.html">首页</a></li>';
    // 遍历data数组,拼接字符串(<li>...</li>)
    for (let i = 0; i < data.length; i ++) {
        lis += '<li><a href="route_list.html?cid=' + data[i]["cid"] + '">' + data[i]["cname"] + '</a></li>';
    }
    // 拼接收藏排行榜<li><a href="favoriterank.html">收藏排行榜</a></li>
    lis += '<li><a href="favoriterank.html">收藏排行榜</a></li>';
    // 将lis字符串设置到ul的html内容中
    $("#category").html(lis);
});

其中 首页收藏排行榜 是固定的,所以添加在 H5 字符串中的首尾,而其他内容通过循环遍历解析后的 json 数据按照一定规律加入字符串。

部分代码并未完全展示,完整代码可以参考我的 GitHub 仓库