【问题标题】:NullPointerException when making call to Spring Data JPA Repository调用 Spring Data JPA Repository 时出现 NullPointerException
【发布时间】:2020-10-30 19:38:54
【问题描述】:

当我调用我的 API 来验证前端的令牌时,我在调用我的 UserDetailsS​​ervice 的 loadUserByUsername 方法时遇到了问题。我能够将用户名传递给该方法,但我的userRepository 无法执行findByUsername 方法,我不确定发生了什么。我在调用之前打印出名称,它返回了正确的用户名,数据库中也存在该名称的用户。

这是我在控制台中得到的:

2020-07-09 22:46:55.121  INFO 18048 --- [nio-8080-exec-4] o.s.web.servlet.DispatcherServlet        : Completed initialization in 10 ms
2020-07-09 22:46:55.153  INFO 18048 --- [nio-8080-exec-4] c.g.Apollo.security.jwt.JwtFilter        : token not presented...
2020-07-09 22:46:55.759  INFO 18048 --- [nio-8080-exec-4] c.g.Apollo.service.UserService           : success...
2020-07-09 22:47:10.885  INFO 18048 --- [nio-8080-exec-5] c.g.Apollo.security.jwt.JwtFilter        : token not presented...
2020-07-09 22:47:10.898  INFO 18048 --- [nio-8080-exec-5] c.g.A.s.jwt.JwtUserDetailsService        : load user... max123
2020-07-09 22:47:10.909  WARN 18048 --- [nio-8080-exec-5] g.e.SimpleDataFetcherExceptionHandler    : Exception while fetching data (/verifyToken) : null

java.lang.NullPointerException: null
    at com.**.Apollo.security.jwt.JwtUserDetailsService.loadUserByUsername(JwtUserDetailsService.java:23) ~[classes/:na]
    at com.**.Apollo.service.UserService.verifyToken(UserService.java:173) ~[classes/:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na]
    at io.leangen.graphql.metadata.execution.SingletonMethodInvoker.execute(SingletonMethodInvoker.java:21) ~[spqr-0.9.9.jar:na]

当我登录用户时,UserRepository 方法工作得很好,但在这里失败了。

JwtUserDetailsS​​ervice,这是从 verifyToken 方法中调用的:

@Slf4j
@Service
public class JwtUserDetailsService implements UserDetailsService {

private UserRepository userRepository;

@Override
public UserDetails loadUserByUsername(String username) {
    log.info("load user... {}", username);
    Optional<User> user = userRepository.findByUsername(username);
    log.info("after");
    if (user.isPresent()) {
        log.info("user:: {}", user.get().getUsername());
        return getJwtUser(user.get());
    } else {
        log.info("user not found");
        return null;
    }
}

public JwtUser getJwtUser(User user) {
    return new JwtUser(
            user.getId(),
            user.getUsername(),
            user.getFirstName(),
            user.getLastName(),
            user.getEmail(),
            user.getPassword(),
            List.of(new SimpleGrantedAuthority(user.getRole().getRoleName().name())),
            user.getEnabled(),
            null
    );
}

用户存储库:

@Repository
public interface UserRepository extends JpaRepository<User, Long> {

    Optional<User> findByUsername(String username);

    boolean existsByUsername(String username);

    Optional<User> findByToken(String token);
}

UserSerice,这是暴露给前端的:

@GraphQLQuery
public User verifyToken(String token) {
    Optional<User> optionalUser = userRepository.findByToken(token);
    if(optionalUser.isPresent()) {
        UserDetails userDetails = jwtUserDetailsService.loadUserByUsername(optionalUser.get().getUsername());
        if(jwtTokenUtil.isTokenValid(token, userDetails)) {
            return optionalUser.get();
        }
    }
    return null;
}

【问题讨论】:

    标签: spring spring-security spring-data-jpa spring-data


    【解决方案1】:

    它正在抛出一个NullPointerException,因为JwtUserDetailsService 中的userRepository 未被注入并且是null

    创建如下构造函数:

    public JwtUserDetailsService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
    

    【讨论】:

      【解决方案2】:

      需要在JwtUserDetailsS​​ervice类中添加@Autowired

      @Autowired
      private UserRepository userRepository;
      

      【讨论】:

        【解决方案3】:

        您的UserRepository 依赖项似乎没有被注入JwtUserDetailsService,因为您没有自动装配它。

        您可以执行以下操作:

        使用构造函数注入自动装配依赖关系,这是推荐的方式:

        private final UserRepository userRepository;
        
        public JwtUserDetailsService(UserRepository userRepository)  {
            this.userRepository = userRepository;
        } 
        

        不建议自动绑定您的私人成员,checkout this post

        由于您已经在使用 Lombok 项目,因此更优雅的方法是使用 @RequiredArgsConstructor 注释您的类,而不是编写构造函数。

           @Slf4j
           @RequiredArgsConstructor
           @Service
           public class JwtUserDetailsService implements UserDetailsService {
        
             private final UserRepository userRepository; 
             ..
        
           }
        

        这里 Project lombok 将为您生成一个构造函数,它将负责依赖注入。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-08-31
          • 1970-01-01
          • 2016-01-12
          • 1970-01-01
          • 2015-05-16
          • 2018-03-11
          • 1970-01-01
          相关资源
          最近更新 更多