黑马旅游网-学习笔记Part06
大约 5 分钟
黑马旅游网-学习笔记Part06
今日目标
- 登录过滤器 🍐✏️
 - 主页导航栏实现 ❤️
 - Redis优化导航栏查询所有
 
知识储备
- 了解session和cookie的缺陷
 - 已经完成过滤器拦截登录代码
 
1. 登录过滤器
登录过滤器
访问页面详情时候,需要校验是否登录,如果未登录,直接跳转到登录页面 
点击查看过滤器流程 👈 👈
代码操作
- 在filter包创建
LoginCheckFilter类 实现Filter接口,配置拦截路径为所有 
@Slf4j 注解是日志注解,导入下列依赖
log.info中{} 是占位符的意思,逗号后面的值即为变量
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.20</version>
</dependency>
/**
 * 检查用户是否已经完成登录
 * filterName:过滤器在对象容器中的名字
 * urlPatterns:匹配路径
 */
@WebFilter(filterName = "loginCheckFilter",urlPatterns = "/*")
@Slf4j
public class LoginCheckFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    //todo 书写拦截逻辑
    System.out.println("我被拦截了");
    }
    @Override
    public void destroy() {
    }
}
2. 在doFilter方法中书写拦截逻辑
filterChain.doFilter(servletRequest, servletResponse)方法是放行,不拦截的意思
🍍 下面代码还缺点东西,用你的调试技术,解决一下吧!! 🍭
/**
 * 检查用户是否已经完成登录
 * filterName:过滤器在对象容器中的名字
 * urlPatterns:匹配路径
 */
@WebFilter(filterName = "loginCheckFilter", urlPatterns = "/*")
@Slf4j
public class LoginCheckFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;  //获取session中值
        HttpServletResponse response = (HttpServletResponse) servletResponse; //重定向
        //1、获取本次请求的URI
        String requestURI = request.getRequestURI();
//        {}占位符
        log.info("接受到的请求路径:{}", requestURI);
        //定义不需要处理的请求路径--白名单
        String[] urls = new String[]{
                "login.html",
                "register.html",
                "register_ok.html",
                "index.html",
                "/css",
                "/image",
                "/error",
                "/fonts",
                "/img",
                "/js",
                "/loginServlet",
                "/registUserServlet",
                "/checkCode",
                "/categoryServlet"
        };
        for (String url : urls) {
            if (requestURI.contains(url)) {
                //如果不需要处理,则直接放行
                log.info("路径:{} 不需要拦截", requestURI);
                //         filterChain.doFilter 放行
                filterChain.doFilter(servletRequest, servletResponse);
                return;
            }
        }
        //4、判断登录状态,如果已登录,则直接放行
        HttpSession session = request.getSession();
        Object user = session.getAttribute("user");
//        如果用户id不等于空,说明已经登陆过,直接放行
        if (user != null) {
            log.info("用户已经登录,直接放行");
            filterChain.doFilter(servletRequest, servletResponse);
            //            直接返回该方法,下面的代码不要执行了
            return;
        }
        log.info("用户未登录");
        //5、如果未登录则返回未登录结果,通过输出流方式向客户端页面响应数据
//        JSON.toJSONString 将对象 转成 JSON字符串 给前端使用  返回的数据一定是NOTLOGIN  且code 为0
        response.sendRedirect(request.getContextPath() + "/login.html");
    }
    @Override
    public void destroy() {
    }
}

2. 主页导航栏实现
主页导航栏实现
需求效果: 👇

接口信息: 👇
- 请求路径:
/travel/categoryServlet - 请求方式:GET
 - 请求参数:无参数
 - 返回数据:category集合的json字符串
 
代码操作
- 检查pom.xml是否有Alibaba的fastjson依赖
 
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.76</version>
</dependency>
- 在控制层CategoryServlet中书写接受参数、查询数据、返回数据等逻辑s
 
@WebServlet("/categoryServlet")
public class CategoryServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //从数据库中拿到 所有的数据 回显给前端
        CategoryService categoryService = new CategoryServiceImpl();
        List<Category> list  =   categoryService.findAll();
        String json = JSON.toJSONString(list);
        //设置响应头信息
        resp.setContentType("application/json;charset=utf-8");
        resp.getWriter().write(json);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
CategoryService接口
public interface CategoryService {
    //查询所有旅游路线
    List<Category> findAll();
}
CategoryServiceImpl接口实现类:
public class CategoryServiceImpl implements CategoryService {
    @Override
    public List<Category> findAll() {
        //创建list集合
        List<Category> categoryList = new ArrayList<>();
        SqlSession session = MybatisUtils.getSqlSessionFactory().openSession();
        CategoryMapper mapper = session.getMapper(CategoryMapper.class);
        categoryList = mapper.findAll();
        return categoryList;
    }
 
}
CategoryMapper接口
public interface CategoryMapper {
    List<Category> findAll();
}
CategoryMapper映射文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.itcast.travel.mapper.CategoryMapper">
    <select id="findAll" resultType="category">
    SELECT  * from tab_category ORDER BY cid
    </select>
</mapper>
3.Redis优化导航栏查询所有
前言
背景: 门户网站每次访问时候查询的分类数据是一样的,且每次都要查询数据库,如果用户激增,会造成数据库访问压力,因此需要使用redis进行优化
核心逻辑: 先查询缓存,如果存在,直接返回数据,如果不存在,然后查询数据库,存入缓存,并返回
点击查看核心逻辑图解 👈 👈
代码操作
1.检查redisclient依赖是否导入
<!--jedis-->
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>2.7.0</version>
    </dependency>
2.检查JedisUtil工具类是否导入成功!
public final class JedisUtil {
    private static JedisPool jedisPool;
    static {
        //读取配置文件
        InputStream is = JedisPool.class.getClassLoader().getResourceAsStream("jedis.properties");
        //创建Properties对象
        Properties pro = new Properties();
        //关联文件
        try {
            pro.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //获取数据,设置到JedisPoolConfig中
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(Integer.parseInt(pro.getProperty("maxTotal")));
        config.setMaxIdle(Integer.parseInt(pro.getProperty("maxIdle")));
        //初始化JedisPool
        jedisPool = new JedisPool(config, pro.getProperty("host"), Integer.parseInt(pro.getProperty("port")));
    }
    /**
     * 获取连接方法
     */
    public static Jedis getJedis() {
        return jedisPool.getResource();
    }
    /**
     * 关闭Jedis
     */
    public static void close(Jedis jedis) {
        if (jedis != null) {
            jedis.close();
        }
    }
}
3.检查redis服务端是否启动,并且配置文件是否配置正确
host=127.0.0.1
port=6379
maxTotal=50
maxIdle=10
- fastjson的JSONObject类作用是将JSON数组转换成List集合
 
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.68</version>
</dependency>
CategoryServiceImpl代码 👇
public class CategoryServiceImpl implements CategoryService {
            //不要求 所有人都用这种方式,  如果你觉得难 那么就用上一节课的 直接查询数据库的方式
    @Override
    public List<Category> findAll() {
        //创建list集合
        List<Category> categoryList = new ArrayList<>();
        //获取redis连接
        Jedis jedis = JedisUtil.getJedis();
        String categorystr = jedis.get("category");
       if (categorystr==null || categorystr.length()==0) {
            //redis中数据为空,那么查询数据库并且将数据插入到缓存
            //查询所有旅游路线
            //查询数据库获取所有数据
            System.out.println("从数据库中查询!!");
            SqlSession session = MybatisUtils.getSqlSessionFactory().openSession();
            CategoryMapper mapper = session.getMapper(CategoryMapper.class);
            categoryList = mapper.findAll();
            //存入redis缓存中
            String jsonString = JSON.toJSONString(categoryList);
            jedis.set("category",jsonString);
           return categoryList;
        } else {
            System.out.println("从缓存redis中查询!!!");
           List<Category> categories = JSONObject.parseArray(categorystr, Category.class);
            return categories;
        }
    }
}

