踩坑之变量命名

###背景 应用中需要内置几个特殊字段(createUser,updateUser,createTime,updateTime,status,batchId,source,id)来记录数据导入的状态。要求这几个字段不和用户自定义的业务字段冲突,就考虑选择的内置字段名称要尽反人类一点,和常规的字段命名习惯相悖。

使用的开发技术照常是Java,SpringMVC,MyBatis。Java的变量命名规则: 变量名大小写敏感. 一个变量名字可以是任意合法的标示符,即一个不限长度的 Unicode字母、数字, 以字母, "$", 或 "_"开头。惯例以字母开头定义变量名 , 而不是 "$" 或 "_"。所以就考虑变量前后都缀上"_"。 然后就开始踩坑。

###以“_”开头 问题:后台接收请求数据后,在SpringMVC解析绑定参数时参数值丢失了。

原因:因为WebDataBind在解析绑定请求参数到变量之前,会做checkFieldDefaults(),checkFieldMarkers()。 默认地,CheckFieldDefaults会把前缀“!”的请求参数的值当作被前缀的参数的默认值,然后把把前缀“!”的请求参数删除。checkFieldMarkers会给被前缀"_"的请求参数在空值的状态下填上设定好的默认的"空值",然后把把前缀“_”的请求参数删除。2段代码如下:

protected void checkFieldDefaults(MutablePropertyValues mpvs) {
	if (getFieldDefaultPrefix() != null) {
		String fieldDefaultPrefix = getFieldDefaultPrefix();
		PropertyValue[] pvArray = mpvs.getPropertyValues();
		for (PropertyValue pv : pvArray) {
			if (pv.getName().startsWith(fieldDefaultPrefix)) {
				String field = pv.getName().substring(fieldDefaultPrefix.length());
				if (getPropertyAccessor().isWritableProperty(field) && !mpvs.contains(field)) {
					mpvs.add(field, pv.getValue());
				}
				mpvs.removePropertyValue(pv);
			}
		}
	}
}

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);
			}
		}
	}
}

###以“$”开头 下划线不行,那就用$吧。SpringMVC是成功绑定获取到值了。但是接下来用Mybatis拼接sql时出错了。$开头的参数全部找不到getter方法,代码跟踪走起。发现mybatis使用org.apache.ibatis.reflection.Reflector反射获取参数值。在初始化Reflector填充<参数,getter>映射获取getter的时,对getter方法进行过滤,规则如下:

private boolean isValidPropertyName(String name) {
    return !(name.startsWith("$") || "serialVersionUID".equals(name) || "class".equals(name));
}

过滤掉以$开头的getter。

###最后 后来就extends一下ConfigurableWebBindingInitializer,把WebDataBind的fieldMarkerPrefix设置成null。

也许是解决方案不对,才会用到反人类的变量命名,才会踩到坑。

转载于:https://my.oschina.net/braveCS/blog/703816

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值