-2

我在使用Spring-MVC(4.2.5),Spring-Security(4.0.3)和MongoDB開發非常簡單的Web應用程序時遇到了一些問題。Spring自動佈線空指針異常

我想實現一個自定義身份驗證提供程序,以便通過數據庫登錄用戶,使用DAO模式。儘管它似乎已經正確地初始化了應用程序上下文,但我在Autowired變量(CustomerDao和CustomUserDetailsS​​ervice)上使用了空指針異常。

的web.xml

<?xml version="1.0" encoding="UTF-8"?> 
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" 
    id="WebApp_ID" version="3.1"> 
    <display-name>AcmeSpring</display-name> 
    <servlet> 
     <servlet-name>SpringController</servlet-name> 
     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
     <init-param> 
      <param-name>contextConfigLocation</param-name> 
      <param-value>/WEB-INF/spring-mvc.xml</param-value> 
     </init-param> 
     <load-on-startup>1</load-on-startup> 
    </servlet> 
    <servlet-mapping> 
     <servlet-name>SpringController</servlet-name> 
     <url-pattern>/</url-pattern> 
    </servlet-mapping> 
    <listener> 
     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
    </listener> 
    <context-param> 
     <param-name>contextConfigLocation</param-name> 
     <param-value> 
      /WEB-INF/spring-security.xml 
     </param-value> 
    </context-param> 
    <filter> 
     <filter-name>springSecurityFilterChain</filter-name> 
     <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> 
    </filter> 
    <filter-mapping> 
     <filter-name>springSecurityFilterChain</filter-name> 
     <url-pattern>/*</url-pattern> 
    </filter-mapping> 
</web-app> 

彈簧mvc.xml

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns:mvc="http://www.springframework.org/schema/mvc" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" 
    xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:mongo="http://www.springframework.org/schema/data/mongo" 
    xsi:schemaLocation="http://www.springframework.org/schema/mvc 
     http://www.springframework.org/schema/mvc/spring-mvc.xsd 
     http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans.xsd 
     http://www.springframework.org/schema/context 
     http://www.springframework.org/schema/context/spring-context.xsd 
     http://www.springframework.org/schema/data/mongo 
     http://www.springframework.org/schema/data/mongo/spring-mongo-1.5.xsd"> 

    <mvc:annotation-driven /> 
    <context:component-scan base-package="controller" /> 
    <context:component-scan base-package="model" /> 
    <context:component-scan base-package="dao" /> 
    <context:component-scan base-package="service" /> 

    <mvc:resources mapping="/resources/**" location="/resources/" /> 

    <bean id="templateResolver" 
     class="org.thymeleaf.templateresolver.ServletContextTemplateResolver"> 
     <property name="prefix" value="/WEB-INF/html/" /> 
     <property name="suffix" value=".html" /> 
     <property name="templateMode" value="HTML5" /> 
    </bean> 

    <bean id="templateEngine" class="org.thymeleaf.spring4.SpringTemplateEngine"> 
     <property name="templateResolver" ref="templateResolver" /> 
    </bean> 

    <bean class="org.thymeleaf.spring4.view.ThymeleafViewResolver"> 
     <property name="templateEngine" ref="templateEngine" /> 
     <property name="order" value="1" /> 
    </bean> 

    <mongo:db-factory id="mongoDbFactory" host="localhost" 
     port="27017" dbname="AcmeSpring" /> 

    <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"> 
     <constructor-arg ref="mongoDbFactory" /> 
    </bean> 

    <bean id="customerDao" class="dao.CustomerDaoImpl"> 
    </bean> 
</beans> 

彈簧的security.xml

<beans:beans xmlns="http://www.springframework.org/schema/security" 
    xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd 
    http://www.springframework.org/schema/security 
    http://www.springframework.org/schema/security/spring-security-4.0.xsd"> 

    <http pattern="/resources/**" security="none" /> 

    <http auto-config="true"> 
     <intercept-url pattern="/user/**" access="hasRole('USER')" /> 
     <form-login authentication-failure-url="/login" login-page="/login" 
      login-processing-url="/login" default-target-url="/user" /> 
     <logout invalidate-session="true" success-handler-ref="logoutSuccessHandler" /> 
    </http> 

    <authentication-manager> 
     <authentication-provider ref="customAuthenticationProvider" /> 
    </authentication-manager> 

    <beans:bean id="customUserDetailsService" class="service.CustomUserDetailsService"> 
    </beans:bean> 

    <beans:bean id="customAuthenticationProvider" class="service.CustomAuthenticationProvider"> 
    </beans:bean> 

    <beans:bean id="logoutSuccessHandler" class="service.CustomLogoutSuccessHandler"> 
    </beans:bean> 
</beans:beans> 

CustomAuthenticationProvider

@Component 
public class CustomAuthenticationProvider implements AuthenticationProvider { 
    @Autowired 
    CustomUserDetailsService userDetails; 

    @Override 
    public Authentication authenticate(Authentication authentication) throws AuthenticationException { 
     String username = authentication.getName(); 
     String password = authentication.getCredentials().toString(); 

     System.out.println(userDetails == null); 

     Customer customer = userDetails.loadUserByUsername(username); 

     if(customer == null) { 
      throw new BadCredentialsException("Username errato"); 
     } 

     if(!password.equals(customer.getPassword())) { 
      throw new BadCredentialsException("Password errata"); 
     } 

     List<GrantedAuthority> authorities = new ArrayList<>(); 
     authorities.add(new SimpleGrantedAuthority(customer.getRole())); 

     return new UsernamePasswordAuthenticationToken(customer, password, authorities); 
    } 

    @Override 
    public boolean supports(Class<?> clazz) { 
     return clazz.equals(UsernamePasswordAuthenticationToken.class); 
    } 
} 

CustomUserDetailsS​​ervice

@Service 
public class CustomUserDetailsService implements UserDetailsService { 
    @Autowired 
    private CustomerDao customerDao; 

    @Override 
    public Customer loadUserByUsername(String username) throws UsernameNotFoundException { 
     return customerDao.findCustomerByUsername(username); 
    } 
} 

CustomerDaoImpl

@Repository 
public class CustomerDaoImpl implements CustomerDao { 
    private static final String COLLECTION = "Customer"; 
    @Autowired 
    private MongoTemplate mongoTemplate; 

    @Override 
    public void create(Customer customer) { 
     this.mongoTemplate.insert(customer, COLLECTION); 
    } 

    @Override 
    public Customer findCustomerByUsername(String username) { 
     Query query = new Query(); 
     query.addCriteria(Criteria.where("username").is(username)); 
     System.out.println(query.toString()); 
     return this.mongoTemplate.findOne(query, Customer.class); 
    } 
} 

棧跟蹤

java.lang.NullPointerException 
    service.CustomUserDetailsService.loadUserByUsername(CustomUserDetailsService.java:18) 
    service.CustomAuthenticationProvider.authenticate(CustomAuthenticationProvider.java:32) 
    org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:167) 
    org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:192) 
    org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:93) 
    org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:217) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 
    org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:120) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 
    org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:120) 
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 
    org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64) 
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 
    org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:53) 
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 
    org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 
    org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213) 
    org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176) 
    org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) 
    org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262) 

我在哪裏錯了? 預先感謝您。

編輯:我沒有手動初始化自動裝入的變量,只是壞貼,我編輯了我的代碼。

EDIT2:通過@iMysak的建議我刪除從彈簧mvc.xml的customerDao bean聲明和彈簧security.xml文件3個服務bean聲明

新的堆棧跟蹤

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.filterChains': Cannot resolve reference to bean 'org.springframework.security.web.DefaultSecurityFilterChain#1' while setting bean property 'sourceList' with key [1]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.web.DefaultSecurityFilterChain#1': Cannot create inner bean '(inner bean)#5adbfd3' of type [org.springframework.security.web.authentication.logout.LogoutFilter] while setting constructor argument with key [4]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#5adbfd3': Cannot resolve reference to bean 'logoutSuccessHandler' while setting constructor argument; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'logoutSuccessHandler' is defined 
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:359) 
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108) 
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveManagedList(BeanDefinitionValueResolver.java:382) 
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:157) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1481) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1226) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:753) 
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839) 
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538) 
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:444) 
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:326) 
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107) 
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4853) 
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5314) 
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145) 
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1408) 
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1398) 
    at java.util.concurrent.FutureTask.run(Unknown Source) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) 
    at java.lang.Thread.run(Unknown Source) 
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.web.DefaultSecurityFilterChain#1': Cannot create inner bean '(inner bean)#5adbfd3' of type [org.springframework.security.web.authentication.logout.LogoutFilter] while setting constructor argument with key [4]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#5adbfd3': Cannot resolve reference to bean 'logoutSuccessHandler' while setting constructor argument; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'logoutSuccessHandler' is defined 
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveInnerBean(BeanDefinitionValueResolver.java:313) 
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:129) 
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveManagedList(BeanDefinitionValueResolver.java:382) 
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:157) 
    at org.springframework.beans.factory.support.ConstructorResolver.resolveConstructorArguments(ConstructorResolver.java:634) 
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:140) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1143) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1046) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) 
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351) 
    ... 26 more 
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#5adbfd3': Cannot resolve reference to bean 'logoutSuccessHandler' while setting constructor argument; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'logoutSuccessHandler' is defined 
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:359) 
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108) 
    at org.springframework.beans.factory.support.ConstructorResolver.resolveConstructorArguments(ConstructorResolver.java:634) 
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:140) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1143) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1046) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) 
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveInnerBean(BeanDefinitionValueResolver.java:299) 
    ... 40 more 
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'logoutSuccessHandler' is defined 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:698) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1175) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:284) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) 
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351) 
    ... 48 more 

我也嘗試添加aop,tx和表達式依賴關係建議here但我得到上面的堆棧跟蹤

+0

嘗試在彈簧security.xml文件中加入這一行:

+0

是的,CustomerDao(接口)和CustomerDaoImpl都在dao包中 – andy

回答

2

這可能是使用多個的問題標籤。請嘗試下一步:

<context:component-scan base-package="controller model dao service" /> 

而不是單獨聲明它們。

+0

即使更改組件掃描也會出現同樣的錯誤 – andy

+0

@andy您是否可以將這些未命中的bean聲明從** spring-security.xml **並放入** spring- mvc.xml **? customUserDetailsS​​ervice和fea其他。只是爲了確保 – iMysak

+0

我嘗試了,但是我得到了一個錯誤:「在名稱爲'org.springframework.security.filterChains'的情況下創建bean」 – andy

1

你犯了經典的Spring bean錯誤。你詮釋了豆:

@Autowired 
CustomUserDetailsService userDetails; 

你叫新:

userDetails = new CustomUserDetailsService(); 

這是不是春天的控制或你的下。你叫新的那一刻,它是出於春天的手。

如果您希望Spring自動連接依賴項,則不能調用new來初始化該引用。讓春天去做吧。

+0

我的代碼中沒有userDetails = new CustomUserDetailsS​​ervice(),對不好的粘貼抱歉:我嘗試刪除所有Autowired註釋並手動初始化dao和服務,然後我忘記刪除該行。我知道如果這些是自動裝配的,我不必初始化這些變量。我編輯了我的問題 – andy

0

你能嘗試擺脫

<beans:bean id="customAuthenticationProvider" class="service.CustomAuthenticationProvider"> 
</beans:bean> 

<beans:bean id="customUserDetailsService" class="service.CustomUserDetailsService"> 
    </beans:bean> 

我認爲當你宣佈@Autowired XML聲明可能是多餘的註釋聲明和組件掃描

+0

刪除這些行我得到「創建名稱爲'org.springframework.security.filterChains'的bean的錯誤」等 – andy

-1

一特級

例如 @Autowired CustomerDao customerDao;

  1. 字段名稱應該與xml文件中聲明的bean名稱匹配。
  2. 您需要實現setter方法,因爲自動裝配發生在三個階段構造函數注入,setter方法注入和接口注入。
  3. 所以,如果你沒有創建setter方法,當您使用自動裝配Autowired對象將拋出NullPointerException:

public void setCustomerDao(CustomerDao customerDao) { 
    this.customerDao= customerDao; 
} 
+0

請參見https:// www。tutorialspoint.com/spring/spring_autowired_annotation.htm –