瑞吉外卖 - 完善后台系统登陆功能(5)

news/2025/1/12 6:12:08/

某马瑞吉外卖单体架构项目完整开发文档,基于 Spring Boot 2.7.11 + JDK 11。预计 5 月 20 日前更新完成,有需要的胖友记得一键三连,关注主页 “瑞吉外卖” 专栏获取最新文章。
相关资料:https://pan.baidu.com/s/1rO1Vytcp67mcw-PDe_7uIg?pwd=x548
提取码:x548

文章目录

    • 1.问题分析
    • 2.代码实现
    • 3.功能测试

1.问题分析

前面虽然我们已经实现了后台系统的员工登录功能,但是其实它并不完善。期中存在的一个问题就是即使我们不通过登陆页面也可以直接通过 “http://localhost:8080/backend/index.html”访问后台主页:

显然,这种设计是不合理的,我们希望的效果应该是,只有登陆成功后才可以访问系统中的页面,如果没有登陆则自动跳转到登陆页面。

具体如何实现呢?我们可以通过过滤器或者拦截器,在过滤器或者拦截器中判读用户是否已经完成登陆,如果没有登陆则跳转到登录界面即可。

具体的处理逻辑如下:

  1. 获取本次请求的 URI;
  2. 判断本次请求是否需要处理;
  3. 如果不需要处理,则直接放行;
  4. 判断登陆状态,如果已经登陆,则直接放行;
  5. 如果未登录,则重定向到登录页面。

2.代码实现

创建一个 filter 包用于存放我们的自定义过滤器,我们可以创建一个 LoginCheckFilter 类实现 javax.servlet.Filter 接口,重写接口的 doFilter() 方法以实现我们的登陆检查逻辑。

LoginCheckFilter 类完整代码如下:

package cn.javgo.reggie_take_out.filter;import cn.javgo.reggie_take_out.common.R;
import com.alibaba.fastjson.JSON;
import org.springframework.util.AntPathMatcher;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;/*** 用户登录检查过滤器*/
@WebFilter(filterName = "loginCheckFilter",urlPatterns = {"/*"})
public class LoginCheckFilter implements Filter {// 需要忽略的 URI 地址private static final String[] IGNORE_URI = {"/employee/login","/employee/logout","/backend/**","/front/**"};// AntPathMatcher 是 Spring 提供的一个通配符匹配类,支持 ?、*、** 等通配符private static final AntPathMatcher ANT_PATH_MATCHER = new AntPathMatcher();/*** 初始化过滤器* @param servletRequest 请求对象* @param servletResponse 响应对象* @param filterChain 过滤器链对象* @throws IOException IO异常* @throws ServletException Servlet异常*/@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {// 类型转换HttpServletRequest request = (HttpServletRequest) servletRequest;HttpServletResponse response = (HttpServletResponse) servletResponse;// 1.获取请求的 URI 地址String requestURI = request.getRequestURI();// 2.判断当前的 URI 地址是否需要忽略boolean check = Arrays.stream(IGNORE_URI).anyMatch(uri -> ANT_PATH_MATCHER.match(uri, requestURI));// 3.如果需要忽略,则直接放行if(check){filterChain.doFilter(request,response);return;}// 4.如果用户已经登录,则直接放行if(request.getSession().getAttribute("employee") != null){filterChain.doFilter(request,response);return;}// 5.用户未登录,通过输出流方式向客户端页面响应数据response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));}
}

上述代码实现逻辑比较简单,我们挑出部分内容进行简单分析。

  1. 为什么要忽略 {"/employee/login","/employee/logout","/backend/**","/front/**"} 几个请求?

    前面两个比较容易理解,用户访问登陆页面或退出登陆的 URI 自然没必要进行登陆检查。至于后面的 {"/backend/**","/front/**"} 也被列为可忽略的 URI 这个并不是必须的,因为如果没有经过登陆页面成功登陆,即便访问成功有也无济于事,因为访问到的页面不会有数据内容。

  2. AntPathMatcher 有何用?

    AntPathMatcher 是 Spring Framework 中的一个工具类,用于进行 Ant 风格的路径匹配(一种常用的路径匹配规则,支持通配符)。AntPathMatcher 可以帮助我们快速实现路径匹配的功能,是 Web 应用中常用的工具类之一。

    支持以下路径匹配规则:

    • ?:匹配任意单个字符
    • *:匹配任意数量的字符,包括 0 个字符
    • **:匹配任意数量的路径,包括 0 个路径
  3. 为什么最终要向客户端返回一个错误的 JSON 对象?

    在上面的源码中我们为什么莫名其妙地向客户端返回一个 R.error("NOTLOGIN"),这可能让你感到疑惑,其实这是因为前端也有自己的拦截器,会根据拿到的响应对象中的数据进行判断从而跳转指定页面。在 static/backend/index.html 页面中我们能找到对应发送 AJAX 请求的 js 文件,其中就包括了一个 request.js:

    我们追踪到 request.js 的拦截器相关位置,便能看到如下关键信息:

    处理逻辑也比较简单,当服务端返回的对象中包含 code === 0data.msg === 'NOTLOGIN' 时,便会清空浏览器的用户信息,然后跳转到登陆页面。这就是为什么我们在实现过滤器的时候最终返回 R.error("NOTLOGIN") 的原因,当然这是为了应承前端的设计,不然我们也可以通过自定义拦截器等方式进行重定向。

最后,想要我们的过滤器生效,还需要再启动类上添加 @ServletComponentScan 注解,以启用自动扫描 Servlet、Filter 和 Servlet 监听器组件。

@Slf4j
@SpringBootApplication
@ServletComponentScan
public class ReggieTakeOutApplication {public static void main(String[] args) {SpringApplication.run(ReggieTakeOutApplication.class, args);}@BeanCommandLineRunner commandLineRunner(){return args -> log.info("项目启动成功......");}
}

在传统的 Servlet 应用程序中,我们通常需要在 web.xml 文件中显式地声明 Servlet、Filter 和 Servlet 监听器等组件。但是,在基于 Spring 的应用程序中,我们可以使用 Spring 提供的 @ServletComponentScan 注解来自动注册这些组件。

当我们在 Spring 应用程序上下文中使用 @ServletComponentScan 注解时,Spring 将扫描指定的包及其子包中的所有 Servlet、Filter 和 Servlet 监听器组件,并将它们自动注册到 Servlet 容器中。这样,我们就可以在不编写冗长的 web.xml 文件的情况下轻松地配置 Servlet 应用程序。

需要注意的是,@ServletComponentScan 注解只会扫描使用了 @WebServlet@WebFilter@WebListener 注解的组件,并将它们自动注册到 Servlet 容器中。如果我们使用传统的 Servlet API 来定义这些组件,则需要手动注册它们。这也是为什么我们要在 LoginCheckFilter 过滤器上添加 @WebFilter(filterName = "loginCheckFilter",urlPatterns = {"/*"}) 注解的原因,其中指定了过滤器的名称为 “loginCheckFilter”,并过滤所有请求。

3.功能测试

启动程序,如果我们不进行登陆,直接访问后台主页 “http://localhost:8080/backend/index.html”,那么就会自动跳转到登陆页面:

当然,我们还可以直接在前端拦截器的对应位置处,打上断点,再直接访问 “http://localhost:8080/backend/index.html”进行断点调试,查看执行细节:

可以看到,客户端正常拿到了预期的数据,然后按照执行逻辑就会跳转到登陆页面了:


http://www.ppmy.cn/news/67750.html

相关文章

最新DNDC模型在土地利用变化、未来气候变化下的建模方法及温室气体时空动态模拟实践技术应用

由于全球变暖、大气中温室气体浓度逐年增加等问题的出现,“双碳”行动特别是碳中和已经在世界范围形成广泛影响。。DNDC(Denitrification-Decomposition,反硝化-分解模型)是目前国际上最为成功的模拟生物地球化学循环的模型之一&a…

RabbitMQ详解(三):消息模式(fanout、direct、topic、work)

消费模式 参考官网:https://www.rabbitmq.com/getstarted.html 简单模式 Simple, 参考RabbitMQ详解(二):消息模式 Simple(简单)模式 简单模式是最简单的消息模式,它包含一个生产者、一个消费者和一个队列。生产者向队…

【地铁上的设计模式】--行为型模式:观察者模式

什么是观察者模式 观察者模式(Observer Pattern)是一种设计模式,它定义了对象之间一对多的依赖关系,当一个对象状态发生改变时,其所有依赖者都会收到通知并自动更新。观察者模式中,被观察者对象通常被称为…

存bean和取bean

准备工作存bean获取bean三种方式 准备工作 bean:一个对象在多个地方使用。 spring和spring boot:spring和spring boot项目;spring相当于老版本 spring boot本质还是spring项目;为了方便spring项目的搭建;操作起来更加简单 spring…

Redis常见命令有哪些?怎么使用?

一、概述: 在了解Redis命令之前,我们要先了解Redis的数据结构,Redis是NoSQL数据库,采用了json存储模式,比MySQL等关系数据库更易于扩展,拥有丰富的数据类型,分基本类型与特殊类型。基本类型包括…

API网关简介|TaobaoAPI接入

API网关是什么 在日常工作中,不同的场合下,我们可能听说过很多次网关这个名称,这里说的网关特指API网关(API Gataway)。字面意思是指将所有API的调用统一接入API网关层,由网关层负责接入和输出。 那么在什…

百度智能云联手爱奇艺,从云到边缘计算全面提升用户体验

近年来,随着人工智能和云计算技术的飞速发展,边缘计算作为一种新型计算架构开始受到越来越多企业的关注和应用。百度智能云和爱奇艺作为国内领先的云计算服务提供商和内容提供商,也开始将边缘计算应用于实际业务中,全面提升用户体…

JAVA项目通过IDEA如何构建可执行JAR

开发JAVA工程代码(main方法启动)如何构建出可以通过java -jar命令直接执行的jar?如果工程中依赖其他jar又如何处理?本文即针对以上两点通过IDEA开发工具来做一个简单的分析和尝试,测试如下四种方法,如有瑕疵请轻喷。 文字目录 1.…