SpringBoot请求中存在空格导致后端无法接收值
前言
最近帮助别人解决问题时碰到了一个很简单的问题但是不仔细看又很难发现的问题。特此记录一篇。但是这个问题只存在于开发者的一个粗心情况下。不适用大多数人遇到的问题。
排查接口接收不到值的几种方式
1. 浏览器F12控制台网络中查看值是否为空 (其它浏览器同理)
2. 表单x-www-form-urlencoded和json两种格式下分别请求大小写问题
//实体类
class Data{
private String AbName;
private String id;
//...省略getter,setter方法
}
//controller访问接口类
@Controller
@RequestMapping("/test")
class TestController{
@PostMapping("/data")
@ResponseBody
public String data1(Data data){
return data.toString();
}
}
使用ApiPost请求这个接口 (使用x-www-form-urlencoded格式)
请求时参数前缀小写 (abName) 后端也是可以拿到值的,但是 (abname) 就拿不到值了
接下来使用一下json格式
json不同于x-www-form-urlencoded格式。这样是拿不到值的,因为后端代码需要更改,更改才可以获取到
//接口代码更改一下
@Controller
@RequestMapping("/test")
class TestController{
//对比上面代码 多了个@RequestBody注解。需要这个注解才能将json数据转换成实体类
@PostMapping("/data")
@ResponseBody
public String data1(@RequestBody Data data){
return data.toString();
}
}
加上注解后重启一下代码… 奇怪的事情就发生了。字段对应上的情况下Json格式下却接收不到数据
把AbName改成abName传递试试
解释: 前端Json格式下发送数据给后端,前缀是大写 (AbName) 收不到数据。前缀是小写(abName)却能接收数据,有点道反天罡的感觉。这也是后端接收不到值时需要排查的地方。查看使用的是什么格式的请求(json,x-www-form-urlencoded,formdata)。检查格式后检查是否有注解。@RequestBody注解存在时,使用x-www-form-urlencoded格式请求接口会出现下面报错。
3. 请求接口中参数存在空值时导致参数为空
这个就是我遇到的问题,百度查找了也没有相关的,但是这应该是程序员掌握的最基本的知识。继续以上面接口代码为例子。我新增了一个html在页面中复现我碰到的问题
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>测试请求中存在空格时操作</title>
</head>
<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
<body>
<div class="test">
</div>
</body>
<script>
//页面初始化执行
$(function(){
//测试随机数
let id = Math.floor(Math.random() * 10);
let code = Math.floor(Math.random() * 10);
//给class为test的元素添加三个a标签
$(".test").append('<a href="/test/data?id=' + id + '&code=' + code +'" class="btn">点击测试</a><br/>');
$(".test").append('<a href="/test/data?id=' + id + '&code= ' + code +'" class="btn">点击测试空格1</a><br/>');
$(".test").append('<a href="/test/data?id=' + id + '&code = ' + code +'" class="btn">点击测试空格2</a>');
})
</script>
</html>
<style>
html,body{
width: 100%;
height: 100%;
}
</style>
就以上代码很少人会这么写,用a标签去请求,我这么使用主要是因为开源框架就是这么提供的。看着会觉得哎这玩意不是三个一模一样的东西吗。有啥区别吗?
首先a标签的href代表一个跳转,跳转不就还是一个请求嘛
第一个a标签测试
从第一个a标签为切入点带大家往下看看
第一个a标签点击后展示的图如下:
可以看到代码中传递出去的id,code都是有值的,AbName忽略,跟这例子没关系。
第二个a标签测试
好像跟第一个a标签没啥区别。但是注意仔细看url地址 code=%207 。这个%20代表空格。详情可以去 http请求的特殊符号对应的变形 了解。
回到第二个标签。说明href中是有个空格的。现在翻到上面html代码不难发现确实多了个空格。但是值后端依旧是拿到了
第三个a标签
再看第三个a标签会发现跟另外两个都不一样。
=前后各一个空格,这时候再去请求一下试试。得到以下结果:
这时候code就拿到的是null,这在大多数情况下是不会发生的,但是用的框架因为有些人习惯于代码格式化,代码符号一多看不出哪里有问题,加上上面是测试代码容易看出,实际开发代码于功能开发情况也层出不穷,出错排查也并非很难,但是不仔细看的话很容易就找不出问题卡在这里大半天。
总结
URL请求参数后不允许有任何字符,否则会导致后端无法识别,从而导致接收值为NULL。在复现过程中还发现请求格式不同也会导致值无法收到。
我这情况不适用多数人,希望大家排查代码时要仔细查找,找到问题所在。