解决hutool的TreeUtil的getNode方法的空指针异常

今天在开发的时候遇到一个问题,场景是这样的,查询支出类别,我将某个公司的部门结构构建成一颗多级的分类树,如果当前的支出类别,配置了只有某些固定的部门才能查看,我就需要用这个配置的部门id去查找这颗树,查询到一颗字树,然后通过token去拿到当前登录用户的地区,如果当前登录的用户的部门,包含在这颗字树,则当前这个用户能看到这个支出类别的选项.那么问题就来了.

这里我一共遇到两个坑,我先说第一个,也就是标题所示的hutool的TreeUtil的getNode方法的空指针异常.

项目启动后发现报错,我在main放大里面自己通过TreeUtil构建一颗树,代码如下

public static void main(String[] args) {
        List<TreeNode<Integer>> list = new ArrayList<>();
        TreeNode<Integer> treeNode1 = new TreeNode<>();
        treeNode1.setId(1);
        treeNode1.setParentId(0);
        list.add(treeNode1);
        TreeNode<Integer> treeNode2 = new TreeNode<>();
        treeNode2.setId(2);
        treeNode2.setParentId(1);
        list.add(treeNode2);
        TreeNode<Integer> treeNode3 = new TreeNode<>();
        treeNode3.setId(3);
        treeNode3.setParentId(1);
        list.add(treeNode3);
        TreeNode<Integer> treeNode4 = new TreeNode<>();
        treeNode4.setId(21);
        treeNode4.setParentId(2);
        list.add(treeNode4);
        TreeNode<Integer> treeNode5 = new TreeNode<>();
        treeNode5.setId(31);
        treeNode5.setParentId(3);
        list.add(treeNode5);
        TreeNode<Integer> treeNode6 = new TreeNode<>();
        treeNode6.setId(211);
        treeNode6.setParentId(21);
        list.add(treeNode6);
        List<Tree<Integer>> build = TreeUtil.build(list);
        TreeUtil.getNode(build.get(0),31);
    }

如代码所示,当去读取节点1,2,21这三个节点都能读取,但是这棵树存在节点31,我去读取的时候,却出现了空指针就很奇怪了,不只是31,从顶节点的第二字节点开始就都读取不到了,堆栈信息如下:

Exception in thread "main" java.lang.NullPointerException
at cn.hutool.core.lang.tree.TreeUtil.getNode(TreeUtil.java:139)
at cn.hutool.core.lang.tree.Tree.getNode(Tree.java:56)
at cn.hutool.core.lang.tree.TreeUtil.getNode(TreeUtil.java:140)
at cn.hutool.core.lang.tree.Tree.getNode(Tree.java:56)
at cn.hutool.core.lang.tree.TreeUtil.getNode(TreeUtil.java:140)
at cn.hutool.core.lang.tree.Tree.getNode(Tree.java:56)
at cn.hutool.core.lang.tree.TreeUtil.getNode(TreeUtil.java:140)
at com.jiuji.oa.finance.sysconfig.service.impl.InvoiceDocConfigServiceImpl.main(InvoiceDocConfigServiceImpl.java:1120)

于是我去阅读了源码,发现问题所在

如上图所示,查询过程中,递归去遍历,但是去问题就出在这里,递归的默认条件是当前节点必定含有子节点,所以当我们遍历到最底层的节点时,他并没有子节点,所以for循环遍历node.getChildren就会出现空指针异常,那么找到问题了就好解决了,我们重写他的方法.

使用我自己定义后的方法去重新读取,结果和预想的一样,成功了,解决了第一个问题.

第二个问题就是,多层嵌套结构,反序列化的问题,因为制作这样的一颗树,我需要将整个depart表,全拉一份,但是这个接口却是经常使用,每次都全量拉表肯定受不了,所以我将这颗树,存入redis中,生命周期为24小时,这样一天只需拉取一次全表即可.问题也由此而来,先看我取出缓存的代码

当有缓存的时候,我会反序列化这棵树,但是反序列化的结果却是有问题的,以下两张图可以看出差别

可以看到,正常的Tree结构,他的Children是一个ArrayList,并且每个节点的结构都是Tree,再看反序列化的结果.

最外层确实反序列化为Tree了,但是内层的结构却还是JSONArray和JSONObject,以至于我后续去用这棵树的getNode方法的时候会出现类型强制转换异常,原因就是JSONObject不能转换成Tree.我去查阅了一定的资料,发现可以使用 new TypeReference去解决

JSON.parseObject(simpleDiffot, new TypeReference<Tree<Integer>>() {});

但是很遗憾,我不知道是我使用的方式不对还是什么,这个问题并没有得到解决,我想到的原因可能是因为 new TypeReference只能解决两层的嵌套,但是如果是像Tree这种,可能存在五六级的嵌套,还是无法解决.这里也是卡了我很久,没有一个好的解决方式,如果哪位大哥有好的解决方式,请给我分享.

接下来,和大家说一下我的笨办法,没错,每当调用getNode的时候,在递归的过程中手动将其反序化.

也就是红框下面的代码.因为代码使用了其他的JSONArray所以,这里要写全包名,后面看不到的部分是Tree.class.问题到此解决完了,如有错误,请不吝赐教!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值