开发Springboot,写完各个Service,调试controller的过程中遇见这个bug:
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed;
nested exception is java.lang.NullPointerException] with root cause
去网上查了一圈,大多数博客都表示这是由于Service层没有加@Service或者bean没有加@Autowired注解造成的。仔仔细细的看了两遍,明明已经加了注解;单元测试用例也能很顺利的通过,那么必然不可能是注解没加或者依赖注入的问题。
后来仔细推敲;既然是跟Controller有关的bug,会不会不是Service端的问题?也有可能是前端的问题。Controller接口如下:
@PostMapping("/searchByMulti")
public ResponseVO getInfoByAll(@RequestBody InfoVO infoVO)
{
……
}
前端通过json向Springboot发送POST请求;根据json数据的格式,自动转化成InfoVO对象。
前端数据格式:
如图所示,是4个数组,分别名叫
Author Conference Institition Research
而后端与之对应的VO数据格式为:
是四个同名的数组。
为了进行验证是否是参数传递出错的问题,我利用Postman向运行中的Springboot发送了Post请求,并且在Controller中对收到的参数进行了打印。
除了跟之前相同的报错之外,看到-----------searchingByMulti----------
成功被打印;说明这个接口确确实实被调用了;但是一看下面的参数,竟然全部都变成了null
!
仔细检查了一遍代码,名字也是对应的,也不存在接口方法写错的问题;
那么进行一下测试,如果换成get方法进行传参,会怎么样?实测,通过get方法完全是可以正确的传递参数的。
那么可以肯定,现在的问题转变成了:
SpringBoot Rest请求Post传实体类接收不到值的问题
上网搜索相关问题,看到一篇有意思的:
springboot post接口接受json时,转换为对象时,属性都为null https://blog.csdn.net/jiangjun0130/article/details/89210172
跟我们问题的基本相仿。
上文提出了一个观点,其实不是Springboot的锅,问题就在于Json格式上。
观点在于:
JAVA总是把实体对象(数据库/Nosql等)转换为POJO对象再处理, 虽然有各类框架予以强力支持. 但实体对象和POJO, 由于"饮食习惯", “民族特色”, "地域区别"等等差异, 需要有些定制需求, 使得能够完美的映射. 这个性化定制需求, 包括名称/时间格式/字段过滤等等约定.
——https://www.cnblogs.com/mumuxinfei/p/4761374.html
就是说,json的命名是有讲究的;在向后端传递的时候会根据一定的规则,把既定的名字给替换掉。比如,你用user_id
,他就有可能根据驼峰命名法把名字给你变成’userId’(例子详见第一篇博客链接);这一切都可以在application.yml
里进行设置。
我这里没有进行设置,经过我这边实测,他是默认帮你把传入的名称全部转换为小写。比如:
一开始的命名:Author Conference Institition Research
全部给你变成:author conference institition research
所以后端的InfoVO才会收不到值。对InfoVO进行修改:
前端干脆也直接换成小写:
进行测试:成功,问题解决。