news 2026/6/10 23:30:34

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/6/10 11:45:16

零基础入门:用OpenSSL生成第一个SSL证书图解指南

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 制作一个交互式SSL证书学习工具&#xff0c;左侧显示教学区&#xff08;分步骤讲解密钥生成、CSR创建、证书签名等概念&#xff09;&#xff0c;右侧提供实践区&#xff08;带预设…

作者头像 李华
网站建设 2026/6/10 11:36:27

TRAE框架解析:AI如何提升你的开发效率

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 使用TRAE框架开发一个基于AI的代码生成工具&#xff0c;能够根据用户输入的自然语言描述自动生成Python代码。要求支持多种编程语言转换&#xff0c;提供实时调试建议&#xff0c;…

作者头像 李华
网站建设 2026/6/10 4:21:32

Qwen2.5多版本对比:云端GPU并行测试,立省3天时间

Qwen2.5多版本对比&#xff1a;云端GPU并行测试&#xff0c;立省3天时间 引言&#xff1a;为什么需要并行测试&#xff1f; 作为技术选型团队的成员&#xff0c;你是否遇到过这样的困境&#xff1a;需要同时测试Qwen2.5的3B/7B/14B多个版本&#xff0c;但本地只有单张GPU卡&a…

作者头像 李华
网站建设 2026/6/9 18:48:12

零基础Linux Docker入门:从安装到第一个容器

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个面向Docker初学者的交互式教程项目&#xff0c;包含&#xff1a;1.基础概念图文解释 2.简单的Hello World容器示例 3.带提示的实践任务 4.常见问题解答。要求使用Markdown…

作者头像 李华
网站建设 2026/6/10 3:35:46

企业级应用:WSA在生产环境中的7个实际案例

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个WSA企业应用案例展示平台&#xff0c;包含&#xff1a;1) 7个典型企业应用场景的详细实现方案 2) 性能对比数据可视化 3) 部署检查清单 4) 问题排查指南。要求使用DeepSee…

作者头像 李华
网站建设 2026/6/10 11:43:03

Qwen2.5-7B镜像对比:5家云服务实测,这家1小时最便宜

Qwen2.5-7B镜像对比&#xff1a;5家云服务实测&#xff0c;这家1小时最便宜 1. 为什么需要对比云服务&#xff1f; 作为个人开发者&#xff0c;想要长期使用Qwen2.5-7B这样的大语言模型&#xff0c;选择合适的云服务平台至关重要。不同的云服务在计费方式、闲置策略、部署便捷…

作者头像 李华