news 2026/4/23 12:24:43

RuoYi 框架中核心的 `PermitAllUrlProperties` 配置类

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
RuoYi 框架中核心的 `PermitAllUrlProperties` 配置类

你提供的这段代码是 RuoYi 框架中核心的PermitAllUrlProperties配置类,其核心作用是自动扫描项目中所有标注了@Anonymous注解的 Controller 类/方法,提取对应的 URL 路径并统一管理,最终为 Sa-Token 等权限拦截器提供“允许匿名访问”的 URL 列表。

一、代码整体功能总结

这个类实现了InitializingBeanApplicationContextAware接口,核心逻辑是:

  1. 在 Spring 容器初始化完成后,扫描所有@RequestMapping注解的 Controller 方法;
  2. 识别标注了@Anonymous注解的类/方法,提取其 URL 路径;
  3. 将 URL 中的路径变量(如{id})替换为通配符*,最终汇总成一个“匿名访问 URL 列表”;
  4. 对外提供getUrls()方法,供 Sa-Token 拦截器等组件获取这些免登录的 URL。

二、代码逐模块详细解释

1. 类注解与核心成员
@Configuration// 声明为Spring配置类,纳入容器管理publicclassPermitAllUrlPropertiesimplementsInitializingBean,ApplicationContextAware{// 正则表达式:匹配URL中的路径变量(如 {id}、{userId})privatestaticfinalPatternPATTERN=Pattern.compile("\\{(.*?)\\}");// Spring应用上下文,用于获取容器中的BeanprivateApplicationContextapplicationContext;// 存储所有允许匿名访问的URL列表privateList<String>urls=newArrayList<>();// 通配符常量,用于替换路径变量publicStringASTERISK="*";}
  • InitializingBean:实现该接口的afterPropertiesSet()方法,会在 Spring 容器初始化完当前 Bean 的属性后执行;
  • ApplicationContextAware:实现该接口的setApplicationContext()方法,可获取 Spring 应用上下文(用于获取RequestMappingHandlerMapping);
  • PATTERN:正则匹配{xxx}格式的路径变量,比如将/system/user/{id}中的{id}匹配出来。
2. 核心方法:setApplicationContext(获取Spring上下文)
@OverridepublicvoidsetApplicationContext(ApplicationContextcontext)throwsBeansException{this.applicationContext=context;}
  • 作用:Spring 容器初始化时,自动将应用上下文注入到当前类的applicationContext成员变量中;
  • 后续可通过该上下文获取RequestMappingHandlerMapping(SpringMVC 中管理所有请求映射的核心 Bean)。
3. 核心方法:afterPropertiesSet(扫描并提取匿名URL)

这是整个类的核心逻辑,Spring 容器初始化完成后自动执行:

@OverridepublicvoidafterPropertiesSet(){// 1. 获取SpringMVC中管理所有@RequestMapping映射的核心BeanRequestMappingHandlerMappingmapping=applicationContext.getBean(RequestMappingHandlerMapping.class);// 2. 获取所有请求映射:key=RequestMappingInfo(URL、请求方式等),value=HandlerMethod(对应Controller方法)Map<RequestMappingInfo,HandlerMethod>map=mapping.getHandlerMethods();// 3. 遍历所有请求映射map.keySet().forEach(info->{HandlerMethodhandlerMethod=map.get(info);// 4. 第一步:扫描方法上的@Anonymous注解Anonymousmethod=AnnotationUtils.findAnnotation(handlerMethod.getMethod(),Anonymous.class);// 如果方法上有@Anonymous注解,提取URL并处理Optional.ofNullable(method).ifPresent(anonymous->Objects.requireNonNull(info.getPatternsCondition().getPatterns()).forEach(url->{// 替换URL中的路径变量(如{id})为*,加入列表urls.add(RegExUtils.replaceAll(url,PATTERN,ASTERISK));}));// 5. 第二步:扫描类上的@Anonymous注解(Controller类)Anonymouscontroller=AnnotationUtils.findAnnotation(handlerMethod.getBeanType(),Anonymous.class);// 如果类上有@Anonymous注解,提取URL并处理Optional.ofNullable(controller).ifPresent(anonymous->Objects.requireNonNull(info.getPatternsCondition().getPatterns()).forEach(url->{urls.add(RegExUtils.replaceAll(url,PATTERN,ASTERISK));}));});}

关键逻辑拆解:

  • 步骤1-2:获取RequestMappingHandlerMapping并拿到所有@RequestMapping映射关系,这是 SpringMVC 内部存储所有接口 URL 的核心数据结构;
  • 步骤4:检查 Controller 方法上是否有@Anonymous注解:
    • 比如@GetMapping("/user/{id}")+@Anonymous的方法,会被识别;
    • info.getPatternsCondition().getPatterns():获取该方法对应的所有 URL 路径(如[/user/{id}]);
    • RegExUtils.replaceAll(url, PATTERN, ASTERISK):将{id}替换为*,最终 URL 变为/user/*
  • 步骤5:检查 Controller 类上是否有@Anonymous注解(优先级低于方法注解):
    • 比如@RestController @Anonymous @RequestMapping("/system/dept")的类,其下所有方法的 URL 都会被加入匿名列表;
  • Optional.ofNullable(…):避免空指针,仅当注解存在时才执行后续逻辑。
4. Getter/Setter 方法
publicList<String>getUrls(){returnurls;}publicvoidsetUrls(List<String>urls){this.urls=urls;}
  • 作用:对外提供获取“匿名URL列表”的入口,你之前的SaTokenConfigAllUrlHandler大概率会调用这个getUrls()方法,获取所有允许匿名访问的 URL。

三、使用场景与示例

1. @Anonymous 注解的使用示例
// 示例1:Controller类上标注@Anonymous,该类下所有方法都允许匿名访问@Anonymous@RestController@RequestMapping("/system/login")publicclassLoginController{@PostMapping("/doLogin")publicAjaxResultdoLogin(){/* 登录逻辑 */}}// 示例2:单个方法上标注@Anonymous,仅该方法允许匿名访问@RestController@RequestMapping("/system/user")publicclassUserController{@Anonymous@GetMapping("/{id}")publicAjaxResultgetUserById(@PathVariableLongid){/* 查询用户逻辑 */}}
2. URL 处理结果示例
原始URL处理后URL(加入urls列表)说明
/system/login/doLogin/system/login/doLogin无路径变量,直接保留
/system/user/{id}/system/user/*路径变量{id}替换为*
/order/{orderId}/detail/{itemId}/order/*/detail/*多个路径变量全部替换

四、与 SaTokenConfig 的关联

你之前的SaTokenConfig中用到了AllUrlHandler.getUrls(),而AllUrlHandler底层大概率会整合:

  1. PermitAllUrlProperties.getUrls()@Anonymous注解的URL);
  2. SecurityProperties.getExcludes()(配置文件中手动排除的URL);
    最终为 Sa-Token 拦截器提供完整的“免登录URL列表”,确保这些URL不会被StpUtil.checkLogin()拦截。

五、核心设计亮点

  1. 自动扫描:无需手动配置匿名URL,只需在类/方法上标注@Anonymous,自动识别并加入列表;
  2. 路径变量兼容:将{id}替换为*,避免因路径变量导致的URL匹配失败(如/user/123能匹配/user/*);
  3. Spring 生命周期整合:利用InitializingBeanApplicationContextAware,在容器初始化阶段完成扫描,保证数据提前加载。

总结

  1. PermitAllUrlProperties是 RuoYi 框架中自动收集@Anonymous注解URL的核心配置类,通过扫描 SpringMVC 的请求映射,提取并处理匿名访问的URL;
  2. 核心逻辑是将URL中的路径变量({xxx})替换为通配符*,确保权限拦截器能正确匹配;
  3. 该类的getUrls()方法为 Sa-Token 拦截器提供“匿名URL列表”,是框架免登录URL管理的关键组件。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/15 8:12:41

SAP中我在核对科目余额时 为什么 BSID中的科目余额汇总 和 FAGLFLEXT中 L5和L6的科目余额是想等的 而和 0L的余额不相等 ?

这是一个非常好的问题&#xff0c;它触及了SAP总账核心表中一个关键的设计差异。您观察到的现象是完全正常的&#xff0c;其根本原因在于 “科目本位币” 与 “公司代码本位币” 的区别。下面我为您详细解释&#xff1a;核心概念&#xff1a;两种关键的本位币公司代码本位币这是…

作者头像 李华
网站建设 2026/4/23 12:23:46

Lubuntu零基础入门:从安装到日常使用

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个交互式Lubuntu学习应用&#xff0c;包含以下模块&#xff1a;1) 可视化安装向导(带截图指导) 2) 常用终端命令练习环境(如ls、cd、apt等) 3) 软件中心模拟器(学习安装/卸载…

作者头像 李华
网站建设 2026/4/22 20:41:28

闪电开发:用Zustand+AI快速验证产品原型

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 构建一个社交媒体快速原型&#xff0c;集成Zustand和AI生成内容。要求&#xff1a;1. 用户个人资料状态 2. 动态帖子列表 3. AI自动生成虚拟数据 4. 实时交互效果 5. 一键导出原型…

作者头像 李华
网站建设 2026/4/23 12:20:20

小白必看:第一次用Maven就报错怎么办?

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个新手引导式解决方案&#xff1a;1) 卡通化界面 2) 分步图解指导 3) 语音解说 4) 错误模拟演示。内容包括&#xff1a;Maven基本概念、安装验证方法、环境变量设置可视化工…

作者头像 李华
网站建设 2026/4/19 3:18:27

传统调试vsAI分析:解决0xC000014C效率对比

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个0xC000014C错误解决效率对比演示项目。需要&#xff1a;1. 模拟产生典型的DLL初始化失败场景 2. 实现传统调试流程(日志分析、依赖检查等) 3. 实现AI辅助分析流程 4. 生成…

作者头像 李华