由于项目是前后端不分离的项目,很多接口都是通过jquery 表单提交参数到后端的,有些没有对传入参数判空,导致出现空指针等系列的问题
具体排查思路:
- 检查浏览器请求的参数,是否包含该字段,具体是在F12 检查具体请求里面有这个被转换为null的字段
- 接口debug 后端接口,检查参数是否接受正常,发现controller 参数接收到的就是 null, 说明在中间有未知的逻辑,对参数进行了处理,将其转换为null了
整个请求链路 前端(js) -> dipatchSevlet ->controller
一顿搜索后发现,spring mvc 在升级版本后,提供了一个功能,用于处理 @RequestParam注解或@PathVariable注解修饰的参数,将其进行转换,再检查 升级后引入包中的mvc 配置,果不其然,发现了问题所在
@Configuration
@ControllerAdvice
public class XXXXWebMvcConfiguration implements WebMvcConfigurer, ApplicationContextAware {
private static final Logger log = LoggerFactory.getLogger(XXXXWebMvcConfiguration .class);
private ApplicationContext applicationContext;
public void setApplicationContext(final @NonNull ApplicationContext applicationContext) throws BeansException {
if (applicationContext == null) {
throw new NullPointerException("applicationContext is marked non-null but is null");
} else {
this.applicationContext = applicationContext;
}
}
@InitBinder
public void initBinder(final WebDataBinder binder) {
StringTrimmerEditor stringtrimmer = new StringTrimmerEditor(true);
binder.registerCustomEditor(String.class, stringtrimmer);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
dateFormat.setLenient(false);
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
}
//.... 省略无关代码
}
因为 mvc 配置类中加了 @ControllerAdvice 导致 InitBinder 全局处理 @RequestParam注解或@PathVariable注解修饰的参数,继续看 StringTrimmerEditor 里面的代码:
public class StringTrimmerEditor extends PropertyEditorSupport {
@Nullable
private final String charsToDelete;
private final boolean emptyAsNull;
/**
* Create a new StringTrimmerEditor.
* @param emptyAsNull {@code true} if an empty String is to be
* transformed into {@code null}
*/
public StringTrimmerEditor(boolean emptyAsNull) {
this.charsToDelete = null;
this.emptyAsNull = emptyAsNull;
}
/**
* Create a new StringTrimmerEditor.
* @param charsToDelete a set of characters to delete, in addition to
* trimming an input String. Useful for deleting unwanted line breaks:
* e.g. "\r\n\f" will delete all new lines and line feeds in a String.
* @param emptyAsNull {@code true} if an empty String is to be
* transformed into {@code null}
*/
public StringTrimmerEditor(String charsToDelete, boolean emptyAsNull) {
this.charsToDelete = charsToDelete; // 重点在这里,emptyAsNull 如果传入的是空串,则转为null
this.emptyAsNull = emptyAsNull;
}
@Override
public void setAsText(@Nullable String text) {
if (text == null) {
setValue(null);
}
else {
String value = text.trim();
if (this.charsToDelete != null) {
value = StringUtils.deleteAny(value, this.charsToDelete);
}
if (this.emptyAsNull && value.isEmpty()) {
setValue(null);
}
else {
setValue(value);
}
}
}
@Override
public String getAsText() {
Object value = getValue();
return (value != null ? value.toString() : "");
}
}
因为引入了 StringTrimmerEditor,且设置传入空串转为null, 导致提交的表单,如果字段为空串,都在controller之前被转为了null,导致了这个问题的发生,只能说用第三方维护的依赖,果然有风险 =,=。
最后贴上 InitBinder 介绍的很详细的文章地址,值得一看:https://juejin.cn/post/7208837219212967996
标签:emptyAsNull,InitBinder,String,StringTrimmerEditor,value,入参,null,public From: https://www.cnblogs.com/charler/p/18386928