【途牛旅游项目】05 - 导航功能,通过Redis缓存实现。


最终效果:

导航实现

在这里插入图片描述

1. 创建测试类,测试查询所有分类

//测试获取所有分类信息Category
public class TestCategoryService {
    
    
    @Test
    public void test01(){
    
    
        //创建业务对象
        CategoryService categoryService = new CategoryService();
        //所有的分类
        List<Category> categoryList=categoryService.findAll();
        //显示
        System.out.println(categoryList);
    }
}

2. 查询所有分类的service

//分类业务
public class CategoryService {
    
    
    private static CategoryDao categoryDao = GetDaoUtils.getMapper(CategoryDao.class);
    public List<Category> findAll() {
    
    

        //查询所有的分类数据
        List<Category> list =  categoryDao.findAll();
        return list;
    }
}

3. 创建对应的javabean对象

//分类信息Category
public class Category {
    
    
    private int cid;//分类id
    private String cname;//分类名称
	//省略get/set方法
}

4. dao和对应映射

CategoryDao

public interface CategoryDao {
    
    
    //获取所有的分类,按照升序排序
    //select * from tab_category order by cid asc;
    List<Category> findAll();

    //通过id查找Category
    //select * from  tab_category c where c.cid =1;
    Category findOneByCid(int cid);
}
<mapper namespace="com.xgf.dao.CategoryDao">
    <!-- 查找所有分类,按升序输出 -->
    <select id="findAll" resultType="com.xgf.bean.Category">
        select cid,cname from tab_category order by cid asc;
    </select>

    <!-- 通过id查找category -->
    <select id="findOneByCid" parameterType="int" resultType="com.xgf.bean.Category">
        select cid,cname from  tab_category c where c.cid =#{cid}
    </select>
</mapper>

5. 测试运行

运行结果:
Preparing: select cid,cname from tab_category order by cid asc;
Parameters:
Total: 8
[Category{cid=1, cname=‘门票’}, Category{cid=2, cname=‘酒店’}, Category{cid=3, cname=‘香港车票’}, Category{cid=4, cname=‘处境游’}, Category{cid=5, cname=‘国内游’}, Category{cid=6, cname=‘港澳游’}, Category{cid=7, cname=‘抱团定制’}, Category{cid=8, cname=‘全球自由行’}]

6. CategoryServlet

@WebServlet("/categoryServlet")
public class CategoryServlet extends HttpServlet {
    
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
            doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        //业务类
        CategoryService categoryService = new CategoryService();
        //获取所有的分类
        List<Category> categoryList=categoryService.findAll();
   
		//以json格式显示在页面上
        Msg msg = new Msg();
        msg.setCode(200);	//响应码
        msg.setData(categoryList);	//数据
        String json = new ObjectMapper().writeValueAsString(info);	//转换为json数据格式
        response.getWriter().println(json);	//响应到浏览器
    }
}

7. 导航jsp页面header.jsp

  • 通过ajax发送get请求
  • jquery的for循环
  • html()函数修改界面
  • js中字符串拼接,建议最外层用单引号,防止拼接字符串遇到双引号需要通过\转译
  • js中的字符串拼接变量的方式 ' + 变量名 + '
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<html>

<body>
<!-- 头部 start -->
<header id="header">
    <div class="top_banner">
        <img src="images/top_banner.jpg" alt="头部导航栏">
    </div>
    <div class="shortcut">
        <!-- 登录状态  -->
        <div class="login" style="margin-left: -100px">
            <%--            将session中的用户数据取出来 --%>
            <%--            判断用户对象是否为空  如果是提示请登录,否则显示用户信息--%>
            <!-- 登录显示  -->
            <c:if test="${user != null}">
                <span>欢迎使用,${user.username}</span>
                <a href="myfavorite.jsp" class="collection">我的收藏</a>
                <a href="${pageContext.request.contextPath}/loginOutServlet">退出</a>
            </c:if>
            <!-- 未登录显示  -->
            <c:if test="${user == null}">
                <span>您还没有登录</span>
                <a href="login.jsp">登录</a>
                <a href="register.jsp">注册</a>
            </c:if>

        </div>
    </div>
    <div class="header_wrap">
        <div class="topbar">
            <div class="logo">
                <a href="/"><img src="images/logo.jpg" alt=""></a>
            </div>
            <div class="search">
                <input name="" type="text" placeholder="请输入路线名称" class="search_input" autocomplete="off">
                <a href="javascript:;" class="search-button">搜索</a>
            </div>
            <div class="hottel">
                <div class="hot_pic">
                    <img src="images/hot_tel.jpg" alt="">
                </div>
                <div class="hot_tel">
                    <p class="hot_time">客服热线(9:00-6:00)</p>
                    <p class="hot_num">400-000-0000</p>
                </div>
            </div>
        </div>
    </div>
</header>

<!-- 头部 end -->
<!-- 首页导航 -->
<script src="js/jquery-1.11.0.min.js" type="text/javascript"></script>
<script type="text/javascript">
    //页面加载成功之后执行该函数
    $(function () {
     
     
        //ajax提交  这个data就是服务器返回的数据Msg
        $.get("categoryServlet", function (data) {
     
     
            if (data.code == 200) {
     
     
                var list = data.data;//获取分类数据
                //变量lis用于拼接导航的显示内容(分类)
                var lis = "";
                //拼接第一项首页
                lis += '<li class="nav-active"><a href="index.jsp">首页</a></li>'
                //循环所有的分类,加入到lis中
                for (var i = 0; i < list.length; i++) {
     
     
                    //在js中,建议在最外行用单引号,避免生成转译的\  list[i].cname获取分类名
                    var li = '<li><a href="route_list.html">' + list[i].cname + '</a></li>'
                    //拼接
                    lis += li
                }
                //拼接最后一项 收藏排行榜
                lis += ' <li><a href="favoriterank.html">收藏排行榜</a></li>'
                //将其显示在页面的ul中
                // $("#nav").html(lis)
                $("#nav").html(lis)
            }
        }, "json");
    })
</script>
<div class="navitem">
    <ul class="nav" id="nav">
        <%--   这里填入脚本查询分类li    --%>
    </ul>
</div>
</body>
</html>

8. 显示效果

在这里插入图片描述

2. 导航优化,实现Redis缓存管理导航

用Redis优化的原因和好处:
  分类的数据在每一次页面加载后都会重新请求数据库来加载,这种经常访问对数据库的压力比较大,而且类似分类的数据不会经常产生变化,所有可以使用redis来缓存这个数据。


Redis缓存流程
在这里插入图片描述
  查询数据先从Redis查询,如果是第一次查询,从Redis缓存没查到,查数据库,然后将数据保存到Redis缓存中,以后每次查询都是直接从Redis缓存中取数据,减少数据库的压力。

2.1 创建属性文件jedis.properties,用来配置连接Redis的基本信息(键值对)

maxTotal=100
maxIdle=15
url=localhost
port=6379

2.2 创建Jedis工具类,连接redis,读取propties文件键值对配置

public class JedisUtils {
    
    
    //单例模式 静态代码块只执行一次,因为创建会很消耗性能
    private static JedisPool pool;
    //静态代码在项目中,如果被使用只会加载一次
    static {
    
    

        //读src下的文件用类加载器的方式
        InputStream inputStream= JedisUtils.class.getClassLoader().getResourceAsStream("jedis.properties");

        //.properties文件专门的读取工具
        Properties properties = new Properties();
        try {
    
    
            //将流中的数据读成map
            properties.load(inputStream);
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }
        // 1:创建连接池的配置对象
        JedisPoolConfig config = new JedisPoolConfig();
        //设置最大链接数
        config.setMaxTotal(Integer.parseInt(properties.getProperty("maxTotal")));
        //设置空闲连接数  "3"
        config.setMaxIdle(Integer.parseInt(properties.getProperty("maxIdle")));
        //2:创建连接池
         pool = new JedisPool(config, properties.getProperty("url"), Integer.parseInt(properties.getProperty("port")));
    }
    public static Jedis getJedis() {
    
    
//        3:从连接池中获取一个连接
        Jedis jedis = pool.getResource();//获取一个连接
        return jedis;
    }

    public static void close(Jedis jedis) {
    
    
        if(jedis!=null){
    
    
            jedis.close();
        }
    }
}

2.3 修改CategoryServlet,通过Redis调用

//通过redis实现分类缓存
@WebServlet("/categoryServlet")
public class CategoryServlet extends HttpServlet {
    
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    

        //访问redis 较快,但是第一次是没有数据的
        //访问service,获取json,将json保存到redis
        Jedis jedis = JedisUtils.getJedis();
        String json = jedis.get("category_list");

        if (json != null) {
    
    
            System.out.println("redis cache");
            response.getWriter().println(json);

        } else {
    
    
            System.out.println("mysql data");
            //创建业务对象
            CategoryService categoryService = new CategoryService();
            //所有的分类
            List<Category> categoryList=categoryService.findAll();
            //显示
            Msg msg = new Msg();
            msg.setCode(200);
            msg.setData(categoryList);
            json = new ObjectMapper().writeValueAsString(msg);
            //将数据保存到redis
            jedis.set("category_list",json);
            response.getWriter().println(json);
        }
        //关闭连接
        JedisUtils.close(jedis);
    }
}

2.4 开启Redis服务器

在这里插入图片描述

2.5 运行

在这里插入图片描述

运行结果:第一次查询
从 mysql data 中读取数据
Preparing: select cid,cname from tab_category order by cid asc;
Parameters:
Total: 8
刷新页面第二次/n次查询:(不查询MySQL数据库,不发送sql语句)
从 redis cache 中读取数据

通过Redis的可视化工具查看分类数据

扫描二维码关注公众号,回复: 11876021 查看本文章

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_40542534/article/details/109018905