将 redis 中的数据更新到数据库时发生空指针异常

A null pointer exception occurred while updating data in redis to the database

提问人:Mazai 提问时间:8/5/2023 最后编辑:PinoMazai 更新时间:8/11/2023 访问量:65

问:

我做了一个博客项目,我希望用户每次点击博客,页面浏览量都会自动更新,我用redis来存储数据,每隔一段时间,redis中的数据就会更新到数据库中,但是当我想将当前登录用户ID更新到数据库中时, 发生异常。我希望你能帮我弄清楚问题出在哪里,谢谢。

这是我的实现类:

@Component
public class UpdateViewCountJob {
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private ArticleService articleService;

    @Scheduled(cron = "0/5 * * * * ?")
    public void updateViewCount(){
        //获取redis中的浏览量
        Map<String, Integer> viewCountMap = redisCache.getCacheMap("article:viewCount");

        List<Article> articles = viewCountMap.entrySet().stream()
                .map(entry -> new Article(Long.valueOf(entry.getKey()), entry.getValue().longValue()))
                .collect(Collectors.toList());

        Long userId = SecurityUtils.getUserId();
        for (Article article : articles) {
            article.setUpdateBy(userId);
        }
        //更新到数据库中
        articleService.updateBatchById(articles);
    }
}

这是我用 mybatisplus 实现的自动填充函数的类:

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        Long userId = null;
        userId = SecurityUtils.getUserId();

        this.setFieldValByName("createTime", new Date(), metaObject);
        this.setFieldValByName("createBy",userId , metaObject);
        this.setFieldValByName("updateTime", new Date(), metaObject);
        this.setFieldValByName("updateBy", userId, metaObject);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("updateTime", new Date(), metaObject);
        this.setFieldValByName("updateBy", SecurityUtils.getUserId(), metaObject);
    }
}

错误消息如下:

2023-08-05 13:42:05.005 ERROR 20388 --- [   scheduling-1] o.s.s.s.TaskUtils$LoggingErrorHandler    : Unexpected error occurred in scheduled task

java.lang.NullPointerException: null
    at com.blog.framework.utils.SecurityUtils.getLoginUser(SecurityUtils.java:13) ~[classes/:na]
    at com.blog.framework.utils.SecurityUtils.getUserId(SecurityUtils.java:29) ~[classes/:na]
    at com.blog.job.UpdateViewCountJob.updateViewCount(UpdateViewCountJob.java:32) ~[classes/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_131]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_131]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_131]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_131]
    at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:84) ~[spring-context-5.3.7.jar:5.3.7]
    at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-5.3.7.jar:5.3.7]
    at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:95) [spring-context-5.3.7.jar:5.3.7]
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_131]
    at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_131]
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) [na:1.8.0_131]
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [na:1.8.0_131]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_131]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_131]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_131]


SecurityUtils 类,如下所示:

public class SecurityUtils {
    /**
     * 获取用户
     **/
    public static LoginUser getLoginUser() {
        return (LoginUser) getAuthentication().getPrincipal();
    }

    /**
     * 获取Authentication
     */
    public static Authentication getAuthentication() {
        return SecurityContextHolder.getContext().getAuthentication();
    }

    public static Boolean isAdmin(){
        Long id = getLoginUser().getUser().getId();
        return id != null && id.equals(1L);
    }

    public static Long getUserId() {
        return getLoginUser().getUser().getId();
    }
}

让我感到困惑的是,当我注释掉 MyMetaObjectHandler 类中自动填充用户 ID 的代码时,没有错误,如下所示:

@Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("updateTime", new Date(), metaObject);
//        this.setFieldValByName("updateBy", SecurityUtils.getUserId(), metaObject);
    }

如果你能帮我解决这个问题,我将非常感谢你!

java redis nullpointerexception

评论

0赞 Tony Pierce 8/6/2023
你能指出哪条线抛出 NPE 吗?很难从堆栈跟踪中分辨出来,因为代码窗口没有行号。

答: 暂无答案