我编写了一个带有自定义用户详细信息服务的 Spring MVC 应用程序。
@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 为空,所以它在上面的行中抛出了一个空指针异常,这意味着自动装配没有在这个服务中注入这个 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();
}
现在,当我创建用户、从任何其他对象获取用户时,这确实可以正常工作,只是这个 CustomUserDetailsService 没有被正确注入。com.securetest.app.service
它与能够使用 @Autowired 的其他服务在同一个包中。
我有 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>
这是我的 security-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<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.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<http use-expressions="true">
<intercept-url pattern="/exam" access="isAuthenticated()" />
<intercept-url pattern="/" access="permitAll" />
<intercept-url pattern="/**" access="denyAll" />
<form-login />
<logout invalidate-session="true" logout-success-url="/"
logout-url="/logout" />
</http>
<beans:bean id="CustomUserDetailsService"
class="com.securetest.app.service.CustomUserDetailsService" />
<beans:bean
class="org.springframework.security.authentication.encoding.ShaPasswordEncoder"
id="passwordEncoder" />
<authentication-manager>
<authentication-provider user-service-ref='CustomUserDetailsService'>
<password-encoder ref="passwordEncoder" />
</authentication-provider>
</authentication-manager>
</beans:beans>
最后只是为了确保我没有遗漏任何东西,我的 servlet-context.xml - 如您所见,这里我使用的是 context-component-scan,它应该将所有内容注入com.securetest.app
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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">
<!-- DispatcherServlet Context: defines this servlet's request-processing
infrastructure -->
<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving
up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<context:component-scan base-package="com.securetest.app." />
<!-- Resolves views selected for rendering by @Controllers to .jsp resources
in the /WEB-INF/views directory -->
<beans:bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<beans:bean
class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<beans:property name="mediaTypes">
<beans:map>
<beans:entry key="html" value="text/html" />
<beans:entry key="json" value="application/json" />
</beans:map>
</beans:property>
<beans:property name="defaultViews">
<beans:list>
<beans:bean
class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
<beans:property name="prefixJson" value="true" />
</beans:bean>
</beans:list>
</beans:property>
</beans:bean>
</beans:beans>
我应该提一下,我很确定这就像我错误地订购了我的 web.xml,反之亦然,因为几乎完全相同的代码适用于另一个项目,但我看不出两者之间的区别。
为什么我没有遇到自动装配故障而只是出现 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>