Springboot过滤器中注入Bean

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: Springboot过滤器中注入Bean

今天被人提了个问题——在过滤器(Filter)中注入Bean后拿不到对象(为null),如何避免这个坑?
废话不多说了,咱们直接看解决方案代码吧!
首先来看一下过滤器中的内容:
认证过滤器配置了,获取用户输入用户名和密码方法,认证成功方法及认证失败处理方法,以及日志入库封装代码;
当认证成功后,记录日志入库的时候,会发现此处的journalService是null,无法获取相对应的Bean对象,
java复制代码

/**
 * 认证过滤器
 */
public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter {
   

    private Logger logger = LoggerFactory.getLogger(TokenLoginFilter.class);
    private TokenManager tokenManager;
    private JournalService journalService;
    private RedisTemplate redisTemplate;
    // 权限管理工具,由SpringSecurity封装提供
    private AuthenticationManager authenticationManager;

    public TokenLoginFilter(AuthenticationManager authenticationManager, TokenManager tokenManager, RedisTemplate redisTemplate,JournalService journalService) {
   
        this.authenticationManager = authenticationManager;
        this.tokenManager = tokenManager;
        this.redisTemplate = redisTemplate;
        this.journalService = journalService;
        this.setPostOnly(false);
    }

    // 1 获取表单提交用户名和密码
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException {
   
        //获取表单提交数据
        try {
   
            User user = new ObjectMapper().readValue(request.getInputStream(), User.class);
            return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(),user.getPassword(),
                    new ArrayList<>()));
        } catch (IOException e) {
   
            e.printStackTrace();
            throw new RuntimeException();
        }
    }

    // 2 认证成功调用的方法
    @Override
    protected void successfulAuthentication(HttpServletRequest request,
                                            HttpServletResponse response, FilterChain chain, Authentication authResult)
            throws IOException, ServletException {
   

        insertJournal(user,request);

        ResponseUtil.out(response, apiResult);
    }

    // 3  认证失败调用的方法
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed)
            throws IOException, ServletException {
   
        logger.info("认证登录失败,失败原因:{}",failed.getMessage());
        ApiResult apiResult = new ApiResult();
        apiResult.setResultCode(ApiResponse.FAIL.getResCode());
        apiResult.setMsg("用户名密码错误");
        ResponseUtil.out(response, apiResult);
    }

    @Async
    public void insertJournal(SecurityUser user,HttpServletRequest request) throws BaseException {
   
        Journal journal = new Journal();
        journal.setCreateTime(new Date());
        journal.setMethod("login");
        journal.setName(user.getUsername());
        journal.setIpAddress(IpUtils.getIp(request));
        journal.setRemark("登录成功");
        journalService.insertSelective(journal);
    }

}

通过上面的代码便是拦截其中注入Bean的操作,此时如果没有任何配置,则注入的Bean全部获取不到对象值,全部为null
接下来我们看解决方案:
次配置类中公共构造函数中会按照系统注入所需要的tokenManager、redisTemplate、defaultPasswordEncoder、userDetailsService、journalServiced对象。
相对应的配置设置会实现商法所说的注入动作,这样即可完成正确的Bean注入操作


@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class TokenWebSecurityConfig extends WebSecurityConfigurerAdapter {
   

    private TokenManager tokenManager;
    private RedisTemplate redisTemplate;
    private DefaultPasswordEncoder defaultPasswordEncoder;
    private UserDetailsService userDetailsService;
    private JournalService journalService;

    @Autowired
    public TokenWebSecurityConfig(UserDetailsService userDetailsService, DefaultPasswordEncoder defaultPasswordEncoder,
                                  TokenManager tokenManager, RedisTemplate redisTemplate,JournalService journalService) {
   
        this.userDetailsService = userDetailsService;
        this.defaultPasswordEncoder = defaultPasswordEncoder;
        this.tokenManager = tokenManager;
        this.redisTemplate = redisTemplate;
        this.journalService = journalService;
    }

    /**
     * 配置设置
     * @param http
     * @throws Exception
     */
    // 设置退出的地址和token,redis操作地址
    @Override
    protected void configure(HttpSecurity http) throws Exception {
   
        http.cors();
        http.exceptionHandling()
                .authenticationEntryPoint(new UnauthEntryPoint()) // 没有权限访问
                .and().csrf().disable()
                .authorizeRequests()
                .anyRequest().authenticated() //任何请求,登录后可以访问
                .and().logout().logoutUrl("/index/logout")//退出路径
                .addLogoutHandler(new TokenLogoutHandler(tokenManager,redisTemplate)).and()
                .addFilter(new TokenLoginFilter(authenticationManager(), tokenManager, redisTemplate,journalService))
                .addFilter(new TokenAuthFilter(authenticationManager(), tokenManager, redisTemplate)).httpBasic();

    }
}

这一步中的关键便是构造函数中为注入Bean赋值,然后配置Filter时注入对象即可。

好了,这样即可完成过滤器中注入Bean操作,觉得有帮助,帮小编点个赞吧!

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
2月前
|
XML Java 开发者
Spring Boot中的bean注入方式和原理
Spring Boot中的bean注入方式和原理
110 0
|
2月前
|
Java Spring 容器
【二十二】springboot整合拦截器实战并对比过滤器
【二十二】springboot整合拦截器实战并对比过滤器
37 0
|
2月前
|
存储 NoSQL Java
Spring Boot统计一个Bean中方法的调用次数
Spring Boot统计一个Bean中方法的调用次数
36 1
|
5天前
|
XML Java 数据库
【SpringBoot:详解Bean装配】
【SpringBoot:详解Bean装配】
10 3
|
22天前
|
Java Spring 容器
SpringBoot 使用Quartz执行定时任务对象时无法注入Bean问题
SpringBoot 使用Quartz执行定时任务对象时无法注入Bean问题
17 1
|
29天前
|
JSON Java 数据库连接
属性注入掌握:Spring Boot配置属性的高级技巧与最佳实践
属性注入掌握:Spring Boot配置属性的高级技巧与最佳实践
28 1
|
1月前
|
Java Spring 容器
SpringBoot中bean的生命周期
Spring Boot的Bean生命周期涉及实例化、属性注入、初始化和销毁。在实例化后,Spring通过构造函数或Setter注入属性,然后调用初始化方法(@PostConstruct、InitializingBean接口)。Bean在应用中使用后,当容器关闭时,会调用销毁方法(@PreDestroy、DisposableBean接口)。依赖注入、配置管理、组件扩展和切面编程是其常见应用场景。示例代码展示了如何通过实现BeanNameAware、BeanFactoryAware等接口以及使用@PostConstruct注解来控制Bean的初始化。
42 2
SpringBoot中bean的生命周期
|
2月前
|
XML Java 数据格式
【springboot原理篇】Bean的加载方式,面试必看
【springboot原理篇】Bean的加载方式,面试必看
|
2月前
|
存储 前端开发 NoSQL
【二十一】springboot整合过滤器实战
【二十一】springboot整合过滤器实战
18 0
|
2月前
|
Java 容器 Spring
SpringBoot:Bean生命周期自定义初始化和销毁
SpringBoot:Bean生命周期自定义初始化和销毁