Java Spring自定义用户详细信息服务空指针异常
我已经编写了一个带有自定义用户详细信息服务的SpringMVC应用程序Java Spring自定义用户详细信息服务空指针异常,java,spring,spring-security,Java,Spring,Spring Security,我已经编写了一个带有自定义用户详细信息服务的SpringMVC应用程序 @Service("userDetailsService") public class CustomUserDetailsService implements UserDetailsService{ @Autowired private UserAccountDao userAccountDao; @Transactional(readOnly = true) public UserDet
@Service("userDetailsService")
public class CustomUserDetailsService implements UserDetailsService{
@Autowired
private UserAccountDao userAccountDao;
@Transactional(readOnly = true)
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
UserDetails user = null;
try {
UserAccount dbUser = (UserAccount) userAccountDao.getByUsername(username);
此时,userAccountDao为null,因此它在上面的一行抛出null指针异常,这意味着自动连线没有将此Dao注入到该服务中。现在Dao本身已经自动连接成这样
@Repository("userAccountDao")
public class UserAccountDaoImpl extends UserDaoImpl implements UserAccountDao {
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private SessionFactory sessionFactory;
@Override
public void addUserAccount(final UserAccount userAccount) {
userAccount.setPassword(passwordEncoder.encodePassword(userAccount.getPassword(), "salt"));
sessionFactory.getCurrentSession().save(userAccount);
}
}
@Repository("userDao")
public class UserDaoImpl implements UserDao {
@Autowired
private SessionFactory sessionFactory;
@Override
public User getByUsername(final String username) {
return (User) sessionFactory.getCurrentSession()
.createQuery("from User where username = :username")
.setParameter("username", username).uniqueResult();
}
现在,当我创建用户、从任何其他对象获取用户时,这个工作正常,只是这个CustomUserDetails服务没有被正确注入。它与能够使用@Autowired fine的其他服务位于同一个包com.securetest.app.service
我有3个context.xml文件-下面是我的web.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml
/WEB-INF/spring/appServlet/security-context.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>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml
/WEB-INF/spring/appServlet/persistence-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
我应该提到的是,我很确定这有点像是我错误地订购了web.xml,反之亦然,因为几乎完全相同的代码适用于另一个项目,但我看不出两者之间的区别
为什么我没有autowire故障,只有nullPointerException
编辑:下面添加了root-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="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.xsd">
</beans>
您的web.xml正在创建两个Spring应用程序上下文。让我们将它们称为Security(在Security context.xml之后)和Servlet(在Servlet context.xml之后)。安全性由ContextLoaderListener侦听器创建,Servlet由DispatcherServlet Servlet创建。安全性是Servlet的父级。这意味着安全性中的bean只对安全性中的其他bean可见,Servlet中的bean可以同时看到安全性中的bean和Servlet中的bean 您在安全性中定义了CustomUserDetailsService(CUDS)bean,在Servlet中定义了UserAccountDao和UserDao bean,因此CUDS bean无法看到它们。如果希望DAOBean连接到CUD,则需要在安全性中为DAOBean添加组件扫描
我不确定NPE。您的web.xml正在创建两个Spring应用程序上下文。让我们将它们称为Security(在Security context.xml之后)和Servlet(在Servlet context.xml之后)。安全性由ContextLoaderListener侦听器创建,Servlet由DispatcherServlet Servlet创建。安全性是Servlet的父级。这意味着安全性中的bean只对安全性中的其他bean可见,Servlet中的bean可以同时看到安全性中的bean和Servlet中的bean 您在安全性中定义了CustomUserDetailsService(CUDS)bean,在Servlet中定义了UserAccountDao和UserDao bean,因此CUDS bean无法看到它们。如果希望DAOBean连接到CUD,则需要在安全性中为DAOBean添加组件扫描
我不确定NPE。我认为,您的安全上下文在您的
servlet上下文之前加载,后者保存DAO的配置。当安全加载时,DAO还没有被扫描,因此没有注入任何东西!使用@Required
进行检查
我为我的项目执行以下操作:
在root context.xml中
<context:component-scan use-default-filters="true"
base-package="com.trelta.accountmanagement, com.trelta.commons">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
在servlet上下文中:
<context:component-scan use-default-filters="false"
base-package="com.trelta.accountmanagement, com.trelta.commons">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan>
我将root context.xml
&security.xml放在context参数中,将servlet context.xml
放在DispatcherServlet
的init参数中。这种方法还增加了模块化。它将WebApplicationContext
相关bean保存在一个文件中,然后将该文件传递给DispatcherServlet
,并将另一个ApplicationContext
bean保存在一个单独的文件中。我认为,安全上下文在servlet上下文
之前加载,后者保存DAO的配置。当安全加载时,DAO还没有被扫描,因此没有注入任何东西!使用@Required
进行检查
我为我的项目执行以下操作:
在root context.xml中
<context:component-scan use-default-filters="true"
base-package="com.trelta.accountmanagement, com.trelta.commons">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
在servlet上下文中:
<context:component-scan use-default-filters="false"
base-package="com.trelta.accountmanagement, com.trelta.commons">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan>
我将root context.xml
&security.xml放在context参数中,将servlet context.xml
放在DispatcherServlet
的init参数中。这种方法还增加了模块化。它将WebApplicationContext
相关bean保存在一个文件中,然后传递给DispatcherServlet
并将另一个ApplicationContext
bean保存在一个单独的文件中。根上下文.xml中有什么?我没有向它添加任何内容,但如上所示。根上下文.xml中有什么内容?我没有添加任何内容,但如上图所示,这听起来很像。顺序是由web.xml定义的,还是仅仅是context.xml文件中项目的顺序?在web.xml中<代码>上下文参数
s首先加载。目前,只需xml注入dao并检查而不是注释。@默认情况下需要自动连线bean。您必须在setter
上设置它。应用程序将在启动期间引发异常。请检查。这听起来很像。顺序是由web.xml定义的,还是仅仅是context.xml文件中项目的顺序?在web.xml中<代码>上下文参数
s首先加载。目前,只需xml注入dao并检查而不是注释。@默认情况下需要自动连线bean。您必须在setter
上设置它。应用程序将在启动期间引发异常。请检查.Err,对,因为它们没有被扫描。扫描能解决问题吗?我想我的回答太简洁了。现在编辑它。你是说我应该做另一个上下文:在security-context.xml中进行组件扫描?这似乎创建了一个BeanCreationException将组件扫描从Servlet移动到安全性,Bean应该可以通过这种方式访问这两个上下文。这会停止所有自动连接工作,并停止应用404的启动,但出现以下异常:很不幸,错误,对,因为它们没有被扫描。扫描能解决问题吗?我想我的回答太简洁了。现在编辑它。你是说我应该做另一个上下文:在security-context.xml中进行组件扫描?这似乎创造了一个beanC