背景:
由于自己傻傻的操作和阴差阳错引发的“血案”,浪费了大量的时间,大家就当看个故事吧
不多说直接上代码:
/**
* 添加评论
* 发表评论
* @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要先好好分析,别一头扎进去
- 写代码要谨慎,不要有觉得自己很熟练不会有出问题这种心态
- 改错要有方法,不要往一个方向死抠,要有发散思维
写在最后:
以上是作者的亲身经历,也许在一些大佬眼中微不足道,甚至看着想笑,但作者通过这次确实收获了很多,写下来只是为了记住这次珍贵的经历,有经历才会有成长,欢迎大家在下方评论进行讨论、提出批评和建议。
文章评论