Spring Boot:Autowired CRUDRepository null,在某些类中

Posted

技术标签:

【中文标题】Spring Boot:Autowired CRUDRepository null,在某些类中【英文标题】:Spring Boot: Autowired CRUDRepository null, in certain classes 【发布时间】:2017-09-03 20:11:24 【问题描述】:

我正在运行一个 SpringBoot 应用程序,其根类使用 @SpringBootApplication@EnableAutoConfiguration 进行注释。

我创建了一个UserRepositoryInterface 接口,它扩展 CrudRepository 接口与我的用户JPA 对象。这个接口没有实现,也不需要一个。此应用程序中也没有任何配置文件。 JPA DB 连接除外,但它有效。

public interface UsersRepositoryInterface extends CrudRepository<User, Long> 

    // Query to search for users via email
    List<User> findByEmail(@Param("email") String email);

我已经成功地将它自动连接到一些 REST 端点中。当我尝试将其自动装配到我的安全类中时,问题就出现了。我正在尝试使用 JWT 进行身份验证,它可以工作。现在我想在登录过程中调用数据库,但我遇到了问题。以下是课程:

首先是WebSecurityConfiguererAdapter 类,我在其中添加了过滤器的路径。请注意带有“new JWTLoginFilter”的行,这是我尝试自动装配的类:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter 

    @Autowired
    private CustomUserDetailsService userDetailsServ;

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http.csrf().disable().authorizeRequests()

                //Allow options pre-flight request
                .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
            // Allow POST request to /login
                .antMatchers(HttpMethod.POST, "/login").permitAll()
            // Others must be authenticated
                .anyRequest().authenticated()
                .and()
            // We filter the api/login requests
                .addFilterBefore(new JWTLoginFilter("/login", authenticationManager()),
                    UsernamePasswordAuthenticationFilter.class)
            // And filter other requests to check the presence of JWT in header
                .addFilterBefore(new JWTAuthenticationFilter(),
                    UsernamePasswordAuthenticationFilter.class);
    

   @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception 
    // Change logging in from username+password to email+password
        auth.userDetailsService(userDetailsServ);
    

还有JWTLoginFilter 类。我省略了一些不相关的代码:

public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter 

    @Autowired
    private UsersRepositoryInterface userRepo;

    public JWTLoginFilter(String url, AuthenticationManager authManager) 
        super(new AntPathRequestMatcher(url));
        setAuthenticationManager(authManager);
    

    @Override
    public Authentication attemptAuthentication(
        HttpServletRequest req, HttpServletResponse response)
        throws AuthenticationException, IOException, ServletException 

        //Check if userRepo is injected
        if(userRepo == null) 
            System.out.println("Null");
        

        AccountCredentials creds = new ObjectMapper()
            .readValue(req.getInputStream(), AccountCredentials.class);
        return getAuthenticationManager().authenticate(
            new UsernamePasswordAuthenticationToken(
                    creds.getEmail(),
                    creds.getPassword(),
                    Collections.emptyList()
            )
        );
    

JWTLoginFilter 中的 println 在被调用时将始终返回 Null

我错过了什么吗?

解决了:

现在工作。

注释JWTLoginFilter
@Component("someName")

并使用

将其注入 WebSecurityConfig
@Resource(name="someName")
private JWTLoginFilter myFilter;

在 JWTLoginFilter 构造函数中硬编码 URL,但我仍然必须将 AuthenticationManager 从 WebSecurityConfig 自动连接到 JWTLoginFilter。

首先必须使 AuthenticationManager 成为一个 Bean。在这里使用了答案:How To Inject AuthenticationManager using Java Configuration in a Custom Filter

@Bean(name = BeanIds.AUTHENTICATION_MANAGER)
@Override
public AuthenticationManager authenticationManagerBean() throws Exception 
    return super.authenticationManagerBean();

然后在这里注入答案:Spring Security authenticationmanager must be specified - for custom filter

@Override
@Autowired
public void setAuthenticationManager(AuthenticationManager authenticationManager) 
    super.setAuthenticationManager(authenticationManager);

同时删除

setAuthenticationManager(authManager);

在 JWTLoginFilter 的构造函数中

【问题讨论】:

能否请您添加您的项目结构? 相关***.com/questions/36663048/… 【参考方案1】:

嗯,你期待什么?您正在通过 new 关键字创建 JWTLoginFilter。 Spring 在这里根本不做任何布线。您应该将此过滤器设置为@Bean@Component 或其他任何使其成为spring bean 并以某种方式将其注入WebSecurityConfig 的方法。

【讨论】:

我对 Spring 很陌生,所以我不知道。有趣的。我有点被愚弄了,但我似乎无法将 JWTLoginFilter 类注入 WebSecurityConfig。有什么建议吗? 相关回答***.com/questions/36663048/…【参考方案2】:

我希望您的问题已经得到解决。但是我添加了一个示例代码 sn-p 供遇到相同问题的人参考。

当我们的过滤器包含自动装配的依赖项时,并且在 spring 配置中使用 new() 实例化我们的过滤器不会自动装配它的依赖项,因为这不是一个字符串管理的 bean。因此,我们需要在 spring 应用程序配置类中自动装配我们的过滤器,从而自动装配其内部依赖项。

PFB示例代码供参考。

@SpringBootApplication
public class MyApplication extends SpringBootServletInitializer 

    @Autowired
    private MyFilter myFilter;

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

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) 
        return builder.sources(MyApplication.class);
    

    @Bean
    public FilterRegistrationBean myFilterRegistration() 
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(myFilter);
        registration.addUrlPatterns("*");
        return registration;
    

过滤器:

@Component
public class MyFilter extends BaseFilter 

    @Autowired
    private EmployeeRepository employeeRepository;

    //your code goes here
       if(employeeRepository != null) 
          System.out.println("employeeRepository is not null");
       


【讨论】:

以上是关于Spring Boot:Autowired CRUDRepository null,在某些类中的主要内容,如果未能解决你的问题,请参考以下文章

spring boot filter -Autowired

如何在 Spring Boot 类之间正确注入 @Autowired?

spring-boot Autowired DiscoveryClient RestTemplate UnknownHostException

单元测试中的 Spring Boot @Autowired 返回 NullPointerException

其他模块中的 Spring Boot MongoDB 存储库不是 @Autowired

如何在spring boot的多个类中使用@Autowired MongoTemplate