解决SpringBoot中Filter中@Autowired注解的类成员变量为NULL

本文解决在SpringBoot中实现SSO单点登录时,自定义过滤器中注入的Bean为null的问题。通过调整Bean的初始化顺序,确保过滤器能够正确获取到所需的依赖。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、问题描述

在采用SpringBoot中加入过滤器处理SSO单点登录过程中遇到所需要注入的类成员变量为Null的问题;

@Bean
public FilterRegistrationBean ssoCasRealmFilter() {
    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(new SsoCasRealmFilter());
    registration.addUrlPatterns("/*");
    registration.setName("SsoCasRealmFilter");
    registration.setOrder(Integer.MAX_VALUE-4);
    System.out.println("SsoCasRealmFilter");
    return registration;
}

public class SsoCasRealmFilter extends CommonSSOLoginFilter {
    @Autowired
    private PermissionService permissionService;//此处permissionService为NULL
    @Autowired
    private RedisService redisService;//此处redisService为NULL
    ....}

2、问题原因

在spring中,web的加载顺序是Listener->flter->servlet,所以说再在flter初始化时,相关的Bean还没有初始化,造成了对象为空。

3、解决问题

将该自定义Filter能作为Spring Bean,以便获得Spring Bean的相关益处,比如可以使用@Autowired进行Bean的注入等。但这里遇到了一个问题,自定义Filter通过@Bean注解后,被Spring Boot自动注册到了容器的Filter chain中,这样导致的结果是,所有URL都会被自定义Filter过滤,而不是Shiro中配置的一部分URL

@Bean
public Filter ssoCasFilter(){
 	return new SsoCasRealmFilter();
}

@Bean
public FilterRegistrationBean ssoCasRealmFilter() {
    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(ssoCasFilter());
    registration.addUrlPatterns("/*");
    registration.setName("SsoCasRealmFilter");
    registration.setOrder(Integer.MAX_VALUE-4);
    System.out.println("SsoCasRealmFilter");
    return registration;
}
<think>嗯,用户想在Spring Boot中实现获取导航栏菜单列表的方法,具体是找一个getMenus的示例。首先,我需要回想一下Spring Boot中处理这类请求的常用方法。通常导航栏菜单可能存储在数据库里,所以需要用到数据库访问技术,比如Spring Data JPA或者MyBatis。根据用户提供的引用内容,里面提到了SpringBoot2.x集成Spring Data JPA的示例代码,所以可能用户倾向于使用JPA。 接下来,我应该考虑如何设计实体类。导航菜单通常有ID、名称、父ID、排序、路径等字段。所以需要创建一个Menu实体类,用JPA的注解来映射数据库表。比如使用@Entity、@Table、@Id、@GeneratedValue这些注解。 然后是Repository层,需要创建一个MenuRepository接口,继承JpaRepository,这样就可以直接使用内置的查询方法。如果菜单有层级结构,可能需要自定义查询方法,比如根据父ID来查找子菜单,或者按排序字段排序。 接着是Service层,这里应该包含业务逻辑,比如获取所有菜单并组装成树形结构。可能需要递归处理父菜单和子菜单的关系,确保返回的数据结构适合前端展示。 Controller层负责处理HTTP请求,通常使用@RestController和@RequestMapping注解。在getMenus方法中,调用Service层的方法获取菜单列表,并返回JSON格式的数据。 另外,用户可能需要菜单以树形结构返回,这时候在Service层需要将平铺的菜单列表转换成树形结构。可以用Java的Stream API来处理,找到顶级菜单(parentId为0),然后递归设置子菜单。 需要注意的是事务管理,在Service方法上添加@Transactional注解,确保数据库操作的一致性。还有路径的配置,比如前端可能通过/getMenus来访问这个接口。 最后,根据用户提供的引用,代码示例的GitHub和Gitee链接可能需要检查是否包含相关的实现,但用户的问题更关注具体实现步骤,所以分步骤给出示例代码会更清晰。同时,确保代码中的LaTeX格式正确,比如变量使用$...$包裹,独立公式用$$...$$,不过在这个问题中可能用不上太多数学公式,但如果有涉及算法的地方需要注意格式。 总结一下,步骤应该是创建实体类、Repository接口、Service层处理业务逻辑、Controller层暴露API,并处理树形结构转换。这样用户就能得到一个完整的获取导航栏菜单列表的示例了。</think>在Spring Boot中实现导航栏菜单列表获取,通常涉及数据库查询、实体类定义及接口设计。以下是分步骤的代码示例: ### 1. 创建菜单实体类 ```java @Entity @Table(name = "sys_menu") public class Menu { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; // 菜单名称 private Long parentId; // 父菜单ID(0表示根节点) private Integer sort; // 排序号 private String path; // 前端路由路径 // getter/setter省略 } ``` ### 2. 创建Repository接口 ```java public interface MenuRepository extends JpaRepository<Menu, Long> { // 查询所有菜单并按排序号升序排列 @Query("SELECT m FROM Menu m ORDER BY m.sort ASC") List<Menu> findAllOrderBySort(); } ``` ### 3. 创建Service实现 ```java @Service public class MenuService { @Autowired private MenuRepository menuRepository; @Transactional(readOnly = true) public List<Menu> getMenus() { List<Menu> allMenus = menuRepository.findAllOrderBySort(); return buildTree(allMenus); } // 构建树形结构 private List<Menu> buildTree(List<Menu> menus) { Map<Long, List<Menu>> parentMap = menus.stream() .filter(menu -> menu.getParentId() != 0) .collect(Collectors.groupingBy(Menu::getParentId)); return menus.stream() .filter(menu -> menu.getParentId() == 0) .peek(root -> setChildren(root, parentMap)) .collect(Collectors.toList()); } private void setChildren(Menu parent, Map<Long, List<Menu>> parentMap) { List<Menu> children = parentMap.get(parent.getId()); if (children != null) { parent.setChildren(children); children.forEach(child -> setChildren(child, parentMap)); } } } ``` ### 4. 创建Controller接口 ```java @RestController @RequestMapping("/api/menu") public class MenuController { @Autowired private MenuService menuService; @GetMapping("/getMenus") public ResponseEntity<List<Menu>> getMenus() { return ResponseEntity.ok(menuService.getMenus()); } } ``` ### 关键点说明: 1. 数据库查询使用Spring Data JPA的派生查询功能[^1] 2. 树形结构构建时间复杂度为$O(n)$,使用哈希表加速子节点查找 3. 接口返回JSON格式数据示例: ```json [ { "id": 1, "name": "首页", "path": "/home", "children": [ { "id": 2, "name": "子菜单", "path": "/home/sub" } ] } ] ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值