Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/350.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java spring@Autowired给出NullPointerException_Java_Spring_Spring Mvc_Spring Security - Fatal编程技术网

Java spring@Autowired给出NullPointerException

Java spring@Autowired给出NullPointerException,java,spring,spring-mvc,spring-security,Java,Spring,Spring Mvc,Spring Security,我正在用Hibernate学习Spring,并用简单的登录制作一个演示项目。我被@Autowired设置为NullPointerException所困扰。我没有得到它背后的正确原因,但我想这是因为Spring无法自己实例化bean 只有当我使用customAuthenticationProvider登录时才会出现问题。如果我使用默认的,用户名和密码为admin,代码运行正常 这是我的密码 web.xml <web-app xmlns="http://xmlns.jcp.org/xml/ns

我正在用Hibernate学习Spring,并用简单的登录制作一个演示项目。我被@Autowired设置为NullPointerException所困扰。我没有得到它背后的正确原因,但我想这是因为Spring无法自己实例化bean

只有当我使用customAuthenticationProvider登录时才会出现问题。如果我使用默认的
,用户名和密码为admin,代码运行正常

这是我的密码

web.xml

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
     http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">

  <display-name>Archetype Created Web Application</display-name>

  <servlet>
      <servlet-name>dispatcher</servlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
      <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
      <servlet-name>dispatcher</servlet-name>
      <url-pattern>/</url-pattern>
  </servlet-mapping>

  <context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>
        /WEB-INF/spring-security.xml
      </param-value>
  </context-param>

  <listener>
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

<!-- Spring Security -->
  <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>

  <context-param>
      <param-name>log4jConfigLocation</param-name>
      <param-value>classpath:log4j.properties</param-value>
  </context-param>

  <listener>
      <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
  </listener>

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

<mvc:annotation-driven />
<context:component-scan base-package="com.ssb" />
<context:annotation-config />

<bean
    class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/views/" />
    <property name="suffix" value=".jsp" />
</bean>

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url"
        value="jdbc:mysql://localhost:3306/springHibernateDemo" />
    <property name="username" value="root" />
    <property name="password" value="admin" />
</bean>

<bean id="sessionFactory"
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="packagesToScan" value="com.ssb.model" />
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.hbm2ddl.auto">update</prop>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
            <prop key="hibernate.show_sql">true</prop>
        </props>
    </property>
</bean>

<tx:annotation-driven transaction-manager="transactionManager" />

<bean id="transactionManager"
    class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

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

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

<http auto-config="true" use-expressions="true">
    <http-basic/>
    <intercept-url pattern="/login" access="permitAll"/>
    <intercept-url pattern="/**" access="isAuthenticated()" />
    <form-login login-page="/login" default-target-url="/home"
        authentication-failure-url="/login?error" login-processing-url="/j_spring_security_check"
        username-parameter="username" password-parameter="password" />
    <logout logout-success-url="/login?logout" logout-url="/j_spring_security_logout"/>
    <!-- enable csrf protection -->
    <csrf/>
</http>

<beans:bean id="customAuthenticationProvider"
    class="com.ssb.components.CustomAuthenticationProvider">
</beans:bean>

<authentication-manager>
    <authentication-provider>
        <user-service>
            <user name="admin" password="admin" authorities="ROLE_USER" />
        </user-service>
    </authentication-provider>
    <authentication-provider ref="customAuthenticationProvider">
    </authentication-provider>
</authentication-manager>

</beans:beans>
AuthServiceImpl.java

@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    public AuthService authService;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        authService.authenticateUser(authentication);
        // it never gets to this line as authService is null
        return new UsernamePasswordAuthenticationToken(authentication.getName(), "");
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return true;
    }

}
@Controller
public class HomeController {

  @Autowired
  HomeService homeService;

  @Autowired
  SessionFactory sessionFactory;

  @RequestMapping(value="/home", method=RequestMethod.GET)
  public String home(Model model){

      User user = new User();
      user.setName("test");
      user.setPassword("test");
      homeService.save(user);

      return "home";
  }

  @RequestMapping(value= "/login", method=RequestMethod.GET)
  public ModelAndView login(
          @RequestParam(value = "error", required = false) String error,
          @RequestParam(value = "logout", required = false) String logout) throws IOException {

          ModelAndView model = new ModelAndView();
          if (error != null) {
              model.addObject("error", "Invalid username and password!");
          }
          if (logout != null) {
            model.addObject("msg", "You've been logged out successfully.");
          }
          model.setViewName("login");
          return model;
      }

}
@Service
public class AuthServiceImpl implements AuthService{

  @Autowired
  HomeDao homeDao;

  @Transactional
  public void authenticateUser(Authentication authentication) {
    homeDao.authenticateUser(authentication);
  }

}
@Repository
public class HomeDao {

  @Autowired
  SessionFactory sessionFactory;

  public void save(User user){
      Session session = sessionFactory.getCurrentSession();
      Roles role = (Roles) session.get(Roles.class, 1);
      user.setRole_id(role);
      session.save(user);
  }

  public void authenticateUser(Authentication authentication) {
      Criteria criteria =  sessionFactory.getCurrentSession().createCriteria(User.class);
      criteria.add(Restrictions.eq("username", authentication.getPrincipal().toString()));
      criteria.add(Restrictions.eq("password", authentication.getCredentials().toString()));
      @SuppressWarnings("unchecked")
      List<User> result = criteria.list();
      System.out.println(result);

  }

}
HomeDao.java

@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    public AuthService authService;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        authService.authenticateUser(authentication);
        // it never gets to this line as authService is null
        return new UsernamePasswordAuthenticationToken(authentication.getName(), "");
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return true;
    }

}
@Controller
public class HomeController {

  @Autowired
  HomeService homeService;

  @Autowired
  SessionFactory sessionFactory;

  @RequestMapping(value="/home", method=RequestMethod.GET)
  public String home(Model model){

      User user = new User();
      user.setName("test");
      user.setPassword("test");
      homeService.save(user);

      return "home";
  }

  @RequestMapping(value= "/login", method=RequestMethod.GET)
  public ModelAndView login(
          @RequestParam(value = "error", required = false) String error,
          @RequestParam(value = "logout", required = false) String logout) throws IOException {

          ModelAndView model = new ModelAndView();
          if (error != null) {
              model.addObject("error", "Invalid username and password!");
          }
          if (logout != null) {
            model.addObject("msg", "You've been logged out successfully.");
          }
          model.setViewName("login");
          return model;
      }

}
@Service
public class AuthServiceImpl implements AuthService{

  @Autowired
  HomeDao homeDao;

  @Transactional
  public void authenticateUser(Authentication authentication) {
    homeDao.authenticateUser(authentication);
  }

}
@Repository
public class HomeDao {

  @Autowired
  SessionFactory sessionFactory;

  public void save(User user){
      Session session = sessionFactory.getCurrentSession();
      Roles role = (Roles) session.get(Roles.class, 1);
      user.setRole_id(role);
      session.save(user);
  }

  public void authenticateUser(Authentication authentication) {
      Criteria criteria =  sessionFactory.getCurrentSession().createCriteria(User.class);
      criteria.add(Restrictions.eq("username", authentication.getPrincipal().toString()));
      criteria.add(Restrictions.eq("password", authentication.getCredentials().toString()));
      @SuppressWarnings("unchecked")
      List<User> result = criteria.list();
      System.out.println(result);

  }

}

您正在将
spring security.xml
加载为spring根上下文,并且在此上下文中没有任何
上下文:组件扫描
,因此在尝试在根上下文中使用
@Autowired
bean时接收NPE是绝对正常的,该根上下文已加载到mvc上下文中,它是一个子上下文

您可以在以下答案中获得更多信息:

为了避免此类错误,我将执行以下操作:

  • dispatcherservlet.xml
    中,只需在
    上下文中映射:组件扫描
    @Controller
    映射的原型 例如:

    <context:component-scan base-package="com.ssb.controller" />
    
    <context:component-scan base-package="com.ssb.repositories" />
    <context:component-scan base-package="com.ssb.services" />
    
  • 同样,您应该将
    dispatcherservlet.xml
    中定义的一些bean移动到
    spring security.xml
    就这些:

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url"
            value="jdbc:mysql://localhost:3306/springHibernateDemo" />
        <property name="username" value="root" />
        <property name="password" value="admin" />
    </bean>
    
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="packagesToScan" value="com.ssb.model" />
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
            </props>
        </property>
    </bean>
    
    <tx:annotation-driven transaction-manager="transactionManager" />
    
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>
    
    spring-security.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xmlns="http://www.springframework.org/schema/security"
      xmlns:tx="http://www.springframework.org/schema/tx" 
      xmlns:context="http://www.springframework.org/schema/context"
      xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/security 
        http://www.springframework.org/schema/security/spring-security.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
    
        <context:component-scan base-package="com.ssb" />
    
        <beans:bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
            <beans:property name="driverClassName" value="com.mysql.jdbc.Driver" />
            <beans:property name="url"
            value="jdbc:mysql://localhost:3306/springHibernateDemo" />
            <beans:property name="username" value="root" />
            <beans:property name="password" value="admin" />
        </beans:bean>
    
        <beans:bean id="sessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
            <beans:property name="dataSource" ref="dataSource" />
            <beans:property name="packagesToScan" value="com.ssb.model" />
            <beans:property name="hibernateProperties">
                <beans:props>
                    <beans:prop key="hibernate.hbm2ddl.auto">update</beans:prop>
                    <beans:prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect
                    </beans:prop>
                    <beans:prop key="hibernate.show_sql">true</beans:prop>
                </beans:props>
            </beans:property>
         </beans:bean>
    
        <tx:annotation-driven transaction-manager="transactionManager" />
    
        <beans:bean id="transactionManager"
        class="org.springframework.orm.hibernate4.HibernateTransactionManager">
            <beans:property name="sessionFactory" ref="sessionFactory" />
        </beans:bean>
    
        <http pattern="/resources/**" security="none" />
    
        <http auto-config="true" use-expressions="true">
            <http-basic />
            <intercept-url pattern="/login" access="permitAll" />
            <intercept-url pattern="/**" access="isAuthenticated()" />
            <form-login login-page="/login" default-target-url="/home"
            authentication-failure-url="/login?error" login-processing-url="/j_spring_security_check"
            username-parameter="username" password-parameter="password" />
            <logout logout-success-url="/login?logout" logout-url="/j_spring_security_logout" />
            <!-- enable csrf protection -->
            <csrf />
        </http>
    
        <beans:bean id="customAuthenticationProvider"
            class="com.ssb.components.CustomAuthenticationProvider">
        </beans:bean>
    
        <authentication-manager>
            <authentication-provider>
                <user-service>
                    <user name="admin" password="admin" authorities="ROLE_USER" />
                </user-service>
            </authentication-provider>
            <authentication-provider ref="customAuthenticationProvider">
            </authentication-provider>
        </authentication-manager>
    
    </beans:beans>
    
    
    更新
    org.hibernate.dialogue.mysqldialogue
    真的
    
    尝试在dispatcher-servlet.xml的末尾放置上下文:component scan base package=“com.ssb”,它可能会起作用,因为在ioc容器中放置bean时需要依赖项,因此在创建AuthService bean时,需要在ioc容器中未创建的依赖项类。确保所有依赖项配置正确的顺序


    Spring
    @Autowired
    不能为
    null
    ,如果在这种情况下应用程序甚至无法启动。只有在xml中未设置注释处理
    context:component scan
    context:annotation config
    或者您自己正在创建bean的新实例时,它才会为
    null
    。在您的情况下,第一种情况类似。@M.Deinum请查看dispatcher-servlet.xml<代码>
  • 就在那里。这是为
    DispatcherServlet
    加载的上下文,而不是由
    ContextLoarListener
    加载的上下文,它们与
    Bean(Factory)后处理器互不影响。
    您是否传递了原型注释所在的确切包名。是的,我传递了确切的基本包“com.ssb”.