遇到一个有意思的事情,springboot 收到表单 radio 字段的值中包含了`, on`字样,刚开始原因不明,迫于时间紧迫用 int 类型规避了这个问题,后来有时间仔细研究了一下,还是自己犯的错误
我们用以下表单就可以重现这个问题
<form th:action="@{form}" method="POST">
<h5>this is a form</h5>
<input id="form-input-radio-cat-1" type="radio" name="cat" value="1" />
<label for="form-input-radio-cat-1"> 类别 1</label>
<input id="form-input-radio-cat-2" type="radio" name="cat" value="2" />
<label for="form-input-radio-cat-2"> 类别 2</label>
<input type="checkbox" name="cat" required /> 确认无误
<button type="submit">submit</button>
</form>
明眼的同学应该一下子就发现问题所在了,这是一个简化的例子,实际的表单要更复杂,所以比较难看出。没看出来的同学也不用着急,往下读,我们的表单类也比较简单
public class DemoForm {
private String cat;
public String getCat() {
return cat;
}
public void setCat(String cat) {
this.cat = cat;
}
}
如果我们选中类别 2、勾选确认无误,提交表单,然后在 Controller 中打印 cat 的值,会得到如下结果:
TestController : form cat: 2,on
由于我没有看出来表单中的错误,所以这个问题困扰了我一些时间,而且由于时程的压力,当时没有很多精力投入到问题的排查中,很快我想到了一个规避的方法:使用 int
类型,这样我们的 DemoForm
就变成这个样子:
public class DemoForm {
private int cat;
public int getCat() {
return cat;
}
public void setCat(int cat) {
this.cat = cat;
}
}
由于 parse 的时候会忽略 ",on"
这部分内容,所以运行时不会有其他问题,当然这个 ",on"
怎么来的,我们也就无从知道了。
由于我「自认为」已经检查过表单,认为前端表单提交不会有问题,并且怀疑是不是因为选中了「类别2」,出于某种机制,springboot 自动加上了该标记,所以很自然的开始从后端排查起来。
几次断点后,大概知道,这个值是从 MutablePropertyValues mpvs
而来,mpvs 中,
cat
的值是一个数组:[“2”, “on”] ,而 mpvs
又来自 ServletRequest request
,那么问题大概可以猜到了,post 的数据很可能传递了两个 cat
的值,我们可以从 request
中检查 postData, 不过我觉得另一个方法更简单
提交表单前打开浏览器的开发者模式,检查表单数据就好了
问题已经很清楚了,前端表单多标注了一个 cat,导致 cat 的值变成了数组,知道了问题,那么修改起来也很简单,去掉相应的 name 属性即可:
<form th:action="@{form}" method="POST">
<h5>this is a form</h5>
<input id="form-input-radio-cat-1" type="radio" name="cat" value="1" />
<label for="form-input-radio-cat-1"> 类别 1</label>
<input id="form-input-radio-cat-2" type="radio" name="cat" value="2" />
<label for="form-input-radio-cat-2"> 类别 2</label>
<input type="checkbox" required /> 确认无误
<button type="submit">submit</button>
</form>