自动装配时出现空指针异常 Class
Null Pointer Exception When Autowiring Class
我正在构建一个 REST API 使用 Spring Boot with Shiro 进行身份验证。当我尝试在我的领域代码中自动装配存储库时,出现 NullPointerException。在别处自动装配存储库不会产生此错误。
这是我的授权域:
@Component
public class CCDAuthorizingRealm extends AuthorizingRealm {
@Autowired
private UserRepository userRepository;
public CCDAuthorizingRealm() { }
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
AuthenticationInfo authenticationInfo = null;
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
String username = token.getUsername();
User user = null;
try {
user = userRepository.findByUsername(username);
} catch (Exception e) {
e.printStackTrace(System.err);
}
if (user != null) {
authenticationInfo = new SimpleAuthenticationInfo(
new SimplePrincipalCollection(username, username),
user.getPassword());
}
return authenticationInfo;
}
....
}
调用findByUsername()方法时出现异常
这是我要注入的存储库的代码。
@Transactional(readOnly=true)
@RepositoryRestResource(collectionResourceRel="users", path="users")
public interface UserRepository extends PagingAndSortingRepository<User, Long> {
User findByUsername(@Param("user") String user);
....
}
为了测试,我将存储库自动连接到我的应用程序 class 中并打印了结果,我没有发现任何错误。为了完整起见,这里是显示的代码:
@SpringBootApplication
public class Application implements CommandLineRunner {
@Autowired
public UserRepository userRepository;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override
public void run(String... strings) {
System.out.println("\nServer up\n");
User user = userRepository.findOne(new Long(1));
System.out.println(user.getUsername());
}
}
非常感谢任何帮助。
编辑
据我所知,这个问题不是重复的,另一个问题的答案也没有解决我的问题。我正在注入 bean 并通知组件的 IoC 容器,但自动装配仍然导致 NPE。
使用范围没有帮助,因为我只需要单个服务对象。 Configurable 标签不是必需的,因为我是自动装配的,不需要创建新对象。
更新
这里是我调用 CCDAuthorizingRealm 的地方。我刚开始使用 Shiro,但我很确定这是正确的。
@RestController
@RequestMapping(produces="application/json")
public class AuthenticationController {
CCDAuthorizingRealm realm = new CCDAuthorizingRealm();
SecurityManager sm = new DefaultSecurityManager(realm);
public AuthenticationController() { }
/**
* Authenticate user with supplied credentials
*
* @param login - credentials
* @return success or failure message
*/
@RequestMapping(value = "/login", method = RequestMethod.POST, consumes="application/json")
public String login(@RequestBody LoginInfo login) {
String response;
UsernamePasswordToken token = new UsernamePasswordToken(
login.getUsername(),
login.getPassword(),
false);
try {
SecurityUtils.setSecurityManager(sm);
Subject currentUser = SecurityUtils.getSubject();
if (currentUser.isAuthenticated()) {
currentUser.logout();
}
currentUser.login(token);
response = token.toString();
} catch (AuthenticationException e) {
response = "Error: Incorrect username or password";
}
return response;
}
}
我目前正在尝试在控制器中创建我的领域的新实例。我这样做是因为当我尝试时:
@Autowired
CCDAuthorizingRealm realm;
SecurityManager sm = new DefaultSecurityManager(realm);
我在初始化安全管理器时会遇到运行时错误,因为它会抱怨领域为空。但是,我不明白为什么 realm 为空,因为它被注释为组件。也许这就是我问题的根源。
我找到了问题的答案。这是我的 applicationContext.xml:
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="/login" />
<property name="successUrl" value="/home" />
<property name="unauthorizedUrl" value="/login" />
<property name="filterChainDefinitions">
<value>
/login = authc
</value>
</property>
</bean>
此配置的问题是登录 URL 被过滤掉了。解决方法是像这样简单地将值更改为 home:
<value>
/home = authc
</value>
我认为将主页 URL 设置在过滤器后面。
我正在构建一个 REST API 使用 Spring Boot with Shiro 进行身份验证。当我尝试在我的领域代码中自动装配存储库时,出现 NullPointerException。在别处自动装配存储库不会产生此错误。
这是我的授权域:
@Component
public class CCDAuthorizingRealm extends AuthorizingRealm {
@Autowired
private UserRepository userRepository;
public CCDAuthorizingRealm() { }
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
AuthenticationInfo authenticationInfo = null;
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
String username = token.getUsername();
User user = null;
try {
user = userRepository.findByUsername(username);
} catch (Exception e) {
e.printStackTrace(System.err);
}
if (user != null) {
authenticationInfo = new SimpleAuthenticationInfo(
new SimplePrincipalCollection(username, username),
user.getPassword());
}
return authenticationInfo;
}
....
}
调用findByUsername()方法时出现异常
这是我要注入的存储库的代码。
@Transactional(readOnly=true)
@RepositoryRestResource(collectionResourceRel="users", path="users")
public interface UserRepository extends PagingAndSortingRepository<User, Long> {
User findByUsername(@Param("user") String user);
....
}
为了测试,我将存储库自动连接到我的应用程序 class 中并打印了结果,我没有发现任何错误。为了完整起见,这里是显示的代码:
@SpringBootApplication
public class Application implements CommandLineRunner {
@Autowired
public UserRepository userRepository;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override
public void run(String... strings) {
System.out.println("\nServer up\n");
User user = userRepository.findOne(new Long(1));
System.out.println(user.getUsername());
}
}
非常感谢任何帮助。
编辑
据我所知,这个问题不是重复的,另一个问题的答案也没有解决我的问题。我正在注入 bean 并通知组件的 IoC 容器,但自动装配仍然导致 NPE。
使用范围没有帮助,因为我只需要单个服务对象。 Configurable 标签不是必需的,因为我是自动装配的,不需要创建新对象。
更新
这里是我调用 CCDAuthorizingRealm 的地方。我刚开始使用 Shiro,但我很确定这是正确的。
@RestController
@RequestMapping(produces="application/json")
public class AuthenticationController {
CCDAuthorizingRealm realm = new CCDAuthorizingRealm();
SecurityManager sm = new DefaultSecurityManager(realm);
public AuthenticationController() { }
/**
* Authenticate user with supplied credentials
*
* @param login - credentials
* @return success or failure message
*/
@RequestMapping(value = "/login", method = RequestMethod.POST, consumes="application/json")
public String login(@RequestBody LoginInfo login) {
String response;
UsernamePasswordToken token = new UsernamePasswordToken(
login.getUsername(),
login.getPassword(),
false);
try {
SecurityUtils.setSecurityManager(sm);
Subject currentUser = SecurityUtils.getSubject();
if (currentUser.isAuthenticated()) {
currentUser.logout();
}
currentUser.login(token);
response = token.toString();
} catch (AuthenticationException e) {
response = "Error: Incorrect username or password";
}
return response;
}
}
我目前正在尝试在控制器中创建我的领域的新实例。我这样做是因为当我尝试时:
@Autowired
CCDAuthorizingRealm realm;
SecurityManager sm = new DefaultSecurityManager(realm);
我在初始化安全管理器时会遇到运行时错误,因为它会抱怨领域为空。但是,我不明白为什么 realm 为空,因为它被注释为组件。也许这就是我问题的根源。
我找到了问题的答案。这是我的 applicationContext.xml:
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="/login" />
<property name="successUrl" value="/home" />
<property name="unauthorizedUrl" value="/login" />
<property name="filterChainDefinitions">
<value>
/login = authc
</value>
</property>
</bean>
此配置的问题是登录 URL 被过滤掉了。解决方法是像这样简单地将值更改为 home:
<value>
/home = authc
</value>
我认为将主页 URL 设置在过滤器后面。