java依赖注入到SpringServlet上下文(onceperrequestfilter)

sirbozc5  于 2021-07-23  发布在  Java
关注(0)|答案(3)|浏览(422)

我实现了一个 OncePerRequestFilter ,在哪里 doFilterInternal() 我想使用一个利用率类 JdbcTemplate 以及属性文件中的用户数据。我意识到它无法访问属性文件(数据库连接和变量)中的数据,并且总是空值。我在网上发现,这是因为不同的背景。
我可以在本地成功地设置一个新的jdbc数据源,但是我不想复制代码,所以我只想像在restcontrollers中一样简单地注入源代码( @Value , @Autowired ).
我怎么能把这些注入到我的利用率类中,这些类将在servlet过滤器中使用,或者直接在我的过滤器中使用?
谢谢您!
更新-代码段:
RestController ,注射 JdbcTemplate 正常工作,但在过滤器我不能注入它,总是抛出 nullPointerException .

@SpringBootApplication
public class AsdApplication {

    public static void main(String[] args) {
        SpringApplication.run(AsdApplication.class, args);
    }

    public static class ApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

        @Override
        protected Filter[] getServletFilters() {
            DelegatingFilterProxy delegateFilterProxy = new DelegatingFilterProxy();
            delegateFilterProxy.setTargetBeanName("MyFilter");
            return new Filter[] { delegateFilterProxy };
        }

        @Override
        protected Class<?>[] getRootConfigClasses() {
            return null;
        }

        @Override
        protected Class<?>[] getServletConfigClasses() {
            return null;
        }

        @Override
        protected String[] getServletMappings() {
            return null;
        }
    }
}
@RestController
public class RestCtrl {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    @GetMapping("/test")
    public ResponseEntity<String> getTest() {
        String result = jdbcTemplate.queryForObject("<query>", String.class);
        System.out.println("result in ctrl: " + result);
        return new ResponseEntity<>("asd ad asd asd asd", HttpStatus.OK);
    }
}
@Component(value = "MyFilter")
public class MyFilter extends OncePerRequestFilter {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String result = jdbcTemplate.queryForObject("<query>", String.class);
        System.out.println("result in filter: " + result);

        User currentUser = new User("username", "password", new ArrayList<>());
        UsernamePasswordAuthenticationToken authenticatedUser = new UsernamePasswordAuthenticationToken(
                currentUser, null, currentUser.getAuthorities()
        );

        SecurityContextHolder.getContext().setAuthentication(authenticatedUser);
        filterChain.doFilter(request, response);
    }
}
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
      httpSecurity.csrf().disable().authorizeRequests().anyRequest().authenticated();
      httpSecurity.addFilterBefore(new MyFilter(), UsernamePasswordAuthenticationFilter.class);
    }
}
spring.datasource.url=jdbc:<sqlserver>
spring.datasource.username=<user>
spring.datasource.password=<pass>
spring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver
ffx8fchx

ffx8fchx1#

你应该用这个:
通过这个类,您可以在非bean类中获得不同的springbootbean。

@Component
public class ApplicationContextUtils implements ApplicationContextAware {

    private static ApplicationContext ctx;

    @Override
    public void setApplicationContext(ApplicationContext appContext)
            throws BeansException {
        ctx = appContext;

    }

    public static ApplicationContext getApplicationContext() {
        return ctx;
    }
}

然后在创建它之后,按以下方式获取bean:

ApplicationContext appCtx = ApplicationContextUtils.getApplicationContext();

// Here you get your dependency
ARequiredClass dependency  = appCtx.getBean(ARequiredClass.class);
eivnm1vs

eivnm1vs2#

因为您实际使用的是springboot,并且希望将其作为springsecurity过滤器链的一部分(这是另一回事!)你需要做的是
创建 @Bean 方法创建过滤器并使其成为bean
创建 @Bean 方法并添加 FilterRegistration 防止bean被spring boot注册为过滤器
配置Spring Security 。

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

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
      httpSecurity.csrf().disable().authorizeRequests().anyRequest().authenticated();
      httpSecurity.addFilterBefore(myFilter(), UsernamePasswordAuthenticationFilter.class);
    }
}

@Bean
public MyFilter myFilter() {
  return new MyFilter();
}

@Bean
public FilterRegistrationBean<MyFilter> myFilterRegistationBean() {
  FilterRegistationBean frb = new FilterRegistrationBean(myFilter());
  frb.setEnabled(false);
  return frb;
}

最后移除 @Component 从你的 MyFilter 因为你不需要它,它会创建一个额外的示例。所有先前的更改(如 ApplicationInitializer 等等。您可以删除。
注意:因为您使用的是Spring Security ,并且以某种方式将其用于身份验证,而不是扩展 OncePerRequestFilter 我建议你延长 Spring 安全期 AbstractAuthenticationProcessingFilter 它与Spring Security 集成得更好(比如激发用于身份验证、日志记录等的事件)。

klsxnrf1

klsxnrf13#

我看到你正在创建一个 MyFilter 而不是使用spring管理的 @Component(value = "MyFilter") ```
httpSecurity.addFilterBefore(new MyFilter(), UsernamePasswordAuthenticationFilter.class);

因此,你将击中一个npe因为 `jdbcTemplate` 为空。您可以将托管示例注入到spring中,而不是创建一个新示例。

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

@Autowired
@Qualifier("MyFilter")
private MyFilter myFilter;

@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
  httpSecurity.csrf().disable().authorizeRequests().anyRequest().authenticated();
  httpSecurity.addFilterBefore(myFilter, UsernamePasswordAuthenticationFilter.class);
}

}

相关问题