场景
遇到一个不常见的问题:
当Controller的参数为 Model参数绑定形式,且参数以下划线开头时,取不到参数,丢失了。
其实这篇文章和SpringCloud关系不大,但是属于Spring家族的相关内容。
例子:
@RestController
public class HealthyController {
@RequestMapping(value = "/test/param", method = RequestMethod.GET)
public String testParam(ParamModel param) {
return param.toString();
}
public static class ParamModel {
private String _api;
private String _app;
}
}
原理
一言不合翻源码:比Google还快
//WebDataBinder.java
public static final String DEFAULT_FIELD_MARKER_PREFIX = "_";
protected void checkFieldMarkers(MutablePropertyValues mpvs) {
if (getFieldMarkerPrefix() != null) {
String fieldMarkerPrefix = getFieldMarkerPrefix();
PropertyValue[] pvArray = mpvs.getPropertyValues();
for (PropertyValue pv : pvArray) {
if (pv.getName().startsWith(fieldMarkerPrefix)) {
String field = pv.getName().substring(fieldMarkerPrefix.length());
if (getPropertyAccessor().isWritableProperty(field) && !mpvs.contains(field)) {
Class<?> fieldType = getPropertyAccessor().getPropertyType(field);
mpvs.add(field, getEmptyValue(field, fieldType));
}
mpvs.removePropertyValue(pv);
}
}
}
}
这里的含义就是 如果你的URL或者Form里面有 下划线开头的参数,他就给你擦了。
具体来讲:
- 只要你有下划线开头的变量,就给你擦了。
- 如果被下划线的变量,还有对应的原始下划线变量,并且没有传原始变量,则填了个空值。
还有这种操作?
问题是谁会用下划线开头的变量?
答曰:PHP,C++,C,Python,谁都有可能。。。。
解决办法
request 里面是可以拿到的,要不就放在ThreadLocal里面?。。
要么,就别用下划线了?
要不,就继承这个DataBinder,替换他的设置?