记由于自己呆瓜操作引发的“血案”

背景:

  由于自己傻傻的操作和阴差阳错引发的“血案”,浪费了大量的时间,大家就当看个故事吧

不多说直接上代码:

    /**
     * 添加评论
     * 发表评论
     * @param commentParam
     * @return
     */
    @RequestMapping(value = "/insert")
    public ResponseUtil insert(CommentParam commentParam) {
        Comment comment = new Comment();
        BeanUtils.copyProperties(comment,commentParam);
        try {
            commentService.save(comment);
            logger.info("发表评论成功"+comment);
            return ResponseUtil.success();
        } catch (Exception e) {
            logger.error("发表评论失败"+e.getMessage());
            return ResponseUtil.fail();
        }
    }

  前端正常传参,调用接口是失败的,看上去代码是很正常的,那是为什么呢,然后接下来我就进行了傻傻的操作,也可以说是阴差阳错

代码变成了如下:

    /**
     * 添加评论
     * 发表评论
     * @param commentParam
     * @return
     */
    @RequestMapping(value = "/insert")
    public ResponseUtil insert(CommentParam commentParam) {
        Comment comment = new Comment();
        BeanUtils.copyProperties(comment,commentParam);
        System.out.println("入参:" + commentParam);
        System.out.println("po对象:" + comment);
        try {
            commentService.save(comment);
            logger.info("发表评论成功"+comment);
            return ResponseUtil.success();
        } catch (Exception e) {
            logger.error("发表评论失败"+e.getMessage());
            return ResponseUtil.fail();
        }
    }

运行结果:

入参:CommentParam(id=null, topicId=null, parentId=null, userId=null, likeCount=null, content=null, createTime=null, updateTime=null)
po对象:Comment(id=null, topicId=null, parentId=null, userId=null, likeCount=null, content=null, createTime=null, updateTime=null)
  • 然后就很顺理成章的理解为入参没拿到,参数映射、绑定失败了

  • 接下来我就进行了长达几个小时的查找资料、测试和改错,先是研究了GET、POST参数传递的知识,接着深入研究了@RequestBody注解,后面也研究了SpringMvc的参数绑定,再后来还深入到源码层面去了解,最后还是一直为null,好家伙,直接就破防了!!!

  • 中午睡了个午觉,起来继续解决这个问题,解决了一会还是这样,最后直接另外开了个方法来细致的测试,代码如下:

    /**
     * 测试参数映射bug
     * 2021年1月6日
     */
    @RequestMapping("/test")
    public void testParam(CommentParam commentParam) {
        System.out.println("==========================================");
        System.out.println(commentParam);
        Comment comment = new Comment();
        System.out.println("==========================================");
        System.out.println(comment);
        BeanUtils.copyProperties(comment,commentParam);
        System.out.println("==========================================");
        System.out.println(commentParam);
    }

运行结果:

==========================================
CommentParam(id=null, topicId=2, parentId=2, userId=2, likeCount=null, content=测试, createTime=null, updateTime=null)
==========================================
Comment(id=null, topicId=null, parentId=null, userId=null, likeCount=null, content=null, createTime=null, updateTime=null)
==========================================
CommentParam(id=null, topicId=null, parentId=null, userId=null, likeCount=null, content=null, createTime=null, updateTime=null)
  • 好家伙,这一运行立马就发现了问题,大家应该都看出来了,原来传参是没有问题,参数正常拿到了,只是后面 BeanUtils.copyProperties()这个方法导致后面两个对象的属性都为null了,这时候就要为大家介绍一下这次的元凶之一BeanUtils.copyProperties()这个方法了:

    BeanUtils提供对Java反射和自省API的包装。其主要目的是利用反射机制对JavaBean的属性进行处理,而BeanUtils.copyProperties(A,B)这个方法将符合条件的属性值全部从A对象赋值给B对象,也就是拷贝,但前提是对应的属性有getter和setter方法。

  • 而我犯的错误就很明显了,使用BeanUtils.copyProperties(A,B)方法时,将两个对象位置放错了,导致将属性值为null的对象复制到拿到前端传参的对象里,导致两个对象的属性值都为null,从而引发了这场“血案”,而且也因为自己一开始测试的不恰当,将两个System.out.println()放在BeanUtils.copyProperties(A,B)方法后面,这才没发现传参是正常的,从而被错误的引导往参数映射方向去思考,导致花费了大量时间,另外一方面原因也是自己还是太没经验了,也沉不住气,长时间没把这个问题解决导致心浮气躁,非常上头,不过也算因祸得福吧,在传参和参数映射、绑定方面还是学到了很多。

总结:

  • 遇到bug要先好好分析,别一头扎进去
  • 写代码要谨慎,不要有觉得自己很熟练不会有出问题这种心态
  • 改错要有方法,不要往一个方向死抠,要有发散思维

写在最后:

  以上是作者的亲身经历,也许在一些大佬眼中微不足道,甚至看着想笑,但作者通过这次确实收获了很多,写下来只是为了记住这次珍贵的经历,有经历才会有成长,欢迎大家在下方评论进行讨论、提出批评和建议。

点赞

发表回复

电子邮件地址不会被公开。必填项已用 * 标注